Webエンジニアなら知っておきたい、依存関係の分類のお話

こんにちは! NILTOチームでインフラエンジニアをしている太田です。

「Webエンジニアなら知っておきたい」ということで、当記事では、プログラミング時の依存関係の分類についてお伝えします。

なお、便宜上ここでの「依存関係」は「プログラミング時に利用する外部および内部のライブラリ」と定義します。 日本語では違和感があるかもしれませんが、パッケージマネージャでよく用いられる「Dependencies」という英単語に置き換えると理解しやすいと思います。

依存関係の分類

依存関係は、大まかに外部依存関係・内部依存関係・推移的依存関係の3つに分類されます。

外部依存関係(External dependencies)

あなたやあなたのチームが書いたコードの一部ではないライブラリやフレームワークです。

今あなたは、特定の機能が必要な関数を書いているとしましょう。 ゼロからコードを書く代わりに、あなたの関数に必要な機能を持つ、外部のライブラリを使用できます。 というか、最近のプログラミングではほとんどの場合、外部ライブラリを使用しますよね。 この外部ライブラリはプロジェクトの外部依存関係ということです。

外部依存関係はさらに、実行時依存関係・開発時依存関係・ビルド時依存関係といった具合に、開発フェーズによる分類がなされることがあります。1

実行時依存関係(Runtime dependencies)

上記の関数の例のように、アプリケーションの実行時に必要となる依存関係のことです。

開発時依存関係(Development dependencies)

開発中に必要な依存関係のことです。

たとえば、ユニットテストを書く際にはテストライブラリが必要です。 コードからドキュメントを作成する際には、ドキュメンテーションジェネレータが必要です。 こういった依存関係は開発中には重要ですが、アプリケーションの実行時には必要ありません。 ですので、これらは開発時依存関係と呼ばれます。

ビルド時依存関係(Build dependencies)

ビルド時に必要な依存関係のことです。

TypeScriptをJavaScriptに変換するためのtscや、gcc・g++といったコンパイラそのものも、ビルド時依存関係に含まれます。 こういった依存関係はコードをコンパイル2するために必要ですが、アプリケーションの実行時は不要です。 ですので、これらはビルド時依存関係と呼ばれます。

内部依存関係(Internal dependencies)

プロジェクト内の別の場所で使えるように、共通の処理をまとめたものです。

たとえば、あなたが書いた関数を、プロジェクトの複数の部分で使用したいとします。 この関数を別のファイルに移動し、他の部分からインポートすれば、プロジェクトの必要な箇所で再利用できますよね。 この関数はあなたが書いてあなたのチームが使用するので、プロジェクトの内部依存関係です。3

推移的依存関係(Transitive dependencies)

依存関係の依存関係です。(わかりにくいですね)

今あなたは、外部依存関係としてライブラリAを使用しているとしましょう。 ライブラリAは、必要な機能を提供するために、別のライブラリであるライブラリBを使用しています。 この2番目のライブラリ、つまりライブラリBは、プロジェクトの推移的な依存関係です。

おわりに

自分で一からコードを書くのではなく、外部依存関係を利用することで、コーディングの作業量を減らし、ソフトウェア開発の生産性を上げることができます。 また、利用する依存関係の分類を理解し、その用途や意味を理解することは、自分の作っているソフトウェアを深く理解することにつながります。

依存関係の選定や意味づけをないがしろにせず、丁寧なソフトウェアづくりを目指していきたいものですね。


  1. 実際の定義方法はパッケージマネージャによって違いがあります。
  2. TypeScriptからJavaScriptへの変換は、厳密には「トランスパイル」と呼ばれます。
  3. 内部依存関係をどのようにデザインするかは、ソフトウェアアーキテクチャと設計の領域に含まれます。