2018-12-02

個別最適の時代は完全に終わった(ソフトウェア品質のパラダイムシフトについて考える)

サイバーセキュリティのことにクビを突っ込んでいると,ソフトウェア品質の概念が根底から変わったのではないかと感じる。

今や製品にOTSソフトウェア(Off The Shelf Software: 即利用可能な商用ソフトウェア)やオープンソースのソフトウェアを使うのは当たり前になっている。

組込みソフトウェアであっても何十万行にもなるソフトウェアにOTSを使わないケースはほとんどない。OSだってOTSだ。

そして,OTSには長い間使っているとサイバーセキュリティ上の脆弱性が見つかる。ここでよく考えた欲しいのはセキュリティの脆弱性は,ソフトウェアのバグ(欠陥)なのかという点だ。

脆弱性となった時点で修正が必要になるのだから,バグ(欠陥)と言えるかもしれないが,これまでソフトウェア品質の中で語られてきた決定論的原因故障(Systematic Failures) とは違うように思うのだ。

Systematic Failures/Faults  (決定論的原因故障/障害)
  • ハードウェアの設計に起因するもの、ソフトウェアのバグやソフトウェアに起因する問題やユーザーオペレーションが原因で発生する障害発生率の予測が難しい故障/障害
  • 出荷前の検査で発見することが難しく、出荷後に故障や障害が発生してから始めて分かることが多い。
  • 開発のプロセス(工程)、ライフサイクルの中で Systematic Failures/Faults の作り込みを防止し、検証や妥当正確認によって発見・除去する。
上記が決定論的原因故障(Systematic Failures) の定義となるが,脆弱性はソフトウェアに起因する問題ではあるがユーザーオペレーションが原因で発生するわけではない。出荷前の検査で発見することは難しく,出荷後に発生してから分かることが多いというのはそのとおりだが,検証や妥当性確認によって発見,除去できないものもある。

なぜなら,脆弱性は悪意を持ったハッカーが意図的にソフトウェアの穴を見つけて,そこを攻撃し,その悪用が成功すると,そこが脆弱性になるからだ。ようするに,仕様通りに作った設計通りのソフトウェアであっても,悪意をもったハッカーにより「正しく作ったソフトウェア」でも「脆弱性」にされてしまうことがあるということだ。

設計通りに作ったソフトウェアでも後々「脆弱性=欠陥」となってしまうのって,ソフトウェア品質を考える上でのパラダイムシフトではないかと思うのだ。どんなに頑張って信頼性を高めようとしても,ソフトウェアに穴を見つけようとするハッカーがいるかぎり「脆弱性=欠陥」は発生してしまう。これはソフトウェアに完成というゴールは存在しないということを意味する。

組込み機器がIoTの流れに乗って,ネットワークにつながるようになると,ネットワーク越しに脆弱性を攻撃される危険にさらされる。世界の中にいる一流のハッカーやあるいは,各国の軍事組織が意図的に作成したマルウェアは,コピーできたり自分自身が増殖したりできるので,IoT機器がインターネットに接続されていれば,そのソフトウェアが市場に存在し続ける限り,脆弱性=欠陥が発生するリスクがある。リスクが発生する確率は確率論で測ることはできない。ハッカーが攻撃したいと思うかどうかだ。

例えば,ハッカーがその製品の企業に気にくわない対応をされたのかもしれない。有名な企業やセキュリティがが高いとされている企業の鼻っぱしを折ってやろうという気になったのかもしれない。セキュリティインシデントを発生させて,わざと株価を低下させようと企んだのかもしれない。ようするに,悪用の可能性(Exploitability)は従来の確率(Probability)や起こりやすさ(Likelihood)の概念では測りきれないのだ。

米国FDA(食品医薬品局)は,2018年10月に医療機器の市販前のサイバーセキュリティに関するドラフトガイダンスを改訂して,医療機器に搭載されているCBOM(Cybersecurity Bills of Materials)のリストを提供することを求めている。サイバーセキュリティの脆弱性を監視する必要があるソフトウェアやハードウェアを搭載しているならば,それをリストにして提出せよと言っている。

そしてCBOMは NIST のNDB(NATIONAL VULNERABILITY DATABASE)と相互参照することを求めている。

NDBは過去の脆弱性の報告があったソフトウェアやハードウェアが全てデータベース化されている。そこに載っているハードウェアやソフトウェアを使っているならば,それをリストにして提出しなさいと言っている。

そして,市販後の新たな脆弱性が見つかったら,脆弱性を含むOTSを搭載する該当製品に対してパッチを当てるように勧告するのだろう。

ようするに,IoT機器のソフトウェアは,クリティカルなソフトウェアに限らず市販前に完成度の高いソフトウェアを作ってリリースしたら終わりにはならないのだ。これまでも,仕様変更やバグが見つかったら,ソフトウェアの改変を行っていたかもしれないが,仮に市販前に仕様通り作った完璧と思ってリリースしたソフトウェアであっても,製品が市場にある限りサイバーセキュリティの対応が終わらないということになってきた。

サイバーセキュリティは商品の価値としては潜在的な価値に分類される。潜在的な価値は,カタログスペックには出てこないが,セキュリティインシデントが発生することで,その潜在的価値がクローズアップされる。

サイバーセキュリティの堅牢性は当たり前品質であるとも言える。ユーザーにとってはできていて当たり前だが,普通に使ってるぶんにはその価値は見えてこない。セキュリティインシデントが発生したときにはじめて,その価値の重要性に気が付く。製造業者側としては,事前に仕込んでおかないといけない価値となる。

メーカーとしては,そこにコストをかけたくないところだが,セキュリティインデントが発生すると,著しく企業価値が下がり,ダメージが大きいので対処しない訳にはいかない。難しいのは,セキュリティ対策には終わりがないので,どこまでやればいいかの線引きが非常に難しいのだ。だから,市販前の考え方としては,クリティカルな製品においては,セキュリティインシデントが発生したときのユーザーのリスクが許容できるかどうかで判断し,また,過去に発生したセキュリティインシデントが再発しないような対策を積み重ねていく。そして,その対応をしたからといって,製品をリリースして終わりではないという認識を持ってセキュリティに対応する。

ユーザーにとってIoT時代はいろいろと便利なサービスが提供されるという点ではいいのだが,メーカーはその裏でサイバーセキュリティ対策をしないといけない。最終的にはそのコストはユーザーが負うことになる。ユーザーは便利の裏側でセキュリティのコストを払うことになるのだ。どこまでコストをかければいいのかはメーカーが判断しなければいけない。日々コストと戦っている製造業者には頭の痛い問題だ。しかも,ソフトウェアのバグの発見とはまた別の意味で,悪用の確率を予測しにくい「やから」が相手ときている。

さて,ソフトウェア品質の話に戻ろう。これまでソフトウェアの品質の議論は,主にリリース前までにいかにバグを潰すかという論点で進んで来たが,今後は市販後も含めたソフトウェアのライフサイクル全体を考えなければいけなくなってきた。

悪意を持ったハッカーはどんなに完成度が高いソフトウェアであっても(わざわざ,堅牢なソフトウェアの穴を見つけようとはしないだろうが)穴を見つけ出そうとする。そこには悪意があるから防ぎようがない。オープンソースのソフトウェアは便利だからみんな使っているが,脆弱性との戦いは一生終わらないと思った方がいいだろう。ソースコードをオープンにして脆弱性を見つけてくださいと言っているのと同じだからしょうがない。ハッカーがその気になるかならないかは,ハッカーの気分次第なのだ。ちなみに,悪意を持ったハッカーではない,善意のハッカーと称する者は,わざわざソフトウェアの穴となりうる脆弱性を見つけてセキュリティインシデントを発生させてみて「この商品は危ないですよ」とデモンストレーションして,多くの人の注目を浴びたいため?に脆弱性をわざわざ指摘してくれる。(脆弱性を見つけた時点で公表する前にOTSの製造業者にお知らせしてくれるが,製造業者としては脆弱性を見つけてくれない方がうれしいと思うのは自分だけだろうか?)

自動車業界はサイバーセキュリティを多層防御で乗りきろうとしているかもしれない。しかし,本当にそれで乗りきれるだろうか。車載ソフトウェアでもどこかでOTSやオーブンソースのソフトウェアは使われているだろう。ナビゲーションシステムやAIのソフトウェアだって使うかもしれない。ナビゲーションシステムは自動車の制御ソフトウェアとつながるようになるかも知れない。そして,ナビゲーションシステムのソフトウェアに脆弱性が見つかってしまったらどうするのだろうか。脆弱性があっても多層防御しているから大丈夫ですと言い切るのだろうか。

ソフトウェアの場合,弱いところがあることが分かってしまうと,どんなに発生確率が低いと説明しても「直せるのなら直せ」と言われ,直さざるを得ない宿命がある。だから,脆弱性が見つかったら,パッチを当てるしかないのだ。そのためには,ソフトウェアを安全にアップデートするしくみが必要になり,アップデートすることを前提にしてソフトウェアをリリースすることになる。

このことは,「ソフトウェア製品はリリース時に完成しない」時代になったということではないか。リリース時にバグはないかもしれないが,潜在的な脆弱性や未来に脆弱性となってしまうソフトウェアが含まれている状態で出荷せざるを得ないのだ。

このサイバーセキュリティを起因としたパラダイムシフトは,企業のソフトウェア開発の体制にも影響を与える。OTSの脆弱性を監視し,脆弱性が見つかったら対応するための組織 PCERT(Product Computer Emergency Response Team)が必要になる。

そして,ソフトウェア品質はソフトウェア部品の信頼性を高めて,それを組み上げるといったアプローチの有効性が低下し,個別最適から全体最適の時代に完全に切り替わったのだと思う。

ようするに,製品のリリース時点では,サイバーセキュリティの脆弱性は発生するという前提で市販後の対応をする必要があり,商品のリリース時には,対ユーザーリスクをなくすことはできないので,できるだけ小さくすることを考えることが必要になったのである。

これはソフトウェアのテストについても同じことが言える。仕様通りに作っても脆弱性となってしまうケースがある以上,テストがソフトウェアの完成度を確認する手段なら,製品リリース時に完全なテストは実施できないことになる。ソフトウェアは一生完成しないという前提に立てば,完全なテストも存在しないと言えないか。完全なテストを行うことを目指すのではなく,ユーザーリスクが最小になるようなテスト,検証,バリデーションを設計しないといけない。

ソフトウェア開発のおいて,また,ソフトウェア品質向上施策において,ソフトウェア部品の信頼性やセキュリティを個別に高めて結合すれば,システムも安全で,高品質でセキュアであるという時代ではなくなった。

ユーザーに対して商品に責任を持つ組織が,全体最適として商品の安全性や信頼性やセキュリティのリスクを最小限にする方策を考え実施し,そして商品が市場にある限り,ライフサイクル全体でOTSの脆弱性対応を含めたサービスを提供することが必要になってきた。

工場で製品作って出荷することが製造業者のゴールではなくなったということだ。そして,そのサービスのコストが最終的には便利と引き換えにエンドユーザーが負うことになる。


2018-11-28

情報系の論文投稿はもううんざり

ソフトウェアテストシンポジウム2019東京(JaSST'19 Tokyo)に共同執筆者として経験論文を投稿し採用された。

採用されたのは大変ありがたいことだ。素直に感謝したい。

シンポジウムは2019年3月27日(水)~28日(木)に開催予定なので,論文はリアルタイムOSのテストの関することで,論文の詳しい内容については触れられないが,毎度のことながら査読コメントにはげっそりさせられる。

誤字や内容についての指摘はありがたく指摘を受け入れたいのだが,論文の査読コメントはなぜ,匿名なのだろうか。それってなんで隠すのだろうっていつも思う。投稿者は名乗るのに, ※1 査読者は匿名なのはなぜなのか。

※1 JaSST では査読時は投稿者が誰か知らされていないという指摘があったため訂正。

査読者がもしも知り合いだったら失礼になるので変なこともかけないのだが,査読者が誰だか分からないから遠慮すべきかどうかもまったくわからない。だから,失礼かもしれないが,言いたいことを言ってしまおうと思う。

査読者が匿名なのは,おそらく投稿者である下々の者が,偉い先生方に対してコメントに反論するなど,あり得ない。受け付けないというということなのだろう。※2 でも,論文査読時のその上から目線が大っ嫌いだ。査読者がそういうつもりでなくても,査読のシステムがそうなっている。査読者は名乗らない,査読に対する意見は受け付けないというシステムなのだ。

※2 投稿者/査読者 ともに匿名にすることで公平性を担保する意図があるそうです。

そして,いつも「フン」と思うのは,論文の作法に則っていないという指摘だ。「最初に他の研究の問題点や違いが述べられていない」とか「考察が先,結論が後」とか,「参照する他の論文をもっと掲載せよ」といったコメントは,ごもっともなのだろうが,本質的な話じゃないなと思う。

例えば,論文の投稿者はその学会やシンポジウムに観客を呼び込むための大切なネタ元であると考える。そうすると,学会やシンポジウムの主催者や査読者は次もその次も気持ち良く論文を投稿してもらう必要がある。ならば,論文査読コメントは次のような書きぶりにしたらどうだろうか。

【論文査読結果のお知らせ】

 この度は,○○学会に論文をご投稿いただき,まことにありがとうございます。投稿いただいた論文を拝読だせていただきました。
 △△に関する研究は貴重であり,たいへん興味深い内容です。□□の結果はソフトウェアのーーを向上させることのつながると思います。
 なお,ーーの部分については,さらにーーのような掘り下げを行えば,さらなる展開が見られるのではないかと思います。
 :
 非常に形式的な指摘で恐縮ですが,ーーの部分は,ーーのようにした方がより論文として説得力が高まると思われます。また,本論文と同じような研究があれば,読者の参考となるため,ーーのデータベースで関連する論文を検索して,参照論文として掲載してはいかがでしょうか。
 :

 ○○学会にて,本研究のご発表をお待ちしております。また,ーー様の更なる研究と投稿をお待ちしております。

【例示終わり】※査読がコメントがこんな感じになることはあり得ないけど。

ソフトウェアのレビューにレビューワとして参加するときは,できるだけ本質的なことを重点的にディスカッションし,形式的な問題はレビューが終わったあとにこっそり指摘したり,メールでお知らせしたりして,プロジェクトメンバのモチベーションが下がらないように気を遣ったりしている。

それは,レビューではエンドユーザーに対する価値向上につなげるために指摘をするのあって,ルールやシステムへの逸脱を是正することが最終目的ではないからだ。ルールやシステムに従うことはあくまでも間接的にエンドユーザーに対する価値向上につながっているのだということをすっかり忘れるソフトウェアの品質保証担当もいる。ルールを守ることが目的になっているケースだ。そういう組織では現場のエンジニアはゲンナリしていたり,QAとは建て前で接して本音を言うのはやめようと諦めてしまったりしている。

だから,問題を解決したい,改善したい,世の中のためになりたいと思って論文という書き物をしているのに,形式的な指摘はイラッとすることがある。

だから,自分は論文書いて査読コメントを受ける度に,論文ではなく本で勝負したいと思う。自分はアカデミアにはなれない,ならない思う。論文で偉い先生方に評価されるより,本で「役に立った」という評価を受ける方が100倍うれしい。
アカデミアが学生を育てて教え子が社会に貢献するようになるのは,すごくやり甲斐があると思う・・・
ちなみに,アカデミアが論文に関して新規性や作法に関する指摘をする理由を知っている。学位を取るためには,学会で論文を採用されることが必要であり,論文採用の条件として過去の論文との違いや新規性が求められるからだ。

でも,ソフトウェアの品質向上に関する分野で,役に立つか立たないかをさておき,新規性を最重要と見るのには,強い違和感を感じる。仮に,同じような研究や実証があったとしたって,それが現場の役に立つならいいじゃないかと思う。

また,情報系のアカデミアが数学的に検証可能な論理が大好きなのも知っている。例えばフォーマルメソッドなどがその例だ。数式を使って論理の正しさを証明できると,いかにももっともらしい論文になるから,みんな好きなんだろう。

でも,まってくれよと言いたい。ソフトウェアを作っているのはロボットじゃない人間だろって思う。人間の思考や振る舞いは数式で表すことができない。最近流行のAIだって,人間の脳神経系のしくみをシミュレートしているのだ。

だから,情報系の論文はもっと心理学とか人間の行動学を取り入れていいはずだ。ソフトウェアのメトリックスで語りきれない部分に解決策があることも多い。

GD3 コンサルティング代表/JMAC GD3 センター長 の吉村達彦はトヨタとGMはすでにどちらも90%以上の品質を実現できているが,GMがトヨタに数%勝てないのは「品質を心配する意識:Awareness : Worrying about Quality」の違いだと言った。詳しくはこちら

「品質を心配する意識:Awareness : Worrying about Quality」はおそらく数値では表せない。でも,数値では表せないところを解明していかないと,最後の数%の品質は上がらないのではないか。そこをもっと研究しろよとアカデミアに言いたい。

みなさんは「ソフトウェアエンジニアリング論文集 80's」という本を読んだことがあるだどうか。

これが,論文の形式に則った論文か?といったものばかりだ。超有名どころの論文だから許されるのか? いや,論文が主張するべきところが共感できるから,受け入れられているのではないか。

最初に載っている論文はワインバーグの論文で,冒頭で宮本武蔵の五輪の書を紹介している。

論文の書き出しはこうだ

宮本武蔵は,五輪の書の中で次のように書いている。
大きな所は見えやすし,ちいさき所は見えがたし,其子細大人数のことは即座にもとをりがたし,一人の事は心一つにてかわることはやきによつて,ちいさき所しる事得がたし。
「大きなところは見えやすく,小さいところは見えにくい。というのは,大人数でやることは急速に転換できないから容易に捕捉できるのに対し,個人のことはその人の心一つですぐ変化するから分かりにくい。」
ソフトウェア研究者の Barry Boehmは "Software Engineering Economics" の中で次のように書いている。
へたくそな管理は,他のいかなる要因よりもソフトウェアのコストを急速に増大させる。
 :
ワインバーグだから許されるのかもしれないが,論文の作法はまったく無視している。この本に掲載されている論文はどれも「中身で勝負」という内容であるように思える。

ソフトウェアの品質を向上させるためにメトリクスを取るというのもよくあるし,メトリクスに関する論文はよく見る。でも,ソフトウェアのメトリクスを取るにしても,それはプロジェクトメンバーがソフトウェアの品質を改善するためにメトリクスを取ろう!となれば,有効なデータとなるだろうが,いやいややらされている状態で有効なデータが取れないのではないか。

それは,結局,ソフトウェアの品質問題はエンジニアという人の問題に帰着するからではないか。だから,数字だけを追っかけても改善するわけもなく,人の問題も同時に改善する気持ちがないと効果が上がらないのではないか。

人の問題は数字にしにくいし,数学的論文にはならないから,人をテーマにした情報系の論文はほとんど見ない?が,それでは結局のところ,現場の改善にはつながらないのではと思う。

P.S.
人材の育成や現場の改善に尽力をつくしているアカデミアの方々には敬意を表します。
アカデミアの友人もたくさんいるのでこの手の記事書くときには気を遣うなあ・・・

2018-11-01

Raspberry Pi3を使ったリアル波形描画(4) オブジェクト指向設計の必要性について考える

組込みソフトウェアの開発で使う言語はいまだにC言語が多いと聞く。

下記の図は,独立行政法人 情報処理推進機構 社会基盤センターが調査した「ソフトウェア開発データ白書 2018-2019」のデータである。

これによると,開発言語がC言語であると解答した組織が108で,C++と解答した組織81をまだ上回っている。ちなみに,一位はJavaの629である。

今どき gcc ですら,c++ は対応済みなので,C言語を使っているのはコンパイラがC++に対応していないという理由ではないと思う。それは「C言語でできるのに,わざわざC++で作り直す,C++を学習し直す必要あるのか?」という単純な問いに答えられないからではないだろうか。

日本人が英語を学習するのと同じで,言語の習得というのはハードルが高く見えるものだ。実際使いこなせるようになるには,それなりに時間もかかる。

だから,「C言語でできるのに,わざわざC++で作り直す,C++を学習し直す必要あるのか?」という問いに対する答えはちゃんと用意しておいた方がよい。

自分なら「ソフトウェアの再利用率を高め,開発効率と品質向上のために必要で,10万行を超える規模のソフトウェアアプリケーションではオブジェクト指向言語を使わないと自転車操業から抜けきれない。」と答える。

実際,同じ機能のアプリケーションソフトウェアをCPUやOSが変わる度に作り直して問題を作り込んでしまっている例を少なからず見るが,作り直す工数も馬鹿にならない上に,リリースしたあとに見つかった不具合の対応がこれまた大変だ。

ソフトウェアは見えにくいから,ソフトウェアアイテム(モジュール)の再利用率も見えにくい。ハードウェアならば,共通部品を使ってコストダウンを図る取り組みが外から見えるのに,ソフトウェアでは過去に作ったことのある機能のソフトウェアモジュールを新たに作り直しても誰も文句を言わない。

そうなってしまう理由はいろいろある。例えばこんな理由だ。
  • その機能のソフトウェアモジュールがすでにあることを知らなかった。
  • ソースコードはあったが,使い方が分からないので新規に作ったほうがいい。
  • 他人の作ったソフトウェアは使いたくない。
  • 新規に作った方が売り上げが上がる。(派遣や請負のソフトウェア開発)
  • 再利用せよという指示がなかった。
  • OSやCPUに依存している箇所があるので使えない。
そもそも,再利用できるようなソフトウェアとして作っていない場合,確かに再利用は難しい。そういう組織は「再利用」という言葉は使わず「流用」という。再利用することを意図して作ったソフトウェアではなく,たまたまそこにあったものを使い回すのが「流用」で,流用レベルでしか使ったことがないのだ。

そういう組織,プロジェクトではコードクローン(同じようなコードがシステムのあちこちに散らばっている状態)が多い。

数千行のソフトウェアで製品が動いていたころ,青春時代を過ごし管理職になった技術者は「ソフトウェアを再利用しなければもう無理」という感覚にならないかもしれない。数十万行,数百万行まで増大してししまったソフトウェアを前に「なぜ,不具合がなくらなないのか」「どうしてソフトウェアエンジニアはミスを繰り返すのか」と自問し続けて負のスパイラルから抜け出せなくなっているのではないだろうか。

その状態を脱却するには,再利用率の高いソフトウェアを作るしかない。資産価値の高いソフトウェアモジュールを再利用できれば,その組織のコアコンピタンスになるし,信頼性の高いソフトウェアモジュールを何回も再利用できれば,開発効率と品質を同時に上げることができる。

C++を体験してみる。Turtle クラスを作成し,オブジェクトを作る

この事例は絶版になってしまった「C++プログラミングスタイル」,1992/8, 山下 浩 (著), 黒羽 裕章 (著), 黒岩 健太郎 (著) を参考にしている。

C++言語を学習するには「基礎からしっかり学ぶC++の教科書」を読むことをお勧めする。これから先は C++言語の概要は知っているという前提で進める。

オブジェクト指向設計でソフトウェアを作成すると,再利用がやりやすいことを 亀のひな形を例にして説明する。

亀の実態がシステムの中で一つしか使われないならば,亀のひな形であるTurtleクラスを作るメリットはあまりないが,システムの中で亀1,亀2 のように複数使用する際には Turtleクラス を作るメリットがある。

また,オブジェクトを使う側の者は,オブジェクトに対して必要な命令を与えて,レスポンスを受けるだけの方が使い勝手が良い。オブジェクトの中身の複雑なアルゴリズムなどは知らない方が,責務を分担できる。責務を分担して,オブジェクトの責任と権限を移譲するという考え方は,大規模・複雑化したシステムでは有効だし,そうしていかないと数十万行以上のソフトウェアシステムではやってられない。

100万行を超えるようなソフトウェアシステムでは「隅々まで把握している技術者がプロジェクトに一人以上いる」という状態を維持できない。

ということで,Turtle クラスを設計してみる。

1.1 Turtle クラスとは
  • X座標,Y座標,向きをクラスの内部(private メンバ)に持つ
  • 外部からは,左を向く,右を向く,指定距離だけ前進することを指示できる。
  • 外部から,現在のX座標,Y座標,向きを尋ねることができる。

Turtle オブジェクトの利用者は,Turtle が内部でどのような動き(処理)をしているのか知らない方が,Turtle を利用しやすい。右を向けとか,左を向けとか,nだけ前進しろとか,今の向きやX,Y座標を聞いたら答えてくれるだけの方が使い勝手がいい。

よしんば,Turtle の中身を知っていると中身をいじりたくなってしまう。これがC言語開発の良くない点だ。

そもそも再利用することを前提に作っていないので,ベターッとソースコードをいじってしまう。さわらなくていいところを隠蔽して,インタフェースだけをアクセスできるようにしようという意図がない。

もちろんC言語でそういった変数や関数の隠蔽は可能だが,そういう意識を持った人だからできることであり,C++を使えば言語上の縛りがあるから,自然とそういった設計になる。

Turtle クラスは ひな形(クラスが持つメンバ変数,メンバ関数が定義されている。このひな形を元にして,オブジェクトを生成(ひな形で定義した変数,関数の領域を確保して,初期化して使えるようにする)する。

同じ性質を持つオブジェクトを複数生成し,それぞれを独自に動かすことができる。
下記の例では, TurtleオブジェクトA と B は別々のタートルとして,動かすことができる。

これは構造体を使って実態を2つ作るのと同じだ。組込みではクラスとオブジェクトは一体一のことが圧倒的に多いからもしれないが,このしくみを使うと意外と簡単におもしろいことができるようになる。

1.2 方向

  0~360° で方向を指定する。






            0°
           ↑
     270° ←  亀   →  90°
                   ↓
           180°

Turtle クラスのソースコード(ヘッダー)ap_turtle.h

#ifndef AP_TURTLE_H
#define AP_TURTLE_H

class Turtle
{
public:
    Turtle();
    void turnleft();                // 左を向く
    void turnright();               // 右を向く
    void forward(int distanse);     // 前進する
    int getXPosition(void);        // 現在のX軸の位置を得る
    int getYPosition(void);        // 現在のY軸の位置を得る
    int getDeraction(void);        // 現在の向きを得る

private:
    int mX;          // X座標
    int mY;          // y座標
    int mD;          // 亀の向き
};

#endif // AP_TURTLE_H

Turtle クラスのソースコード ap_turtle.cpp

#include "ap_turtle.h"

Turtle::Turtle()
{
    mX=0;
    mY=0;
    mD=0;
}

void Turtle::turnleft()
{
    mD=mD-90;
    if (mD < 0) mD = mD+360;
}

void Turtle::turnright()
{
    mD=mD+90;
    if (mD>360) mD=mD-360;
}

void Turtle::forward(int distanse)
{
    if ((mD==0)||(mD==180)) mY=mY+distanse;
    if ((mD==90)||(mD==270)) mX=mX+distanse;
}

int Turtle::getXPosition()
{
    return mX;
}

int Turtle::getYPosition()
{
    return mY;
}

int Turtle::getDeraction()
{
    return mD;
}

Turtle クラスのソースコード main.cpp

#include
#include "ap_turtle.h"
#include
 using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Turtle turtleA;
    Turtle turtleB;

    printf (" Tuttle A Position (X , Y) = ( %3d , %3d ) \n", turtleA.getXPosition(), turtleA.getYPosition());
    printf (" Tuttle B Position (X , Y) = ( %3d , %3d ) \n", turtleB.getXPosition(), turtleB.getYPosition());

    turtleA.forward(10.0);
    turtleB.turnright();
    turtleB.forward(20.0);

    printf (" Tuttle A Position (X , Y) = ( %3d , %3d ) \n", turtleA.getXPosition(), turtleA.getYPosition());
    printf (" Tuttle B Position (X , Y) = ( %3d , %3d ) \n", turtleB.getXPosition(), turtleB.getYPosition());

    return a.exec();
}

サンプルプログラムの解説

  • Turtle クラスのオブジェクト turtleA と turtleB を生成し,現在の位置を表示。
  • turtleA を 10前進させる。
  • turtleB を左に向かせる。(左に90度)
  • turtleB を 20前進させる。
  • turtleA と turtleB の現在の位置を表示。
Turtle クラスの向きの変え方や前進,後退の仕方は Turtle クラス の内部に隠蔽させているので,turtleA や turtleB を動かす側のユーザーは,現在の位置確認と右向け,左向けといくつ前進させるのかだけを指示すればよい。

こうしておけば,そのソフトウェアアイテム(オブジェクト)を使う側の視点と,内部のしくみの視点を分離することができる。

内部のしくみの信頼性が高く,ソフトウェアアイテム(オブジェクト)の使い勝手がよければ,このソフトウェアアイテムは再利用資産となる。

ソフトウェアアイテム(オブジェクト)が複数の製品群に渡って再利用可能な資産となれば,新に作らなければいけないソフトウェアが減り,開発効率が上がる。

だだし,再利用可能な資産となるかどうかは,そのソフトウェアアイテム(オブジェクト)に何をさせるのか,どんな責務を持たせるのか,今後のソフトウェア修正の要求に耐えうるのかといった要件を満足させるくらいの出来でないとダメだ。やみくもに作ったのでは再利用資産にはならない。

そういう意味で Turtle クラス はちょっと工夫すれば,有名なテキストベースのゲームスタートレックゲームに応用できる。

次回は,Turtle クラス を修正して,スタートレックゲームの簡易版を作ってみる。


スタートレックシミュレーションゲーム(Wikipedia)

<スタートレックゲームのオリジナルの動画>
  1. スタートレックゲームのソースコードと解説
  2. MZ-80 でスタートレックゲームを遊んでいる動画
  3. Apple II でスタートレックゲームを遊んでいる動画