仕様と実装の違い @Tomofiles
目次
はじめに
こんにちは、Tomofilesです。
この記事は、技術的なトピックの周辺でよく登場する、仕様と実装の違いをしっかり認識して、物事を考えられるようにしよう、とオススメするものです。
IT業界の様々なテクノロジーやシステム(仕組み)は、すべてが仕様と実装という2つの視点で語られていると言っても過言じゃないと、私は考えています。
つまり、この視点を持っているかどうかで、まだ知らないテクノロジーの吸収力の向上や、ピントが合ったアウトプット(仕事など)につながります。
この記事が、日々勉強をし続けなければいけないエンジニアの、モチベーションアップにつながれば幸いです。
コンピュータの世界は仕様だらけ
そもそも、コンピュータの世界は、仕様だらけです。
有名な例が、コンピュータ間通信の理論モデルであるOSI参照モデルです。
コンピュータとコンピュータの間において、ある情報を通信して交換する際に、7つの層(レイヤー)に考え方を分割して整理したものがOSI参照モデルです。
初心者エンジニアでも、名前くらいは聞いたことあるかもしれないですね。
実はこのOSI参照モデルは、実際にコンピュータ間の通信を行うことはできません。
通信方法を取り決めたものであることには変わりないのですが、ルールを取り決めをしただけなので、そのルールに則って活動する人がいて初めて、実際に通信が可能になるのです。
つまり、IT業界のテクノロジーの中には、ルールの取り決めばっかりするヤツがいる、ということです。
誰かが統一されたルールを決めるっていうのは結構重要で、自分がこのルールに従って動くことで、同じようにルールに従って動く相手と、価値を共有できます。
スポーツにおけるルールと一緒で、プレイヤー同士がルールに則ってプレーすることで、お互いにエキサイトできるってことですね。
決められたルールは仕様として、何らかの標準化団体が標準仕様としてアーカイブします。
例えば、OSI参照モデルなら、国際標準化機構(ISO)という組織です。
こういう団体に認めてもらうことで、広くいろんな人が標準仕様として認識して利用されるようになるのです。
ソフトウェアに限らず、ハードウェアも含めて、コンピュータを構成するものは、ほぼすべてにおいて仕様が定義されています。
RAMのようなコンピュータの部品も、ハードウェアとして仕様が決まっているので、みんな同じ仕組みで作られます。だからこそ、互換性が生まれるので、同じ仕様の製品なら、何でも交換できるということなのです。
インターネットを構成する仕様
OSI参照モデルは、本当に大雑把で抽象的な概念しか定義していないので、OSI参照モデルに(基本的に)準拠して、もっと具体的な仕様に落とし込んだものに、TCP/IPという仕様があります。
乱暴に言ってしまえば、OSI参照モデルを拡張したものがTCP/IP、というイメージで、同じく仕様として標準化されています。
TCP/IPは、2つの仕様をまとめた総称です。
IP(インターネット・プロトコル)と、TCP(トランスミッション・コントロール・プロトコル)の2つですね。
Internet Protocol - Wikipedia
Transmission Control Protocol - Wikipedia
超簡単に説明すると、
- IP : IPアドレスを頼りに、パケット(意味あるデータの最小単位)を宛先まで転送する仕組み
- TCP : IPをベースに、データ転送の信頼性を確保する仕組み
という感じになります。
これらは、それぞれOSI参照モデルの7つのレイヤーにおける、ネットワーク層とトランスポート層にあたるものです。
そろそろ難しくなってきたんじゃないかと思います。わからなければ、今は理解する必要はないです。
重要なのは、
- IPによって、世界中のルーター同士が接続されて、パケットが転送されて、たとえ地球の裏側でも到達できる
- TCPによって、通信相手のコンピュータとのデータの交換が確実に行われて、途中で紛失したりしない
という世界観を構築しているということです。
これが、現在のインターネットの仕組みです。
仕様を実装するということ
ここまで見てきたインターネットの仕組み、TCP/IPは具体的にどのように実現されているのでしょうか?
正直、私だったり、初心者エンジニアのような方は、ネットワークエンジニアでも目指さない限り、そこまで深い知識は必要無いです。
必要になったら勉強するで、構わないと思います。
(このスタンスは非常に重要で、自分で優先度を考えて、勉強するものを決めていったほうがいいです)
さて、簡単に説明していきましょう。
この、インターネットの仕組みは基本的に、
- IP : 市販のルーター
- TCP : 市販のコンピューター
というふうに、市販品に実装されています。つまり、メーカーが作っちゃってるんですね。
だからこそ、誰もが簡単にインターネットに接続できるので、これだけ当たり前に使われるインフラになったのです。
ネットワークに強いエンジニアは、この市販品を組み合わせて、セキュリティーの高いネットワークなど、目的を持ったネットワークが構築できます。
この話で重要なのは、仕様に則った実装品を作るというのは、正確さが求められるということです。
せっかく性能の良いルーターを製品化するとしても、ルーターとしてのIPの仕様に違反していたら、その製品はルーターではありません。
つまり、確実に仕様に則る必要があるのです。
市販のコンピューターも同様です。TCP/IPの仕様に準拠していない限り、インターネットの価値を享受することはできません。
仕様という誰もが享受できる価値は、実装者の確実な準拠があって初めて、目に見える形で実現するということですね。
仕様と実装の違い
さて、ここまで細かく見てきましたが、改めて仕様と実装の違いを整理してみたいと思います。
-
仕様
- 本当に実現したいこと→目的を持って取り決めしたもの
- 取り決めしたことをみんなで共有して、共通の価値にする
-
実装
- 仕様を正確に準拠して、動作するプログラムを作成すること
- 仕様を満たしていれば、実装方法はいくつあっても良い
- 次第にコスト面がフィーチャーされていく
こんなところでしょうか。
この仕様と実装という2面性は、IT業界におけるテクノロジーを語る上で、重要な視点になります。
多くの言語・ライブラリー・フレームワークは、仕様と実装の両面を持っています。
良い仕様は広く他の言語・ライブラリー・フレームワークに取り入れられて標準化していきますし、良い実装をしているライブラリーは、信頼され、省メモリ・省通信量・省容量などの異なる特徴で選択されることになり、広く普及していきます。
そのため、何か新しいテクノロジーを学習しようとする際は、仕様面と実装面の両方の視点からのアプローチして、理解しようと取り組むことが重要です。
しかし、基本的に最初のうちは、実装面のメリットしか見えません。
実装面から仕様面へ
例えば、Websocketという技術があります。
Websocketはクライアントとサーバの間の双方向通信を実現する仕組みです。
インターネットは、基本的にWorld Wide Webという考え方で構築されており、HTTPを基本のプロトコルに、JSON等の構造化されたデータを、URLを識別情報として、情報を交換することで成り立っています。
つまり、シンプルに一つのデータを送信して、一つのデータを返却してもらい、通信終了という仕組みが、すべての基本となるのです。
Websocketは、この基本だけではどうにもならない、連続した一時的な情報(ストリームデータ)を扱うのに特化した、通信プロトコルになります。
基本(WWW)に対して、例外・亜種・裏技のような存在が、Websocketなのです。
WebsocketはブラウザのJavaScriptにAPIが用意されていますし、各プログラミング言語にもWebsocketクライアントライブラリーが提供されているので、それらを使用することで簡単にWebsocketを使用したアプリケーションが構築できます。
しかし、これだけでは、仕様と実装における、実装面の理解・把握しかできていません。
ウェブの世界に、どうして双方向通信という機能が、Websocketという変な名前がついて、語られているのか?
そこを深堀すると、WWWというインターネット上に構築されている情報通信の考え方(仕様)が見えてきますし、Websocketというのが実は異端児だというのが見えてくるのです。
Websocketの例は、あくまで一例でしかないですが、テクノロジーはこのように、別のテクノロジーと関連していますし、別の何かを補うように増築する形で登場したものだったりすることが多いです。
ぜひ、このように、何らかのライブラリー・フレームワークを学習する際は、仕様面(目的・経緯など)を意識してみてください。
世界が広がりますよ。
ウォーターフォール型開発の罠
ここまで、テクノロジーにおける仕様と実装の2面性を見てきました。
重要なのはここからなのですが、私や初心者エンジニアのような(もしかしたら)SIerでエンジニアとして従事している方は、参画したプロジェクトは基本的にウォーターフォール型開発を採用しているかと思います。
ウォーターフォール型は、世間では色々言われる開発手法ですが、根本的に間違ったものではありません。ちゃんと効果的に運用すれば、期待する成果は発揮されます。
(何を期待しているかによりますがね)
ウォーターフォール型は、要求定義、外部設計、内部設計、コーディング、テスト、運用、という感じで構成され、トップダウンで水が流れるように進んでいくことから、そのように呼ばれています。
ウォーターフォール型は、基本的に長期スパンで推進していくことから、変化に柔軟に対応できないという弱点があり、現在はアジャイル型開発手法と、状況に合わせて比較・選択されます。
初心者エンジニアが新人としてプロジェクトに参画するときは、このウォーターフォール型の製造工程や試験工程から入ることも多いかと思います。
そこでは、設計書の書き方や、設計書通りソースコードを記述し、試験を行ってレビューをしてもらう、というのが、一般的な作業では無いでしょうか?
新人の頃は、このような仕事の仕方を覚えるというのは、重要ではあります。
とにかく、自分の与えられた役割を完遂し、プロジェクトに貢献する感覚をつかむことが必要です。
ですが、できるだけ早いタイミングで気づかないといけないことがあります。
それは、ウォーターフォール型開発手法もまた、仕様の一つであり、我々エンジニアは、一生懸命、実装を行っているということです。
なんのためにウォーターフォール型開発手法などというものが存在するのか?
考えてみてください。
ソフトウェア開発というのは、長い年月(それでもここ50年ほどの歴史しかない!)を掛けて、様々な開発上の課題・問題にぶち当たって、それをなんとか乗り越えてきたという、歴史があります。
そんな中、そういった先陣のスーパーエンジニアたちが、叡智を結集して、誰でも、どんなプロジェクトでも、深刻な課題・問題を回避して、ある一定の品質を保った成果物を作成することができるという、フレームワークにまとめ上げたものが、ウォーターフォール型開発手法なのです。
そのような目的で作られた仕様(ウォーターフォール型開発手法)は、正しくルールに則って、正確に実装(設計書・製造・試験・レビュー)を行わないといけません。
ソフトウェア開発を委託された側としては、ウォーターフォール型開発手法を採用していると宣言するだけで、一定の品質を担保していると顧客に宣言していることと同等なので、品質の証明に対して非常に便利です。
ですが、実際にウォーターフォール型開発を実現するエンジニアたちは、ルールにがんじがらめにされて、活動には正確さが求められ、クリエイティブを発揮することができなくなります。
そのため、実装面のクオリティーを上げることだけにこだわっていると、その先に待っているのは、代替可能性とコスト(金額)での評価となってしまいます。
そろそろ皆さんの耳が痛くなってきたかもしれないですね。
でも、「とにかく人を集めてください・切ってください」と「もっと安く作れませんか」という交渉との戦いが、実装型エンジニアの行き着く先だということを、覚えておいてください。
仕様・実装両型エンジニアのススメ
もちろん、人がどんな道を進もうが自由ですが、私が8年ほどSIer業界でITエンジニアを経験してきて気づいたことは、実装型エンジニアはあまり楽しそうに仕事をしていないということです。
基本的に仕様は自分のテリトリー外から発生するものだと考えているので(それに、自分が下手に仕様を作って、責任を負いたくないという傾向も)、発生した仕事を正確に地に足がついたやり方で、実行していきます。
信頼性があって頼もしいですが、私のようにちょっと色々考えちゃうエンジニアから見ると、明らかに変な仕様でも正しく実装しちゃうので、仕様を検証して改善するような状況が発生しにくく、はたから見てやきもきすることが多いです。(もちろん、技術力はあるので、勉強になることがあるのは、確かです)
そんなSIer界隈でも、一つだけ身の振り方をオススメするとしたら、小さくて、新規開発で、継続して改修を行いそうなプロジェクトに参画することです。
あまり無いですが、大手SIerの中でも、先行投資で新しい領域に小さく参入することもあるので、そういうところを狙ってみる。
こういうところは、あまり資金が無いので、贅沢なウォーターフォール型開発ができず、つまみ食い(最低限必要な工程だけ)になります。 このウォーターフォールの解体が重要で、ガチガチに固まったフレームワークの部分抽出をするということは、フレームワークの目的を理解してから行わないと意味がありません。
私も最初のうちは、目的を意識せずにやっていたので、課題・問題が大量に出て、品質が上がらないという状況に直面しました。
ですが、次第に、各工程で最低限決まっていないといけないことが何であり、その情報を如何に表現して、後ろの工程に引き継いでいくか、という視点を持つことで、徐々にフォーカスが合った開発ができるようになりました。
つまり、重要なのは、設計書を作ることでも、テストケース表を作ることでもない、その中身・目的であるということです。
なので、初心者エンジニアの皆さんには、実装型の仕事をいち早く覚えて、その上でウォーターフォールの解体を経験してみてください。
チームでソフトウェアを開発するということが、どれだけ難しくて、どれだけ楽しいものか、わかるようになると思います。
おわりに
今回は、仕様と実装の2つの面から、いろんな物事にアプローチしましょう、というお話でした。
実装面の仕事ももちろん大事なのですが、そういう正確さを求められる作業の中でも、仕様的な面からのアプローチは重要となります。
例えば、ある画面機能を担当することになったとき、あなたはまず、どんなことを考えますか?
- 設計書ってどうやって書けば良いのかな?
- ソースコードレビューで誰々がOKって言ったから、(自分が中身に自信がなくても)、OKだよね
- 設計書に書いてないけど、ここでエラーが発生したら、メッセージダイアログでエラーコード出したほうが良いよね
こんな感じの仕事をしていると、危ない兆候です。
そもそも要件をちゃんと聞いていくと、その画面自体がいらない可能性だってあるんです。
つまり、この画面機能が必要だって結論が出て、自分の元まで話が降りてきた経緯って、ちゃんと自分の中で消化できてますか? ということです。
それに、ソースコードに関しても、自分でロジックの目的と妥当性を説明できて、広く認めてもらうことで、OKとなるイメージを持つことが大事です。
エラーについても、コーディング時に勝手にエラーメッセージを作り上げてはいけません。
ユーザーに伝えるメッセージは、伝えた後のユーザーの具体的な次のアクションを想定して、決めないといけません。
わかりますかね、この危ない兆候のニュアンスが。
今、自分がやっている作業の裏側(本当はすぐ真横)には、そのようになった経緯と目的があるんです。
往々にして、そういった経緯と目的は、きれいにフォーマット化された要件資料を作る段階で、抜け落ちてしまい、下まで降りてこないことが多いのですが。(それか、そもそも考えていない)
逆に言うと、自分の仕事に対しても、経緯と目的を意識して、自らの考えを口で説明できて、それらを目に見える形で表現し、みんなに共有することができれば、理想的です。
ぜひ、この記事を読んで、自分の普段の仕事と比較して、取り入れるべき内容だなと感じたら、取り入れてみてください。
どんな作業が仕様的アプローチが必要で、どんな作業が実装的アプローチが必要か、意識して考えるだけでも、かなりの違いがあります。
それでは、今回はこの辺で。