プロジェクトへの新しいライブラリの追加に抵抗する

建てる家を建てる そのため、プロジェクトにX機能を実装する必要がありましたが、現時点では、ソフトウェア開発理論家は、既存のライブラリYを取得し、それを使用して必要なものを実装する必要があると言います。



実際、これはソフトウェア開発における古典的なアプローチです-自分自身または他者の開発(サードパーティライブラリ)の再利用です。 そして、それがほとんどのプログラマーの動きです。



しかし、記事や本の理論家は、プロジェクトに住んでいる多数のサードパーティライブラリのサポートが、たとえば10年後にどうなるかについて言及することを忘れています。



すべての新しいライブラリをプロジェクトに追加することを強く抵抗することをお勧めします。 しかし、私を正しく理解してください。 ライブラリを使用してすべてを自分で作成する必要はないと言っているわけではありません。 それは単に愚かです。 ただし、1人の開発者の気まぐれで新しいライブラリがプロジェクトに追加されることがよくあります。その目的は、何らかの小さな「ウィケット」を使用することです。 新しいライブラリを追加するのは難しくありません。 そうしてはじめて、チーム全体が長年のサポートの負担を負うことになります。



いくつかの大規模なプロジェクトの開発を見て、多数のサードパーティライブラリを使用することに関するいくつかの問題をリストできます。 おそらく、私はすべての問題をリストするわけではありませんが、次のリストでさえあなたに考えるよう促すはずです:
  1. 新しいライブラリを追加すると、プロジェクトのサイズが急速に増加します。 高速インターネットと大容量SSDの時代では、これは重要な問題ではありません。 ただし、プロジェクトがバージョン管理システムからのダウンロードを1分ではなく10分で開始すると、これはすでに不快です。
  2. ライブラリの機能の1%を使用する場合でも、原則として、プロジェクト全体に含まれます。 その結果、ライブラリが既製のモジュール(たとえば、DLL)の形式で使用される場合、配布サイズは非常に急速に増大します。 ライブラリをソースコードの形式で使用すると、コンパイル時間が大幅に増加します。
  3. プロジェクトのコンパイルに関連するインフラストラクチャはより複雑になっています。 一部のライブラリには追加のコンポーネントが必要です。 簡単な例:ビルドにはPythonが必要です。 その結果、しばらくして、プロジェクトをビルドするには、最初にコンピューター上で補助プログラムの庭全体を成長させる必要があります。 どこかで動作が停止する可能性が高くなります。 説明するのは難しい、感じなければならない。 大規模なプロジェクトでは、何かが絶えず「脱落」し、すべてが機能しコンパイルできるように常に努力する必要があります。
  4. 脆弱性を気にする場合は、サードパーティのライブラリを定期的に更新する必要があります。 攻撃者が脆弱性を検索するためにライブラリのコードを調査することは有益です。 まず、多くのライブラリが開いており、次にライブラリの1つに穴が見つかったため、このライブラリが使用されている多くのアプリケーションにすぐにマスターキーを取得できます。
  5. コンパイラの新しいバージョンへのアップグレードで問題が発生します。 確かに、新しいコンパイラに適応するために急ぐことのないライブラリがいくつかあります。 そして、あなたは自分で待つか、ライブラリーに何らかの形で現れる必要があります。
  6. 別のコンパイラへの切り替えで問題が発生します。 たとえば、Visual C ++を使用しているが、Intel C ++を使用したい場合。 確かに、何かがうまくいかないライブラリがいくつかあります。
  7. 別のプラットフォームに移行する際に問題が発生します。 「非常に異なるプラットフォーム」でもありません。 Win32アプリケーションをWin64に変換するだけで十分です。 すべて同じ問題が発生します。 いくつかのライブラリはこれに対応できず、それらをどうするかが明確ではありません。 特に不愉快なのは、図書館が放棄され、もはや開発されていない状況です。
  8. 遅かれ早かれ、タイプが名前空間にない多くのCライブラリを使用すると、名前が交差し始めます。 これにより、コンパイルエラーまたは隠れたエラーが発生します。 たとえば、計画した列挙型からではなく、定数の使用が開始されます。
  9. プロジェクトで多くのライブラリを使用している場合、もう1つ追加しても害はありません。 あなたは壊れた窓の理論から類推することができます 。 その結果、プロジェクトの成長は制御できなくなります。
  10. 私が覚えていない、知らない他の多くの否定的な側面があります。 ただし、いずれの場合でも、ライブラリを追加すると、プロジェクトサポートの複雑さが急速に増加します。 この複雑さは、最も予想外の場所に現れます。


もう一度強調します。 サードパーティのライブラリの使用を停止することはお勧めしません。 プログラムでPNG画像を使用する必要がある場合は、LibPNGライブラリを使用し、ホイールを再発明する必要はありません。



しかし、PNGを使用する場合でも、停止して考える必要があります。 ライブラリは必要ですか? 画像を使用して実行する必要がある操作は何ですか? おそらく、タスク全体が何らかの種類の画像を* .pngファイルに保存することになった場合、システム関数を使用して行うことができます。 たとえば、Windowsアプリケーションがある場合、 WICが役立ちます。 また、MFCライブラリを既に使用している場合は、CImageクラスがあるため、コードを複雑にする必要はありません(StackOverflow Webサイトの説明を参照)。 マイナス1ライブラリ-すばらしい!



私は自分の練習から例を挙げます。 PVS-Studioアナライザーの開発中、いくつかの診断には単純な正規表現が必要でした。 一般的に、正規表現は静的分析には場所がないと確信しています。 これは非常に非効率的なアプローチです。 私もこのトピックに関する記事を書きまし 。 ただし、行で正規表現を使用して何かを見つける必要がある場合があります。



既存のライブラリの一部を「ねじ込む」ことが可能です。 それらはすべて冗長であることは明らかでしたが、正規表現は依然として必要であり、いくつかの決定が必要でした。



偶然、私は美しいコード(ISBN 9780596510046)の本を読んでいたその瞬間でした。 この本は、シンプルでエレガントなソリューションについて書かれています。 その中で、非常に単純な正規表現の実装に出会いました。 ほんの数十行です。 それだけです!



この実装を本から取り出し、PVS-Studioで使用を開始しました。 そして、あなたは何を知っていますか? これまで、この実装の可能性は十分です。 複雑な正規表現は必要ありません。



結果。 プロジェクトに追加のライブラリが表示される代わりに、必要な機能を作成するのに約30分かかりました。 ライブラリを「あらゆる場面で」使用したいという欲求は抑えられました。 そして、それが正しい決定であることが判明しました。 これは、数年の間、このすべての場合に同じ機能が必要ではなかったという事実によって確認されています。



このケースは、可能な限り簡単な解決策を探す必要があると最終的に確信しました。 可能であれば、ライブラリを破棄するとプロジェクトが簡単になります。



おそらく読者は、正規表現を検索するためのコードの種類を知りたいと思うでしょう。 本から転載します。



エレガントさをご覧ください。 このコードは、PVS-Studioへの統合中に私によってわずかに変更されましたが、その本質は変更されていません。

本からのコード
//   . // c    "" // .()     // ^     // $     // *        //   int matchhere(char *regexp, char *text); int matchstar(int c, char *regexp, char *text); // match:        int match(char *regexp, char *text) { if (regexp[0] == '^') return matchhere(regexp+1, text); do { /*      */ if (matchhere(regexp, text)) return 1; } while (*text++ != '\0'); return 0; } // matchhere:        int matchhere(char *regexp, char *text) { if (regexp[0] == '\0') return 1; if (regexp[1] == '*') return matchstar(regexp[0], regexp+2, text); if (regexp[0] == '$' && regexp[1] == '\0') return *text == '\0'; if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) return matchhere(regexp+1, text+1); return 0; } // matchstar:     *    int matchstar(int c, char *regexp, char *text) { do { /*  *       */ if (matchhere(regexp, text)) return 1; } while (*text != '\0' && (*text++ == c || c == '.')); return 0; }
      
      









推奨事項。 プロジェクトへの新しいライブラリの追加に抵抗します。 ライブラリが不可欠であることが明らかな場合にのみ追加する必要があります。



考えられるいくつかの操作を次に示します。
  1. おそらく、必要な機能は、システムのAPIまたは既に使用されているライブラリの1つによって既に提供されています。 この質問をご覧ください。
  2. ライブラリの非常に小さな機能を使用する場合は、自分で実装するのが理にかなっています。 「ライブラリを接続する方が良いのに、突然何か他のものが必要になる」という議論は価値がありません。 ほぼ常に、このライブラリから将来的には何も使用されません。 プログラマーは、本当に必要ではない普遍性に過度に引き寄せられます。
  3. 問題を解決するライブラリが複数ある場合は、要件を満たす最も単純なライブラリを選択してください。 上記で書いたように、「突然ライブラリを利用する場合に備えて」考えを追い払ってください。
  4. ライブラリの追加を開始する前に、待ってから考えてください。 お茶を飲み、気を散らし、同僚とタスクについて話し合います。 おそらくその過程で、サードパーティのライブラリの助けを借りずに、まったく異なる方法で問題を解決することが可能であることがわかります。


PSここの多くの人々はそれを好まないでしょう。 たとえば、ポータブルユニバーサルライブラリを使用するのではなく、WinAPIを使用することをお勧めします。 これを行うことにより、プロジェクトを1つのオペレーティングシステムにアタッチするという事実に基づいて、これに異議があるでしょう。 そして、プログラムを移植可能にすることは非常に困難です。 私はこれに同意しません。 多くの場合、「オペレーティングシステムを別のオペレーティングシステムに移行する」という考えは、開発者の頭の中にしかありません。 実際、そのようなタスクは決して経営者によって提起されることはありません。 あるいは、人気の瞬間や移植の必要性が生じる前であっても、過度の複雑さと汎用性のためにプロジェクトは「曲がり」ます。 さらに、上記の問題のリストの項目(7)を忘れないでください。



All Articles