翻訳記事:エンタープライズ アプリでReactを選択したら解雇されそうになった話
本記事は、I Almost Got Fired for Choosing React in Our Enterprise App( https://medium.com/better-programming/i-almost-got-fired-for-choosing-react-in-our-enterprise-app-846ea840841c ) を原著者Razvan Dragomir氏の許可を得て翻訳したものです。
エンタープライズ アプリでReactを選択したら解雇されそうになった話
Reactは我々の開発を楽にするはずだった。それどころか障害物が作成された。
Razvan Dragomir
2021.01.23
2018年の夏のことだった。私の上司Adrianから、カナダの大企業のCTOであるJamesとのSkypeミーティングに参加するよう頼まれた。
お互いを知り合ううちに、私はJamesが大きな野望を持ったスマートな人物であると気付いた。彼のビジョンは、大規模なWPFのデスクトップアプリをクラウド上のWebアプリへ移行することだった。
彼の友好的な態度は好ましく、切実に我々と協力したがっていると思えた。 彼はインドに開発パートナーを持っていたが、Webアプリケーションの開発経験が不足しているとのことだった。
Adrianと私は、このようなシチュエーションに対する標準的なアプローチに倣った。 さらに何回かの通話の後、我々は全体を把握し、非機能要件を発見するためのフェーズを開始した。 これらは注目すべき主なポイントである:
巨大なアプリケーション — 220ページを超え、ほとんどはメンテナンス画面であり、そのうち20%は高度にカスタマイズされている。
大量のデータ表示、とくにあらゆる機能を備えたグリッド:グループ化、列固定、行展開、カスタム列、名前付け。
複数のチームが同時にプロジェクトを動かせるモジュラーアーキテクチャ。
複数年にわたるプロジェクト。時間とともに新たな機能が追加される。
オフラインのサポートが必須ではない。
新しいチームメンバーへの迅速なオンボーディング。
とくに古いデスクトップアプリで作業している .NET開発者向け。
アーキテクトとしての私の役割は、アーキテクチャの詳細、アプローチ、ロードマップ、ガイドライン、そして最重要項目として使用される技術スタックが含まれる技術提案を作ることだった。
Jamesは将来を見据えた技術を求めていると何度も言っていた。だが彼はAngularJSが非推奨となった後の評判が悪いことからAngularの採用には否定的だった。
私はすでに、中小規模でAngularとReact双方を使ったプロジェクトの実装にいくつか成功していたので、本当にどちらにも執着してはいなかった。どちらでも実現できると感じていた。
このプロジェクトで私はReact with Reduxを選択し……2年後に後悔した。
我々は3人の開発者のチームを割り当てて概念実証に取り組み、2か月後に成功をおさめた。素晴らしい応答性のユーザーインタフェース、非常に高速なビルド時間、そして超高速の開発。 誰もが満足していた。
障害物 #1: .NET開発者のチーム参加
概念実証の後は、クライアントのアウトソーシングチームの開発者が合流した。 知識共有はまだ始めておらず、CTOから「やあ、Răzvan。明日は本物のアウトソーシングチームと会わないといけないね」とメールが送られてきた。
我々はミーティングを設け、テクニカルリードは私を質問と解決策で迎え撃った:
- 「依存性の注入はどこですか?『必要ない』とはどういうことですか?」:これはInversifyJSだよ!
- 「関数コンポーネント? ダメダメダメ。我たちは好きじゃないからクラスコンポーネントを使いましょう!」
- 「なぜこれらの関数はただぶら下がっているだけなのですか? なぜ静的にするためサービスクラス内でカプセル化しないのですか?」
- 「APIのリトライポリシーはどこですか? PollyJSで実装しましょう」
- 「なぜクラス名がパスカルケースの場合にファイル名がダッシュケースとなるのですか? クラス名を反映させるため、今後は
SomePageComponent.tsx
という名前にします」 - そして、私をもっとも悩ませた件:「Visual Studio CodeでなくVisual Studioで実行するにはどうすればよいでしょうか?」
私は確信した。彼らはReactで .NETのガイドラインとデザインパターンを使いたがっている。私は何度もこのような出来事を見てきた — 新しい技術のやり方に適応できず苦労している開発者だ。だから私はそれらの方法がReactにとって異端であることについての議論を厭わなかった。
しかし、この場合はよくあるようにCTOがチームを支援している。CTOは私と知り合ってたった2か月、一方、彼のチームとは長年一緒に働いてきているのだ。私は彼らの提案に同意するよう妥協しなければならなかった。
私はReactがJavaや .NETの開発者向けではないことに気がついた。 この場合は、デザインパターンが似ているAngularが適切な選択だったろう。
障害物 #2: それらは決してReactではない
Reactは独断的でないライブラリで、横断的関心事をどのように実装するかについて、独自の見解を持っていない。したがってどのように実装するか、とくに他のライブラリを使用したいか意見を述べることは、あなたとチームの責任となる。 もちろん、車輪の再発明をしたくないので、あなたはサードパーティーのライブラリを使う。そしてReactのすべてに多くのオプションが存在する。
概念実証にあたり、ほとんどの横断的関心事を我々がどのように扱うべきかに関して、すでに私は意見を持っていた。今、彼らは新しいチームメンバーで再検証しなければならないのだ。これは最小の検討事項リストである:
- どのルーターを使うべきか?
- Reduxの他、非同期のアクションには何を使うべきか? Trunk? Saga?
- 我々はAxiosを使うべきか? それともブラウザAPIで
fetch
するべきか? - Redux-Formsか、Formiqか、またはFinal-Formか?
- Styled-Components、makeStyle、SASS、またはplain CSSか?
- 国際化ライブラリは?
我々はこれらの検討にさらに3週間を費やした。私にはあなたが叫んでいるのがわかる。
「ちょっと! それらのライブラリを選ぶのに3週間もかからないよ!」と。
ええと……業務プロジェクトへようこそ。彼らは多くの決定を行い、あなたは決定基準を作成する必要がある。リサーチを行い、概念実証を作成して結果を検証し、調査結果を提出する。そして議事録にすべてを記録し、ライブラリを最新の状態に保つのだ。
そして私は、各開発者がサードパーティーのライブラリを習得する時間について考えていなかった。私は2つのReactプロジェクトで同じ依存関係、プロジェクト構造、ガイドラインを持っているのを見たことがない。これはAngularやVueのようにプロジェクト間で知識の流用ができないことを意味している。
3週間経っても機能的なユーザーストーリの実装は進まず、CTOは心配し始めた。
障害物 #3:React Hooksが人気となる
9か月後、我々は50ページ以上を作成していた。開発者たちは関数コンポーネントがクラスコンポーネントと同じくらい良いことに気づき、それらを使い始めた。その結果、進行中のプロジェクトは元々のコーディング規約に従わなくなっていた。 これは各開発者が個人で選択したようなものだ。そして私はそれを許容していた。
React Hookはリリースと同時に普及した。チームは複雑な気持であった。 クラスは人とマシン両方を混乱させ、その一方で他の人は新しいコーディングパターンに熱中している、という示唆に対し何人かの開発者は腹を立てていた。
我々が使用しているすべてのサードパーティーのライブラリにはHooksのためのサポートが追加されており、React界隈全体がその方向へ進んでいるように見えた。よって我々は何をすべきだろうか? 元のコーディング規約から外れ、コンポーネントを実装する第3の道を追加するべきか? 遡って既存のページとコンポーネントをHooksへ移行する方法は存在しないのだ!
チームはRedux Hooksの使用に賛成している。なぜならば、Reduxのconnect()
を使い、コンテナからダンプコンポーネントを分離する必要がないからだ。これは理にかなっていたため、我々は今後、新しいページとコンポーネントにHooksを使うということで合意した。
また、古いものはそのまま残しておくことにした。
そして、それが我々の最終的な3つの方法だった。もう一貫性はどこにもなかった。
さらに悪いことには、何名かの開発者はReduxを使用せず、その代わりにuseState
を使用する考えを薦めはじめていた。これは単一のグローバル状態を持つという考え方を混乱させることになる。
Suspense
はまだ実験的な機能だ。私はそれがリリースされた時に何が起こるか心配だった。
障害物 #4:開発の遅れ
継続的インテグレーション用のセットアップを行ったとき、ビルドには npm install
を含めておよそ3分かかった。 しかし今、1年後では約15分かかっている。
我々は2GBで不十分だったRAMを4GBに拡張するようNode.jsを構成する必要があった。
これは大きな問題ではない。気になるのは、ビルドに時間がかかり開発の45~60分後にはホットローディングが機能しなくなる。そして再起動に5分以上かかる — とくにWindowsマシン(LinuxシステムではNode.jsの方がより高速だと思う)での開発者が文句を言い始めたことだ。時折、彼らはnode_modules
をすべて削除し、依存関係を再ダウンロードする必要があった。単にそうしないと動かなかったのだ。
あなたは合計600MBのnode_modules
に依存関係が1200以上あると予想できるだろうか?
エンタープライズアプリケーションでは、すべてがコスト中心だ。 たとえば開発者が時給40ドルで一日に6回再起動の必要があるとする。 6回/日 × 5分 × 240日/年 × 40ドル/時間 × 8人の開発者 = 38,400ドル/年だ。 これは企業にとって大きな金額ではないが、プロジェクトのスポンサーにとっては毎年のよいボーナスとなる。結局のところ、これは最新のテスラ モデル3に等しいのだ。
障害物 #5:Redux-Sagaは緩やかに死ぬ
ほとんどの開発者は私に同意しないだろうが、私はビジネスロジックの大部分が Reduxの非同期アクションに内包されていると思っている。 ほとんどの場合は、検証、APIの呼び出し、エラーハンドリング、Reduxミューテーションのトリガー、または通知トースターのトリガーを実行できる唯一の場所だ。 これらがフロントエンドアプリケーションでのビジネスロジックと見做されないのなら、一体それは何なんだろうか?
我々はRedux-Sagaを使っているが、これは不要な複雑さを追加するので良くない決断だった。Thunkで十分だっただろう。
エンタープライズアプリケーションでは、たまに依存関係をアップグレードし再検証する必要がある。セキュリティ更新、パフォーマンスの向上やAPIの機能追加に、破壊的変更がないことを期待しているため、これはよい習慣だ。 Redux-Sagaは取り残されているように見える。前回の更新は1年以上前で、GitHubの課題は誰も修正していないまま、いまだに増え続けている。
開発者がReactを愛する3つの理由:シンプルである、柔軟性がある、そしてエコシステムである。 Reactのチームは新しいアイデアによる実験を楽しんでいる。しかし、これはエコシステムを殺しているのだ! 彼らはその責任を取る勇気を持たなければならない!
実際に、Reactは概ね下位互換性を持っているが、React周りのエコシステムはそうでない。開発者とサードパーティのライブラリは常に最新の機能とアーキテクチャパターンを使うが、一方で古い実験的機能は取り残されている。 これは中小規模のプロジェクトなら、ごく簡単に適応できるため問題にならない。しかし年月を重ねた大規模プロジェクトでは、これらの実験は許せない振る舞いとなるだろう。
もう2020年9月になる。私はテクニカル運営委員会のリスク評価結果へReact-Sagaを含めることに決めた。
ビジネスロジックの30%はsagaの内部に存在するため、ハイリスクであると睨んでいるからだ。 我々がプロジェクトを開始した時、CTOは理性を失い、愚かな決断をした私を非難した。
プロダクトマネージャーが必要としていたのは、まさに騒ぎ立てる機会であった。彼は次のような質問を開始する機会としてこれを利用した:
- なぜ我々がライブラリのアップグレードに多大な時間をかけているのか?
- なぜ開発速度が鈍くなったのか?
- なぜアプリケーションはバグが増え、不安定になったのか?
事態はマネジメントレベルにまでエスカレートした。私は何時間もかけて、当時、我々が最善の決断をしたことを証明するための証拠を探した — これは私が望む週末の過ごし方ではない。
何回かのふりかえりミーティングを経て、我々は再び穏やかな航海をしている。結局、プロジェクトはほぼ完了し、メンテナンスの段階に近づいている。
まとめ
私はReactを愛している。私はすべての個人的なプロジェクトでReactを使用し、新しい仕事の先駆けとしてReactを推奨したいと思っている。しかし、私の苦々しい体験の後ではエンタープライズアプリケーションにReactを使うのはオススメしない。もう二度としない。
ところで、このような事例は私だけじゃないんだ。
元記事の著者について
Razvan Dragomir
Software Architect at TSS-Yonder
Better Programming
Advice for programmers.