契約は、ソフトウェア開発の不可欠な部分です。それらは開発コストを削減し、開発者の生活を楽にします。しかし、問題があります。古いおとぎ話のように、適切に文書化されず、口コミでチーム全体に伝えられないため、物事が複雑になることがよくあります。広がりながら、合意は変化します。突然、新しい詳細が表示され、古い詳細は失われます。最終的には、すべてのチーム メンバーが頭の中にそれぞれの同意のイメージを持っています。
さらに悪いことに、チームがこれらの合意事項の文書化を開始するとき、彼らはでたらめにそれを行い、多くの場合、疎結合のドキュメントの混乱を作成します。その半分は最新でさえありません。
この記事では、契約書を文書化する正しい方法を説明しますので、契約書が役に立ちます。
では、どうすれば協定を役立つものにできるでしょうか。それらを文書化するだけでなく、次のようにします。
それらは使いやすいです。
これらの合意に従うのに必要な労力は最小限でした。
これらの契約がまだ有効であるかどうかを理解するのは簡単です。
なぜこれらの協定が存在するのかを理解するのは簡単です。
理想的には、それらは自動化されていました。
契約を分類する方法はたくさんあります。それらを抽象化レベルで分割します。
さまざまなレベルの合意には、それらを文書化し、さまざまなメリットをもたらすさまざまな方法が必要です。レベルごとに見ていきましょう。
これらの協定の目的は、コードを統一し、包括的で、読みやすいものにすることです。ここではいくつかの例を示します。
一重引用符の代わりに二重引用符を使用します。
これらの呼び出しをメソッドにラップするConfig
クラスを除いて、コードから ENV を直接呼び出すことはありません。
Service オブジェクトには接尾辞Service
と 1 つのパブリック メソッドcall
あります。
この種の契約は、読者の認知負荷を軽減し、未知のコードに早く慣れるのに役立つように作成されています。マーティンが言ったように、コードは書かれたものよりも最大 10 倍多く読み取られます。
Ruby on Rails フレームワークに関するあなたの意見とは裏腹に、Ruby on Rails フレームワークにはconvention over configuration
根底にあり、これにより、Rails 開発者は誰でも他の人のプロジェクトを開いてすぐにナビゲートすることができます。
では、これらの規則を文書化するにはどうすればよいでしょうか。リンターツール!適切なリンター ルールがない場合は、独自のリントを記述します。ほとんどすべてのリンターでそれが可能です: これはGo 言語の例で、ここはRubyの例です。
このような規則にリンターを使用すると、次の 3 つの利点が得られます。
開発者がそれらについて考える必要はありません。リンターはすべてのエラーを強調表示し、多くの場合、それらを修正します。
チームでコード レビューを使用すると、レビュアーはこれらのことについて考える必要がなくなり、より重要なことを検討する時間が増えます。
開発者は、開発サイクルの最初の段階で問題に気付くので、後でコンテキストに戻る時間を費やさずにすぐに修正します。契約を維持する方が安くなります。
もう 1 つのボーナス: 新しいリンター ルールを作成することは、ジュニア開発者にとって優れたトレーニングです。このタスクを完了している間、彼はコードの解析と AST の構築について多くを学び、言語をより深く理解するでしょう。
これは、アーキテクチャを思慮深く、一貫性があり、統一することを目的とした高レベルの合意です。いくつかの例:
Python を使用して通常のサービスを記述し、システムの負荷の高い部分に Elixir を記述します。
バックエンドは記述された形式でエラーを返します。
プロメテウスでメトリックを送信するには、各サービスが必要です。 /metrics
エンドポイントでは、メトリックを送信するためのポートがPROMETHEUS_PORT
環境変数によって構成されます。
このような合意は、認知負荷を軽減するだけでなく、さらに 3 つの問題を解決します。
運用コストを削減します。サービスが同じ方法で、同じログ形式で、同じメトリクスを公開する場合、サービスの維持とインシデントへの対処がはるかに簡単になります。
設計コストを削減します。開発者は毎回ゼロからアーキテクチャを設計する必要はありません。事前に考えていたので、基本的なことを気にすることなく、特定の機能またはサービスのみを設計する必要があります。
通信費を削減します。 Kafka でのサーバーの応答またはイベントの形式が事前に決定されている場合、開発者は対話のたびに議論する必要はなく、単に規則を参照するだけで済みます。
このような契約はより複雑であり、私は 2 つのステップで修正することを好みます。
ステップ 1 - 説明
Architecture Decision Record (ADR) は、このような合意を文書化するためのツールです。その魅力は、契約とともにメタ情報をキャプチャすることです。なぜそのような契約が採用されたのか。どの代替案が議論されましたか。最後に改訂されたとき。契約はまだ有効ですか?
これにより、新しいチーム メンバーは決定の理由を理解し、周りの人にそれについて尋ねる必要がなくなります。
ADR はいくつかの主要なブロックで構成されています。
協定はどのような問題を解決しますか?
問題を解決するためにどのようなオプションが検討され、その長所と短所は何でしたか?
最終的に選ばれた選択肢は?
実装コストの計算など、追加のブロックが存在する場合があります。
ADR は、変更履歴や議論の履歴を確認できるシステムに保管しておくと便利です。私が選んだのは Github と Notion で、それぞれに長所と短所があります。 Github の利点は、すぐに使用できるレビュー ツールとバージョン履歴があることです。データベースとタグを操作する便利さから、Notion は優れたソリューションになる可能性があります。また、非開発者でも簡単に処理できます。
ADR を使い始めたい場合は、リポジトリを参照することをお勧めします。ここには、さまざまな ADR テンプレートとその使用方法の例があります。
ステップ 2 - 自動化
ADR は、コード レベルの規則よりも自動化が難しく、設計リンターはまだ発明されていません (残念です!)。ただし、契約の種類によっては、部分的に自動化することも可能です。
言語、ライブラリ、およびインフラストラクチャへのサービスの埋め込みに関する契約のサービス テンプレートを作成および更新します。その後、開発者は新しいサービスをゼロから作成するのではなく、テンプレートからコピーして、構成済みの Dockerfile やメトリクスの発行などをすぐに受け取ります。
同様に、1 つのアプリケーション内でクラス ジェネレータを作成できます。いくつかのアプリケーション層 (コントローラー => フォーム => サービス オブジェクト) について合意したとします。その場合、新しい機能のすべてのレイヤーを一度に生成する単純なコンソール コマンドを作成できます。
この方法では自動化できないいくつかの原則に同意している場合は、トラッカーのマージ リクエストまたはタスクに自動的に追加されるチェックリストを整理できます。したがって、開発者はタスクを渡す前にそれらをすばやく確認できます。
各企業には、プロセスに関する多くの合意があります。たとえば、次のとおりです。
会社での採用の仕組みについて説明します。
リリース ロールアウト プロセスの説明。
大規模なタスクの設計レビューの要件。
週に 2 回チーム ミーティングを実施し、現在のタスクと障害について話し合います。
最近まで、私はこれらの契約を文書化することについて考えていませんでしたが、それらは会社の成功に大きく影響します。これらの合意の文書化は、上記のタイプの利点をもたらすだけでなく、プロセスを合理化し、それらを目に見える平面に移し、それらの便宜について考えることができます.
からアイデアを得ました。彼は、ADR に似たツールである Process Decision Record (PDR) を提案しました。唯一の違いは、アーキテクチャの決定ではなく、プロセスに関する決定を記述していることです。さらに、彼は、各 PDR に「再考日」を入れることを提案しました。これは、採用後nか月後に、ドキュメントに戻って問題が最善の方法で解決されるかどうかを確認する日付です (ちなみに、同じことができます)。 ADRあり)。
自動化に関しては、できることはほとんどありません。 Jira でワークフローを設定したり、会議のリマインダーを設定したり、その週の結果のプレゼンテーションを自動的に準備するボットを作成したりすることで、一部のプロセスを自動化できます (ただし、これは外国の会社で行いました)。
しかし、多くの場合、プロセスを実際に自動化することはできません。主な目標は、従わないよりも簡単に従えるようにすることです。それでも、プロセスが従うのがすでに簡単な場合でも、契約書を文書化することは依然として役立ちます。形式化と合理化により、プロセスを改善できます。
ドキュメンテーションとその後の自動化は有益です。開発に費やす時間が短縮され、アプリケーションがよりサポートされやすくなり、プロセスがよりスマートになります。
「私たちは善人であり、それがなくてもコードを開発できる」ため、これはすべて不必要な官僚主義であると考えることができます。しかし、実際には、協定はかなりの時間とお金を節約し、従業員の神経細胞を保護します。確かに、契約に反するものを絶対的に扱って拒否する必要はありません。これは、契約を更新する必要があるか、最初にその側面のいくつかについて考えていなかったことを示している可能性があります。
チーム内で契約書の文書化をまだ開始していない場合は、抽象化レベルの低いものから高いものへと移行してください。コード レベルの契約書から始めて、アーキテクチャ レベルの契約書から始めて、プロセス レベルの契約書に対処してください。契約文書はチームで開発する習慣であり、抽象度の低い概念から始める方がはるかに簡単です。
また、すべてのタイプが記事に記載されているわけではありません。たとえば、設計合意書をライブラリ コンポーネントとして文書化できます。
新しいタイプの契約はそれぞれ、同じ 3 つの段階を経ます。
それを文書化する方法を考えてください。
それを自動化する方法を考えてみましょう。
時間が経つにつれて、それを維持するよりも多くのリソースを節約するようにしてください。
そして最後。文書化プロセス中に、既存の契約の一部が明らかに、何の正当化もされておらず、チームの時間を浪費し、一般的に有害であることが判明する場合がありますが、あなたはすでにそれらに慣れています。この場合、チームの心にある習慣の壁を克服し、合意を受け入れるよりも拒否する方が重要な場合があることをチームに納得させる必要があります。しかし、それはまったく別の話です。
ここにも掲載されています。