はじめに

こんにちは。
キャスレーコンサルティング IT(インテグレーションテック)部の松岡です。

いつの間にか6月!!!

今年ももう半年!?
あっという間ですね・・・

梅雨の季節になり、ムシムシ…ベトベト…で嫌になっちゃいますね。
気温も高くなってきたので、熱中症に気をつけて小まめに水分補給しましょう!

ところで、そろそろ4月入社の新人さんは
「なにか作ってみたい!」
と、思ってるのではないでしょうか。

そこで今回、章を数回に分けて“じゃんけん”をテーマにブログを書こうと思います。
アプリケーションアーキテクチャや、デザインパターンの考え方を織り交ぜながら
設計から実装までを、一気通貫でやっていきたいと思います!!

要件

まず、じゃんけんといえば「グー」「チョキ」「パー」の組み合わせで勝敗が決まるゲームですよね。

なので、じゃんけんAPIには”グー”,”チョキ”,”パー”のいずれかを送り、
じゃんけんAPI側の出し手(“グー”,”チョキ”,”パー”)と
勝敗の結果(“勝ち”,”負け”,”あいこ”)を返すようにしましょう。

それだけではつまらないので、
 ・じゃんけんの成績照会機能
 ・じゃんけんAPIの戦略変更機能
も追加しましょう。

また、APIシステムは基本的に
 「その処理の結果が正常終了したか」
 「失敗して異常終了してしまったか」
以下のような項目を、一緒に返すのがベターです。

結果コード 「0:正常」「9:異常」のような処理の結果
結果詳細コード 必須ではないがあると障害時の切り分けが楽(例 「9001:桁数不一致」など)
結果メッセージ 処理結果の説明。異常終了時に設定されるイメージ

今回は、上記項目の「結果コード」と「結果メッセージ」をレスポンスに含めるようにしたいと思います。

設計

では、どうやって通信するか、ルールを決めましょう。
受け渡す項目の拡張性を考え、HTTP(POST)のJSON形式でやり取りしたいと思います。

プロトコル HTTP
メソッド POST
データ形式 JSON

次に、じゃんけんAPIとやり取りする情報を定義します。
以下がAPI定義書となります。

API定義書



※今回はありませんでしたが、同じ項目が複数発生する場合は
 項目型を”Array”で定義し、その出現回数も決まっていればその数値も定義します。

では、じゃんけんAPIのアプリケーションの全体構成と骨組みを考えていきましょう。

フレームワーク設計

じゃんけんAPIを呼び出す為に、じゃんけんClientというアプリケーションを追加しています。

今回はメインではないので、詳しくは説明しませんが、
JavaScriptで、POST送信するHTMLが一個あるようなイメージです。

大まかな流れとしては、クライアント(じゃんけんClient)からHTTPリクエストが送られ、
最初にEndpointで受け取ります。
その後、URIのリソース名を条件に必要なサービスに振り分けられ、業務ロジックが処理されます。

その時に必要に応じて、Repositoryを介してDBへのアクセス(検索、登録、更新、削除)をします。

そして、その結果をEndpointからクライアントに返却します。

重要なのは、アプリケーションが行う処理の流れをブロックに分け、抽象化させること。
つまり、処理の共通的な部分を切り出し、そこをベースとして各固有の処理を後で実装するようにすれば
開発者は「リクエストの受け取り」「サービスの振り分け」「リクエストのデコード/エンコード」
「DBアクセス」のような基本処理部分を意識せずに、固有の処理の実装に集中できるのです!

続いて、図中の下にある技術要素の簡単な説明です。

■Linux
 検証環境のOS

■Tomcat9
 Webコンテナ

■Spring Boot
 ベースがSpring Frameworkなので、DIコンテナはもちろん
 Webアプリケーションに必要な機能をプラガブルに追加できる為、開発の柔軟性が高くなります。
 また、小中規模のアプリケーションなら簡単に開発できてしまうのがいいところ。
  ⇒一部のWebコンテナがエンベデッドされてるため、開発環境での検証がスピーディーになります。
 そして、Spring Frameworkから進化したところは、プロパティファイル1つで
 だいたいが設定できてしまうこと!
 (設定ファイルの管理が楽)

■Mybatis
 昔からある有名なO/Rマッパー。(旧名:iBatis)
 シンプルで学習コストも低いのでおすすめです。
 別に用意されている「MyBatis Generator」を使用すれば、DBからテーブル情報を取得し
 エンティティクラスや、DAOクラスなどを自動生成してくれます。
 そして、Spring Bootからもプラグインとして用意されているので手間要らず!

■Thymeleaf
 Clientには、こちらのテンプレートエンジンを使用します。

タグを使用して動的にHTML表示が出来るので、
今回は、これでじゃんけんAPIから返ってきた値を画面に表示したいと思います。

DB設計

今回時間の都合上、ER図は用意できなかったのですが
使用するテーブルは以下になります。
 ※小ネタですが、テーブルの物理名にMT_XXXやTT_XXXのような接頭字を決めることで
  そのテーブルがマスタテーブルなのか、トランザクションテーブルなのか
  見分けがつきやすくなります。

【マスタ】
・MT_JANKEN_HAND[じゃんけん出し手マスタ]
 ⇒「0:グー」「1:チョキ」「2:パー」が登録されている
・MT_JANKEN_COMB[じゃんけん組み合わせマスタ]
 ⇒じゃんけんの組み合わせ情報が登録されている
・MT_JANKEN_STRATEGY[じゃんけん戦略マスタ]
 ⇒じゃんけんの戦略情報が登録されている
・MT_JANKEN_STRATEGY_USER[じゃんけん戦略ユーザーマスタ]
 ⇒ユーザー毎のじゃんけんの戦略情報が登録されている

【トランザクション】
・TT_JANKEN_SCORE[じゃんけん成績テーブル]
 ⇒クライアントごとにじゃんけんの成績が登録される

各テーブルには
「作成者」「作成日時」「更新者」「更新日付」「行バージョン」
を、共通で持たせるようにします。

「作成者」「作成日時」「更新者」「更新日付」は、
開発フェーズよりも運用フェーズで効果が発揮されます。

障害発生時の調査や、パフォーマンスチューニングを行う際、ログファイル以外に調査対象として
これらの項目があると、処理の切り分け及び原因箇所の特定ができ、問題解決につながる為追加しています。

そして、ここでのポイントは「行バージョン」をテーブルにもたせる事です。

今回、ユーザー毎に設定してある戦略を更新するAPIがあるので
同一レコードを、複数クライアントから更新してしまう恐れがあります。

こういった場合に、データの整合性を保証するのに「楽観ロック」というものがあります。
楽観ロックは、更新対象のレコードが取得時と同じ状態であることを条件に更新することで、
データの整合性を保証する方式です。

取得時と同じ状態であることを判断するために、行バージョンを使用します。
UPDATEの条件に「更新する前に取得したレコードの行バージョンと値が同じもの」という設定をいれ、
失敗(更新件数が0)した場合には、排他制御で異常終了するようにアプリケーションで制御します。

他にも、「悲観ロック」というものもありますが、
今回のように同一ユーザー情報を、別々のクライアントから更新するといった
「あまり発生しないケース」は、楽観ロックでも十分です。

逆に、不特定多数のクライアントから頻繁に同一レコードを操作して、整合性が保証できなくなる場合は、
行ロックをかけ、先にそのレコードを触った人が勝つように「悲観ロック」をかけます。

次に、じゃんけんの処理フローを考えたいと思います。

じゃんけんの処理フロー(アクティビティ図)

以下の情報を元に、後でServiceの処理を実装していきます。
戦略の取得から、出し手算出処理までの実装は「ストラテジーパターン」を採用したいと思います。
(※次回、詳しく説明)

ここまで設計しましたら、次は詳細設計~実装へ進んでいこうと思います。

最後に

今回は、一旦ここまでにします。

次回は、本内容のフレームワーク設計とアクティビティ図をベースに
デザインパターンとあわせた、クラス設計をやっていこうと思います。

お読みいただき、ありがとうございました。

松岡一也
CSVIT事業部 IT(インテグレーションテック)部 松岡一也
甘いの大好き6年目エンジニア