DUICUO

私のささやかな意見: ビジネスからオープンソースへの移行に関するいくつかの考察

この記事では、商用プロジェクトとオープンソース プロジェクトの違いについて、いくつかの側面から説明します。主なポイントは次のとおりです。

  • 成果物: オープンソース プロジェクトの成果物はより複雑であり、ソース コード、開発プロセスなどは透明性が求められ、あらゆる面で高い要件が求められます。
  • エンジニアリング: オープンソース プロジェクトは人材不足に直面しており、エンジニアリングと自動化に対する要件が高く、適切な環境の事前設計と構築が必要です。
  • 自動テスト: オープンソース プロジェクトでは自動テストに対する要件が高く、体系的なテスト システムを設計する必要があります。
  • 依存関係の管理: オープンソース プロジェクトの依存関係の管理はより厳格にする必要があり、複雑さを軽減するために依存関係の構造を合理的に設計する必要があります。
  • コミュニケーション: オープンソース プロジェクトでは、GitHub Issues などの非同期通信ツールがよく使用されます。これらをエンジニアリング手法と組み合わせることで、効率を向上できます。

序文

議論を始める前に、まずこの問いについて考えてみてください。オープンソースのメリットは何でしょうか?具体的な答えは状況によって多少異なるかもしれませんが、一般的には少なくとも2つのメリットがあります。

  1. 個人またはチームの影響力を拡大する: 特定の問題を解決するのが得意な個人またはチームが存在すること、あるいは @evan、@zack、@Langchain など、この分野の権威となって大きな影響力を持つ個人またはチームが存在することを、コミュニティ内のより多くの人々に知らせます。
  2. エコシステムの共構築:理想的には、オープンソースのアプローチは、より多くの優秀なエンジニアを製品開発に参加させ、彼らの知恵と努力を結集させ、ニーズや問題に敏感になることを容易にします。その結果、イテレーションのスピードが速くなり、限られた人数の商用チームと比較して、多くのロングテールニーズを満たす技術的な製品を開発できる可能性が高くなります。

これらのメリットは多くの現実世界の問題を効果的に解決できるため、多くの実務家にとって「オープンソース」はある程度「政治的正しさ」のデフォルトオプションとなっているようです。その結果、十分な調査も行わずにオープンソース分野に飛び込み、コードをGitHubにアップロードしてコミュニティに「公開」すればオープンソースの地位を獲得できると、ナイーブに(この言葉はあまり良くありませんが)考えてしまうチームや個人がいます。しかし、その後の努力が不足していることが多く、たとえ時間と労力を費やし続けても、期待した目標を達成することは難しい場合が多いのです。根本的な原因は、多くの人が商用開発とオープンソース開発は全く異なるものであることを認識していないことにあると私は考えています。

恥ずかしながら、私は10年以上フロントエンド開発に携わっていますが、大きな影響力を持つオープンソースプロジェクトに正式に参加したことがありません。そのため、商用プロジェクトの運営方法に馴染みがあり、これは多くの読者の方々もそうだと思います。幸いにも、私の仕事は様々なオープンソース製品の基盤となる実装を深く理解することを必要としており、徐々にコツを掴んできました。商用プロジェクトとオープンソースプロジェクトの違いについて、いくつか考えがあるので、皆さんと共有したいと思います。

商用プロジェクトとオープンソースプロジェクト

まず、商用プロジェクトでは通常、アプリケーションの最終的な実行可能インターフェースのみを提供すれば良いため、機能性、安定性、パフォーマンスといった要件を満たすことに重点が置かれます。具体的な実装の詳細は、外部から見ると完全にブラックボックスです。しかし、オープンソースプロジェクトの成果物ははるかに複雑です。機能性に加えて、すべてのソースコード、開発プロセス、エンジニアリング設備、さらにはコミュニケーションや議論のプロセスまでもが外部に対して透明です。したがって、オープンソース製品は結果だけでなくプロセスにも責任を負わなければなりません。優れたオープンソースプロジェクトでは、コードの品質、安定性、インターフェースの使いやすさ、スケーラビリティ、ブランチモデル、開発標準、バージョン管理、エンジニアリング設備など、あらゆる側面が製品の一部であり、慎重な検討と維持管理が求められます。

非常に詳細な例を挙げると、ブランチモデルでは、ブランチにはどのように名前を付けるべきか?どのブランチをどのブランチにマージできるか?機能ブランチはいつメインブランチにマージすべきか?どのブランチの安定性を確保する必要があるか?そして、どのように安定性を確保できるか?さらに、どのブランチが正式バージョンをリリースできるか?どのタグをいつ追加すべきか?線形履歴を維持する必要があるか?などなど。

さらに、ブランチモデルの仕様は、様々なバックグラウンドを持つ開発者がプロ​​ジェクトに迅速に参加できるほどシンプルである必要があります。理想的には、参加者が基本的なミスを犯さないように、自動化ツールを補完することも重要です。中国の多くの商用チームは、FBDの派生形であるトレーニングモデルに慣れているかもしれませんが、このアプローチは複雑すぎて、理解と運用にコストがかかり、多くの場合オープンソース環境とは互換性がありません。そのため、TBDに切り替えることがよくありますが、TBDモデルは非常に高い安定性が求められるため、非常に複雑で重要な自動テストのニーズが生じます。

写真

例えば、バージョン管理に関して言えば、semver モデルについては誰もが知っています(NPM 依存関係管理の複雑さを参照)。しかし、パッチはいつリリースすべきでしょうか?マイナーバージョンはいつリリースすべきでしょうか?この決定の基準は何でしょうか?誰が決定するのでしょうか?バージョン 0.x から 1.0 にいつ切り替えることができるでしょうか?後方互換性は必要でしょうか?そして、どの機能とインターフェースで後方互換性を維持する必要があるでしょうか?つまり、優れたオープンソースプロジェクトを開発しようとする場合、普段は気にすることのないこれらの問題を慎重に検討する必要があります。そうしないと、将来的に技術的リスクや PR リスクにつながる可能性があります。

もちろん、これはオープンソースプロジェクトが商用プロジェクトよりも必ずしも困難または複雑であることを意味するものではありません。むしろ、Webpack、ESLint、RSPack、Viteなど、多くの優れたオープンソースプロジェクトは、特定の問題の解決に焦点を当て、コミュニティが必要に応じて様々なロングテール要件を拡張・実装できるように、アーキテクチャ内に十分な柔軟な論理スロットを残しています。そのため、オープンソースプロジェクトは通常、技術的な複雑さは比較的高いものの、その機能は非常に収束的です。対照的に、Taobao、Douyin、Volcano Engineなどの商用製品の機能的複雑さには上限がほとんどありません。機能が十分に複雑になると、全体的なアーキテクチャと技術的な複雑さが非線形に増加することは避けられません。内部の技術的な詳細の多くは最適ではないか、移植性や再利用性がないかもしれませんが、深いレベルの技術的な難しさが伴うことは否定できません。したがって、両者の間に絶対的な優劣はないと考えています。結局のところ、それらは異なるシナリオで異なる問題を解決しているだけであり、明らかな優劣はありません。

オープンソースに関わる前に、そのコストとメリットを理解すること、さまざまなエンジニアリングの詳細の違いを理解すること、ROIがプラスかどうか、チームが十分な能力と技術的専門知識を持っているかどうかなどを評価することが、さらに重要だと思います。オープンソースのためにオープンソースを避けるのはやめましょう。

エンジニアリング

オープンソースプロジェクトには、一般的に人材不足という大きな特徴があります。情熱を持ってプロジェクトに全身全霊で取り組める人はそう多くありません。多くの場合、参加者は生計を立てるため、あるいは感情的なニーズを満たすためといった、普段の仕事以外の貴重な自由時間をオープンソースに費やすため、実際に投入できる時間は限られています。同時に、優れたオープンソースプロジェクトは、参入障壁が高いのが一般的です。プロジェクトの実装原則やアーキテクチャ設計を深く理解し、全体的な設計やコーディングスタイルに沿ったプルリクエスト(PR)を送信することはさておき、環境を初期化してプロジェクトを実行する方法、意味のあるPRを送信する方法、そして高品質な問題を送信する方法を理解するだけでも、かなりの学習時間が必要になる場合があります。

プロジェクトマネージャーの視点から見ると、開発者の数が一定レベルに達すると、チームメンバーの質のばらつきが、必然的に一連のプロセス品質問題につながります。例えば、ユニットテストすら実行できないプルリクエストが大量に送信されたり、様々な標準やガイドラインに沿ってコードが記述されなかったり、明らかにパフォーマンスに問題のあるコードが送信されたりすることが挙げられます。原則として、問題の発見が早け​​れば早いほど、修正コストは低くなります。そのため、リポジトリ管理者は、こうした低品質な開発活動を防ぐために、積極的な品質管理に多大な時間と労力を費やす必要があります。

どちらのケースも、最終的には時間と空間の複雑さの問題に帰着します。商用プロジェクトでは、チームコラボレーションによって引き起こされるエントロピーの増加は、限られた空間複雑さの範囲内で、合理的な分業体制に基づいたチーム構造の構築、開発プロセスと標準の改善、人的資源の強化、行動制約の強化によって軽減できます。

しかし、このアプローチはオープンソースプロジェクトには現実的ではありません。参加グループは通常、大規模で、地理的に分散しており、スキルレベルや文化的背景もさまざまであるため、商用企業の管理モデルを模倣して各メンバーに特定の責任を割り当てることは困難です。代わりに、個人が自分の専門知識に基づいて自発的に特定の問題を解決します(これこそがオープンソースの魅力です)。しかし、このような個人視点の解決策は、リポジトリのコンテキストでは必ずしも最適ではありません。第二に、オープンソース環境では、標準化されたドキュメントを通じて個々の開発行動を制約することが困難な場合が多いです。包括的な開発マニュアルがあったとしても、それを完全に読んで受け入れる忍耐力を持つ人はほとんどいません。さらに、ドキュメントの拘束力は非常に弱いため、監督者が開発の詳細を継続的に監視する必要があり、非効率的です。

これらの問題は最終的に、比較的実現可能な解決策、つまりエンジニアリングへと繋がります。エンジニアリングとは、単にツールを積み重ねるだけでなく、複雑かつ包括的なエンジニアリング問題であることに注意してください。一般的に、オープンソース環境では、商用プロジェクトよりもエンジニアリングと自動化に対する要件がはるかに厳しくなっています。Bundle、Lint、UT、E2Eといった共通インフラストラクチャの設定だけでなく、具体的なシナリオに合わせて様々な自動化ワークフローを構築する必要があるのです。

オープンソース プロジェクトを開始するときは、事前に適切なエンジニアリング環境を設計および構築するための労力を投資する価値があります。これらの自動化されたプロセスにより、非常に低コストで、プロジェクトの品質が長期的に低下するのを防ぐことができるためです。少なくとも、世界中から多くの低レベルの問題を回避し、経営陣のレビューの負担を軽減できます。エラーが発生したときにタイムリーで適切なフィードバックを提供できるため、プロジェクトへの参入障壁が低くなります。また、さまざまな重要なプロセスを標準化できるため、人間の偶然性によって引き起こされるランダム エラーを回避できます。

もちろん、エンジニアリングは万能薬ではありません。プロジェクトのアーキテクチャ設計が十分に優れているか、ユーザードキュメントが十分に網羅され明確であるか、プロジェクト全体の計画など、自動解決が不可能、あるいは困難なエッジケースは数多く存在します。こうした問題は、依然として人間の介入に大きく依存しています。

自動テスト

これは強調すべき重要な点です。オープンソースプロジェクトでは、従来の商用プロジェクトよりもはるかに高い自動テスト要件が求められます。商用チームでは通常、専任のテスターを任命し、製品の品質を定期的にチェックし、最終的な品質に責任を持つ、あるいは少なくともセーフティネットとしての役割を担わせます。しかし、前述のように、オープンソースプロジェクトではそのような専任の役割を担うことは稀です。そのため、開発者は製品の品​​質に直接責任を負い、様々なテストを自ら行う必要があります。しかし、仕事に情熱を注ぐ開発者にとって、様々なテストを繰り返し実行するための時間を割くことは難しく、また、それらを綿密に行うことも困難です。

そのため、オープンソースプロジェクトでは、よりアジャイルで人手を必要としないソリューション、すなわち自動テストが自然と採用されてきました。自動テストでは、コード自体がコードの安定性をテストします。具体的なテスト手法には、ユニットテスト、エンドツーエンドテスト、パフォーマンステスト、APIテストなど、多種多様なものがあります。多くの高品質なオープンソースプロジェクトでは、具体的な状況に応じて、これらの自動テストソリューションを1つ以上採用しています。機能コードに対して複数のテストケースを作成し、コードマージ前やリリース前などの重要な段階でチェックポイントを設定してテストコードを実行します。すべてのテストケースに合格し、テストカバレッジが要件を満たした場合にのみ、プロセスを続行できます。

テストケースは、ある意味、プロジェクトメンバー間で文書化されていない、強い拘束力を持つ契約のようなものと言えます。コードを変更しようとする者は、この契約を遵守し、既存のテストケースがパスすることを確認する必要があります。あるいは、必要に応じて、反復的な機能に対応するためにこれらの契約を更新する必要があります。テストケースコードの開発と保守自体は時間のかかる作業ですが、契約が詳細かつ包括的であればあるほど、エラーが発生する可能性は低くなります。プロジェクトの状況に全く精通していない新人でも、テストフレームワークとその他の品質管理ツールのみを使用して、第三者の支援なしに、準拠したコードを作成できます。これは、オープンソースプロジェクトにおける人材の配分とよく一致しています。

理論上、テストケースの完成度が高いほど、プロジェクト全体の品質は安定します。しかし、自動テストには技術的な障壁と人的コストの問題があります。上記のような理想的な状態を実現するのは容易ではなく、テストシステムの体系的な設計が必要です。一般的な手法としては、以下のようなものがあります。

  1. ユニットテスト(UT)技術は、コードモジュール内のすべての論理分岐をカバーするホワイトボックステストを実装するために使用されます。カバレッジを追求するだけでは意味がありません。むしろ、様々な論理境界シナリオ(これは困難ですが)をさらに考慮し、推論する必要があります。特に、非同期操作や並行操作などの複雑なタイミングシナリオは重要です。例えば、ボタンコンポーネントをテストする場合、基本的な機能の検証だけでなく、連続クリックが連続イベントトリガーにつながるかどうかをテストするためのテストケースを設計する必要があります。
  2. エンドツーエンド(E2E)テクノロジーを活用することで、製品インターフェース上でブラックボックステストを実施できます。これにより、エンドユーザーの視点から製品を操作し、プロセスと結果の正確性を検証できます。ユニットテストと比較して、このテスト手法はコードモジュールを統合した後の運用パフォーマンスに重点を置き、ユーザーエクスペリエンスに近いため、ユニットテストの補足として適しています。
  3. 次に、必要に応じて、ベンチマークなどのツールを使用して、製品のコア アルゴリズムや頻繁に実行されるコード スニペットのパフォーマンス テストを実行し、パフォーマンスの下限値を確保できます。

依存関係管理

依存関係管理は複雑なエンジニアリング上の問題です(「NPM依存関係管理の複雑さ」を参照)。不適切な管理は、パフォーマンス、安定性、その他の品質問題に容易につながる可能性があります。したがって、理論的には、商用プロジェクトとオープンソースプロジェクトの両方において、サードパーティの依存関係の使用を制御し、悪用を防止するための高度な管理手法が一般的に求められます。NPMパッケージベースの製品の場合、これらの制御手段はさらに厳格化する必要があります。多くのオープンソースプロジェクトは、最終的にNPMパッケージの形でその使用方法を提供しています。

npm、pnpm、yarnなどのパッケージマネージャーを使用してパッケージをインストールする場合、ツールはすべての子孫依存関係を再帰的に分析してインストールします。そのため、ユーザーは新しいパッケージごとに、対応する依存関係グラフをインポートする必要があります。依存関係構造が複雑になるほど、次のような問題が発生しやすくなります。

  • 依存関係のインストールによりパフォーマンスの問題が発生する可能性があります。
  • 基礎となる依存関係の問題は上方に広がり、上位層アプリケーションの安定性に影響を及ぼす可能性があります。
  • 不安定な依存関係グラフは、実際にインストールされているバージョンに大きな変更をもたらし、最終的にはプロジェクトの安定性に影響を与える可能性があります。
  • 依存関係の重複は簡単に発生する可能性があります。例えば、NPM パッケージが [email protected] への依存関係を宣言し、ユーザーの package.json でも [email protected] への依存関係を宣言している場合、ユーザーのプロジェクトでは最終的に lodash の 2 つのバージョンをインストールする必要があります。

写真

NPMパッケージのサブ依存関係が増えるほど、パフォーマンスと安定性が低下し、ユーザーの学習曲線が長くなり、パッケージの「使いにくさ」を強く感じさせると言っても過言ではありません。したがって、このようなシナリオでは依存関係を抑制し、依存関係グラフの複雑さを最小限に抑えるよう、依存関係構造を慎重に設計することが重要です。そのためには、必要に応じて以下のような緩和策を検討してください。

  • シンプルなコードスニペット(例:エスケープ文字列正規表現)は、追加のサブ依存関係を追加することなく、リポジトリに直接コピーできます。ソフトウェアエンジニアリングではコピーは軽視されることが多いですが、適切な冗長性はソリューションの複雑さを軽減するのに非常に効果的です。
  • あるいは、単純な依存関係をプロジェクトコードと一緒に単一のバンドルファイルにパッケージ化し、サブ依存関係を `devDependencies` として宣言することで、ユーザー側での重複インストールを回避できます。このアプローチは、基本的にサブ依存関係をスナップショットとしてプロジェクトコードにバンドルすることを意味します。これにより冗長性は生じますが、サブ依存関係のバージョン変更の影響を受けないため、安定性とパフォーマンスが向上します。
  • 複雑な依存関係の場合は、peerDependencies として設定することも検討できます。これにより、ユーザーはサードパーティの依存関係のバージョンを自身で管理できます。これにより、他の複雑な問題が発生する可能性がありますが、競合を効果的に回避できます。

結局のところ、依存関係管理は見落とされやすいにもかかわらず非常に複雑であり、不適切な管理はユーザーの評判に直接影響を与える可能性があります。読者の皆様には、依存関係管理の原因と結果、そして様々なベストプラクティスをより深く理解するために、「NPMにおける依存関係管理の複雑さ」の記事をぜひお読みください。

通信する

商用開発チームは通常、インスタントメッセージング(IM)ソフトウェア(Lark、WeChat Work、Bear Chatなど)を主要なコミュニケーションツールとして使用します。しかし、オープンソースプロジェクトではIMはほとんど使用されません。代わりに、GitHub Issues、Disco、Redittなどのツールが、バグレポート、RFC、使用方法の問い合わせなど、プロジェクトの詳細を伝える際に好まれます。

これらのフォーラム形式のツールは、インスタント メッセージング (IM) に比べると効率や利便性がはるかに劣りますが、オープン ソース プロジェクトに最適な選択肢となる多くの特性を備えています。

  1. これらのツールは、情報の流れをタイムライン形式で整理し、特定のトピックを中心に議論を集中させます。これにより、コミュニケーションのテーマが非常に焦点化され、道に迷う可能性が低くなり、信号対雑音比が大幅に高まります。
  2. 十分にオープンで、ほぼ透明性も高く、誰でも非常に低い参入障壁でこの種の情報環境に入ることができます。同時に、検索エンジンによる検索にも非常に有益です。
  3. 歴史的記録の追跡が容易になり、新規参入者が歴史的背景を理解しやすくなり、これらの種類の問題がプロジェクト ドキュメントの自然な一部になります。
  4. オープンソース プロジェクトのメンバーは世界中に存在し、タイム ゾーンが一致しないため、リアルタイムのコミュニケーションはあまり意味がなく、非同期のコミュニケーション ツールの方が自然に適しています。

したがって、IM のリアルタイム性によってもたらされるコミュニケーション効率が部分的に犠牲になるとしても、オープンソース環境における主流のコミュニケーション方法として、GitHub Issues や Disco などのツールの使用を優先することが推奨されます。

しかし、多くの学生はメールやGitHubの通知を定期的に確認する習慣がないかもしれません。オープンソースプロジェクトに取り組む初期段階では、こうした習慣に慣れるのが難しいかもしれません。幸いなことに、これらのツールは非常に便利なオープンインターフェースシステムを提供しており、これを利用して自動化ツールを設計・実装し、情報フローの効率を向上させることができます。例えば、GitHub IssuesではGitHub Actionsを使用できます。

  1. 問題の変更をリッスンし、IM インターフェイス (例: Feishu: feishu-bot-webhook-action) をコールバックして、対応するグループに動的に転送し、リアルタイムのパフォーマンスを向上させます。
  2. アクティブな問題や PR などを定期的に要約してレポートにまとめ、IM ソフトウェアに送信して情報のブロックを回避します。
  3. 情報過多を防ぐために、非アクティブな問題を定期的に閉じます。
  4. LLM と連携して、問題が作成されると、AI がコンテンツを分析し、自動的に初期フィードバックを提供します。
  5. などなど。

まとめると、オープンソース環境においてインスタントメッセージ(IM)を主要なコミュニケーション手段として使用することは推奨されません。GitHub Issuesなどの非同期コミュニケーションツールに切り替え、様々なエンジニアリング手法を用いて情報フローの効率性を向上させることをお勧めします。

やっと

この記事はやや散漫で、幅広い分野をカバーしているものの、オープンソースアプリケーションと商用アプリケーションの違いは、ここで議論されている範囲をはるかに超えています。これはあくまでも概要であり、さらなる議論を促すことを目的としています。しかし、最も重要な点は、商用チームがオープンソース分野に進出する前に立ち止まり、期待とコストを明確に理解し、文化の違いによって生じる問題解決の方法やアプローチの変化を考慮する必要があるということです。