楽水

人々の創造が自由に表現できる舞台づくり

未分類

生成AIと創るマイクロサービス

投稿日:

先日、OpenAI社から ChatGPT-5 がリリースされました。
特に、コーディング能力が上がったという話なので、今回、GhatGPT-5と共創してマイクロサービスを開発してみました。
そこで、今回はChatGPT-5と共創してマイクロサービスを開発する方法についてまとめます。

マイクロサービスの技術スタック

今回、開発したフロントエンドアプリの技術スタックは次のようになります。

  • 言語
    Java
  • フレームワーク
    SpringBoot
  • POM(Project Object Model)
    ここでは、POMの内容を記述します。
    POM(Project Object Model)とは、Mavenにおけるプロジェクトのビルド、依存関係、パッケージング、リリース管理などを定義するXML形式の設定ファイルです。
    Mavenとは、Javaプロジェクトのビルド、依存性管理、パッケージング、リリース管理を自動化するツールのことです。
  • application.properties
    ここでは、application.propertiesの内容を記述します。
    application.propertiesとは、アプリケーションの設定を記述するためのプロパティファイルです。
    このファイルは、Spring Boot アプリケーションの起動時に自動的に読み込まれ、様々な設定項目(ポート番号、DB接続情報、ログレベル、CORS設定など)を外部から制御することができます。
    以下は、よく使う設定項目の例です。
    server.port=8080:アプリの起動ポート
    spring.datasource.url=jdbc:postgresql://localhost:5432/mydb:DB接続URL
    spring.datasource.username=root:DBユーザー名
    spring.datasource.password=pass:DBパスワード
    spring.jpa.show-sql=true:SQLログを表示
    logging.level.root=INFO:ログレベル設定
    spring.profiles.active=dev:使用するプロファイルの切り替え
    cors.allowed-origins=http://localhost:3000:CORSの許可設定(独自定義のプロパティ)
  • 開発環境
    IntelliJ IDEA(JetBrains)、Eclipse IDE、Spring Tool Suite (STS)などの開発環境を指定します。

マイクロサービスの仕様の定義

マイクロサービスの仕様の定義は、次のように進めます。

  1. マイクロサービスの仕様を定義する
    どのように仕様を定義するかも含めてGPT-5と決めていきます(共創)。
  2. その内容でマイクロサービスのソースコード、および、必要な定義ファイル一式を生成するようにGPT-5に指示する
  3. GPT-5が生成したソースコード一式を実行してマイクロサービスを起動し、それが仕様通りになっているか検証する
  4. 不具合があれば、次回から不具合がでないように仕様を改善する

このプロセスを、マイクロサービスが不具合なく実行されるまで繰り返し、マイクロサービスの仕様を完成させます。
マイクロサービスの仕様の構成例は次のようになります。

  1. アプリケーション名
    製品管理システム
  2. プロジェクトの目的
    「本プロジェクトでは、ドメイン駆動設計の考え方を適用してSpringBootでソースコード一式を作成します」などプロジェクトの目的を記述します。
  3. 技術スタック
    上述の通りです。
  4. 共通仕様
    ここでは、個々のAPIや画面に共通する仕様について次のような観点で記述します。

    • 設計手法
      ここでは、次の例のように指示します。
      本プロジェクトでは、ドメイン駆動設計(DDD)の考え方を適用し、以下の各層を Spring Boot により実装してください。

      • Entity
        @Entity アノテーションを用いて、JPA エンティティとして定義してください。
      • Value Object
        @Embeddable アノテーションを用いて値オブジェクトとして実装してください。
      • Repository
        JpaRepository または CrudRepository を継承したインターフェースとして実装してください。
      • ApplicationService
        @Service アノテーションを付与したクラスで、ユースケースレベルの処理を実装してください。
      • DomainService
        @Service を付けたクラスで、ドメインロジック(エンティティに属さない操作)を実装してください。
      • RestController
        @RestController アノテーションを使用し、外部インターフェースとなる REST API を JSON ベースで提供してください。
    • アプリケーションアーキテクチャ
      ここでは、次の例のように指示します。
      本プロジェクトでは、「ヘキサゴナルアーキテクチャ(Hexagonal Architecture、別名:Ports and Adapters)」を採用してください。
      以下のような責務分離に従い、Spring Boot を使って各層を構成してください。

      • ドメイン層(domain.model)
        Entity、ValueObject、DomainService、Factory を含む。ビジネスルールを集約します。
      • アプリケーション層(application.service)
        ユースケースごとの ApplicationService を定義し、ドメイン層の呼び出しと調整を行います。
      • インフラ層(アダプタ)(adapter 以下)
        DB(JPA Repository)、REST(Controller)、Messaging(ActiveMQ連携など)を含み、外部との接続を担います。
    • パッケージ構成
      ここでは、パッケージ構成を指示します。

      • ベースパッケージ
        com.x.y
      • アプリケーション層
        com.x.y.application.service
        アプリケーションサービス(ユースケースレベルの処理)を格納。
      • ドメイン層
        com.x.y.domain.model
        エンティティ、値オブジェクト、ファクトリなど、ドメインモデルを格納。
        com.x.y.domain.service
        ドメインサービス(エンティティに属さないビジネスルール)を格納。
      • アダプター層(外部接続)
        com.x.y.adapter.db.rdb
        RDB用のリポジトリ(Spring Data JPA)を格納。
        com.x.y.adapter.db.nosql
        NoSQL用のリポジトリを格納(必要な場合のみ)。
        com.x.y.adapter.messaging
        メッセージングに関するクラス(Event、Sender、Receiver)を格納。
        com.x.y.adapter.rest
        REST API 関連のクラス(RestController、RestTemplateなど)を格納。
      • 共通設定
        com.x.y.config
        アプリケーション全体に関わる設定クラスを格納します。以下のような構成を含めます。
        SecurityConfig:CORSや認証フィルターの設定。
        OpenApiConfig:OpenAPI 3 に基づくAPIドキュメントの設定。
        AuditingConfig:作成日時・更新日時を自動記録するJPA監査設定。
      • 例外処理
        com.x.y.exception
        共通の例外クラスや例外ハンドリングクラスを格納します。以下のような構成を含めます。
        BusinessException:業務例外(ビジネスルール違反)。
        DomainException:ドメイン層での不整合やバリデーションエラー。
        GlobalExceptionHandler:@ControllerAdvice による全体的な例外ハンドリング。
    • セキュリティ対応
      ここでは、次のように、セキュリティ対応に関する指示をします。

      @Configuration + @EnableWebSecurity + WebSecurityConfigurerAdapterを拡張したSecurityConfigを作成し、次の構成を実装してください。
      CORS(クロスオリジン)設定
      認証フィルター(AuthFilter)の登録
    • 楽観ロック対応
      ここでは、楽観ロックに対応させるための指示をします。

      集約ルート(対応するテーブル)に、@Versionを設定して楽観ロックを実現してください。
    • データマネジメント対応
      ここでは、データマネジメントに対応させるための指示をします。

      監査すべきエンティティの作成日時・更新日時・作成者・更新者などの情報を自動的に記録・管理できるようにしてください。
    • ページネーションの実現
      ここでは、ページネーションを実現させるための指示をします。

      Spring Data JPAのPageとPageableを使ってListを返すものはページネーションに対応させてください。
    • OpenAPI対応
      ここでは、OpenAPIに対応させるための指示をします。

      @Configurationを定義することでRestControllerをOpenAPIに対応させてください。
    • エラーハンドリング
      ここでは、エラーハンドリングに関する指示をします。

      Spring Bootで@ControllerAdviceを使ったエラーハンドリングを行うと、アプリケーション全体の例外処理を一元化できます。
      具体的には、Spring Bootでは、次の流れで自動的に例外を発生させてください。
      HTTPリクエスト
      DispatcherServlet
      Controllerメソッド呼び出し
      Exception発生!
      DispatcherServletがキャッチ
      @ExceptionHandlerのあるメソッドを探索
      ControllerAdviceが見つかる
      GlobalExceptionHandlerの処理が実行される
      ResponseEntityを返す(HTTPレスポンス生成)
    • エラーメッセージの国際化
      ここでは、Spring Bootで メッセージの国際化(i18n)を実現するための指示をします。

      • メッセージファイル
        Spring Bootで使用するメッセージの国際化(i18n)対応のため、次の3つのメッセージリソースファイルを src/main/resources に配置する形式で作成してください。
        ・messages.properties(デフォルト:空で可)
        ・messages_ja.properties(日本語)
        ・messages_en.properties(英語)
      • 実装方針
        ①@ConfigurationクラスMessageConfigを作成し、以下の設定を行うこと
        ResourceBundleMessageSourceによるメッセージ読み込み(UTF-8, basename=messages)
        AcceptHeaderLocaleResolverによるロケール判定(ヘッダー `Accept-Language` を優先し、指定がない場合は Locale.JAPANを使用)
        ②国際化されたエラーメッセージを取得するため、MessageSourceを使用する実装例を含めること
  5. ユースケース
    ここでは、マイクロサービスが関係するシステムユースケースを記述します。
    GPTは、このユースケースを確認して、実装すべきドメイン駆動設計の要素を判断します。

モデルドリブン開発

「モデルを中心にシステム開発を行い、モデルから自動的に実装を生成する世界」を目指して提唱された考え方にMDA(Model-Driven Architecture:モデル駆動アーキテクチャ)があります。
具体的には、PSM(Platform Specific Model)まで創れば、それに基づいて自動的にソースコードやデータベースのスキーマが生成されるというものです。
MDAは、2001年にOMG(Object Management Group)によって提唱されたものですが、当時の技術では、事実上、それを実現することはできませんでした。
しかし、2025年の現在、生成AIの目覚ましい進歩によって、ようやくMDAの目指した世界が実現できるようになったと考えてます。
ここでは、今回、実際に行った、モデルをベースに自動的にソースコードを生成してシステムを開発するモデルドリブン開発の流れについて説明します。
MDAのCIM、PIM、PSMは、ビジネスストラクチャマトリクスの型、種類、実例に対応します。

それでは、ビジネスストラクチャマトリクスも参照しながら、CIM、PIM、PSMの順で、法人顧客管理システムを開発する流れを見ていきましょう。

CIMの設計

MDAでは、CIM(Computation Independent Model)を計算機処理に依存しないモデルと位置づけています。
つまり、CIMは業務をモデル化してもので、それを実現するシステムに依存しません。
なので、技術の進歩によって、CIMの実現手段であるシステムが置き換わっても、業務の本質を表すCIMが変わることはありません。
さて、CIMはビジネスストラクチャマトリクスでいうと「型」の部分になります。
ビジネスストラクチャマトリクスの縦軸でいうと、システム開発で関係するのは、アプリケーション、データ、ITの部分になります。
なので、CIMは、アプリケーションタイプ、データタイプ、ITタイプということになります。
なお、エンタープライズアーキテクチャでいうと、それぞれ、アプリケーションアーキテクチャ、データアーキテクチャ、テクノロジーアーキテクチャになります。
ここでは、IT基盤は除外して、アプリケーション、データの部分を対象にして説明します。
一つひとつ見ていきましょう。

データタイプの設計

データタイプは、概念レベルのデータで、データタイプの構造が概念データモデル、あるいは、概念レベルのドメインモデルになります。
下図は、UMLのクラス図で描いた製品のドメインモデルです。

これを見ると、このビジネスでは、次のような観点で製品を管理することがわかります。

  • 製品は、その種類の最小単位である品目として管理する。
  • 品目は、「PN(Parts Number)」という品目情報と、「PS(Part Structure)」というPNの親子関係を管理するBOM(Bills of materials:部品表)の構造を持つ。
  • 品目の種類には、設計品目、製造品目、販売品目、購買品目、サービス品目がある。
  • 各品目は、種類ごとに、複数の単価を持つことができる。
  • 各品目は、種類ごとに、仕様、サイズ、色など様々な分類基準で分類することができる。

マーケティングマネジメント―持続的成長の開発と戦略展開」という書籍で、フィリップ・コトラーは、製品の階層構造を次のように説明しています。

  • ニーズ・ファミリー
    製品ファミリーのもととなる中核ニーズ。
    生命保険の例
    安全。
  • 製品ファミリー
    中核ニーズを満足させる全ての製品クラス。
    生命保険の例
    貯蓄と所得。
  • 製品クラス
    製品ファミリーの中で機能的一貫性を持っているとみなされる製品グループ。
    生命保険の例
    金融手段。
  • 製品ライン
    製品クラスの中で、機能、顧客、販路、価格水準などを同じくすることで密接に関連づけられている製品グループ。
    生命保険の例
    生命保険。
  • 製品タイプ
    製品ラインの中で、形態や様式が同じもの。
    生命保険の例
    長期契約の生命保険。
  • ブランド
    製品ラインの中の一つあるいは複数のアイテムにつけられた名前であり、アイテムの特性や出所を明らかにするもの。
    生命保険の例
    プルーデンシャル。
  • 品目(アイテム)
    製品ラインやブランドの中で、サイズ、価格、外見、その他の特性で区別される単位。
    生命保険の例
    プルーデンシャル更新可能長期保険。

上図のドメインモデルでは、この分類の品目を管理し、その上位概念としてのニーズ・ファミリーからブランドまでを品目分類基準とその値で定義できるようにしていることがわかります。
次に、設計品目、製造品目、販売品目、購買品目、サービス品目の関係を次のように設計します。

このドメインモデルは、設計→製造→サービスのエンジニアリングチェーンと、購買→製造→販売というサプライチェーンの流れから構成されています。
それから、各関連の多重度によって、ビジネス上、次の要件を満たす必要があることがわかります。

  • 製造品目から販売品目への関連
    同じ製造品目であっても販売独自の視点で販売単価の異なる販売品目を設ける可能性がある。
  • 販売品目から製造品目への関連
    複数の製造品目をまとめて一つの販売品目にする可能性がある。
  • 製造品目から購買品目への関連
    同じ製造品目(この場合部品です)であっても購買独自の視点で購買単価の異なる購買品目を設ける可能性がある。
  • 購買品目から製造品目への関連
    購買独自の購買品目がある可能性がある(製造品目が0になる場合がある)。
  • 製造品目から設計品目への関連
    「工程」など製造独自の製造品目がある(設計品目が0になる場合がある)。
  • 設計品目から製造品目への関連
    一つの設計品目に対して異なるバージョンの製造品目がある可能性がある。
  • 製造品目からサービス品目への関連
    一つの製造品目に対して異なるバージョンのサービス品目がある可能性がある。
  • サービス品目から製造品目への関連
    「役務」などサービス独自のサービス品目がある(製造品目が0になる場合がある)。
    複数の製造品目をまとめて一つのサービス品目にする可能性がある。

このようなビジネス上のデータ要件は、ビジネスメタデータとして定義します。
そして、システム開発や業務パッケージ導入の要件定義の際、それが満たすべきデータ要件として定義します。

アプリケーションタイプの設計

次に、アプリケーションタイプですが、これは、概念レベルの本質的な(製品や技術に左右されない)アプリケーションの型で、ビジネスアーキテクチャの一つ、ジョブを支援する役割を表します。
システム開発するときは、まず、ビジネスアーキテクチャのビジネスプロセスから、アプリケーションタイプのユースケースを洗い出します。

PIMの設計

MDAでは、PIM(Platform Independent Model)をIT基盤に依存しないモデルと位置づけています。
つまり、PIMはシステムをモデル化しものですが、業務を実現するシステムの論理的な仕組を表したものでもので、それを実装するIT基盤に依存しません。
なので、技術の進歩によって、PIMの実装手段であるIT基盤が置き換わっても、システムの論理的な仕組を表すPIMが変わることはありません。
さて、PIMはビジネスストラクチャマトリクスでいうと「種類」の部分になります。
なので、PIMは、アプリケーションカテゴリ、データカテゴリということになります。
ここでは、CIMの概念レベルのドメインモデルを構成する設計品目、製造品目、販売品目、購買品目、サービス品目を、独立させて、それぞれを管理するマイクロサービスを開発することにします。
なぜならば、設計品目、製造品目、販売品目、購買品目、サービス品目は、それを管理するためのドメイン知識が異なるので、それぞれが独立したドメインと考えたほうがよいと判断したからです。
次の図は、販売品目の論理レベル(データカテゴリ)のドメインモデルの例になります。

これを見ると、クラスのステレオタイプとして、集約(aggregation)、エンティティ(entity)、値オブジェクト(value object)などドメイン駆動設計の概念が設定されていることがわかります。
ここでは、設計手法としてドメイン駆動設計(DDD)を適用し、その考え方(論理)に基づいて論理モデル(PIM)を設計しています。
このドメインモデルの集約は、販売品目になります。
CIMのドメインモデルでは、設計品目、製造品目、販売品目、購買品目、サービス品目に共通の品目があり、品目番号、品目名など共通の属性が定義していました。
PIMのドメインモデルでは、品目番号、品目名など、各品目に共通の属性を値オブジェクトとして抽出して定義しています。
これは、品目という抽象クラスを設け、それを継承させて各品目を定義すると、親クラスに変更が入る都度、子クラスも影響を受けることになります。
各品目は、それを管理するためのドメイン知識が異なり、独立性が強いので、継承による設計は、保守性を下げることになります。
さて、CIMのドメインモデルでは、設計品目、製造品目、販売品目、購買品目、サービス品目に関連がありましたが、PIMのドメインモデルでは、それを、多対多の関連品目として実現しています。
この関連品目は、各品目に共通の値オブジェクト、品目番号や品目名を保持しています。
このように、各品目に共通の属性を値オブジェクトにすることで、それを各品目で使い回すことができます。
次に、CIMのドメインモデルでは、各品目は、部品表の階層構造を持っていますが、PIMの販売品目のドメインモデルでは、それを品目関連で実現しています。
最後に、CIMのドメインモデルでは、各品目は、単価を持っていますが、PIMの販売品目のドメインモデルでは、販売チャネルや顧客分類ごとの提供条件ごとの単価を持つことで実現しています。

PSMの設計および実装

PIMの設計結果に基づいて、以下のようにGPT-5に指示してソースコードおよび関連ファイル一式を生成させます。

添付したドメインモデル(画像 or テキスト)とマイクロサービスの仕様をもとに、
以下の構成で、STSで動作するSpring Bootアプリケーションのソースコード(完全実装版:CRUD対応)一式を src/ に作成し、ZIPファイルで提供してください。
なお、Javaコードは、UTF-8エンコーディング、日本語コメント付きで作成してください。
以下を必ず含めてください。

  1. Entity
    @Entity アノテーションを使用し、JPAエンティティとして実装してください。
    ドメインモデル(画像 or テキスト)の属性、型、関係(例えば @ManyToOne, @Enumerated)をすべて反映してください。
  2. ValueObject
    ドメインモデル(画像 or テキスト)のクラスでステレオタイプがvalue objectになっているものがあれば、 必ず、@Embeddable を用いて値オブジェクトとして定義してください。
    なお、ドメインモデル(画像 or テキスト)のクラスでステレオタイプがenumurationになっているものがあれば列挙型として定義してください。
  3. Repository
    Spring Data JPA の JpaRepository を継承するインターフェースを作成してください。
  4. DomainService
    ドメインルールやエンティティに属さないビジネスロジックがあれば、ドメインサービスを記述する @Service クラスを作成してください。
  5. ApplicationService
    Entity の CRUD 処理を行う @Service クラスとして、ユースケースレベルの操作を実装してください。
  6. Factory
    Entity 生成の統一ロジックが必要な場合は、専用のファクトリクラスを作成してください。
  7. RestController
    マイクロサービス仕様5にあるユースケースを @RestController としてすべて実装してください(JSON対応)
    その際、関係するDTOも定義してください。
  8. Config
    次の構成をすべて含めてください:
    ・SecurityConfig:@EnableWebSecurity を使い、CORS設定(application.propertiesにある cors.allowed-origins)と、空の AuthFilter を適用してください。
    ・OpenApiConfig:OpenAPI 3 に対応した GroupedOpenApi 設定クラスを用意してください。
    ・AuditingConfig:作成日時・更新日時を @CreatedDate、@LastModifiedDate で自動記録できるよう @EnableJpaAuditing を設定してください。
    ・メッセージ設定クラス(MessageConfig)の作成
    以下の設定を行ってください。
    ResourceBundleMessageSource(UTF-8、basename = “messages”)
    AcceptHeaderLocaleResolver(Accept-Language ヘッダーを優先し、指定がない場合は Locale.JAPAN を使用)
  9. ExceptionHandler
    以下の例外を処理する共通エラーハンドラ(@ControllerAdvice)を作成してください:
    •BusinessException(業務例外)
    •DomainException(ドメイン例外)
    •OptimisticLockException(楽観ロック失敗)
    •MethodArgumentNotValidException(バリデーションエラー)
    •DataIntegrityViolationException(DB制約違反)
  10. 起動クラス
    @SpringBootApplication を含む main クラスを含めてください。
  11. エラーメッセージの国際化(i18n)対応
    Spring Boot アプリケーションにおけるエラーメッセージの多言語対応(日本語・英語)を実装してください。
    以下3つのファイルを src/main/resources/ に配置してください。
    messages.properties(デフォルト:空でOK)
    messages_ja.properties(日本語)
    messages_en.properties(英語)
    以下のコード体系に基づいてメッセージを記述してください。
    日本語の場合
    # messages_ja.properties
    error.customer.not.found=顧客ID {0} に該当する顧客が見つかりません。
    error.customer.update.empty=更新する項目がありません。
    customer.name.notnull=顧客名は必須です。
    英語の場合
    # messages_en.properties
    error.customer.not.found=Customer with ID {0} was not found.
    error.customer.update.empty=No fields to update.
    customer.name.notnull=Customer name is required.
    エラーメッセージの取得例
    以下のように MessageSource を利用してロケールに応じたエラーメッセージを取得できる実装を含めてください。
    @Autowired
    private MessageSource messageSource;

    String errorMessage = messageSource.getMessage(
    “error.customer.not.found”,
    new Object[]{customerId},
    LocaleContextHolder.getLocale()
    );

※ pom.xml と application.properties は、すでに提供済みの内容を使用してください。
再生成や再構築は不要です。必要に応じて pom.xml に依存を追加するだけにしてください。

-未分類

執筆者:

関連記事

DevOpsとは

今回は、DevOpsについて次の観&#2885 …

制約理論(TOC: Theory of Constraints)とは

ここでは、制約理論につい&#12 …

変化に強いシステムを創る

ここでは、環境の変化に柔&#36 …

アプリケーション品質を上げるための開発方法

ここでは、次のソリューシ&#12 …

テクノロジーアーキテクチャの設計方法

今回は、テクノロジーアー&#12 …