即座に行動せよ、そして破壊せよ?組み込み開発には当てはまらない
「即座に行動せよ、そして破壊せよ(move fast and break things)」は、Mark Zuckerberg氏がFacebookの開発文化に植え付けたアプローチです。 新機能を迅速に立ち上げて実行するためには素晴らしいことですが(たとえ完璧でなくても)、組み込み開発に同じアプローチを適用しようとすると、その輝きは失われます。
その理由は、ドメインがまったく異なるためです。Facebookは、多くの機能ポイントを備えたWebおよびデータベース中心の開発に基づいており、ホットな新機能が正しく機能しなくてもおそらく大きな被害を受けることはありません。組み込みシステムは、その性質上、リソースに制約があり、一般に1つの機能、またはいくつかの機能のみを実行することを目的としています。したがって、「即座に行動せよ、そして破壊せよ(move fast and break things)」という哲学をを組み込みシステムに適用すると、システム全体を役に立たなくする可能性があります。組み込みシステムが提供している機能にもよりますが、結果は良くても困惑するような、最悪の場合は悲惨なものになる可能性があります。
これは、組み込みシステムでRapid Application Development(RAD)メソッドを使用できないことを意味するでしょうか?RADを使用することはできますが、その方法には十分注意する必要があります。
“急いでいると、私たちはより速くも生産的にもなりません”
早く動くということは、コードの品質がコードを早く納品することよりも後回しにされていることを意味し、WISCY症候群と呼ばれることもあります。Why Isn't Somebody Coding Yet?(なぜ誰かがまだコーディングしていないのですか?) また、このコードのテストは、全く行われていないか、非公式性が高い状態で行われていることを意味しています。これらはどちらもプロジェクトをトラブルに巻き込む可能性があるので、ソフトウェア品質保証のベストプラクティスを遵守する必要があります。
開発者が機能の追加(またはバグの修正)を急いでいる場合、システムの残りの部分との統合テストを省略し、作成したばかりのコードだけを対象とした少数のテストを実行して、自分のコードのデスクチェックだけを行う傾向があります。その理由は、コードをドアの外に出すことを急ぐ文化にあります。Lemi Ergin氏が言うように、「急いでいると、私たちの速度も生産性も向上しません。それはストレスを増やし、集中力をそらします。私たちに必要なのは、創造性、有効性、集中力です。」 [1] ソフトウェアのデプロイを迅速に行う能力は、コードの品質から始まります。
組み込み開発にはスケーラビリティが必要
開発者がコードを作成する際には、スケーラビリティを促進し、システムの複雑さを最小限に抑える開発プロセスに焦点を当てる必要があり、「技術的負債」を減らす方法を常に探す必要があります。システムをシンプルに保つことで、開発者は必要に応じて機能を追加したり、システムをスケールアップしたりすることが容易になります。ただし、これを行うと、ソフトウェアを適切に設計するのに時間がかかります。
RADの状況での誘惑は、開発チームが直面している現在の問題を解決する「迅速で汚い」ソリューションを採用することです。これがまさに「技術的負債」という言葉が登場した理由です。拡張可能なソリューションを計画しないことにより、開発者は基本的に後続プロジェクトのアプリケーションを書き直すことになり、ソフトウェアの密結合のためにバグの修正や機能の追加を悪夢のようにします。密結合とは、ソフトウェアモジュールがどれだけ互いに依存しているかということで、コードのどの行を変更しても(組み込みシステムでは、コードのタイミングさえも)、システム全体が壊れてしまう可能性があります。しかし、このレベルの計画は、締め切りを目前にしているときには贅沢なことのように見え、Kelsie Anderson氏が「カウボーイコーディング」と呼んでいるものにつながる可能性があります。このような行動は、便利さのためにソフトウェアの品質に手を抜き、時間の経過とともに、密結合と技術的負債の増加によってシステムが複雑になります。
そのため、実際には開発が遅くなり、プロジェクトのコストが高くなります。 [2] Erginが述べているように、「高品質のコードベースがなければ、機敏になることはできません。」 [1]
すべてはコードの品質から始まります-とてもシンプルです
スケジュールを満たすためにコードをまとめる時間さえほとんどないときに、コード品質をどのように向上させることができるでしょうか?幸いなことに、MISRA、CWE、CERT Cなどのコーディング標準があり、それを行うことができます。これらの標準については以前の論文で取り上げましたが、これらの標準の最も重要な点は、危険なコーディング動作とCやC++言語標準の穴を回避することで、安全で信頼できるコーディングプラクティスを促進することです。
これらの標準からの逸脱を探すためにコードを自動的にスキャンできるコード分析ツールを使用することで、コードをデスクチェックしながら、これらの問題を迅速に発見して修正することができます。言い換えれば、「ゾーン内」にいる間、コードに関するフィードバックが即時に得られます。この即時フィードバックにより、開発者がバグを修正する頻度を、ビルドサーバからのフィードバックよりも50%以上高くすることにつながります。 [3] これらの標準に従うと、コード品質を即座に向上させ、ソリューションの技術的負債を減らすのに役立ちます。それと同時に、コードに挿入されるバグの数を減らし、存在するバグをより迅速に見つけて修正することができます。また、このような構造化されたコーディングのアプローチにより、機能追加が容易になり、より迅速に機能を追加することが可能になります。しかし、それは方程式の半分にすぎません。なぜなら高品質のコードベースを使用しても、適切にテストする必要があるからです。
コードの品質とテストの組み合わせは不可欠です
Steve McConnellは、彼の独創的な著作であるCode Completeにおいて、テストとコード品質の関係について考察しています:
「テストはそれ自体ではソフトウェアの品質を向上させることはできません。テスト結果は品質の指標となりますが、それ自体は品質を向上させるものではありません。テストの量を増やしてソフトウェアの品質を改善しようとすることは、より頻繁に体重を測定して減量を試みることと同じです。体重計に乗る前に何を食べるかで体重が決まり、使用するソフトウェア開発手法によって、テストで検出されるエラーの数が決まります。
体重を減らしたい場合は、新しい体重計を購入するのではなく、食生活を変えてください。ソフトウェアを改善したい場合は、より多くのテストをするのではなく、より良い開発をしましょう。」[4]
従来、テストは非常に手動のプロセスでしたが、自動テストを可能にする新しいツールが開発チームに提供されています。これらのツールの有効性はベンダごとに異なりますが、次のような驚くべきことを実行できます。要件トレース(このコードは実際に仕様の要件にマップされますか、それとも単なる「金メッキ」されているだけなのか)、単体テスト(この特定のモジュールはそのすべての機能をうまく実行していのるか)、統合テスト(すべてのユニットが互いにうまく機能しているのか)、その他多数。自動化されたテストの魅力は、開発者にとってはちょっとしたサイレンソングになるかもしれません。米国国防総省は、開発チームは、自動テストが実際に何ができるのか、自動テストに合格することでコードのリリース準備が整うのかという点で、自動テストへのアプローチについて現実的である必要があると警告しています。[5]
組み込みソフトウェアの最も一般的な問題の2つには、競合状態(どの条件が先に終了するかによって異なる出力が得られる)と初期化の問題があります。
これらはどちらも、ブルームーンで一度だけ現れる欠陥につながる可能性がありますが、再現するのが非常に難しく、修正してテストすることが困難です。
自動化されたテストは一般に、これらのタイプの問題を見つけるのが得意ではありません。多くの場合、これらの問題を顕在化させる方法を見つけるには創造性が必要です。
古典的な方法の1つは、デバイス上で同時に複数のボタンを押すことです。ボタンを同時に(1マシンサイクル以内に)押すと、異なる結果が得られますか?
1つのボタンが押されてから、割り込みサービスルーチン(ISR)が最初のボタンを押す前に完了する前に別のボタンが押された場合はどうなりますか?
通常、これらは手動テストで行われ、入力を正しく取得するには多くの試行が必要になる場合がありますが、人はそれを非常にうまく行います。
品質保証の真言の1つは、「早期にテストし、頻繁にテストする」ことで、開発プロセスがどの程度精査に耐えているかを測定することです。これにより、開発の早い段階で是正措置を講じることができ、時間とコストを大幅に節約できます。IBMは、プロジェクトの要件収集フェーズでバグを修正するのに100ドルかかる場合、通常のテストと修正サイクルで修正するには約1,500ドル、本番環境で1回修正すると10,000ドルかかる見積もってますが、この数字はあなたの組織に合わせてスケールアップすることができます。[6] できるだけ多くのバグをできるだけ早く見つけたいことにすぐに気付きます。このため、要件仕様からテストケースを作成し、通常は設計の開始と同時に開始するテスト駆動開発(TDD)が登場しました。この考え方は、コードが記述され、要件に基づくこれらのテストに合格するように改善されるというものです。これは、書いて、テストして、そのモジュールが動作するまで繰り返し、次のモジュールに進む 非常に短い開発サイクルが繰り返されます。ただし、引き続き最初のモジュールと他のモジュールへの統合をテストします。この考えは、最初は開発を遅くすることで、最後に急速にスピードを上げるというものです。
コードの品質を重視して開始することで早く動く
要約すると、開発を迅速に進めたい場合は、まずコーディング標準を通じてコード品質を向上させる必要があります。幸いなことに、これを支援するツールがあり、ずさんな、またはエラーが発生しやすいコーディング手法に起因するバグを迅速に発見し根絶することができます。次に、簡単に変更、メンテナンス、拡張できるように、緩い結合でスケーラブルにコードを設計する必要があります。最後に、自動化されたテストが組織に何をすることができるかについて現実的に考え、すべてのテストを完全に自動化することはできないことを認識する必要があります。これらのことを行うには、前もって時間がかかりますが、長期的には利益を得ることができます。
Article written by Shawn Prestridge, Industry profile and US FAE Team Manager at IAR Systems
References
- https://www.infoq.com/articles/slow-down-go-faster/
- https://www.targetprocess.com/articles/speed-in-software-development/
- https://cacm.acm.org/magazines/2018/4/226371-lessons-from-building-static-analysis-tools-at-google/fulltext
- Steve McConnell, Code Complete, Second Edition (Microsoft Press, 2009), 501.
- https://www.afit.edu/stat/statcoe_files/
0214simp%202%20AST%20IG%20for%20Managers%20and%20Practitioners.pdf - https://crossbrowsertesting.com/blog/development/software-bug-cost/