ちゃんなるぶろぐ

エンジニア5年生🧑‍💻 オライリーとにらめっこする毎日。

【10分でわかる💻💻💻】マイクロサービスアーキテクチャ〜ざっくり概要だけ〜

どうも、ちゃんなるです🐻

職場でここ数年、巨大なモノリシックアプリケーションのマイクロサービス化が進められています。

ですが私はその作業に関わってなく、マイクロサービスの知識があまりありません…。

なので、今回「マイクロサービスアーキテクチャをざっくりと紹介します🖐️

マイクロサービスアーキテクチャの概要

マイクロサービスアーキテクチャは、アプリケーションを小さな独立したサービスに分割するアプリケーションアーキテクチャのひとつです。

アプリケーションの柔軟性・拡張性・保守性の向上が目的です。

各サービスは、独自のプロセスとデータストアを持ち、APIを介して相互通信します📡 また、サービスが独立しているため個別に開発・デプロイ・スケーリング・保守することができます👏

マイクロサービスアーキテクチャの基本概念と設計原則

対比されるアーキテクチャ「モノリシックアーキテクチャ

大きな単一機能を持ち、​単一の塊で構成されているため、​システムやソフトウェアが1つのモジュールでできており、​分割されていない設計のことを指します​。

メリットは、​​システム全体が1つのモジュールで構成されているため、​​システム全体を把握しやすく、​​開発や運用が比較的簡単であることです。​​また、​​あらゆるサポートを一元的に提供できるため、​​問題が発生した場合に対処しやすい場合もあります。

​​デメリットは、​​システムの一部を変更する際、​​全体を修正・テストする必要が生じることで、​システムの規模が大きくなるほど​開発速度の低下が問題として取り挙げられます。

単一責任原則

各マイクロサービスは、1つの責任のみを持つように設計する必要があります。

これにより、サービスが容易に理解、開発、テスト、デプロイメントされることが可能になります。

※下記がわかりやすいと感じました

qiita.com

ドメイン駆動設計

ドメイン駆動開発(DDD)は、​​ユーザーが従事する業務に合わせてソフトウェアを開発する手法であり、​​ユーザーの業務知識をコードに反映させることができます。*1

このDDDは、マイクロサービスの境界を明確に定義するのに役立ちます。

障壁の高いコンポーネント設計

マイクロサービスは、内部実装の詳細をサービス自身の外側に対して隠蔽し、明確に定義されたインターフェース(例えばHTTP APIを通じてのみ他のサービスと通信するという点が非常に重要です。

これにより、各サービスが独立して進化し、互いに影響を与えずに変更できます。

RESTful APIとの関連性

マイクロサービス間の通信には、通常RESTful APIが使用されます。

RESTful APIは、HTTPプロトコルを使用してリソースにアクセスする方法であり、マイクロサービス間の連携をHTTP通信で行うことが一般的です。

※RESTful APIについての詳細は省略します。RESTful APIの満たすべき条件は下記サイトを見てみて下さい。

restfulapi.net

マイクロサービスアーキテクチャのメリットとデメリット

メリット:スケーラビリティと柔軟性の向上

各サービスは独立してデプロイおよびスケールできるため、システム全体のパフォーマンスと可用性が向上します。

メリット:独立したチームでの開発

各サービスが独立して開発およびデプロイされるため、サービスとチームを一意に結びつけることでフルサイクル開発化*2に繋がり、自律的な開発チームが築ける可能性があります。

これにより、開発サイクルが短縮され、より迅速に機能を市場に投入することができます。

デメリット:複雑さの増加と運用コスト

マイクロサービスアーキテクチャのデメリットは、システムの複雑さが増加し、運用コストが高くなることです。

サービス間の通信、データ管理、セキュリティ、および監視など、多くの側面で追加の調整が必要となります。 ただし、適切なツールとプロセスを用いて運用管理を行うことで、これらの課題を軽減することが可能です。

まとめ

マイクロサービスアーキテクチャは、スケーラビリティ、柔軟性、および独立したチームでの開発を促進する一方で、複雑さや運用コストが増加することが挙げられます。

適切な設計原則、実装手法、および運用管理を用いることで、マイクロサービスアーキテクチャを効果的に活用し、ビジネスの成長を促進することができます。

参考文献

martinfowler.com

cloud.google.com

www.splunk.com

knowledge.sakura.ad.jp

and-engineer.com

mercart.jp

フルサイクル開発とは

どうも、ちゃんなるです🐻

最近身の回りでたびたび「フルサイクル開発」と聞くようになりました🖐️

恥ずかしながら、初めて耳にしてからすぐには調べてはおらず、ソフトウェアエンジニアをまる2年やっているのにわかっていませんでした💦

なので、今日はこいつをまとめます。

概要

フルサイクル開発とは、​ソフトウェア開発ライフサイクルの全ての段階において、​設計、​実装、​テスト、​デプロイ、​運用、​サポートまでを担う開発スタイルを指します。

出典:Netflixにおけるフルサイクル開発者―開発したものが運用する

​フルサイクル開発者は、​開発ライフサイクルのあらゆる場面で、​手動で行われていたものを自動化していきます。これにより、本質的な価値提供にほぼ全てのリソースを向けることができ、​開発アジリティの向上と開発チームのスケーリングを実現します🔥

また、​フルサイクル開発者は機能拡充だけでなく、​DevOpsの理解と実践もすることになります。​開発者の視点で問題を評価し、​自分たちが開発したものを運用することによって、​より良いプロダクトを提供し続けることにつながります👍

フルサイクル開発の意義

意義は、「全てのソフトウェアの開発サイクルを担当することで、​より高速でプロダクトをリリースすることができること」です。

​フルサイクル開発者は、​設計、​実装、​テスト、​デプロイ、​運用、​サポートまでを担当するため、​分業による手間やコストを排除することができます。​フルサイクル開発者によって構成されたチームは、​より高速でプロダクトをリリースすることができるため、​ビジネスに貢献することができます。

下記は実際に「フルサイクル開発」を体験されている方の意見です。

前職は企画やインフラというように分業された環境でしたが、自身の好奇心からフルサイクルに近い動きをしていました。だからこそ分かるのですが、分業状態だと依頼などでどうしてもコミュニケーションコストがかかります。フルサイクルな開発の意義の一つは、そうしたコストを排除することによるスピード感だと思います。*1

確かに、コミュニケーションはコストがかかります。その一方で、それが計測しづらく開発リソースへの影響が軽視されがちだと私は日頃感じています…。

なので、コミュニケーションコストを削減できるという点で「フルサイクル開発」は魅力的ですね✨

メリット

  1. 分業による手間やコストの排除と、それによる高速かつ高品質なプロダクトリリースができる。
  2. DevOpsの原則を深く理解し、開発者視点での問題評価によってサービスの改善ができる。
  3. 各開発チームが小さな責任範囲を持ち、他の機能との依存関係を気にせず開発が進められる。(そのため、たとえば​マイクロサービスアーキテクチャで分かれた機能ごとのチーム編成が可能ですね)

デメリット

  1. スキルセットの要求が高く、多岐にわたる知識と経験が必要で、適切な人材の確保が難しい。
  2. 個々の開発者が多くのタスクを担当するため、負担やストレスが増加し、バーンアウトのリスクが高まる(これは主観ですがサステナブルでなく深刻な問題だと感じます👀💦)。
  3. 少数の開発者が全てのフェーズを担当するため、専門的な知識が欠けたり、特定の分野での最適解が見逃される可能性がある。

まとめ

フルサイクル開発は、開発者がソフトウェア開発ライフサイクルの全ての段階を担当する開発スタイルで、プロダクトの高速リリースやコミュニケーションコストの削減が期待できる一方で、人材確保の難しさや開発者の負担増が懸念されるデメリットもあります。

しかし、フルサイクル開発は開発アジリティの向上やビジネスへの貢献を実現することができるため、チームや組織にとって大きな魅力がある開発スタイルです。

導入を検討する際には、開発者のスキルセットやチームの構成、開発フローを慎重に評価し、組織のニーズに合った最適な取り組み方を見つけることが重要です。

また、バーンアウトのリスクを軽減するために、開発者のサポートや継続的な教育を行うことが不可欠です。

最後に、フルサイクル開発は、DevOps文化を推進することにも繋がります。

開発者が自分たちが開発したものを運用することで、問題の早期発見と解決ができ、サービスの改善を促すことができます。

このように、フルサイクル開発は、現代のソフトウェア開発において、新たな可能性を提供する重要な概念となっています✨

参考文献

【10分でわかる🇯🇵🇺🇸🎙️】TypeScriptでDesign Pattern〜Interpreter Pattern〜

どうも、ちゃんなるです!

今回は、Interpreter Patternを紹介します🖐️

概要

Interpreter Patternは、特定の文法や言語を解釈・評価するアルゴリズムを表現する際に役立ちます。

簡潔なコードで柔軟性と拡張性が向上し、言語の規則を変更しやすくなるのがInterpreter Patternの大きな利点です。

今回示すプログラムの設計

具体的なシナリオとして、電卓アプリケーションを考えます。

ユーザーが入力した数式を解釈し、計算結果を返すプログラムを設計します。

クラス図

サンプルコードのクラス図:Mermaid Live Editorで作成

クラス名 役割
Expression 抽象式クラス。すべての式クラスの基底となる。
TerminalExpression 数値リテラルを表すクラス。
NonTerminalExpression 二項演算を表すクラス。
Context 解釈のための情報を提供するクラス。
CalculatorContext 電卓アプリケーションの文脈を表すクラス。

サンプルコード

abstract class Expression {
    abstract interpret(context: Context): number;
}
class TerminalExpression extends Expression {
    private value: number;

    constructor(value: number) {
        super();
        this.value = value;
    }

    interpret(context: Context): number {
        // 必要に応じてcontextの値を使う
        return this.value;
    }
}
class NonTerminalExpression extends Expression {
    private left: Expression;
    private right: Expression;
    private operation: string;

    constructor(left: Expression, right: Expression, operation: string) {
        super();
        this.left = left;
        this.right = right;
        this.operation = operation;
    }

    interpret(context: Context): number {
        switch (this.operation) {
            case '+':
                return this.left.interpret(context) + this.right.interpret(context);
            case '-':
                return this.left.interpret(context) - this.right.interpret(context);
            case '*':
                return this.left.interpret(context) * this.right.interpret(context);
            case '/':
                return this.left.interpret(context) / this.right.interpret(context);
            default:
                throw new Error('Invalid operation');
        }
    }
}

Interpreter Patternの特徴として、処理の文脈(Context)を扱うことが挙げられます。

今回の例は単純な四則演算なので特に必要ないのですが、Context内に具体的なより複雑な処理を持たせることで、より柔軟な設計が可能になります🖐️

abstract class Context {}
class CalculatorContext extends Context {}

実際に使ってみましょう🖐️

以下のような式を解釈するプログラムを実装します。

(5 + 4) * 3 / 2
const context = new CalculatorContext();
const expression = new NonTerminalExpression(
    new NonTerminalExpression(new TerminalExpression(5), new TerminalExpression(4), '+'),
    new TerminalExpression(3),
    '*'
);
const result = expression.interpret(context) / 2;
console.log(result); // 13.5

上記のように、解釈する式を作り、interpretメソッドを呼び出すことで計算できます🖐️

また、CalculatorContextクラスを継承したクラスを作成することで、変数などの文脈情報を追加することもできます👍

Interpreter Patternの使い道

組み合わせられるデザインパターン

  • Composite Pattern: 複雑な文法構造を木構造で表現する際に適用できます。

chan-naru.hatenablog.com

  • Visitor Pattern: インタプリタの動作を変更したい場合に、Visitorパターンと組み合わせることで柔軟性を向上させることができます。

chan-naru.hatenablog.com

  • Flyweight Pattern: 大量のインスタンスを効率的に扱うことができるパターンで、頻繁に使われるオブジェクトを再利用することでメモリ使用量を削減できます。インタプリタにおいて、共通するオブジェクトが多数存在する場合に適用できます。

chan-naru.hatenablog.com

まとめ

Interpreter Patternは特定の文法や言語を解釈・評価する際に役立ち、簡潔なコードで柔軟性と拡張性が向上します。

電卓アプリケーションの例を通じて、TypeScriptでの実装方法とクラス図を、加えて適用される典型的なシナリオと、他のデザインパターンとの組み合わせも紹介しました👍

ぜひ参考にして、効率的で拡張性の高いプログラムを設計してみてくださいね🔥

参考文献

www.oreilly.com

en.wikipedia.org