トレタ開発者ブログ

飲食店向け予約/顧客台帳サービス「トレタ」、モバイルオーダー「トレタO/X」などを運営するトレタの開発メンバーによるブログです。

2024年を振り返り

こんにちは、トレタ VPoEの北川です。

こっそりと始めていた2024年の開発部アドベントカレンダーもいよいよ最終日となりました。今年の締めくくりとして,プロダクト開発部で実施した2024年の振り返り会についてご紹介します。

振り返り会の流れ

今年の振り返り会の目的は、「お互いにフィードバックを行い、お互いを高め合うこと」でした。

最近読んだ書籍に「みんなのフィードバック大全」という本があります。その本によるとフィードバックには「ポジティブフィードバック」と「ギャップ(ネガティブ)フィードバック」の2つに大別されるそうです。

日頃のコードレビューや業務改善の中では、「ここはもっとこうした方がいいと思う」という「ギャップフィードバック」がどうしても多くなりがちです(少なくとも私自身はその傾向がある)。

そこで今回の振り返り会では、他のメンバーの行動で良かったことに注目し、「ポジティブフィードバック」を行うことにしました。この取り組みにより、メンバーが自身の行動が他者にとって助けになっていることを再認識し、それが各自の長所を伸ばすきっかけとなれば、という思いです。

会の流れとしては、以下の3つのテーマに基づいた振り返りを各自ポストイットに書き出し、全員で発表しました。

  • 自分でやってよかったこと
    • 例:「あのプロジェクトでリーダーとして頑張れた!」
    • 例:「新しい技術を取り入れたおかげで効率が上がった!」
  • 他の人のよかったこと
    • 例:「△△さんが相談に乗ってくれて助かった!」
    • 例:「○○さんのコードレビューがとても分かりやすかった!」
  • 挑戦したいこと
    • 例:「次はもっと効率的にタスクを管理してみたい」
    • 例:「新しいフレームワークを試してみたい!」

共有された内容のサマリー

やってよかったこと

プロジェクト管理・チーム運営

  • 週報の導入
    • チーム内の情報共有がスムーズになり、デザイナーなど普段直接会話が少ないメンバーの動きを把握できました。
    • 他のメンバーも週報を通じて、活動の成果を共有しやすくなりました。
  • キックオフミーティングの実施
    • プロジェクトごとの初期段階で認識のズレを減らし、各メンバーの役割分担が明確になりました。
  • UI/UXのチーム分割
    • 専門性に基づく分業により、効率性と生産性が向上しました。
    • デザインプロセスの進行がスムーズになりました。
  • オンボーディング改善
    • 新メンバーの早期戦力化に成功し、チーム全体の生産性に貢献しました。
    • 具体的な改善点として、ドキュメント整備やタスクの段階的なアサインを実施しました。

技術的な取り組み

  • テストの充実化
    • UnitテストとAPIテストの拡充により、コード品質が大幅に向上しました。
    • テストカバレッジが20%から70%以上に改善しました。
  • 型の活用と防御的プログラミング
    • 開発の安定性を高め、リリース後のバグを削減しました。
  • 新ツールの導入
    • APIクライアントツール「Bruno」の採用でテスト効率化を実現しました。
    • KnipやTypeScript 5の活用で開発体験を向上しました。
  • 大規模リリースを遅延なく実現
    • 急な差し込み案件にも柔軟に対応し、信頼感の高いチーム運営を実現しました。

チームワーク・サポート

  • 各メンバーが持ち場を超えて協力し合い、迅速な問題解決を実現しました。
  • デザイナーやPdMが仕様変更やドキュメント更新に迅速に対応しました。
  • 林さんや藤田さんをはじめとするメンバーが複雑なプロジェクトで高い成果を残しました。

他の人のよかったこと

感謝の声

  • エンジニア Fさん
    • コメント付きのPRでコードレビューをしやすくしてくれました。
  • QA Hさん
    • 出社対応や軽減税率調査で迅速なサポートを提供し、外部機器の検証を軽快に行い助かりました。
  • QA Sさん・Yさん
    • 仕様整理や挙動確認への協力でチーム全体の生産性向上に寄与していました。
  • デザイナー陣
    • 度重なる仕様変更にも柔軟に対応し、デザインデータやドキュメントを整備してくれました。

リーダーシップ

  • PjM Fさん
    • 多岐にわたるプロジェクトで認識統一や混乱の収拾を実施し、高い当事者意識を発揮してくれました。
  • PdM Kさん
    • 広範囲を網羅する知識とサポート力で、チームの屋台骨として活躍していました。

挑戦したいこと

技術的な目標

  • コード品質向上
    • 静的コード分析の導入。
    • 自動テスト環境の整備でレビューコストを削減。
    • E2Eテストの充実化と統合テストの導入。
  • AI活用
    • AIを用いたテスト設計やレビュー効率化。
    • 仕様書や設計書の自動生成でメンテナンス性向上を目指します。

プロセス改善

  • 古い仕様書のアップデート
    • 整合性が取れていない部分を精査し、最新状態に更新。
  • 進行管理の効率化
    • チーム間連携の強化とスケジュール管理の最適化を進めます。

振り返り会を終えて

「〇〇さんが△△をやってくれたおかげで、こちらの作業で助かりました」という声は、年末にふさわしいほっこりした気持ちになりました。

特に「ドキュメント整備のおかげで助かった」という声が多く、開発やQA、その後の問い合わせ対応など多くの場面でドキュメント整備の効果が実際に現れていることを知り、その重要性を再認識しました。

他には、自分が直接関与している部分以外で、テストの改善やツール導入による効率化といった下支えとなる取り組みが評価された点も良かったと思います。本人が意識的にアピールしない部分であっても、他のメンバーから称賛され、その活躍が共有される機会となったのは、今回の成果の一つです。


おわりに

ポジティブフィードバックは「常に」やっていくことが大事、ということが冒頭で紹介した「みんなのフィードバック大全」には書かれています。

今年の取り組みを土台により強固なチーム文化を築き上げていけるように活動していくので、また色々な取り組みをブログに書き記していければと思います。

2024年もお世話になりました。ありがとうございました!

2025年もどうぞよろしくお願いいたします。

チームで取り組むGo開発:開発体験向上の施策のご紹介

はじめに

こんにちは、サーバーサイドエンジニアの@shiroemonsです。

こちらはトレタAdventCalendar2024 22日目の記事です。

今回は、現在進行中のGoプロジェクトにおけるディレクトリ構成と、開発体験を向上させるために実施した施策について紹介します。

ディレクトリ構成

このディレクトリ構成は、チーム全体で議論を重ね、各メンバーが実装しやすく効率的な形を目指して構築しました。以下がその詳細です。

.
├── cmd # エントリーポイント
│   ├── api # APIサーバー(実際はProject名)
│   └── seeder # 開発環境ダミーデータ生成処理
├── config # 環境変数読み込み
├── db
│   └── migrations # DBマイグレーション
├── docker # Dockerfile
├── docs # ドキュメント
├── firebase # Firebase Emulator Suite設定ファイル
└── internal
    ├── db
    ├── handler # 抽象化先の処理への振り分け
    │   ├── router.go # ルーティング定義
    │   └── v1
    │       └── executor # ユースケース初期化
    ├── http
    │   └── response # レスポンス定義
    ├── infrastructure # 共通インフラ処理
    ├── model # DBモデル定義
    ├── {module} # 抽象化先の名称
    │   ├── infrastructure # 各モジュールのインフラ処理
    │   ├── prepare # 各モジュールの事前処理
    │   ├── values # モジュール内で使用する値オブジェクト
    │   └── {domain} # ビジネスロジックやドメイン処理
    │       ├── repository # DBや外部APIとのやり取り
    │       └── usecase # ユースケース
    ├── errors # エラー定義
    ├── service # 共通サービス処理
    ├── testhelper # テストヘルパー関数
    │   ├── ddl # テスト用DDL
    │   └── testdata # テスト用データ
    ├── util # 汎用的なコード
    └── values # 共通値オブジェクト

開発体験向上の施策

1. 初期データ挿入ツールを作成

プロジェクトの初期段階では、各メンバーが開発環境のデータベースに個別でテストデータを作成し、動作確認を行っていました。しかし、データ構造が複雑であったため、データ作成には多くの手間がかかり、さらにメンバー間で作成するデータにばらつきが生じていました。この状況は動作確認の効率を低下させる一因となっていました。

この問題を解決するために、初期データを効率的に挿入・更新するツール「seeder」を開発しました。このツールはGoで独自に実装され、開発環境において使用することを前提としています。seederは、TSVファイルからデータを読み取り、加工してデータベースにアップサート(挿入・更新)する機能を提供します。

このツールをプロジェクトの早い段階で導入したことで、以下のような効果が得られました。

  1. テストデータの準備が容易に: 手作業で複雑なデータを作成する必要がなくなり、効率的にデータを準備できるようになりました。
  2. 動作確認のハードルが低下: メンバー全員が同一のデータを使用できるため、動作確認が容易になり、プロジェクト全体のスムーズな進行に寄与しました。
  3. 開発効率の向上: テストデータの準備にかかる時間が短縮され、その分のリソースを開発や改善に集中させることができました。

seederの導入により、プロジェクトの開発環境を標準化し、チーム全体の生産性を向上させることができました。これにより、プロジェクトの初期段階からスムーズな開発体制を築くことができ、メンバーの負担軽減にもつながりました。

2. カバレッジレポートの精度向上

seederを導入することで開発効率が大幅に向上した一方、カバレッジレポートの値が大きく下がるという課題が発生しました。この問題の主な原因は以下の2点です。

  1. 開発環境のみで使用するseederがカバレッジ対象に含まれていたこと
  2. テストで使用する自動生成されたモックファイルがカバレッジ計測に影響していたこと

これを解決するために、カバレッジレポートから除外すべきファイルを明確に定義し、それらを簡単にフィルタリングできるスクリプトを作成しました。この取り組みにより、以下の改善を実現しました。

改善内容

  1. 正確なカバレッジレポートの生成
    • 実際のコードカバレッジに影響を与えない部分を除外することで、レポートの精度を向上させました。
  2. 効率的なテスト分析
    • 本来注力すべきコードのカバレッジを明確に把握できるようになり、テストの改善ポイントを特定しやすくなりました。
  3. メンテナンス性の向上
    • 除外対象をスクリプト化することで、プロジェクト全体での運用が容易になりました。

解決策: 除外スクリプトの導入

以下は、カバレッジレポートから不要なファイルを除外するためのスクリプトfilter_coverage.shです。

#!/bin/sh

# 入力引数のチェック
if [ $# -ne 1 ]; then
  echo "Usage: $0 <coverage_file>"
  exit 1
fi

COVERAGE_FILE=$1

# .coverageignore ファイルの存在チェック
if [ ! -f .coverageignore ]; then
  echo ".coverageignore file not found!"
  exit 1
fi

# .coverageignore ファイルを読み込む
IGNORE_FILES=$(cat .coverageignore)

# 一時ファイルを作成
TEMP_FILE="coverage_filtered.out"
cp "$COVERAGE_FILE" "$TEMP_FILE"

# 除外ファイルごとにフィルタリング
for FILE in $IGNORE_FILES
do
    grep -Ev "$FILE" "$TEMP_FILE" > temp.out && mv temp.out "$TEMP_FILE"
done

mv "$TEMP_FILE" "$COVERAGE_FILE"

echo "Filtered coverage report saved to $COVERAGE_FILE"

.coverageignore

以下は、カバレッジレポートから除外すべきファイルを定義する.coverageignoreファイルの例です。

# このファイルには、カバレッジレポートから除外したいファイルパスを記載します。
# 各ファイルパスは新しい行に記載してください。
# ファイルパスには正規表現を使用できます。

# 開発環境用のアプリのため除外
cmd/seeder/main\.go

# 自動生成されたモックファイルを除外
.*_moq\.go

この設定例では、cmd/seeder/main.goは開発環境でのみ使用されるスクリプトであり、本番環境には関係がないためカバレッジレポートから除外しています。また、*_moq.goは自動生成されたモックファイルであり、実際のコードではないためレポートに含める必要がありません。

使い方

  1. カバレッジ計測を実行

     go test -race -shuffle=on ./... -coverprofile=tmp/coverage.out
    
  2. スクリプトで除外ファイルをフィルタリング

     ./filter_coverage.sh tmp/coverage.out
    
  3. カバレッジレポートを確認

     go tool cover -html=tmp/coverage.out
    
    • カバレッジレポートの確認には、octcovの利用がおすすめです。

Makefileで簡易化

手順1と手順2を1つのMakeコマンドとして統合し、さらに手順3も別のMakeコマンドとして設定することで、テスト実行とカバレッジレポートの確認を効率化できます。

test:
    go test -race -shuffle=on ./... -coverprofile=tmp/coverage.out
    ./filter_coverage.sh tmp/coverage.out

coverage-report:
    go tool cover -html=tmp/coverage.out

これにより、以下のコマンドでカバレッジ計測とレポート確認が可能になります。

make test
make coverage-report

3. テストデータの自動生成

データベース関連のテストでは、テストデータの準備が大きな手間となることがあります。特に複雑なデータ構造を扱う場合、手動でのデータ作成には多くの労力が必要であり、チーム内でデータ内容がばらつくリスクも存在していました。しかし、seederを活用することで、効率的にデータを生成し活用できるようになり、これを基盤としてtestfixturesを用いた自動生成の仕組みを導入しました。

github.com

このアプローチにより、以下の効果を実現しています。

  1. テストデータ準備の効率化: 手動での作業を削減し、開発速度を向上。
  2. データの一貫性確保: チーム内で同じデータセットを共有可能に。
  3. 信頼性向上: 自動生成されたデータにより、テストの再現性が高まる。

これにより、テストデータの準備に伴う負担を大幅に軽減し、開発環境を標準化することで、プロジェクト全体の効率を高めました。

解決策: テストデータ自動生成スクリプトの導入

以下は、テストデータを自動生成するためのシェルスクリプトgenerate_testdata.shです。

このスクリプトでは、PostgreSQLデータベースからのデータダンプを利用して、不要なファイルの削除やタイムスタンプの加工も自動化しています。

#!/bin/sh

# testfixtures の dump を実行する
testfixtures --dump -d postgres -c "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:5432/$POSTGRES_DB?sslmode=disable" -D internal/testhelper/testdata

# 不要なファイルを削除
find ./internal/testhelper/testdata -type f -name "*.yml" -exec grep -q '^\[\]$' {} \; -exec rm {} +
echo "データがないテーブルの不要なファイルを削除しました。"

# created_at と updated_at を RAW=NOW() に置換
find ./internal/testhelper/testdata -type f -name "*.yml" -exec sed -i -E \
  -e 's/created_at: [-0-9T:.Z]+/created_at: RAW=NOW()/g' \
  -e 's/updated_at: [-0-9T:.Z]+/updated_at: RAW=NOW()/g' {} +
echo "created_at と updated_at を RAW=NOW() に置換しました。"

echo "すべての処理が完了しました。"

使い方

  1. スクリプトを実行してテストデータを生成
    • データベース用の環境変数は用意しておく
     ./generate_testdata.sh
    

Makefileで簡易化

手動でスクリプトを実行する手間を減らすため、Makefileに統合することでワンコマンドでの操作が可能になります。

generate-testdata:
    sh ./generate_testdata.sh

実行コマンド:

make generate-testdata

4. git push前の品質チェック

GitHubでコード管理をしており、GitHub Actionsでテストとリントのチェックを行っています。しかし、開発環境上でテストやリントを実行せずにgit pushを行い、CIで失敗して気付くという課題がありました。

この問題を解決するため、Git hooksのpre-pushを活用し、git push前にテストとリントを実行するスクリプトを導入しました。このスクリプトは、開発者がコードをリモートリポジトリに送信する際に自動的に呼び出され、以下を確認します。

  1. テストの成功: コードの変更が既存の機能に影響を与えていないことを保証します。
  2. リントチェック: コーディングスタイルの統一と品質の確保を支援します。

この仕組みにより、コード品質の低下を防ぎ、以下の効果を得られます。

  • 早期の問題発見: テストやリントの失敗を事前に検出でき、手戻りを防ぎます。
  • CI/CDパイプラインの成功率向上: CIでのエラー発生率を削減し、スムーズなデプロイを支援します。
  • チームの効率化: コーディングスタイルの統一により、レビューの効率が向上します。

デメリットとして、pushまでにテストとリントをチェックするため、実行時間がかかり開発スピードが低下する場合があります。しかし、手戻りを防げると考えると十分に有効なアプローチです。

解決策: git hooks pre-push の活用

以下は、git push前にコード品質を確保するためのスクリプト.githooks/pre-pushです。

このスクリプトでは、git pushの実行前にテストとリントを自動的に実行することで、コード品質を向上させるとともに、CI/CDパイプラインでのエラーを未然に防ぐ仕組みを提供しています。

#!/bin/sh

# Dockerのパスを追加
export PATH=$PATH:/usr/local/bin

# テストを実行
echo "🚀 Running tests..."
if ! make test; then
    echo ""
    echo "=========================="
    echo "❌       Tests failed       "
    echo "=========================="
    echo ""
    exit 1
fi

# Lintを実行
echo ""
echo "🔍 Running linter..."
if ! make lint; then
    echo ""
    echo "=========================="
    echo "❌      Linting failed      "
    echo "=========================="
    echo ""
    exit 1
fi

echo ""
echo "=========================="
echo "✅    All checks passed     "
echo "=========================="
echo ""

exit 0
  • make lintでリントのチェックをしています。

使い方

  1. git hooksを設定

     git config --local core.hooksPath .githooks
    
  2. コードの品質チェックを自動化

    git pushコマンド実行時にスクリプトが自動的に呼び出され、テストとリントが実行されます。

5. APIクライアントツール「Bruno」の導入

APIの動作確認を行う際には、従来はPostmanを使用していましたが、チームメンバーごとに確認方法が異なることや、設定に手間がかかるといった課題がありました。さらに、新規メンバーへの情報共有も効率的とは言えませんでした。

これらの課題を解決するため、APIのドキュメント作成と共有にはBrunoを採用しました。Brunoは、Postmanに代わる軽量なAPIクライアントツールであり、特にテキストベースの管理とバージョン管理に優れています。

github.com

導入した理由

  1. ドキュメントとしての扱いやすさ:
    • Brunoではリクエストをテキスト形式(.bru拡張子)で保存できるため、Gitを用いた変更履歴の管理や差分の確認が容易です。
  2. チームでの共有が簡単:
    • .bruファイルをリポジトリに保存して共有することで、新しいメンバーでも簡単に環境をセットアップできます。
  3. 軽量で効率的:
    • PostmanのようなGUIを使用して直感的に操作できるため、APIリクエストの作成や実行が簡単です。また、CLIツールとしても利用できるため、スクリプト化や自動化にも対応しています。

解決策: Brunoを導入する

  1. macOSであれば以下のコマンドで簡単にインストールできます。

     brew install bruno
    
  2. 初期設定は直感的なGUIで構成されており、PostmanなどのAPIクライアントを使用した経験があれば、初めてでも簡単に操作できます。さらに、設定済みのファイルを読み込むだけでセットアップが完了し、すぐに利用を開始できます。

効果

Brunoの特長を活かすことで、APIドキュメントの管理が格段に効率化しました。これにより、チーム全体のAPI開発が迅速かつスムーズに進行し、情報共有の手間を大幅に削減できました。結果として、プロジェクトの生産性と進行速度が向上しました。

まとめ

Goプロジェクトにおける開発体験を向上させるための施策について紹介しました。

開発体験を向上することで、テストカバレッジが20%だったのを70%以上まで引き上げることができました。今回の施策により、特にDBのテストを書くハードルが下がり、テストが書きやすいディレクトリ構造にしたことが大きな要因だと感じています。

この記事が、皆さんの開発に少しでも役立てば幸いです。

おわりに

トレタでは一緒にチームで働いてくれるエンジニアのメンバーやプロダクトマネージャーとして活躍してくれる人を求めています。飲食店の未来をアップデートする事業に興味のある方はお気軽に話を聞きにきてください。

sites.google.com

堅牢なフロントエンド開発を支えるAPI型チェックと防衛的プログラミング

こんにちは、トレタ VPoEの北川です。

フロントエンドアプリケーションで社内外のAPIを利用する際には、セキュリティやデータ整合性の問題、スキーマの不整合、予期しない変更への対応といった数々の課題がつきものです。 こうした課題に対応し、信頼性の高いフロントエンドを構築するために、弊社では防衛的プログラミングと厳密な型チェックを活用しています。これにより、APIとの連携におけるリスクを最小限に抑え、開発の効率と品質を両立させています。

本記事では、防衛的プログラミングの考え方、型チェックを厳密に行う理由、実際の開発現場の例を交えてご紹介します。


API利用におけるセキュリティの重要性

まず、JavaScriptにおける潜在的なセキュリティリスクとして、プロトタイプ汚染が挙げられます。この攻撃手法では、悪意のあるデータを用いてオブジェクトのプロトタイプが不正に変更され、アプリケーション全体に予期しない影響を与える可能性があります。

JavaScriptのオブジェクトはプロトタイプを通じてプロパティやメソッドを継承します。この仕組みを利用して、攻撃者はAPIレスポンスのJSONオブジェクトに特殊なキー(例: __proto__)を含め、プロトタイプを改変します。その結果、アプリケーション全体で動作が予期せぬ形に変更される可能性があります。

具体的なリスクとしては、以下が挙げられます:

  • リモートコード実行:悪意のあるコードがシステム内で実行される。
  • データ改ざん:重要な設定やデータが不正に変更される。
  • サービス停止:予期しないプロパティ変更によるエラーでアプリケーションが動作停止する。

このようなリスクを回避する方法の一つとして、APIレスポンスの厳密な型チェックを行う方法があります。詳細については以下の記事をご参照ください:


厳密な型チェックとスキーマ駆動開発

弊社では、フロントエンドとバックエンドの連携において、スキーマ駆動開発を採用しています。この手法では、開発初期にAPIスキーマを定義し、両チームがそのスキーマに基づいて並行して作業を進めます。

しかし、スキーマ通りに実装したつもりでも、繋ぎ込み時に不具合が発生することがあります。例えば、スキーマ変更の共有漏れや実装ミスによる不整合が挙げられます。このような場合、スキーマに「過不足なく」準拠しているかどうかを検証する仕組みが必要です。

そこで、クライアント側では防衛的プログラミングにより厳密な型チェックを行い、不具合発生時の原因特定とスムーズな修正を実現しています。

新しい機能追加の場合

新機能を既存のシステムに追加する際、非破壊的変更であっても注意が必要です。例えば、新しいフィールドやオプションが追加される場合、クライアント側でそれに対応するロジックが正しく実装されていないと、全体の整合性が崩れる可能性があります。

例えば、あるAPIにオプショナルなフィールドを追加したとします。このフィールドは必須ではないため、既存の仕様を大きく損なうことはありません。しかし、特定の機能やユースケースにおいて、このフィールドが適切に設定されない場合、システム全体の整合性が崩れるリスクが発生します。

この場合は互換性の有無に関わらず、サーバーとクライアント間での正確なコミュニケーションと早期の検知体制が重要です。フロントエンド側で厳密な型チェックを行っていると、必須フィールドでなくてもフィールドが追加されたことでエラーが発生します。 これにより、仕様変更や新機能追加時の対応漏れを防ぎ、システム全体の安定性を保つことができます。

外部APIの場合

一方で、外部APIに対しては、内部APIとは異なる柔軟なアプローチが必要です。外部APIは、提供元によって予告なく変更される可能性があり、必ずしも事前に提供されたスキーマ通りのデータが返ってこない場合もあります。

例えば、ある外部APIを利用する際、仕様と異なるデータが返されることが判明した場合、厳密な型チェックを維持することでかえってエラーが頻発し、開発スピードやシステムの安定性に悪影響を及ぼすことがあります。このような場合、柔軟性を優先したロジックを導入することで、APIの変化に適応しやすくしています。

具体的には、レスポンスデータのバリデーションやエラーハンドリングを強化し、予期しない変更にも耐えられる仕組みを構築しています。


型チェックのデメリットと今後の方針

厳密な型チェックは、多くの場面で開発を効率化し、信頼性を向上させる一方で、デメリットも存在します。特に、リソースが限られているプロダクトでは、型チェックの厳密さが負担となる場合があります。

例えば、開発リソースが縮小されたプロダクトでは、型チェックの更新が滞り、APIの後方互換性を保つことが難しくなる場合があります。一方で、活発に開発が行われているプロダクトでは、厳密な型チェックが問題の早期発見や修正を可能にし、信頼性向上に大きく寄与しています。

そのため、弊社ではプロダクトのフェーズや状況に応じて型チェックの適用範囲を調整し、効率と柔軟性のバランスを図っています。


さいごに

弊社の防衛的プログラミングと型チェックのアプローチをご紹介しました。記載した通りプロジェクトの規模やフェーズにおいて合う合わないがありますが、堅牢で安定したサービス提供に向けた開発の参考にしていただければと思います。

© Toreta, Inc.

Powered by Hatena Blog