エンジニアとしてどのように年齢を重ねていくことが望ましいのか?

設計のできるエンジニアになろう

»

 ソフトウェア・エンジニアとして仕事を始めて、最初に覚える事はプログラミング言語ではないでしょうか?

 最近では、学生時代になんらかのプログラミング言語を習得してから社会人になることも珍しくないですが、入社時にプログラミング言語の知識を持ち合わせていない場合もあるでしょう。入社時点でのプログラミング能力は若干の差があるとしても、ソフトウェア・エンジニアを職とした人たちが最初に習得すべき課題は、プログラミング技術だと考えます。

 プログラミング言語の基本的な仕様を習得し、簡単なプログラムを作成するようになるまでには、さほど多くの時間をかけずに実現が可能です。プログラミング技術を磨くには、多くのプログラムを開発することと、他人が書いたプログラムを読み、その意図を理解することが一番だと思います。他人が書いた賢いコードやきれいなコードを読むことで、自分にはない発想を学び、上手に自分のものにしていくことが重要です。

 このように、ある程度経験を積むことで、1人でプログラムを作成できるように成長したエンジニアの次の課題は、ソフトウェア設計です。

 わたしが社会人として最初の会社に入社した時代は、ソフトウェア設計とプログラミングを分業していましたので、プログラミングを習得してから設計者へと“格上げ”されていきました。最近では、設計と実装を明確に分離せずに進める傾向にあり、これは、オブジェクト指向設計やAgile開発が浸透してきている影響だと思います。

 ソフトウェアは、プログラマがある種の設計をしながら作成されていくものだと考えますので、わたしもこのアプローチは正しいと思います。しかし、ソフトウェア・エンジニアとして成長していく過程において、一度に多くのことを習得することは困難であり、段階を経て一人前になることが一般的です。その前提に立つと、プログラミング ⇒ 設計の順序で、エンジニアとしての腕を磨いていくことは効果的な方法だと思います。

■ プログラマが備えるべき設計スキル

 プログラムを開発する際、設計上で気をつけたいポイント。

  1. モジュール(クラスなど)の凝集度が高く、疎結合であること
  2. 重複する機能が点在していないこと(コピー&ペーストをしていないか)
  3. テスタブルであること

● 凝集度と結合度

 凝集度とは、クラスなどが単一の機能で構成されているかの尺度です。

 必ずしも単一機能で構成されている必要はありませんが、機能の凝集度が高いほうが、機能に対する実装単位が単純化され、より理解しやすい構造になります。また、特定機能に対する変更が発生した際に、他の機能に対する影響度を最小限に留めることが可能です。

 一方、結合度において重要なことは、呼び出す側と呼び出される側の関係は弱いほうが良く、情報の受け渡しが疎結合の状態を目指して設計することです。

 疎結合の状態とは、コンポーネント同士の依存関係が弱く、柔軟にそれぞれのコンポーネントを交換、変更することができ、一方へデータまたはデータの構造体を渡すことにより、目的とする結果を得るという関係です。

 このような関係だと、データを受け取ったプログラムが内部でどのような処理をしているかを意識する必要がなく、呼び出す側は、いわゆるブラックボックスとして考えればよいわけです。よって、呼び出されるプログラムに何らかの変更が生じても、2つのプログラム間のインターフェースに変更がなければ、呼び出し側のプログラムは、特に変更を意識する必要がありません。

 逆にコンポーネント同士が密な関係を密結合といい、呼び出し側から、呼び出される側が保有している情報を直接変更するような場合や、その逆の場合があります。密結合は、動作は高速ですが、それぞれの変更がそれぞれのプログラムに大きな影響を与える可能性があり、変更容易性を低下させることになります。

● 重複の防止

 同一のソースコードを、複数に点在させてはならないという基本的な考え方です。

 実装言語の仕様によって実現方法は異なりますが、共通的な機能は一箇所にまとめることが望ましいです。同一のコードが複数箇所に存在した場合、変更の対応に手間がかかることはいうまでもありません。プログラミングしている時に、一連のソースコードをコピー&ペーストしたくなったら要注意です。

● テストが容易

 開発したプログラムのテストが、容易に実施可能であることが重要です。

 上記の凝集度、結合度が理想的に守られているプログラムは、テスト容易性が高いといえるでしょう。 

 凝集度が高ければ、より小さな機能単位でテストが可能であり、結合度が低い(疎結合)プログラムでは、プログラム単体でのテストが容易になります。このような構造で設計されたプログラムは、テストの自動化も容易となり、開発効率向上と品質向上へつながります。 

■ そのほか、設計上で注意したいこと

 ソフトウェアの設計といっても、その抽象度のレベルは様々です。

 通常、最初から詳細なソフトウェア設計をするわけではなく、抽象度の高いところから段階的に詳細化(低い抽象度)していきます。前述の設計上で気をつけたいポイントは、プログラミングレベルの抽象度の低いレベルでの注意点です。ソフトウェアは、多くの場合、膨大な数のクラス(モジュールなど)が連携しあって動作するものです。一般的には、最小単位のかたまり(例えばクラス)を一定の目的で束ねて集約(例えばサブシステム)し、さらにそれらを複数束ねて集約(例えばパッケージ)するといったように階層化された構造になります(図-1)。

 クラス群を構造化していく上での設計上の注意点は、以下になります。

  1. サブシステム間インターフェイス設計
  2. 隠蔽性
  3. 依存関係

● サブシステム間のインターフェース設計

 ここでいうサブシステムとは、UML(Unified Modeling Language)でいうサブシステム(<<Subsystem>>)を示しています。

 具体的には複数のクラス群から構成されており、ひとつ以上のインターフェースを公開し、その内容については公開していないという特徴があります。クラス群は、関連性の高い一定の目的を達成するための集合体です。サブシステムが公開するインターフェースは、そのサブシステムが実現すべき機能を考慮し、将来の拡張も踏まえた設計とすることが重要です。 

● サブシステムの隠蔽性

 上記のように、サブシステムはその内容を公開しないという特徴がありますが、これは被利用者からの独立性を保つために重要な概念です。よって、サブシステムを構成するクラス群は、それらが保有する要素の可視性に注意して設計することが重要です。サブシステム外から、サブシステム内の要素を直接、参照・操作できない可視性とすることで、隠蔽性が保持されます。

● 依存関係

 レイヤーを跨(また)ぐ依存関係が存在する場合、自分と同じレイヤーか、もしくはより抽象度の高いレイヤーへの依存を許可するような設計が必要になります。自分より抽象度が低いレイヤーへの依存や循環依存(互いに依存しあっている)関係を回避する設計にする必要があります。

■ 最後に

 今回のテーマでは、プログラムの実装に近いフェーズでの設計における原則的なポイントを紹介しましたが、現実の設計&実装では、全てが原則通りにはいかない場合があります。

 現実的な解決策として、部分的に冗長な設計をする場合があります。ここで重要なことは、原則を遵守する部分と、冗長な設計をする部分をどのように決定するのか、その判断の基準にあると考えます。しかし、その答えを導く方法は、場面ごとに適切な判断を下すしかありません。適切な判断を導き出すには、経験を重ねていくしかないのかもしれません。

1

Comment(0)

コメント

コメントを投稿する