CIにおける構造品質の見える化と違反検知による迅速なフィードバック


日本のソフトウェア開発現場においても、開発の効率化や品質の向上のために、継続的インテグレーションに取り組んでいるプロジェクトは年々増えています。

継続的インテグレーションと言えば、自動ビルドや静的解析、テストの自動化を真っ先に思い浮かべる方が多いと思います。一般的に、ソフトウェア開発では開発の後半の作業になるほど、必要工数が増えていくため、これは理にかなった考えと言えると思います。

一方で、弊社ではお客様より次のようなご相談を受けることも多いです。

  • そもそものソフトウェアの品質が改善されない限りはテストでいくら検証したところで、品質が上がらず、開発を繰り返す毎にテスト工数や開発全体の工数が増えていってしまう。(保守性の低下)
  • テストだけで品質保証をおこなうことには限界を感じている。

こうした状況に陥った場合、バグを修正することが最優先となり、その場しのぎの一時的な対応が増え、当初の設計意図に反した実装が施されるようになり、急激に技術的負債が蓄積されていきます。

こうした状況を改善するには、ソフトウェア開発ライフサイクルのより早い段階で問題を把握し対応する、すなわち”シフトレフト”が重要となります。

図1 シフトレフトとは

 


目次

  • ソフトウェア構造の見える化ができていないプロジェクトの問題点
    • ソフトウェア構造が可視化できていないことの問題点
    • ソフトウェア構造の可視化と構造違反を継続的にフィードバックすることの意義
  • CIビルド時にソフトウェア構造(アーキテクチャ)の見える化に取り組む
    • 【step1】LattixWebで最新の構造を見たいときに見られる状態にする
    • 【step2】アーキテクチャのルールを見える状態にする
    • 【step3】新しくルール違反が出た際に迅速にフィードバックする
  • Lattixとは
  • まとめ

ソフトウェア構造の見える化ができていないプロジェクトの問題点

・ソフトウェア構造が可視化できていないことの問題点

多くのソフトウェアは、開発が進む中で徐々に巨大化していきます。ソフトウェア規模が小さいうちは、当初の設計意図に従いつつ仕様追加やメンテナンスをする上で必要十分なレベルで、全体構造や設計意図が開発メンバー内で把握されています。これによって当初の設計意図に沿った開発が進められ、品質は高い状態に保たれます。

しかし、ソフトウェア規模が大きくなると、全体構造の把握が困難になったり、当初の設計では立ち行かなくなるなどの弊害が発生しやすくなります。

さらに、時間の経過とともに途中から参画するメンバーが増えたり、開発メンバーの入れ替わりにより、当初の設計意図や全体構造など十分な理解がなされずに開発が進むことで、設計意図に反した実装が混入するようになり、品質が徐々に低下していきます。

こうした状況を踏まえ、「シフトレフト」を達成するには、現在のソフトウェア構造の継続的な可視化と管理が必要となります。

・ソフトウェア構造の可視化と構造違反を継続的にフィードバックすることの意義

上記のように、レイヤー構造をはじめとする全体構造の把握や、個々のモジュールの内部構造理解、および開発メンバーに設計意図が浸透していない場合、ソフトウェア構造(アーキテクチャ)が崩れていきます。

こうした構造の崩れは、目に見えないうちに蓄積し、バグのもぐらたたき問題や、変更規模に反する影響範囲の拡大など、プロジェクト遅延に直結する問題として現れます。

図2 アーキテクチャ崩れの問題

構造の乱れは日々発生しますが、蓄積してしまうと取り除くことが困難になります。1か月以上前の変更箇所を、構造修正しテストをする大変さを想像してみてください。このため、ソフトウェア構造を継続的に可視化し、設計意図に反する変更はルール違反として検出するフィードバックの仕組みが重要となります。

CIビルド時にソフトウェア構造(アーキテクチャ)の見える化に取り組む

【step1】LattixWebで最新の構造を見たいときに見られる状態にする

ソフトウェアの構造(以降「アーキテクチャ」)を俯瞰的に可視化する方法として、DSMという方法があります。
詳細は省略しますが、モジュール同士の依存関係の強度を数値で表し、可視化する方法です。

図3-aから図3-cはApache httpサーバーのソースコード(C言語)をアーキテクチャ分析ツールLattixにより、その構成要素(ファイルやディレクトリ、関数等)間の依存関係を分析し、LattixWebで表示したDSMです。(LattixWebはLattixプロジェクトデータをダッシュボード形式で表示可能なWebアプリケーションです。)
全体構造の把握(図3-a)や、特定サブシステム同士の依存関係の詳細(図3-b、図3-c)など、俯瞰的な視点で様々な粒度の要素同士の依存関係を把握することができます。レイヤーをまたぐ逆方向の依存関係の存在やその詳細を把握したいときなどにも活用可能です。

図3-a Apache httpサーバーのDSM

図3-b 選択したサブシステム間の依存関係を表示

図3-c 階層構造表示により特定サブシステムから特定ファイルへの依存関係を表示

【step2】アーキテクチャのルールを見える状態にする

設計意図を十分に理解せずに変更をしてしまい、意図せずアーキテクチャを壊してしまうことは、誰にでもあるミスです。

Lattixでアーキテクチャルールを設定すれば、普段から誰でもアーキテクチャルールが見られる状態にしておけるので、設計意図に沿ったアーキテクチャルールが開発現場に浸透していき、アーキテクチャを保つのに役立ちます。

結果として、設計と実装を一致させる意識が向上し、変更時にレイヤーをまたぐ循環依存などによる広範囲への影響から発生するテスト増大やデグレードの防止に繋がります。

【step3】新しくルール違反が出た際に迅速にフィードバックする

Lattixでアーキテクチャルールを設定できたら、LattixWebにプロジェクトをアップロードしましょう。
以降はデイリー、もしくはウィークリーでのビルド時にLattixによる検知をおこない、新たなルール違反が発生した場合には迅速に開発メンバーにフィードバックしましょう。

このプラクティスにより、テスト工数の削減や設計手戻りの時間短縮はもちろんのこと、放置した場合に発生が予見される「構造崩れによる意図しない箇所への影響」などのデバッグ工数や修正工数も削減することになります。

新たなルール違反が発生した場合の対応

新たなルール違反が発生した場合には、次の2つのいずれかの操作を行います。

  • 該当の依存関係を見直し、修正する。
  • アーキテクチャルールを見直し、修正する。

たとえば組込みソフトウェアでは、割り込み処理のように、どうしても避けられない逆方向の依存関係が存在します。このような場合は、レイヤー間では逆方向の依存関係の禁止ルールは維持しつつ、例外ルールを設定することで、以降ルール違反とはしないように設定することができます。

もし、新たなルール違反を挿入してしまった場合は、該当の依存関係を入れずに済むように実装します。
以下に対処する場合の一例を示します。

  • グローバル変数を定義する箇所をその想定スコープに合わせて変える。
    モジュール内部でしか使用しないグローバル変数は該当モジュールの内部に配置する。システム直下に全部入りグローバル変数ファイルを作成しない。
  • データの渡し方を工夫する。
    グローバル変数で渡さないようにする。ただし、1つ1つの変数アクセスに対処しようとすると、木を見て森を見ずの対応になりがちとなる。コンポーネント間のデータ受け渡しの機構(メッセージングの機構(Pub/Sub=Brokerパターンやファイル渡しなど))を作ることでコンポーネントそれぞれの独立性を高め、疎結合にする。
  • 抽象化する。
    具象モジュールに依存させない。
  • ラッパーを挿入する。
    関数名や引数の変更の影響を吸収でき、モジュール間の結合を弱めることができる。
  • モジュールにprivate/publicなヘッダーを分けて作成し、モジュール外からはpublicなヘッダーのみインクルードして使用する。privateなヘッダーへの依存はルールで禁止する。
  • 依存関係逆転の原則に従い、直接の関数コールをやめる。
  • ファイル名やディレクトリ名に”Common”や”Lib”など拡張解釈可能な名称(抽象的な名称)は避ける。
    どうしても使用する場合も”StackHandlerCommon”のように機能範囲を限定して細分化する。さらに可能なら、”XxxYyyCommon”(名称の抽象度が高い)の代わりに”XxxYyyUtil”や”XxxYyyHelper”(名称の抽象度が低い)など使用目的が明確なモジュール名にする。

 

Lattixとは

アーキテクチャ分析ツール「Lattix」はJAVA, .NET, C/C++などで開発されたソフトウェア、UML/SysMLなどのモデルについて、これらを構成する要素とそれらの依存関係を、DSM(Dependency Structure Matrix)と呼ばれる手法により、直感的でわかりやすい表形式(マトリクス)で可視化します。また、Lattix製品群の1つであるLattixWebは、Lattixプロジェクトや各種レポートなどをWebダッシュボードにて共有・表示するWebアプリケーションです。リポジトリ機能を持つため、バージョン間の影響差分や複数バージョンにわたるプロジェクトの傾向を把握することが可能です。
Lattixは、ソフトウェアアーキテクチャ理解を容易にし、ソフトウェア開発の効率化、品質の向上と安定化を実現します。

まとめ

保守性品質低下の氷山の一角である、「不吉なにおい」や「技術的負債」は、言うなればソフトウェアの”カビ”です。後回しにすると、デグレード発生やデバッグ工数、修正工数、テスト工数の増加を招き、何倍もの工数となってはね返ってきます。しかし、早めに対策することで問題が小さいうちに、つまり少ない工数で対処可能です。
本記事では対策の実現方法として、CIに組み込みことで早めにフィードバックすることの重要性をお伝えしました。
Lattixを使用して、アーキテクチャの見える化を行い、保守性品質の意識向上や設計違反の早めのフィードバックに取り組みましょう。