Frontend Fundamentals
(frontend-fundamentals.com)Tossフロントエンドチャプターは、良いフロントエンドコードの基準について紹介するサイトを公開しました。
- フロントエンド開発者が主に使うTypeScriptをベースに説明
- 可読性/予測可能性/凝集度/結合度の4つの観点からベストプラクティスを提示
- 実際のフロントエンドでよく使うライブラリを活用した例を提供
4つの基準
-
可読性
可読性(Readability)とは、コードの読みやすさを指します。コードを変更しやすくするには、まずそのコードがどのように動作するのかを理解できなければなりません。 -
予測可能性
予測可能性(Predictability)とは、一緒に協業する同僚が関数やコンポーネントの動作をどれだけ予測できるかを指します。予測可能性の高いコードは一貫したルールに従っており、関数やコンポーネントの名前、パラメータ、戻り値を見るだけでもどのように動作するかが分かります。 -
凝集度
凝集度(Cohesion)とは、修正すべきコードが常に一緒に修正されるかどうかを指します。凝集度の高いコードでは、コードの一部を修正しても意図せず別の部分でエラーが発生しません。一緒に修正されるべき部分が必ず一緒に修正されるよう、構造的に支えられているからです。 -
結合度
結合度(Coupling)とは、コードを修正したときの影響範囲を指します。コードを修正したときの影響範囲が小さく、変更による範囲を予測できるコードが、修正しやすいコードです.
8件のコメント
コンポーネントやフックの最小管理単位として、なぜファイルを使うのか気になります。IDEのサポートやtree shakingが不十分だからなのかなと推測はしているのですが、確信が持てず質問しています。
コードを読んでいて、関数1つだけのファイルや、import/export文しかない
index.tsファイルを見ると、覚えておくべきことが増えるんですよね。単一ファイル内でフックとコンポーネントを混在させる方式と比べると、必要以上に認知負荷を高める配置だと思います。それでもなお、そのような配置を使う利点や理由はあるのでしょうか?こういう場でよく言われる「良い開発」の大前提は、多くの開発者が作業しているという点です。
おっしゃる「覚えておくことが増える」= 自分がプロジェクト全体に責任を持っている、という意味ですが、
開発者が多い環境では、自分が担当する部分だけを開発します。
問題が起きたらその部分だけを見ればよく、関連するすべての部分を見る必要はありません。
ある意味では、極端な最適化の代わりに生産性を選んだと言えると思います。
おっしゃる通り、業務分担を細分化できる環境では、本文の内容は適切な選択です。コードを分離する際のトレードオフや判断基準が説明されていれば、より完成度の高い文章になると思います。
私の場合、フロントエンド開発をするときに、コンポーネントやフックの最小管理単位としてファイルを使う理由は以下のとおりです。
つまり、1つのモジュールに1つのユニットテストを対応させやすいということです。
フロントエンド開発は純粋関数によるパラダイムが主流だと考えていますが、1つのファイル内に複数の関数が存在すると、ユニットテストを書く際に1対1の対応が難しくなります。
もし
remark-plugin.jsという1つのファイル内に複数のユーティリティ関数があるなら、テストをどう書くべきでしょうか。remark-plugin.test.jsファイルを1つだけ作って、複数のユーティリティ関数に対するテストをまとめて書くのがよい選択でしょうか。このような状況で
remark-pluginsというディレクトリを作り、その中でユーティリティ関数を1つずつ分割してテストを書くのであれば、後々それぞれの関数の役割をより明確にでき、GitHub のコミット追跡もずっと整理しやすくなるなどの利点があると思います。サーバー開発における commonjs や、クライアント側での webpack などのモジュールバンドラーは、
index.jsファイルを特定ディレクトリのエントリーファイルとして指定することが多いです。これは昔からよく使われてきた慣習でもあるので、そういうものとして受け入れて使っている面もあります。ただ、私が最も重要だと思う理由は、関数型プログラミングの純粋関数パラダイムでは外部状態に依存してはいけないため、1つのファイルに複数の関数が集まっていると、外部状態を参照してしまうミスが起きる確率が高くなると考えているからです。(ES6 でモジュールスコープが登場した理由を考えてみるとよいかもしれません。)
個人的には、1つのファイルの中に複数のユーティリティ関数が混在しているよりも、それぞれのファイルに関数が分かれているほうが、コミット履歴の追跡はずっと簡単になる気がします。
あるモジュールで機能が追加されたりバグが修正されたりしたときに、他のモジュールを参照する必要なく、その1つのモジュールだけに集中すればよいからです。
書いているうちに文章が長くなって、少しまとまりのない書き方になってしまいました。(まだツリーシェイキング関連については理解が浅いので、あまり多くは語らないようにします……)もちろん、私の言うことが正解とは限らないので、参考程度に見ていただければと思います。
これはいいですね
すらすら読めるようにとても上手に書かれていました。おすすめです。
共有してくださってありがとうございます! 私もじっくり読まなければと思います。
FEに限定して書かれていますが、単にソフトウェア全般であれば応用しやすい話だと思います。良いインサイトを共有してくださってありがとうございます。