Webフロントエンドの開発効率を高く保つための考え方
これまでいろんな現場でWebフロントエンド開発をしてきて、メンテナンスしやすく効率の高いWebフロントエンド開発をする上で重要になる考えが自分なりにまとまってきたので記事にしてみます。
Worse is Betterという考え方
自分が見てきた中でWebフロントエンドの開発効率が落ちてしまう一番の要因は、きれいで理論的には優れているアーキテクチャを構築しようとしてそれ自体がもたらす複雑性を支えきれないというパターンです。
少し前にフロントエンドにClean Architecture(以下CA、あの同心円の図を指すのは誤用に近いですがここではそれに乗ります)を導入する記事が流行ったと思いますがあんな感じです。ああいったクラスベースでDIが重要となる設計手法はサーバーサイドのJavaでSpringを使うのとは違ってReactがサポートしているものではないため、CAの実現自体に高い設計スキルが必要になると思います。もちろんつくるアプリケーションの複雑度にもよりますが、フロントエンドでCAを必要とするほど複雑なアプリケーションはそう多くはないと思います。
CAによって外部に依存しない純粋なビジネスロジックを表現したコードを手に入れることができますが、そのトレードオフとしてコード量や複雑性が増加することは無視できません。CAを諦めて、サーバーサイドのOpenAPIの型に直接依存するようにして薄く作るとコード量が少なく理解しやすいコードベースを構築できます。そうすることでCAのメリットとなるビジネスロジックの純粋性はトレードオフとして失われますが、代わりに得られたコードのシンプルさによる理解のしやすさや変更容易性を重視するというのが(自分の理解する限りでの)Worse is Better的な考え方です。
コードの品質の価値を過小評価しない
書籍Clean Architectureはあの同心円の図が独り歩きしてますが、設計以前の考え方に結構なページ数が割かれていてしかもとても参考になります。
序盤に出てくる刺さったフレーズを2つ雑に要約してみます。- 汚いコードを書く方がクリーンなコードを書くより常に遅い
- スタートアップだから、開発初期だからコードが汚くていいということはない
- ソフトウェアの構造は振る舞いと同等の価値を持つ(構造≒変更が容易であること)
- 完璧に動作するけど変更ができないより、バグだらけだけど変更が容易な方が良い
特に2番目は個人的には目からウロコで、ソフトウェアのユーザーに提供する動作・振る舞いと同じくらいアーキテクチャとコード品質が適切に保たれていることが大事という視点はなかったです。同書では構造というエンジニアにしか見えない価値を守るのはエンジニアの責任であり、そのためにはPdMやセールスといったステークホルダーと「闘争」して構造を守る必要があるとまで書かれています。そして1番目にもあるようにコードの品質を高くすることが結局は開発速度を速くするのであればそこに注力するのが正しいと言えそうです。この1番目については書籍Clean Architectureにあるような設計テクニックをつぎ込んできれいで正しい「良い」アーキテクチャを目指したくなりますが、トレードオフを見てWorse is Better的な設計・コードを採用すべきだと思います。
公式ドキュメント+αくらいの基礎的な知識を身につける
案外おろそかにしがちですが公式ドキュメントに加えていくつか入門記事を読めばわかるくらいの正しい実装方法を知らないがために変な実装をしてしまい、あとからかなりの工数をかけて修正することになるというのもよく見ました。サーバーサイドエンジニアが仕方なくフロントエンドを書いてるといった事情があるとは思うのですが、そういった間違った実装は書いた瞬間からリライトの工数が必要になる負債です。Reactだと useEffect
のdepsがよくわからんからとりあえず空配列にしたり、Contextで済むようなDIをJavaの経験からクラスベースの自前DIを構築するとかそんな感じです。本来の意味とはずれてそうな一般的な用法としての技術的負債はだいたいこのくらいの原因なのではと思っています。
t_wadaさんの質とスピードという発表から、質もスピードも結局はエンジニアのスキルを上げるしかないという身も蓋もない結論を個人的には感じました。いきなり経験豊富なエンジニアに追いつくのは難しいですが、今すぐできて最も費用対効果が高いのがこの公式ドキュメント+αくらいの知識をつけることではないかと思っています。
チームの一人でも良いのでそのくらいの知識を習得することのコストはすぐ取り返せます。流行りのNext.jsやRecoil、DDDといった発展的な内容の前にまずはベースとなるReactの知識を最低限抑えるべきです。根本となるReactの知識がおろそかな上に書かれた発展的なコードは必ずと言っていいほど品質の低いものになるはずです。
プログラミング言語、フレームワーク、ライブラリが想定している書き方のとおりに書く
サーバーサイドで強い言語を経験するとTypeScriptに物足りなさを感じてオレオレモナドみたいなのを書いたり、React/Reduxの上にCAを構築するというようなのを割と見ますが負債になりやすいパターンです。
私見になりますがモナドといった関数型言語の強い概念はHaskellの do
構文やScalaの for
式のような関数型言語のシンタックスのサポートと標準APIとの互換性があってこそのもので、そのどちらもない環境では関数型やりたいだけみたいな感じになります。一見物足りなさを覚える言語やライブラリでもトレードオフの上でそうなっていることを理解したり、オレオレ増築物にチームメンバーが費やすメンテナンスや理解のコストを言語やライブラリ自体の経験に向けるほうが建設的です。
CAについてはこの記事では否定的なことばかり書いてしまいましたが、フレームワークとしてAngularを選択しているならAngularはクラスのDIをサポートしているFWなのでCAはまさにFWが想定している範囲に収まる書き方になります。関数型の書き方がどうしてもしたいならElmやPureScriptを選択するなど、技術選定も含めてアーキテクチャや書き方を決める必要があります。
追記: A Philosophy of Software Designがおすすめ
2022/1/28 追記
この記事を書いたあとにA Philosophy of Software Designという本を読んだんですが、ソフトウェア設計の目的を「複雑さの軽減」であるとしてその複雑さの定義や複雑性がもたらすデメリット、その対処法をわかりやすく書いていて非常におすすめです。(ググると第1版がヒットしますが、現在最新は第2版なので購入の際は気をつけてください)
書籍Clean Architectureも個人的にはよかったですが、書籍の後半で述べられている具体的な設計手法についてはWebフロントエンド・Reactという観点だとクラスベースでDIを多用するスタイルは何も考えず適用するとデメリットのほうが多く、一歩引いて読むほうがいいかなと思いました。
A Philosophy of Software Designで扱う「複雑さの軽減」はフロントエンド・サーバーサイドおよびプログラミング言語を問わず適用できる目的だと思います。加えて、複雑さを軽減するための手法を説明している章でもやりすぎると逆効果になることはたびたび書かれていて、手段が目的に切り替わらないようなバランス感覚がとても優れていると感じました。
英語で書かれているのでハードルが高いですが、平易な英語なので読みやすい方ですし翻訳ソフトに掛けながら読むこともできると思います。
(おまけ) React、GraphQL、よくできたデザインシステムのもたらす開発効率
これについてはかなり私見が入りますが、ある現場のReact、GraphQL、PolarisというShopifyが開発しているReact製のデザインシステムを採用した開発はこれまで経験した中で最高の開発効率でした。
結論だけ書いておくとReactとGraphQLが宣言的であること、ReactのコンポーネントツリーとGraphQLのQueryのデータツリーを一致させることとよくできたデザインシステムの相性は非常に良く、宣言的で理解しやすい開発効率の高いコードベースを構築できます。
まとめ
長々と書いてしまいましたが要するに複雑なこと、余計なことはせず基本に忠実にやるのがいいのではということです!
Discussion
フロントエンド側でゴリゴリにビジネスロジックを書くのは適してないんでしょうかね。