[開発プロセス#3]プロセスから何を実現したいのか?

一連の記事は「開発プロセス」というカテゴリを設定することにします。

1つ前の記事は、現在の開発ではアジャイルが前提である、あるいは勝手にアジャイルになるということも多々あるということで、アジャイルのプロセスに少し踏み込み、そこでドキュメントは不要なのではなく、いかに負荷をかけずにドキュメントを作るかという視点が必要であるということを説明しました。

実際にシステムを作る場合、当然ながら最初は100点を目指して作りますが、それを実現するためのいろいろな品質基準があります。例えば、ISO/IEC 25010:2011を基にしたJIS 25010:2013などがあります。製品品質モデルの上位カテゴリを見ると、機能適合性、性能効率性、互換性、使用性、信頼性、セキュリティ、保守性、移植性という項目が並んでおり、これらを一定以上のレベルで実現することで、品質を確保することにつながります。つまり、品質を高めるために具体的に何を行うのかを検討する材料はすでに工業規格となっています。

最近ではWebアプリケーションやスマホで稼働するアプリケーションを作る機会は多くなっています。開発時には、機能適合性、性能効率性、使用性という点について、すべての開発に関わる人が多少なりとも意識しやすところです。これらに関わる内容は、開発を進める上で、常に話題としてチームの中に流れ、また、チェックもされるということになります。信頼性は最も重視されることであるのですが、対策を具体的に行い結果をきちんと出すのはなかなか難しい領域でもあります。一般論で進めた結果、完成したシステムが不安定だったということは多くの開発関係者は体験しているでしょう。セキュリティや保守性は、どちらかといえば、当たり前的な意識がまずあって、場合によっては「常識」ということで、議論されない可能性もあります。極端な例ですが、システム請負会社はセキュリティ対策は仕様に入れなくてもやっていて当たり前という判決も出ています。当たり前なので議論の俎上に上がらないというのは、実は誰も気づかず、あるいは気づいても実装はしていないということにつながります。セキュリティへの注目が集まる一方で、臭いものには蓋をする的な意識が共有化されていないでしょうか? また、保守については、初期開発ではそこまで頭が回らないという切羽詰まった状況も日常化していないでしょうか。

機能や仕様を考える上で意識に上りやすい「機能適合性、性能効率性、使用性」、重要性は意識しているが実現が難しい「信頼性」、いくぶん消極的な方向に行きがちな「セキュリティや保守性」という傾向があるように感じます。「互換性、移植性」については要件や利用状況に絡むことであり、他の項目と傾向が違うように感じます。信頼性については、様々な手法やプラクティスがあることもあって、マネジメント上で注力すれば、それなりにやり方はある方法です。こうした分類から、セキュリティと保守性にテコ入れが必要なのではないかと考えます。

現在、多くの開発は保守開発である事は、多くの人が指摘するところです。IT関連費用のうち、運用コストが45%、新規開発24%、保守開発31%となったという調査もあります。開発関係者と話をしていても、実際、データベーステーブルがないところから開発ができるような機会はあまりなく、誰かが昔作ったシステムの改修といった仕事が増えていることが話題になります。また、従来からの開発手法では、新規開発と保守開発は明確に「契約」段階での分離があったかもしれませんが、アジャイル開発や、あるいは顧客のニーズが変化するような場合は、現実には初期開発の途中からでも保守開発の側面が強くなります。

事実上保守開発を普段から定常的にやっているのだとすれば、機能実装をスムーズにする仕様書という考え方に加えて、保守開発、つまり改変する箇所が明確になるような仕様書である必要があると考えます。そのためには、抽象度の低い具体的な機能のモデル内での明確化と、フレームワークやライブラリを利用する前提の上での境界線の明確化であると考えます。抽象度の高い記述方法で、自由に実装をしてしまうと、別の人がモデルを見たときに大まかなコンセプトは伝わりますが実装の上で考えたことはコードと突き合わせて解析しなければなりません。また、フレームワークの機能をどこまで利用しているのかが明確でないと、フレームワークの仕組みを保守するのか、独自に作ったプログラムを保守するのかも、やはりプログラムを読み解かないとわからないことになります。この点を踏まえて、どのようなドキュメントを作るのかを考えます。

なお、前述のJIS 20010では、保守性の項目に対する細目として、モジュール性、再利用性、解析性、修正性、試験性が挙げられています。「モジュール性と再利用性」は、適切な設計かどうかという点に大きく依存しますし、「試験性」も試験が可能なように作ってあるかどうかという点に依存します。一方、「解析性、修正性」について、開発プロセス上でより重視できるような仕組みを組み込むというのが大きな目的です。

保守開発の最も大きな問題点は、目の前で動いているコードしかないという状況で、改良にかからないといけない点です。また、巨大な既存システムの全貌はわかりません。全貌がわからないと保守できないというのは却下されべき言い訳としか理解されません。わからないけど改良しないといけません。その場合でも、改修対象の機能に絞って初期開発と同様のモデリングをすべきです。ただし、変更結果の波及範囲は検証すべきでしょうし、不明な箇所の扱いにも配慮は必要です。ここで、ドキュメントを書いている時間がないとか、費用がないといったことが言われて、それでもなんとかしたいという要望があることも事実です。時間や費用がなくても、最低限のドキュメントを揃えることが、まずは改修箇所の把握には必要です。その場合は、ボトムアップに解析をして、関連するデータベース内部のスキーマからER図を作ったり、特定の処理に限定してクラス図を作るなどすることで、効率化は図れます。一連の説明では、困難な場合でドキュメントは作るという前提で話を進めます。

次回から具体的に何を作ればいいかということを説明します。

[開発プロセス#2]何のための何を目指したプロセスか?

開発プロセスにおけるアーキテクチャ設計として先日記事を公開しましたが、継続して記事を続けるにあたって、ヘッダに [開発プロセス#N] (Nはシリアル番号)を入れることにします。前回は大まかな話でしたが、今回は検討する開発プロセスの目的を定めます。今回は、当たり前の話ばかりだと思います。

開発において、いきなりプログラミングすることはまずないと思いますが、何らかの検討を経て実装に入ります。実装なくしては当然ながら完成しないので、実装、すなわちプログラミングは開発の中心と思われているかもしれません。しかしながら、実際に開発経験があると理解できることは、事前に検討して問題解決していることと、実装しながら問題解決に当たるのとでは、前者の方がはるかに効率的であり、出来上がったコードの質が高くなるということです。「仕様書をちゃんと書けよ」ということになる一方、仕様に関する成果物に労力をかけないまま実装に入ることもあります。これらの上流工程にどの程度時間をかけて、どの程度の成果物を得ればいいのかということの議論は昔から今に至るまで、そしてきっと未来永劫続くことと思います。ウォーターフォール形式など、開発プロセスが決まれば、1つのプロセスの終了と、検討結果に関する成果物とが対応することになり、いわば自動的に仕様書を書くことが前提になります。一方、仕様書を記載したり、あるいは変更結果を反映させる作業は決して小さな負荷ではありません。アジャイル開発のように、完全な仕様書を書くよりも動くコードを書くことを優先させる手法も出てきている一方、このことを都合よく解釈して「アジャイルはドキュメントは書かなくてもいい」と決めつける人たちがいることも事実です(アジャイル勘違い集#3)。しかしながら、こうした決めつけが出てくる背景には、設計の成果物の労力に見合う結果が得られるのかという懸念があるのではないでしょうか。

実装に入るまでのプロセスを重要視し、仕様書を作るという立場は崩しません。しかしながら、アジャイルソフトウェア宣言には「包括的なドキュメントよりも動くソフトウェアを、」とあります。包括的な、すなわち完全なドキュメントでないけども、設計する上で考えたアイデアや制約などがドキュメントとして参照できる必要があります。ではコードをしっかり書けばいいという考え方もあります。Googleへの注目が増大される時代に、「Googleでは仕様書ではなくコードを見る」のだというイメージが定着し、ここでも勝手な解釈になるのでしょうけど「仕様書はなくてもすごいシステムは作れる」と思ったと考えられます。また、コードは常に最新であるという主張は間違いはありません。しかしながら、コードはコードであり仕様ではありません。コメント欄に記述できる内容も限られていますし、コード上で明示的ではないあるいはその真髄に迫るには時間をかけて解析しないといけないような様々なノウハウが実装には注ぎ込まれているはずです。コードで仕様に関するコミュニケーションがとれるとしたら、その内容に精通したプログラマ同士だけでしょう。オープンソース開発では、コミッターの時間的制約などでそうした状況になりがちであり、単体テスト等のテストを自動化することと組み合わせれば、十分にワークする方法であることは多数のオープンソースプロジェクトから言えるのではないでしょうか。しかしながら、コードを読み解くということは、時間をかけて解析したプログラマ以外に可能かというと、ほぼ無理でしょう。顧客や発注側はそこまではしない、あるいはできないでしょう。「しない」理由は、それをやるくらいなら自分で開発できるから発注しないからです。プロジェクト管理者、あるいはユーザーテストの管理者、導入教育担当、こうした開発に関わる様々な人が、プログラマ並みにコードを読むことができるかといえば、能力的なことだけでなくビジネスに直面するコストの問題でできないと言えます。

受託開発では顧客の要望がコロコロ変わるようなことは普通にあり、これは「消極的なアジャイル」とも見ることができます。追加の開発に対しても費用が出ないことあるのに、ドキュメントの更新に追加の費用を請求する雰囲気は現場にはありません。こうして「使えないドキュメント」が山積みされることになるのですが、その使えないドキュメントでも、過去のある時点をキャプチャした情報として活用せざるを得ない場合もあるわけです。

こうした現在の開発プロセスにおいて、成果物として何が求められるのかを再考するのが、一連の[開発プロセス]記事の1つの大きな目的です。すなわち、ドキュメントに記述されることを、ドキュメントに対する負荷を可能な限り最小化したプロセスとして再考するのが目的です。以下、まとめてみました。

  • 仕様書は作成する必要がある。特に強くコミットしているプログラマ以外のコミュニケーションにはなくてはならない。
  • 仕様書が膨大になると、更新が滞り、最新の結果が反映されなくなる。仕様の変更に対してドキュメントの更新は必要だが、その負荷を最小化したい。

この次は、開発されるシステムがどうなることを意図しているのかということを記載します。こちらの方が先に記載すべきかもしれませんが、目的の話題が何度か続くとういうところです。

開発プロセスにおけるアーキテクチャ設計

INTER-Mediatorに適した開発プロセスを考えていましたが、うまくまとまりません。なんでかなと考えたのですが、INTER-Mediatorを使うという前提なしで考えるべきであり、それを元にINTER-Mediatorへの適用をする必要があると考えます。つまり、一般的な意味でのWebアプリケーションだとかスマホアプリといったものを開発するときに、どんなアーキテクチャが前提となり、設計上何を考えれば要求・要件から実装に近づけるのかという一般論をまずはまとめるべきなのでしょう。最近、たまたま、いろんな仕事の中でアーキテクチャ関連の話題の基本を再勉強する機会があり、その中で一般論になんとなく近づいている感があるので、いっそのこと、考えながらブログでまとめていくという過程で進めようかと考えた次第です。

システム開発では、要求や要件を出発点として、仕様を策定して実装に持ち込みます。外部仕様、内部仕様という区分けがある場合もあります。また、データベースを使う場合は原則としてレイヤー構造になり、データベースが底辺を担うことからドメイン分析した結果をスキーマとして記述して、実装段階では確定したデータベース定義にすることになります。こうした、設計の定石とも言えることはたくさんあり、特定の開発チームや流派、カルチャーに応じてその表現は違うものではありますが、システムを意図した通りに稼働させるという意味では目指す方向は同じであり、場面によって言い方が違うだけの場合もよくあるわけです。一方、様々なノウハウがあるものの、ある要件を満たすようにシステムを作る場合の実装に向けた機能分解は、単一の答えが存在する問題ではありません。同程度に正しい解答はいくつも作れるでしょう。結果的に、「状況に合わせて最適化する」というなんとでも取れるようなアドバイスしか出てこないことにもなりかねません。しかしながら、機能をどのように分解して、それぞれの個別の動作をどのように実装するのかということが、開発の上では非常に重要な決定であることは言うまでもないことです。ベテランや才能のある人は、そういうことをスラスラとできるのかもしれませんが、初心者あるいはある領域の経験が浅いと悩むものです。手っ取り早く知りたいという要求は年々高まり、「ベストプラクティス」や「ティップス」といった情報が重宝されるようにもなります。

こうした設計を完成させるに至る知見は、例えばオブジェクト指向分析や、コンポーネント分析、パターンなど、様々な手法があります。それらをうまく束ねた統一的な開発手法も多数存在します。私が考えていることは、そうした開発手法の1つを作り上げることであり、その結果をもとにして、INTER-Mediatorでの開発手法を確立するということです。車輪の再発明っぽく見えるかもしれませんが、問題点を検討すると、やはり時代に応じた道具に対応した手法はその都度更新されていくものではないかとも考えられます。

現在の様々な開発手法が発展したのは、オブジェクト指向プログラミングが当たり前の時代になり、コンピューターの性能が高まり、そしてインターネットで世界中が繋がって、Webという基盤ができた頃の時代です。一方、現在はスマホ登場やフロントエンドの発展が著しく、サーバー単体での開発手法以上のものが求められています。従来はWeb開発とネイティブ開発、つまりOSのAPIを直接利用する開発は、大きく違っていたのに対して、現在は言語やフレームワークは違っても同じような実装をしているという感覚があります。この領域で業務をしている人は薄々気づいていることではないでしょうか。これは、何か共通のアーキテクチャを持ち込むべきではないかと考えました。まずは、そのための問題意識として持ったことを箇条書きにします。

  • Webシステムはサーバー中心なのは仕方ないとしても、クライアント側のアーキテクチャをどう表現するのが適切だろうか?
  • スマホアプリはサーバー接続する場合が多く、「サーバー側」「スマホ側」という2つのアプリケーションの連動を行っている。最近のWebも「スマホ側」が「JavaScript処理」に置き換わるだけの違いとも言える。つまり、今時のシステムは、サーバーサイド、クライアントサイドを統合的に議論できるアーキテクチャを基盤として持つ必要があるのではないか。
  • コンピューターが速くなり、メモリーも豊富になると、RDBである必要性は薄くなる一方、やはり安定した保存はRDBが理解しやすいとも言える。RDB前提のシステム設計はある意味安定するのだが、逆に必然としてRDBが出てくる理由付けはないのだろうか?
  • サーバーサイドのアーキテクチャはともかくMVCである。いろんなMVCが存在する一方、正しいとか正しくないとか、本物だとかそうじゃないという議論があるものの、MVCは大雑把な機能分類として考えれば、役立つ場面は多いのではないだろうか。
  • クライアントのアーキテクチャはMVCなのだろうか? 違うのだろうか? クライアントサイドの主要な機能はUIの運用とその高度化であるとしたら、MVVMがいろいろな意味で包括性の高いアーキテクチャではないだろうか? ただし、バインディングとオブザーバーを基調としているだけに、それらを実装していないフレームワークはMVVMとして俯瞰できるかどうかが難しい点であると言える。
  • MVCとMVVMを出発点に考えるとしたら、それらの中での機能分割の指標としては、ロバストネス分析をベースに検討できるのではないか、ロバストネス図の要素はビュー、コントロール、エンティティであり、ほぼMVCのコンポーネントに対応するものの1対1ではない。しかしながら、要件をロバストネス分析して、MVCやMVVMを基本としたアーキテクチャとして表現することは、オブジェクトし志向分析の結果を見ても可能であると考えられる。
  • MVCなどのアーキテクチャパターンで設計しても、実装できないかもしれないし、実装するために変形が必要な場合もあるのかもしれない。過去の様々な設計手法では、汎用化がされる一方で、使用するフレームワークの制約やあるいは特有のコールドポイントの扱いなどが考慮されたものは見たことはない。しかしながら、フレームワークによる制約は可能な限り早期に検討する必要がある事柄ではないだろうか。あるいは、フレームワーク制約を組み込む段階がいつなのかを明確にすべきではないだろうか。
  • サーバーとクライアントの分類はどうすべきだろうか? 最初はそれらは関係なく、要件満たすような必要な処理に分割し、あるところで「線を引く」という作業になるのだろうか? そうすれば、サーバーとクライアントの両方を巻き込むシステムの設計はスムーズにできそうだ。

とりあえず、思いつくまま挙げましたので、ポエムに近づきつつあります。これらの考えを少しずつほぐして、手法として使えるまでにすることが目標です。

(続く)