tag:blogger.com,1999:blog-193505602024-02-23T01:11:14.841+09:00Embedded Software Manufactory組込みソフトウェア工房 ("Manufactory" とは 17世紀初頭に使われていた製造所を表すことば)sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.comBlogger348125tag:blogger.com,1999:blog-19350560.post-15908177777343392992023-11-03T23:17:00.003+09:002023-11-03T23:22:18.469+09:00「組込みソフトエンジニアを極める」がB5版のオンデマンド出版になります。<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLLxEJLOPRvGSCq6BuYeo2cCM1rO-vaYVvowNrdjKwdFdgAoZFyMRVajGHJe6goXlerKdFRI8zZBTzzSlguzb45MuAqnD1ft0o4TbLR94eSBPVh7DUSYM7WAR0VYgKfa5C_gtZiV7rPeoCFdtas36JR_87kxydpNzCavpn3wKHwU1ykKP9cfUJ/s500/NEOBK-2910706.jpg" style="clear: left; display: inline; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="500" data-original-width="351" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLLxEJLOPRvGSCq6BuYeo2cCM1rO-vaYVvowNrdjKwdFdgAoZFyMRVajGHJe6goXlerKdFRI8zZBTzzSlguzb45MuAqnD1ft0o4TbLR94eSBPVh7DUSYM7WAR0VYgKfa5C_gtZiV7rPeoCFdtas36JR_87kxydpNzCavpn3wKHwU1ykKP9cfUJ/s320/NEOBK-2910706.jpg" width="225" /></a></p><p></p><p>「<a href="https://amzn.to/3sbEYWu" target="_blank">リアルタイムOSから出発して組込みソフトウェアエンジニアを極める</a>」ですが、印刷製本コストが値上がりで、今までの形式(普通の印刷)や価格では重版はできなくなり、オンデマンド出版で判型がB5になります。価格もちょっとだけ上がって税込み2200円になります。</p><p>大きさは一回り大きくなって、やや薄くなり開きやすくなったと思います。</p><p>日経BPでの初版が2006年で、その後、エスアイビー・アクセスでの初版が2011年、改訂版が2016年、オンデマンド版が2023年となります。</p><p>2006年の初版から 17年経ちもう少しで一万部ですが、まだまだ使える内容です。実際、組込みソフトウェアもネットワークにつながることが普通になって、規模も増大する一方です。とはいうもののソフトウェアプロダクトラインをちゃんと実践している企業ってまだ少ないですもんね。</p><p>この本の原稿書いていたときは、セキュリティのことなんか一ミリも考えていませんでしたが、今原稿書くなら、セキュリティについてもガッツリ解説しないとダメなんだろうなって思いますね。</p><p>そういう意味では、セキュリティについてもクリアできないと、組込みソフトエンジニアを極めたことにならないんだな。これから社会に出て行くエンジニアって、学習しなければいけないことがどんどん増えていくみたい。でも、そこをAIがサポートして補っていくんだろう。</p><p>となると、ソースコード書くところよりも、もっと上流の設計の考え方とか、ビジネスと技術をどう融合させるかといったところのが技術者の大事な役割になると思うので、まだまだこの本が役に立つ時代は続きます。この本は、技術だけでなく、ビジネスや組込みソフトウェア開発そのものにエンジニアがどう向き合うかについても書いたつもりです。</p><p>Amazon の原稿判型の在庫がなくなり次第、B5版のオンデマンド版に変わる予定です。</p>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-62899258240060391842023-06-28T15:48:00.005+09:002023-06-29T07:13:39.470+09:00FDAの医療機器ソフトウェア機能の市販前申請ガイダンスが18年ぶりに改訂された<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbxXEh6avkbEXYhHRJWWhauJCBnkNRC1L3N7cwcLeiM7KyTS8YJHR3FL96-S99dAxyRtAu2NeanRKZCbIeQ5dWGlUsPYLeTYkn4ooe5T1NmcSUebUjOS-nQLWKnKsFlj3Y7tB5hv2512XIXmJE3tscC9N93TnBOVpVBwWMEaIe8E1ew_OiiqOV/s752/fda.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="377" data-original-width="752" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbxXEh6avkbEXYhHRJWWhauJCBnkNRC1L3N7cwcLeiM7KyTS8YJHR3FL96-S99dAxyRtAu2NeanRKZCbIeQ5dWGlUsPYLeTYkn4ooe5T1NmcSUebUjOS-nQLWKnKsFlj3Y7tB5hv2512XIXmJE3tscC9N93TnBOVpVBwWMEaIe8E1ew_OiiqOV/s320/fda.png" width="320" /></a></div>FDA 米食品医薬品局 が、医療機器を市販前申請する際の<a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents/content-premarket-submissions-device-software-functions" target="_blank">「デバイスソフトウェア機能の市販前申請の内容」(Content of Premarket Submissions for Device Software Functions)のガイダンス</a>を 2023年6月14日に発行した。<br /><br />このガイダンスは、米国で医療機器を販売する際に、ソフトウェアが含まれている場合は、このガイダンスに従って必要なドキュメントを FDA に提出しなさいという内容だ。<p></p><p>この文書は、2005年5月に発行された「医療機器に含まれるソフトウェアの市販前提出の内容に関するガイダンス」に代わるもので、内容はだいぶ変わっている。</p><p>とはいうものの 2021年11月にドラフトが公開されていたので、こんな感じで変わるということはアナウンスされていた。(FDAのガイダンスは ドラフト→ Final というプロセスを踏むが、ドラフト段階でもできているかどうか聞かれる)</p><p>一番の変更点は、2005年までのガイダンスでは、タイトルが「Guidance for the Content of Premarket Submissions for Software Contained in Medical Devices」(<span style="color: #2b00fe;"><u>医療機器に含まれるソフトウェア</u></span>のための市販前ガイダンスの内容)だったのが、「Content of Premarket Submissions for Device Software Functions」(<span style="color: #2b00fe;"><u>デバイスソフトウェア機能</u></span>の市販前申請の内容)になった点だ。</p><p>これは何を意味しているかというと、2005年のガイダンスでは、<span style="color: #2b00fe;">「医療機器に含まれるソフトウェアに関するいろいろな説明をせよ」</span>だったのが、2023年のガイダンスでは、<span style="color: #2b00fe;"><u>医療機器に含まれるではなく、医療機器ソフトウェアの機能 </u></span>がターゲットになったという点が異なる。</p><p>同じように見えるかもしれないが、2005年のガイダンスでは、医療機器に含まれるソフトウェアが審査の対象だった。2023年のガイダンスでは、医療機器に含まれるソフトウェアだけでなく、医療機器が提供する機能として、医療機器が連携するクラウド上のソフトウェアや、スマホやタブレットのブラウザやアプリケーションなども含めて<span style="color: #2b00fe;"><u>「医療機器単体でできることだけでなく、ネットワークを含めたトータルのシステムでできること、しようとしていること」</u></span>を説明することが求められるようになった。<br /><br />以前は、ソフトウェアに障害が発生したときの患者への影響に応じて Level of Concern が Minor, Moderate, Major の3段階に設定され、それぞれのレベルに応じて提出するドキュメントが分かれていたが、今回は、基本ドキュメントと拡張ドキュメントの2段階になった。<br /><br />拡張ドキュメントになる条件は以下になる。<br /></p><blockquote><b>医療機器のソフトウェア機能に関連する障害や欠陥が、患者、デバイスの使用者、または使用環境の他の人々に対して死亡または重大な負傷の恐れを伴う危険な状況を引き起こす可能性がある場合</b></blockquote><p></p><p>下記に各ドキュメントレベルに応じて、求められる内容を示す。</p>
<table border="1" style="width: 100%;">
<tbody>
<tr>
<td align="center" bgcolor="#00ffff">Software Documentation Elements<br />
ソフトウェア ドキュメント 要素</td>
<td align="center" bgcolor="#00ffff">Basic Documentation Level<br />
基本ドキュメントレベル</td>
<td align="center" bgcolor="#00ffff">Enhanced Documentation Level<br />
拡張ドキュメントレベル</td>
</tr>
<tr>
<td>Documentation Level Evaluation<br />
ドキュメント レベル評価</td>
<td colspan="2">A statement indicating the Documentation Level and a description of the rationale for that level.<br />
ドキュメンテーションレベルを示す声明と、そのレベルの根拠の説明。</td>
</tr>
<tr>
<td>Software Description<br />
ソフトウェア説明</td>
<td colspan="2">Software description, including overview of significant software features, functions, analyses, inputs, outputs, and hardware platforms.<br />
ソフトウェアの説明、重要なソフトウェアの特徴、機能、分析、入力、出力、およびハードウェアプラットフォームの概要を含める。</td>
</tr>
<tr>
<td>Risk Management File<br />
リスクマネジメントファイル</td>
<td colspan="2">Risk management plan, risk assessment demonstrating that risks have been appropriately mitigated, and risk management report.<br />
リスクマネジメント計画、リスクが適切に軽減されていることを示すリスクアセスメント、およびリスクマネジメント報告書。</td>
</tr>
<tr>
<td>Software Requirements Specification(SRS)<br />
ソフトウェア要求仕様書(SRS)</td>
<td colspan="2">SRS documentation, describing the needs or expectations for a system or software, presented in an organized format, at the software system level or subsystem level, as appropriate, and with sufficient information to understand the traceability of the information with respect to the other software documentation elements (e.g., risk management file, software design specification, system and software architecture design chart, software testing).<br />
SRS(Software Requirements Specification)文書は、システムまたはソフトウェアのニーズや期待事項を組織的な形式で記述し、ソフトウェアシステムレベルまたはサブシステムレベルに応じて、他のソフトウェア文書要素との情報のトレース性を理解するための十分な情報を提供する(例:リスクマネジメントファイル、ソフトウェア設計仕様、<span style="color: #2b00fe;">システムおよびソフトウェアアーキテクチャ設計図</span>、ソフトウェアテスト結果など)。</td>
</tr>
<tr>
<td><span style="color: #2b00fe;">System and Software Architecture Design<br />
システム及びソフトウェアアーキテクチャ設計</span></td>
<td colspan="2"><span style="color: #2b00fe;">Detailed diagrams of the modules, layers, and interfaces that comprise the device, their relationships, the data inputs/outputs and flow of data, and how users or external products (including information technology (IT) infrastructure and peripherals) interact with the system and software.<br />
デバイスを構成するモジュール、レイヤー、およびインターフェースの詳細な図解、それらの関係性、データの入力/出力とデータのフロー、およびユーザーや外部製品(情報技術(IT)インフラストラクチャや周辺機器を含む)がシステムとソフトウェアとのやり取りをする方法についての図解。</span></td>
</tr>
<tr>
<td>Software Design Specification (SDS)<br />
ソフトウェア設計仕様(SDS)</td>
<td>FDA is not recommending the SDS as part of the premarket submission. Sponsor should document this information on the design via the DHF for the device. During premarket review, FDA may request additional information, if needed, to evaluate the safety and effectiveness of the device.<br />
FDAは、市販前申請の一環としてSDS(Software Development Standards)の提出を基本ドキュメントレベルでは推奨していない。製造業者は、医療機器の設計に関するこの情報をデバイス履歴ファイル(DHF)に文書化する必要がある。市販前審査中、FDAは、必要に応じて、医療機器の安全性と有効性を評価するために追加の情報を要求することがある。</td>
<td>SDS documentation, including sufficient information that would allow FDA to understand the technical design details of how the software functions, how the software design completely and correctly implements all the requirements of the SRS, and how the software design traces to the SRS in terms of intended use, functionality, safety, and effectiveness.<br />
SDS(Software Development Standards)文書には、FDAがソフトウェアの機能の技術的な設計詳細、ソフトウェア設計がSRSのすべての要件を完全かつ正しく実装している方法、およびソフトウェア設計が意図された使用目的、機能、安全性、有効性に関してSRSとのトレース性を理解するために十分な情報が含まれる。</td>
</tr>
<tr>
<td>Software Development, Configuration Management, and Maintenance Practices<br />
ソフトウェア開発、構成管理(コンフィグレーションマネジメント)及び保守</td>
<td>A summary of the life cycle development plan and a summary of configuration management and maintenance activities;<br />
ライフサイクル開発計画の概要と、構成管理および保守活動の概要の要約。<br />
OR<br />
又は<br />
A Declaration of Conformity36to the FDA-recognized version of IEC 62304, including subclauses 5.1.1-5.1.3, 5.1.6-5.1.9, clause 6 (Software maintenance process), and clause 8 (Software configuration management process), among others as applicable.<br />
FDAが認識しているIEC 62304のバージョンに対する適合性宣言(Declaration of Conformity):該当する場合には5.1.1-5.1.3、5.1.6-5.1.9の細分箇条、箇条6(ソフトウェア保守プロセス)、および箇条8(ソフトウェア構成管理プロセス)などが含まれる。</td>
<td>A summary of the life cycle development plan and a summary of configuration management and maintenance activities;<br />
ライフサイクル開発計画の概要と、構成管理および保守活動の概要の要約。<br />
OR<br />
又は<br />
A Declaration of Conformity36to the FDA-recognized version of IEC 62304, including subclauses 5.1.1-5.1.3, 5.1.6-5.1.9, clause 6 (Software maintenance process), and clause 8 (Software configuration management process), among others as applicable.<br />
FDAが認識しているIEC 62304のバージョンに対する適合性宣言(Declaration of Conformity):該当する場合には5.1.1-5.1.3、5.1.6-5.1.9の細分箇条、箇条6(ソフトウェア保守プロセス)、および箇条8(ソフトウェア構成管理プロセス)などが含まれる。</td>
</tr>
<tr>
<td>Software Testing as Part of Verification and Validation<br />
検証(ベリフィケーション)および妥当性確認(バリデーション)の一部としてのソフトウェアテスト</td>
<td> A summary description of the testing activities at the unit, integration
and system levels;<br />
ユニット、統合、およびシステムレベルでのテスト活動の概要説明<br />
AND<br />
及び<br />
System level test protocol including expected results, observed results, pass/fail determination, and system level test report.<br />
システムレベルのテスト手順書(テストプロトコル)を含み、期待される結果、観測された結果、合格/不合格の判定、およびシステムレベルのテストレポートを含む。</td>
<td>Basic Documentation Level, PLUS <br />
基本ドキュメントレベルに<br />
加えて<br />
unit and integration level test protocols including expected results, observed results, pass/fail determination, and unit and integration level test reports.<br />
ユニットおよび統合レベルのテスト手順書(テストプロトコル)を含み、期待される結果、観測された結果、合格/不合格の判定、およびユニットおよび統合レベルのテストレポートを含む。</td>
</tr>
<tr>
<td>Software Version History<br />
ソフトウェアバージョン履歴</td>
<td colspan="2">A history of tested software versions including the date, version number, and a brief description of all changes relative to the previously tested software version.<br />
以前にテストされたソフトウェアバージョンの履歴を含み、日付、バージョン番号、以前にテストされたソフトウェアバージョンとの関連でのすべての変更の簡単な説明が含まれる。</td>
</tr>
<tr>
<td>Unresolved Software Anomalies<br />
未解決のソフトウェア異常</td>
<td colspan="2">List of remaining unresolved software anomalies with an evaluation of the impact of each unresolved software anomaly on the device’s safety and effectiveness.<br />
未解決のソフトウェアの異常のリストと、各未解決のソフトウェアの異常がデバイスの安全性と有効性に与える影響の評価。</td>
</tr>
</tbody>
</table>
<br />特に注目して欲しいのは、<span style="color: #2b00fe;">System and Software Architecture Design(システム及びソフトウェアアーキテクチャ設計)</span>の部分で、<span style="color: #2b00fe;">「デバイスを構成するモジュール、レイヤー、およびインターフェースの詳細な図解、それらの関係性、データの入力/出力とデータのフロー、およびユーザーや外部製品(情報技術(IT)インフラストラクチャや周辺機器を含む)がシステムとソフトウェアとのやり取りをする方法についての図解。」</span>の提出を求められることになった。<div><br /></div><div>今回のガイダンスには Appendix B に このシステム及びソフトウェアアーキテクチャ設計図の例が3つ示されている。</div><div style="text-align: left;"><br />1. ハンドヘルド診断デバイス</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_IHYwjGLM2sChDiGlNR08Ve7ZjUqbkhQRG1OQ_QBMencj6dEhS_WTFZYtFCpU2mZGqgapvba6d0PQbvXsRzOa7Qg3Lqc7s2dmUsOhB03GuLog-22ThHNJpLsyihmT_wtLzONtqnMooZY2DjoXhJsmOX8hCTBweYT8DR3BD7j2yRaWenxlXm-4/s608/Figure1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="429" data-original-width="608" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_IHYwjGLM2sChDiGlNR08Ve7ZjUqbkhQRG1OQ_QBMencj6dEhS_WTFZYtFCpU2mZGqgapvba6d0PQbvXsRzOa7Qg3Lqc7s2dmUsOhB03GuLog-22ThHNJpLsyihmT_wtLzONtqnMooZY2DjoXhJsmOX8hCTBweYT8DR3BD7j2yRaWenxlXm-4/w400-h282/Figure1.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">2. 患者と医療提供者向けのアプリケーションを備えた埋め込み式治療デバイス<br /><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlycYP_GIXOi7vh-IBgUwMQfq-M2pLqq5yYNVFnr1dPY9D8p6R5UR9hrKUiTRRvrg8JRKMXkrsFp2RBisb-Ds3E7j_-z62gaHmQL76rMNAu_nCZ77hPraLuCi2rrhfKIZcXaW2HVB867atTk9KDJimsm--sBAaP4v3PyPyj9PMyH4m7eZOVMcG/s619/Figure2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="442" data-original-width="619" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlycYP_GIXOi7vh-IBgUwMQfq-M2pLqq5yYNVFnr1dPY9D8p6R5UR9hrKUiTRRvrg8JRKMXkrsFp2RBisb-Ds3E7j_-z62gaHmQL76rMNAu_nCZ77hPraLuCi2rrhfKIZcXaW2HVB867atTk9KDJimsm--sBAaP4v3PyPyj9PMyH4m7eZOVMcG/w400-h285/Figure2.png" width="400" /></a></div><br />3. 取得された医療画像を解析するためのクラウドベースのデバイスアルゴリズムのシステムおよびソフトウェアアーキテクチャ<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWD10gqb3Cr0592Vn1OOYvFJbGAMrSqQpwtgCYkaH2k2o2QsSD1g87N9GEIuX1WRdaTkp3Nc4D2hsrHfcGXfInLc5Qqns7j7p2q15mUvPrsKxnImIMpnXNygzyrbzpiHy3TSS8XXttknw1ll3sWDHYfDkrE3eG-KUJqHrGdW5kWHdmc7R2aXV1/s569/Figure3.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="392" data-original-width="569" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWD10gqb3Cr0592Vn1OOYvFJbGAMrSqQpwtgCYkaH2k2o2QsSD1g87N9GEIuX1WRdaTkp3Nc4D2hsrHfcGXfInLc5Qqns7j7p2q15mUvPrsKxnImIMpnXNygzyrbzpiHy3TSS8XXttknw1ll3sWDHYfDkrE3eG-KUJqHrGdW5kWHdmc7R2aXV1/w400-h275/Figure3.jpg" width="400" /></a></div><br /><div><br />これらのダイアグラムはハードウェア、ソフトウェアを含むシステム全体の静的なアーキテクチャ図で、この図は 一般的なURLの表記ではなく FDAの独自の表記法である。</div><div><br /></div><div>凡例を付けていれば、この様式とまったく同じでなくてもよいようだが、このFDAが示す表記法で 医療機器申請をすれば審査が早く進むのだろう。</div><div><br /></div><div>特徴的なのは、ハードウェアモジュール、ソフトウェアモジュール、OTS(市販されている既製のソフトウェア製品)を区別しており、それらの関係性をインタフェースの矢印線で示しているところだ。</div><div><br /></div><div>2の 「患者と医療提供者向けのアプリケーションを備えた埋め込み式治療デバイス」のアーキテクチャ図を見ると分かるのは、埋め込み式の治療デバイスが物理的な医療機器なのだが、実際には、リーダー/プログラマと通信したり、リーダー/プログラムを通して、クラウドにデータを送ったり、モバイル端末でデータを見たりするような使い方をする(=意図する使用としている)ことである。</div><div><br /></div><div>ようするに、現代の医療機器は、医療機器単体で使用することは少なくなってきていて、ネットワークに接続して、クラウドで機械学習したり、モバイル端末で医療機器の情報を閲覧したりすることが当たり前になってきているということだ。そのため、患者リスクは医療機器の中だけに留まらず、医療機器から外に出た情報がどのように使われるのかも含めて、リスクマネジメントしないといけなくなってきている。</div><div><br /></div><div>だからこそ、FDAのガイダンスのタイトルが<span style="color: #2b00fe;">「<u>医療機器に含まれるソフトウェア</u>のための市販前ガイダンスの内容」</span>から<span style="color: #2b00fe;">「<u>デバイスソフトウェア機能</u>の市販前申請の内容」</span>に変わったのだ。</div><div><br /></div><div>規制当局としてチェックしなければいけないのは医療機器に含まれるソフトウェアだけではなくなったので、医療機器のソフトウェア機能として、ネットワークを含めた接続機器や機能全体を審査しないといけなくなったのである。</div><div><br /></div><div>それにともない、医療機器が出力する情報は仕様を公開するので自由に使ってくださいという考え方はNGとなっている。相互運用性(Interoperability)を医療機器製造業者が定義した上で、その安全性や有効性の妥当性を確認する必要があるということになる。</div><div><br /></div><div>そうなると、医療機器からどんな情報が出たり入ったりしていて、どんな機器やシステムと接続しているのか、それらの機器・システムには市販のソフトウェアが使われてるのかどうかを見る必要が出てくる。だからこそ、<u>システム及びソフトウェアアーキテクチャ設計図</u>が必要となった。</div><div><br /></div><div>また、システム全体の機能として安全性や有効性を確認するためには、それぞれの機能モジュールの要求仕様を確認した上で、それらの要求仕様が検証され、バリデーションされているかのトレースを取る必要がある。</div><div><br /></div><div>そのため、システム及びソフトウェアアーキテクチャ設計図の各モジュールには、要求仕様の番号が記載されている。(例 SWReq X.Y) また、ところどころで機能モジュールの Intended Use(意図する使用)がノートで説明されている。例えば、1のハンドヘルド診断デバイスでは、解析エンジンのノートに下記のノートが付けられている。</div><div><blockquote>Analysis engine consists of software algorithms for analyzing signals acquired from patient (解析エンジンは患者から取得した信号を解析するためのソフトウェアアルゴリズムで構成されています)</blockquote></div><div>システム及びソフトウェアアーキテクチャ設計図が、SRS(ソフトウェア要求仕様)でも提示を求められているのは、各モジュールの要求仕様を確認したり、トレースを取ったりしたいからである。</div><div><br /></div><div>医療機器ソフトウェアの安全性や有効性を確認するために、規制当局がシステムアーキテクチャまで踏み込んで審査する時代になった。</div><div><br /></div><div>システムエンジニアやソフトウェアエンジニアは、ソフトウェアを作る以前に、さまざまなモデリングができなければいけなくなってきている。今回は、システム及びソフトウェアアーキテクチャ設計図だが、サイバーセキュリティでは脅威モデリングとしてデータフローダイアグラムを信頼境界も含めて描くことが求められてる。</div><div><br /></div><div>現代のソフトウェアエンジニアは当たり前にモデリングができることが求められるようになった。</div><div><br /></div><div>今回の FDA が要求する システム及びソフトウェアアーキテクチャ設計図 は、<a href="https://www.sparxsystems.jp/" target="_blank">UML モデリングツール EnterpriseArchitect</a> で描くことができる。</div><div><br /></div><div>↓アドインの説明</div><div><a href="https://www.sparxsystems.jp/products/EA/tech/SSAD.htm" target="_blank">System and Software Architecture Diagramの作成</a></div><div><br /></div><div>EA 16.1 にこのアドインを取り込んで描いた図を示す。</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtQs5-M7aH0sdWYB_cNncaSNfLedWgzsnOAd47Hf1e_ZfmH7l3ccGco3BfVgMyk6zoVuKJ4sox5bkBcRC_xdGK7j8ZRRWdfvyZNK6-Qt5ZLtzaUv5lvtK98Iw_GmKbco9G50F4CLE168iPI9LjIL-Vi1ltibmc-Yqakmvg01De-wi6vHHqixS3/s1409/EA_Figure1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="909" data-original-width="1409" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtQs5-M7aH0sdWYB_cNncaSNfLedWgzsnOAd47Hf1e_ZfmH7l3ccGco3BfVgMyk6zoVuKJ4sox5bkBcRC_xdGK7j8ZRRWdfvyZNK6-Qt5ZLtzaUv5lvtK98Iw_GmKbco9G50F4CLE168iPI9LjIL-Vi1ltibmc-Yqakmvg01De-wi6vHHqixS3/w400-h258/EA_Figure1.png" width="400" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOnNwz02VbfXZX5h_u6-GB118wkxVIP0vuLxdfRC2h5ApAkF62QGs5St5ocdibN-8WXvrD0dLaeiNlbSPwzrCJE2B7NFCL0C9bkUmNK9zd1bLAMCH1Xx4g76oP9mKg02_3KE2bvcXxxDhsyZepYFxv3tfZpupWsUBUR8o3oNWHbd7dViw8Zly9/s1720/EA_Figure2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1072" data-original-width="1720" height="249" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOnNwz02VbfXZX5h_u6-GB118wkxVIP0vuLxdfRC2h5ApAkF62QGs5St5ocdibN-8WXvrD0dLaeiNlbSPwzrCJE2B7NFCL0C9bkUmNK9zd1bLAMCH1Xx4g76oP9mKg02_3KE2bvcXxxDhsyZepYFxv3tfZpupWsUBUR8o3oNWHbd7dViw8Zly9/w400-h249/EA_Figure2.png" width="400" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ELbROmx_PwS60th-WEderUlB_VYSlt8WvILLAYRTmznlv4L93U6Z2V1kCb-4G7dafXrStASL2J4Te0YsISzaW9VA9KCn8c4Wvz_jTtPf5IHgsEcQKfklkIzdPyMwcfQ6wD-Uf_OZT-zS4He1LihueIDeoJvonnIOYN4kDuyow8tg_t45E9KQ/s1094/EA_Figure3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="647" data-original-width="1094" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ELbROmx_PwS60th-WEderUlB_VYSlt8WvILLAYRTmznlv4L93U6Z2V1kCb-4G7dafXrStASL2J4Te0YsISzaW9VA9KCn8c4Wvz_jTtPf5IHgsEcQKfklkIzdPyMwcfQ6wD-Uf_OZT-zS4He1LihueIDeoJvonnIOYN4kDuyow8tg_t45E9KQ/w400-h236/EA_Figure3.png" width="400" /></a></div><br /><div><br /></div><div>すり合わせ的に作ってきたソフトウェアシステムは、こんなに綺麗に機能=モジュールになっていないかもしれないが、AIなど多様な機能を取り入れたシステムを実現するには、機能分割されたモジュールを組み合わせた設計にしていく必要がある。<br /><br />すり合わせ一本でここまでソフトウェアを開発してきた技術者には、モデリングできるように今回のようなシステムアーキテクチャを描く練習するとともに、是非「<a href="https://www.amazon.co.jp/gp/product/4434217461/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4434217461&linkCode=as2&tag=embeddedsoftw-22" target="_blank">リアルタイムOSから出発して 組込みソフトエンジニアを極める</a>」を読んで、どうやって時間分割のハードルを越えて、さらに機能分割のハードルを越えるのかを学んで欲しい。</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheE30dgCwLOmbr47FXOThAQL6BwE-vr1CyR0Uyt_v1F0LIGNDtgm2wgSAEain6AnO42DGzQdfH2fQlm1JRaIsVlxREEezwReyPcyiXG6PjdNIkMXhNLXdPJRgPs6kUQYPPNFLwPSqkRH0WsUUCqDwXpp4BqT3zFiyGi4OFfE9zz5AhdkDwKk0M/s457/LOAD_MAP.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="324" data-original-width="457" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheE30dgCwLOmbr47FXOThAQL6BwE-vr1CyR0Uyt_v1F0LIGNDtgm2wgSAEain6AnO42DGzQdfH2fQlm1JRaIsVlxREEezwReyPcyiXG6PjdNIkMXhNLXdPJRgPs6kUQYPPNFLwPSqkRH0WsUUCqDwXpp4BqT3zFiyGi4OFfE9zz5AhdkDwKk0M/w400-h284/LOAD_MAP.gif" width="400" /></a></div><br /><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><br /></div><br />
</div>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-57517165428433485682023-04-10T10:53:00.001+09:002023-04-10T10:53:05.052+09:00医療機器のサイバーセキュリティ規制強化へ<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirtjtazqUypbm_I4Q4XEyGnMQnFkeZ5HZ8jJ4WqFOW6vWGDa3wIdk83ThMxA53c8JGpyFOjzD2vIhtALjZ3_AVxsYrV7436ZvYSXeMF_sdC_stGDPxPhDtQyJGJrkyu-PptS2bZerWGlcIpM0PERJ9mqhvPw-Fk7kYQpyo5Tzjv_29JTa2cw/s4592/AdobeStock_290783716.jpeg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="3448" data-original-width="4592" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirtjtazqUypbm_I4Q4XEyGnMQnFkeZ5HZ8jJ4WqFOW6vWGDa3wIdk83ThMxA53c8JGpyFOjzD2vIhtALjZ3_AVxsYrV7436ZvYSXeMF_sdC_stGDPxPhDtQyJGJrkyu-PptS2bZerWGlcIpM0PERJ9mqhvPw-Fk7kYQpyo5Tzjv_29JTa2cw/s320/AdobeStock_290783716.jpeg" width="320" /></a></div>2023年3月31日付けで、厚労省から医療機器のサイバーセキュリティ規制強化に関するいくつかの通知が発出された。<p></p><p>どんな通知なのかを説明したいと思う。</p><p></p><ol style="text-align: left;"><li> <a href="https://www.mhlw.go.jp/hourei/doc/tsuchi/T230404I0010.pdf" target="_blank">医療機器の基本要件基準第12条第3項の適用について(令和5年3月31日薬生機審発0331第8号)(PDF,155KB) </a></li><li><a href="https://www.mhlw.go.jp/hourei/doc/tsuchi/T230404I0050.pdf">医療機器のサイバーセキュリティ導入に関する手引書の改訂について(令和5年3月31日薬生機審発0331第11号・薬生安発0331第4号)(PDF,1435KB) </a></li><li><a href="https://www.mhlw.go.jp/hourei/doc/tsuchi/T230404G0080.pdf">医療機関における医療機器のサイバーセキュリティ確保のための手引書について(令和5年3月31日医政参発0331第1号・薬生機審発0331第16号・薬生安発0331第8号)(PDF,971KB)</a></li></ol><p></p><p><span style="font-size: large;">「医療機器の基本要件基準第12条第3項の適用について」の医療機器の基本要件基準とは何か</span></p><p><br /></p><p>PMDAに<a href="chrome-extension://efaidnbmnnnibpcajpcglclefindmkaj/https://www.pmda.go.jp/files/000240068.pdf">詳しい説明資料</a>があるのでこれを参照して欲しい。</p><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS9McMIg1Efbcj0v9ZDoHYvM-2h3p_D6235G6kqRDNtXPoiIHO5AyQu_s1CG8HmVELbzPJoReNVZXe83D53WK5t7jDk2vsIdf2gdJ0de398nZo6RfjMyqvJcnOkzznBOSKdTSLb7oNPy0jusdJ6lY3Q2Chqeq0BIqi_6jcdAk8PgBtdIsjjA/s1261/%E5%9F%BA%E6%9C%AC%E8%A6%81%E4%BB%B6%E5%9F%BA%E6%BA%961.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="937" data-original-width="1261" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS9McMIg1Efbcj0v9ZDoHYvM-2h3p_D6235G6kqRDNtXPoiIHO5AyQu_s1CG8HmVELbzPJoReNVZXe83D53WK5t7jDk2vsIdf2gdJ0de398nZo6RfjMyqvJcnOkzznBOSKdTSLb7oNPy0jusdJ6lY3Q2Chqeq0BIqi_6jcdAk8PgBtdIsjjA/s320/%E5%9F%BA%E6%9C%AC%E8%A6%81%E4%BB%B6%E5%9F%BA%E6%BA%961.jpg" width="320" /></a>簡単にいうと、薬機法(法律)で医療機器は認証基準への適合が必要となっていて、基本要件基準第41条にて、厚生労働大臣は必要な基準を設けることができるとある。医療機器の基本要件基準は厚労省からの告示によって示されている。<br /><br /><br /></div><br /><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkgVezGUMRN29qywUSqs9bWV2HId4w8_DIAJNSBR7z6HoXiipjiKiG6qTBJ7GynS9nHSCMGp1qHSSZsEXrZSYlPtvyOnJvvYXVimP52vqCm5zHf1qaKz7ivpxlVmYoQ2rwiMPt0BWObnkA6x4NuBI7OhohV8TJdU0KYJvVmY0QEEHuO1YdbA/s1246/%E5%9F%BA%E6%9C%AC%E8%A6%81%E4%BB%B6%E5%9F%BA%E6%BA%962.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="928" data-original-width="1246" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkgVezGUMRN29qywUSqs9bWV2HId4w8_DIAJNSBR7z6HoXiipjiKiG6qTBJ7GynS9nHSCMGp1qHSSZsEXrZSYlPtvyOnJvvYXVimP52vqCm5zHf1qaKz7ivpxlVmYoQ2rwiMPt0BWObnkA6x4NuBI7OhohV8TJdU0KYJvVmY0QEEHuO1YdbA/s320/%E5%9F%BA%E6%9C%AC%E8%A6%81%E4%BB%B6%E5%9F%BA%E6%BA%962.jpg" width="320" /></a></div><br /><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-rCeXTGr8hM3MktW9LJVqB63ACohDNIG7Qk2r4nnmFuMBK-SnMYaACsQMcIdRhna6_GzLmKcRcHX5Vk5msY71lOdhDezPa_Sf8QI9jAe8GBqfkSXC0mH81QQjieq794SAwK37yLxETodp1WU6Sac9MOsOHYV-xdKJtAs2YoIz6KlST3fhAQ/s1241/%E5%9F%BA%E6%9C%AC%E8%A6%81%E4%BB%B6%E5%9F%BA%E6%BA%963.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="940" data-original-width="1241" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-rCeXTGr8hM3MktW9LJVqB63ACohDNIG7Qk2r4nnmFuMBK-SnMYaACsQMcIdRhna6_GzLmKcRcHX5Vk5msY71lOdhDezPa_Sf8QI9jAe8GBqfkSXC0mH81QQjieq794SAwK37yLxETodp1WU6Sac9MOsOHYV-xdKJtAs2YoIz6KlST3fhAQ/s320/%E5%9F%BA%E6%9C%AC%E8%A6%81%E4%BB%B6%E5%9F%BA%E6%BA%963.jpg" width="320" /></a></div><br /><p>医療機器の基本要件基準の第12条は、「プログラムを用いた医療機器の対する配慮」で、今回 第12条の 3項にサイバーセキュリティ要求が追加された。<br /><br />実は第12条2項は 2017年5月に追加されたJIS T 2304(医療機器ソフトウェア―ソフトウェアライフサイクルプロセス)への適合を求めた追加だった。<br /><br />第12条3項は、2023年3月9日に追加の告示が発出されている。今回 出た通知は、第12条3項の施行に関する通知となる。</p><p><span style="font-size: large;">医療機器の基本要件基準第12条第3項</span></p><p></p><blockquote>3.プログラムを用いた医療機器のうち、他の機器及びネットワーク等と接続して使用する医療機器又は外部から不正アクセス及び攻撃アクセス等が想定される医療機器については、当該医療機器における動作環境及びネットワークの使用環境等を踏まえて適切な要件を特定し、当該医療機器の機能の支障が生じる又は安全性の懸念が生じるサイバーセキュリティに係る危険性を特定及び評価するとともに、当該危険性が低減する管理が行われていなければならない。また、当該医療機器は、当該医療機器のライフサイクルの全てにおいて、サイバーセキュリティを確保するための計画に基づいて設計及び製造されていなければならない。</blockquote><p></p><p>これが追加された第12条3項の内容になる。この3項の説明が冒頭の3/31付けの通知1 に書かれている。その内容を紹介する。</p><p><span style="font-size: medium;">趣旨</span></p><p></p><blockquote><p>基本要件基準は、医療機器が具備すべき品質、有効性及び安全性に係る基本的な要件を規定したものであり、医療機器に対しリスクマネジメントの適用によってリスクを許容可能な範囲まで低減することが要求されている。</p><p>サイバーセキュリティ対策については、「医療機器におけるサイバーセキュリティの確保について」(平成27年4月28日付け薬食機参発0428第1号及び薬食安発0428第1号)、「医療機器のサイバーセキュリティの確保に関するガイダンスについて」(平成30年7月24日付け薬生機審発0724第1号及び薬生安発0724第1号)等において必要な対応を行うよう求めてきたところであるが、今般、令和2年3月に国際医療機器規制当局フォーラム(IMDRF)において、「医療機器サイバーセキュリティの原則及び実践に関するガイダンス」が取りまとめられたことに伴い、IMDRF N47文書(Essential Principles of Safety and Performance of Medical Devices and IVD Medical Devices)及びN60文書(Principles and Practices for Medical Device Cybersecurity)を踏まえ、プログラムを用いた医療機器に対しサイバーセキュリティを確保するための設計及び製造、ライフサイクル活動として、①製品の全ライフサイクルにわたって医療機器サイバーセキュリティを確保する計画を備えること、②サイバーリスクを低減する設計及び製造を行うこと、③適切な動作環境に必要となるハードウェア、ネットワーク及びITセキュリティ対策の最低限の要件を設定すること、の3つの観点を基本要件基準に盛り込むこととし、基本要件基準第12条に第3項を追加する改正を行ったものである。</p></blockquote><p></p><p>要約すると、</p><p>IMDRF N47文書、N60文書をベースにしている。</p><p></p><ol style="text-align: left;"><li>製品の全ライフサイクルにわたって医療機器サイバーセキュリティを確保する計画を備えること</li><li>サイバーリスクを低減する設計及び製造を行うこと</li><li>適切な動作環境に必要となるハードウェア、ネットワーク及びITセキュリティ対策の最低限の要件を設定すること</li></ol><p></p><p>の3つの観点を基本要件基準に盛り込んだということになる。</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicei8NA6SG5G8YV39rfNQb-0_gFcRzi4SWheeSzXkK31E1r-ZjYBgn0QBr13zWZ61XBR2XZM9iujusyRauPaFtBQgu7nfqB7hJVAPJNU80drUNZXXrsVjIRA3ja_wmuSfL2R99d1MMZfXoDddR7tbzpNdw14XxO6ZsBN3XEYXCfQVJAiUk_A/s1491/IMDRF.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1021" data-original-width="1491" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicei8NA6SG5G8YV39rfNQb-0_gFcRzi4SWheeSzXkK31E1r-ZjYBgn0QBr13zWZ61XBR2XZM9iujusyRauPaFtBQgu7nfqB7hJVAPJNU80drUNZXXrsVjIRA3ja_wmuSfL2R99d1MMZfXoDddR7tbzpNdw14XxO6ZsBN3XEYXCfQVJAiUk_A/s320/IMDRF.jpg" width="320" /></a></div>IMDRF は 各国の規制当局の集まりで、ここで決まったことを各国の医療機器規制当局が自国の規制に適用することになっている。<p></p><p>IMDRFの成果として有名なのが、MDSAP(医療機器単一審査プログラム)で、各国とも ISO 13485 (ISO 9001 の医療機器版)を医療機器製造販売業者に求めているが、国によって微妙に異なる部分を各国統一部分+差分という形にして、1回審査をパスすれば、それぞれの国で審査し直さなくてもよいというプログラムを作った。これによって、米国の非常に厳しい査察を定期的に受ける必要がなくなった。(全体としては米国の審査基準に近づいたので米国以外の審査としてはハードルが上がったと言える)</p><p>IMDRF はN60文書として医療機器の対するサイバーセキュリティのガイダンスを発行していて、冒頭の2の文書が、IMDRF N60文書の日本適用版という位置づけになっている。</p><p>冒頭1の施行通知の解説を続ける。</p><p></p><blockquote>(1) 「プログラムを用いた医療機器のうち、他の機器及びネットワーク等と接続して使用する医療機器」とは、他の機器(医療機器、IoT機器、周辺機器、外部記録媒体(USB、SD、HDD、CD、DVD等)、電子カルテ、PC(外部からの持ち込みPC含む))、ネットワーク(院内システム、院外システム、グローバル)等に接続して電磁的情報のやり取りをする医療機器である。</blockquote><p></p><p><span style="color: #2b00fe;">ここは対象となる医療機器の説明をしてる。</span></p><p><span style="color: #2b00fe;">・他の機器にネットワーク等に接続して電磁的情報をやり取りする医療機器が対象。</span></p><p></p><blockquote>(2)「外部からの不正アクセス及び攻撃アクセス等」は、脆弱性を攻撃対象とする等の設計者が通常使用において想定していない手法等を用いた悪意を持った不正アクセスや、意図的に過剰な負荷を与えたる攻撃(DoS攻撃(Denial Service Atttack)、DDoS攻撃(Distributed Denial of Service Attack)等)、マルウェア(悪意のあるソフトウェア)の感染を意図する攻撃によるアクセス等を想定している。昨今のサイバー攻撃についてはその攻撃形式が多様化・高度化しており、今後はこれらの攻撃手法の他にも対応することも必要となり得る。</blockquote><p></p><p><span style="color: #2b00fe;">ここは、外部からの不正アクセス及び攻撃アクセスの説明。</span></p><p></p><blockquote>(3)「動作環境及びネットワークの使用環境等を踏まえて適切な要件を特定し」とは、医療機関、在宅、救急、植込み型機器等の動作環境並びに接続するネットワーク種別やオペレーティングシステム及び各種ライブラリ等のプラットフォームといった使用環境を特定し、その使用環境に適した運用体制等を含めた医療機器の意図する使用に適切な要件を設定することである。</blockquote><p></p><p><span style="color: #2b00fe;">使用環境の特定について説明と、医療機器の意図する使用と使用環境の要件を設定すること。</span></p><p></p><blockquote>(4)「当該医療機器の機能に支障が生じる又は安全性の懸念が生じるサイバーセキュリティに係る危険性を特定及び評価するとともに、当該危険性が低減する管理」とは、他のリスクと同様に、サイバーセキュリティに係るリスクに対しても、適切にリスクマネジメントを行い、例えば、<span style="color: #2b00fe;">JIS T 81001-5-1</span>に示されている通り、サイバーセキュリティの脆弱性を特定し、その悪用によって生じる脅威や悪影響に伴うリスクを評価し、適切にリスクをコントロールすることである。</blockquote><p><span style="color: #2b00fe;">サイバーセキュリティのリスクを評価する。悪用によって生じる脅威や悪影響に伴うリスクを評価し、リスクをコントロールする。</span></p><p></p><blockquote>(5)「ライフサイクルの全てにおいて、サイバーセキュリティを確保するための計画に基づいて設計及び製造」とは、全ライフサイクルにわたってサイバーセキュリティを確保するため、設計・製造工程における取組だけでなく、医療機関との連携、脆弱性対策(市販後のアップデート等を含む)に係る計画等も踏まえ、それが達成できるように、また、問題点や脆弱性が見つかった場合に対応できるように設計・製造を行うことである。</blockquote><p></p><p><span style="color: #2b00fe;"> 設計・製造工程における取り組みだけでなく、脆弱性対策、医療機関への報告、連携を計画し、達成する。</span></p><p>JIS T 81001-5-1 とは IEC 81001-5-1 の JIS版で、「ヘルスソフトウェア及びヘルスITシステムの安全,有効性及びセキュリティ-第5-1部」というタイトルの規格だ。</p><p>IEC 81001-5-1は、IEC 62443-4-1 の要求事項を IEC 62304 のプロセスに当てはめた形の規格 であり、すでに産業用の制御システムのセキュリティ規格として存在していた IEC 62443-4-1 を医療機器のライフサイクルプロセスに置き換えた規格だ。</p><p>実は、この規格をJIS化するにあたっては、通常は2~3年かかる作業を約1年という短い期間で実現している。これは、厚労省が 医療機器の基本要件基準 のサイバーセキュリティ要求の適合と示すために、この規格を使おうと考えていたからだ。</p><p>冒頭1の通知では、「例えば、JIS T 81001-5-1に示されている・・・」というように、JIS T 81001-5-1 以外の規格を使ってもいいよというニュアンスで説明しているが、実際のところは「JIS化したんだから、JIS T 81001-5-1 に適合しろよ」といった本音がにじみでている。</p><p>IEC 81001-5-1 のような国際規格を日本が世界に先駆けて医療機器規制に使うというのは非常に珍しいことで、これまではEUが規制に取り入れてから、日本も追随するというパターンだった。</p><p>サイバーセキュリティに関しては日本の特に医療分野、医療機器分野では対応が遅れているとされていたため、今回は厚労省が世界に先駆けて、医療機器への規制を強化したといえる。</p><p>冒頭の通知3は、医療機関向けのサイバーセキュリティに関するガイダンスになる。</p><p>サイバーセキュリティは、医療機器製造業者だけでも医療機関だけでも達成することはできない、両者と規制当局は医療情報システムの提供者などが協力してはじめて達成できる。</p><p>よって、各者の情報開示や、レガシーシステムに対する補完的対策などが重要になってくるため、医療機器製造者向けのガイダンスと医療機関向けのガイダンスの両方が発出されている。</p><p>また、現行のシステムが医療機関においてどのようなネットワークにつながっているのか、また、どのようなセキュリティ対策(=信頼境界があるのか)、どのような脅威が想定されるのかを分析すること(=脅威分析)が必要であり、医療機器製造販売業者は、今度、脅威分析図、システム構成図を医療機関に示すことが必須になってくる。</p><p>このとき使うのが脅威モデリング(データフローダイアグラムを使うのが一般的)だ。</p><p>今後、このブログの中で脅威モデリングの説明をしていきたいと考えている。</p><p>プログラム医療機器を開発しようとしてる方は、まず3月31日付けで発出された3つの通知をよく読んで内容を理解することをお勧めする。</p><p><span style="color: #2b00fe;"><br /></span></p><p></p>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-91830680233423766422023-01-01T15:58:00.002+09:002023-01-08T20:01:02.751+09:00久しぶりの投稿<p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqpNSGYgj0wdfPPPSHTz3U2A8ypDbhGfnry2AuhBNeWQfMbxL3zD-ytzBtKnKrJaomRzkGPxwQHrt1N4frwe3y1BTQCAJ5JuoVR-J0WoZ9erwhnteUhDihFE2CE3yEEwkLpH25Sy43QgMGFVQOtG5UDzz-UPa21pfHp21rN9BfNF80rCr8sA/s7360/AdobeStock_550651796.jpeg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="4912" data-original-width="7360" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqpNSGYgj0wdfPPPSHTz3U2A8ypDbhGfnry2AuhBNeWQfMbxL3zD-ytzBtKnKrJaomRzkGPxwQHrt1N4frwe3y1BTQCAJ5JuoVR-J0WoZ9erwhnteUhDihFE2CE3yEEwkLpH25Sy43QgMGFVQOtG5UDzz-UPa21pfHp21rN9BfNF80rCr8sA/s320/AdobeStock_550651796.jpeg" width="320" /></a></div>1年3ヶ月ぶりの投稿。ふと、Facebook で友人が近況を書き込んでいるのをみて、「あ、そういえばブログ更新してなかった」て気が付いた。<p></p><p>このブログを始めたきっかけは、自分の本を出版して読者との交流しながら情報発信したいと思っていたからだった。あと、組織内で思ったこと、感じたことをブログに書くことである意味ストレス解消していたのかもしれない。また、書くことで自分の考えを整理して伝えるスキルを高めたいという思いもあった。</p><p>20年以上、組込みソフトウェアの開発をしてきたが、技術者への支援の仕事を経て、今は、組込み機器からの情報をクラウドに上げて、ユーザにサービスを提供するソフトウェアの開発をマネジメントしている。在宅勤務が増えて仕事の取り組み方も変わって、仕事をしているときとしないときの、ON/OFFがはっきりするようになって、OFFのときは仕事の事を考えなくなった。</p><p>若い時は会社にいても家に帰ってきても抱えてる課題をどう解決しようかと考えていたが、今はスキルが高まってきたせいか、ONのときに課題解決の道筋が見えるようになってきたので、OFFのときは仕事のことはあまり考えないようになった。こういった状況の変化で、ブログの更新が滞っていたのかもしれない。</p><p>環境が変化したとはいえ、今になってもいろいろを思うところはある。ソフトウェアは複数のエンジニアが関わって作っていくものだし、事業も関係する人々とコミュニケーション取りながら進めて行くので、その中で何かしら感情がぶつかったりすることはある。そういうことがあると、ブログに自分の考えを書きたくなってくる。</p><p>最近思うのは、組織ってやっぱり蛸壺的になるもんだということだ。組織が大きくなるほど、エンドユーザとの接点がなくなり、自分のやっていることがユーザのためというよりは、組織のため、さらに自部門のため、さらに自分の利益のためになる。最近、他部門の技術者が「その機能、入れるのか入れないのかだけ、言ってください」という発言をしたので、「そうじゃないだろう、ユーザにとって必要かどうかを考えるんだろう」とたしなめたことがあった。上から言われたことだけやる仕事って面白くないようなって思う。自分が作ったものをユーザが喜んでくれることを糧に仕事ができれば、技術を吸収するスピードだって速くなる。</p><p>自分がそういう考えで35年以上働いてきて感じるのは、組織の中にいても自分は個人商店だという認識を持っていたのはよかったなということだ。</p><p>入社したてのころはスキルがなくて、とても独立してやっていくことはできなかったので、早く一人前になりたいと貪欲に技術を吸収しようと思っていた。ある程度、外の世界の人達と渡り合えるようになってからは、いつでも独立するぞという気持ちでいたつもりだ。</p><p>ただ、組織と自分のポリシーにオーバラップがある内は、多少イヤなことがあっても我慢しようと思った。実力さえ身につけることができれば、組織が方向性が自分の生き方と異なると思ったら、迷わずに外に出ようと考えることができた。個人商店として何とかやっていきそうという自信が付いてなければ、組織にかじり付くしかなかったけれど、いつでも個人商店としてやっていけるとなれば、組織に対してもそれ相当の発言ができる。</p><p>そして、組織の事業を支えるようなプロジェクトに関わるようになれば、顧客満足を高めることの実感を得ることができるようになる。</p><p>自分はエンドユーザにどのような価値が提供できるのかから始まり、それを実現するための技術は何か、その技術を習得するためにどうしたからいいかという順番で物事を考えるようにしている。</p><p>いろいろな技術者と話しをしていると、そういう思考ではなくて、このファンクションをどうやったら実現できるかから話しをはじめる人がいることに気が付く。</p><p>「組込みソフトエンジニアを極める」の著書では、技術的なこととともに、エンドユーザに提供する価値を実現する技術を身につけることの大切さを書いたつもりだ。</p><p>そういった思考をする訓練をしてきたことによって、さまざまな課題にぶつかったときに、組織内のセクショナリズムなど、エンドユーザ価値に関係がない、また逆行するような事柄は実にくだらないと考えることができるようになった。</p><p>35年以上ソフトウェアエンジニアとして働いてきて思うのは、やっぱりソフトウェアは人が作ってるので、人=技術者のことをよく理解しないと何事もうまくいかないということだ。</p><p>「組込みソフトエンジニアを極める」や「リコールを起こさないソフトウェアのつくり方」で、欧米と日本の技術者の考え方の違いについてしつこいくらい書いたのは、そこを理解しなければ開発はうまくいかないと直感していたし、実際、欧米で培われたプロセスアプローチはそのまま適用したのでは日本ではうまくいかないと実感したからだ。</p><p>ソフトウェアの面白さって、人と密接に関係しているところかもしれないと、今更ながら感じる。</p>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-22568022533367765912021-09-10T07:12:00.000+09:002021-09-10T07:12:43.394+09:002021年11月1日にヘルスソフトウェア向けリスクマネジメント・トレーニング講座(オンライン)を開催します<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxxOdLxlPcZXRKaOgwtQYJLAtj3kSgUlcqw89-pYyc1vPWKzmSWdWAPzTBCNlAkGRr_un4LhEVFB6c0bFSnQ10VN-vKscCwgxj54w6hgtPN2LAW2Eb-F31l_BsYmkeHiVb8RHn/s300/Training.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="200" data-original-width="300" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxxOdLxlPcZXRKaOgwtQYJLAtj3kSgUlcqw89-pYyc1vPWKzmSWdWAPzTBCNlAkGRr_un4LhEVFB6c0bFSnQ10VN-vKscCwgxj54w6hgtPN2LAW2Eb-F31l_BsYmkeHiVb8RHn/s0/Training.png" width="300" /></a></div>GHS 一般社団法人ヘルスソフトウェア推進協議会は、2021年11月1日にヘルスソフトウェア向けリスクマネジメント・トレーニング講座(オンライン)を開催します。<p></p><p>本リスクマネジメント・トレーニング講座は、GHS 開発ガイドラインの Level-1 の要求を実践するために必要な知識、技術を習得するための講座です。一般社団法人 ヘルスソフトウェア推進協議会(GHS)は、これまで、9回に渡りトレーニング講座を開催し、のべ200名以上の参加者が ヘルスソフトウェアのリスクマネジメントに関するスキルを修了しています。</p><p>本講座は、分かり易い資料、少人数に分かれたグループワーク・グループディスカッション、経験豊富な講師やモデレータによる丁寧な指導が特長の参加者の満足度が高いセミナです。</p><div><div><b>リスクマネジメント・トレーニング講座(オンラインセミナ)プログラム</b></div><div><br /></div><div>10:00~10:05<span style="white-space: pre;"> </span>開講挨拶(トレーニング講座開講の挨拶とスケジュール確認,連絡)</div><div>10:05~10:15<span style="white-space: pre;"> </span>テスト 受講者事前知識調査</div><div>10:15~11:00<span style="white-space: pre;"> </span>講義1 安全(セーフティ)の考え方</div><div>11:00~11:10<span style="white-space: pre;"> </span>アイスブレイク(Zoomのブレイクアウトルームを使ってみる)</div><div>11:10~12:00<span style="white-space: pre;"> </span>演習1 Intended Use(意図する使用)の定義と安全面とセキュリティの特質を明確化</div><div>12:00~12:45<span style="white-space: pre;"> </span>昼食休憩</div><div>12:45~16:25<span style="white-space: pre;"> </span>※途中休憩あり</div><div><span> </span><span> </span><span> </span><span> </span>演習2 演習1 Intended Use(意図する使用)の発表</div><div><span style="white-space: pre;"> </span>演習3 仮想ヘルスソフトウェアアプリのリスク分析演習</div><div><span style="white-space: pre;"> </span>演習4 リスク分析結果発表(各グループ)とディスカッション</div><div><span style="white-space: pre;"> </span>解説 分析例の解説</div><div>16:25~16:40<span style="white-space: pre;"> </span>GHS リスクマネジメント様式集(3種)と記入例とヘルスソフトウェアのサイバーセキュリティ要求について</div><div>16:40~16:50<span style="white-space: pre;"> </span>質疑応答</div><div>16:50~17:00<span style="white-space: pre;"> </span>アンケート記入・提出</div></div><div><br /></div><div>詳しくは、<a href="https://www.good-hs.jp/seminar.html" target="_blank">こちら</a>をご覧下さい。</div><div><br /></div><div>演習では仮想のヘルスソフトウェア(健康アプリ)を題材にして、危害にいたる可能性のある一連の事象、危険状態、具体的な危害をリストアップし、それらが発生する確率(可能性)と重大度を分析して対策を考えます。</div><div><br /></div><div>個人ワークの結果を持ち寄り、他社の参加者とグループディスカッションを行うことにより、自分では気が付かなかった視点があることに気付き、演習を経験することで、持ち帰って自社製品でもリスク分析できるようになることを目指します。</div><div><br /></div><div>※コンサルティング関係の方の参加はお断りしています。</div>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-43659773767544273772021-08-31T09:07:00.004+09:002021-09-02T06:55:03.425+09:00IEC 62304 準拠と謳っている RTOS が医療機器規制当局から注意喚起を受ける<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR3FmPFTXVI3O6PPR2jjaAcrkYGnlMhZ8T0F-i0qv5Ty09emfXx39mzPcS-yWQGZ1N0AESxLQnJBSmmD6J8KzSJLve_3uSPHVBdhb-PnieTwjZxdg8NAeLWSHWAPhOjjqfRid-/s2048/AdobeStock_420735893.jpeg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1253" data-original-width="2048" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR3FmPFTXVI3O6PPR2jjaAcrkYGnlMhZ8T0F-i0qv5Ty09emfXx39mzPcS-yWQGZ1N0AESxLQnJBSmmD6J8KzSJLve_3uSPHVBdhb-PnieTwjZxdg8NAeLWSHWAPhOjjqfRid-/s320/AdobeStock_420735893.jpeg" width="320" /></a></div>富士ソフトが扱う blackberry QNX リアルタイムOS に 脆弱性が見つかり、米国FDA, 日本の厚労省が 医療機関や医療機器製造業者に対して注意喚起を行っている。<p></p><p>厚労省通知 2021年8月23日 『<a href="http://www.medicounter.jp/assets/safety/iryo_anzen/000242645.pdf" target="_blank">医療機器のオペレーティングシステムに係る脆弱性への対応について(注意喚起)</a>』</p><p>本件については下記の記事の解説が分かり易い。</p><p>【ZD Net Japan 『<a href="https://japan.zdnet.com/article/35175369/" target="_blank">米政府機関、ブラックベリー製品の脆弱性で注意喚起</a>』より引用】</p><p></p><blockquote><p>米サイバーセキュリティ・インフラセキュリティ庁(CISA)は、BlackBerryの製品に存在する「BadAlloc」の脆弱性に関するセキュリティアラートを発表した。BadAllocは、2021年の初めにMicrosoftの研究者が発表した脆弱性だ。</p><p> また米国時間8月17日、BlackBerryは同社の「QNX Real Time Operating System(RTOS)」がBadAllocの脆弱性の影響を受ける可能性がある問題についてのアドバイザリーを発表した。<span style="color: #2b00fe;">QNX RTOSは医療機器や自動車、工場などで使用されており、国際宇宙ステーションでも使われている。同社は最近、QNX RTOSがおよそ2億台の自動車で使われていると明らかにしたばかりだ。</span></p><p> CISAは、QNX RTOSは一部のIoT機器やOT/ICSシステムで使用されており、これらのシステムを保護するための対策が急務だと付け加えた。BlackBerryは影響を受ける製品の完全なリストを公開している。</p><p> <span style="color: red;">CISAのアラートでは、「リモートの攻撃者にCVE-2021-22156を悪用されると、対象デバイスがサービス妨害状態に陥ったり、任意のコードが実行されたりする可能性がある。BlackBerryのQNX RTOSは幅広い製品で使用されており、この製品が侵害されると、悪意を持った攻撃者に極めて重要度が高いシステムの制御を奪われる可能性があり、国家的に重要な機能のリスクが高まる」と述べている。</span></p><p> 「CISAは、現時点ではこの脆弱性が積極的に悪用されている事例を把握していない。CISAは、重要インフラ企業や、影響を受けるQNXベースのシステムを開発、保守、サポート、使用しているその他の組織に対して、影響を受ける製品にできる限り早くパッチを適用することを強く推奨する」</p><p> CISAによれば、一部のRTOSのソフトウェアをアップデートするには、機器を取り外すか、敷地外の施設に持ち込んで、メモリーを物理的に交換する必要があるという。</p><p> BlackBerryのアドバイザリーには、同社がこの脆弱性を修正するためにリリースした多数のアップデートの情報が掲載されている。<span style="color: red;">Microsoftは4月に、BadAllocは25件のCVEにまたがる問題であり、消費者向け製品から医療用IoTや産業用IoTまでさまざま分野に影響を与える可能性があると述べている。</span></p><p> 米国の政治専門ニュースメディアであるPoliticoは8月17日、4月にBadAllocの脆弱性に関する情報が開示されて以降、BlackBerryと米国の政府関係者との間で交わされてきた舞台裏での議論について報じた。</p><p> 記事では、BlackBerryは同社の製品がBadAllocの影響を受けることを否定し、米政府がこの問題に関してアラートを公表することに抵抗したとされている。</p><p> また、CISAの担当者が、QNXシステムに関するセキュリティアラートについて、影響を受ける業界や国防総省などと事前に連携を取っていたことや、外国の政府関係者にもこの脆弱性について説明する予定であることも報じられている。</p><p> <span style="color: red;">BlackBerryは6月に、QNXはAptiv、BMW、Bosch、Ford、GM、本田技研工業、Mercedes-Benz、トヨタ自動車、Volkswagenが製造する多数の自動車に採用されていると発表している。</span></p></blockquote><p>【引用終わり】</p><p>サイバーセキュリティに関する脆弱性は市販後に見つかることがあり、それ自体はあってもまったく不思議ではないので、この脆弱性が見つかったからといって QNXの品質が悪いとは思わない。</p><p>どの製品にもありうるので、ここは粛々とパッチを当てたり、QNXの外側の環境で緩和策を取ることが重要と考える。</p><p>今回の記事で取り上げたのは、blackberry QNX について、日本の販売元の富士ソフトが QNXは IEC 62304(医療機器ソフトウェア - ソフトウェアライフサイクルプロセス)のソフトウェア安全性クラスC に準拠証明書付きで出荷されると宣伝しており、これが IEC 62304 のリスクベースアプローチの考え方から逸脱していて、単に商品を売るために 規格を利用しているに過ぎないことを示したかったからだ。</p><p>【<a href="https://www.fsi-embedded.jp/product_detail/5850/" target="_blank">QNX OS for Medical 概要・特長</a> 】より引用</p><p></p><blockquote><p>医療機器の複雑さが日増しに増加する昨今、規制の監視が益々厳しくなって来ています。根源が知られており事前認証されたコンポーネントを選択することで、認証プロセスが相当楽になります。<span style="color: #2b00fe;">QNX OS for Medical(医療用QNX OS)は、独立サードパーティにより「医療機器ソフトウェア - ソフトウェア ライフサイクル プロセス」の標準規格であるIEC 62304準拠であると評価されています。</span>この製品はARMとx86プロセッサーでサポートされています。</p><p>医療用QNX® OSは、医療機器メーカー用のQNXソフトウェア システムズソリューションの主要素です。これは、市場投入前の認証業務に必要な時間と手間を低減することで医療関係のお客様が厳しい規制要件を満たすお手伝いをするためにデザインされています。医療用QNX OSは、QNXの標準オペレーティングシステムにより100% API互換で、お客様が最大限にソフトウェアを再使用し、それぞれ異なる認証要件を持つ複数製品用の共通プラットフォームを構築できるようになります。<span style="color: #2b00fe;">この製品は独立サードパーティ評価によるIEC 62304クラスC準拠証明書付きで出荷されます。</span></p></blockquote><p></p><p>【引用おわり】</p><p>このブログサイトでも幾度となく、IEC 62304 が自動車ドメイン等で幅をきかせている機能安全規格ではなく、医療機器のインシデントに対して、医療機器のソフトウェア開発プロセスをリスクベースアプローチでの再発防止を目的として策定されたものであることを説明してきた。</p><p>機能安全規格では、製品に使用している部品の開発プロセスが機能安全規格が定めるプロセスどおりに作られているかどうかを認証することを推奨しているが、IEC 62304 はあくまでも医療機器の開発プロセスをリスクベースアプローチで開発することを求めていて、部品単位での規格適合など求めていない。</p><p><i>※機能安全という名前が良くない。安全(Safety)は機能(Function)ではない。機能的安全というのもおかしい。安全機能は手段でしかなく、本質を示していない。機能安全という言葉自体が安全の本質を目指していないと感じる。</i></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhed5v4t6l4lO-EDsUv2WR7d17YhrkrP1b21IwijZshT8YqRJ51CMShl-ESZjdMH65caEDU6TiIDSI_B5p5juTrnjaFmFOCYIbn0ZFxKgdUJs2Xo8u51TLTbalAIrWagkoMxogQ/s800/Safety1.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="530" data-original-width="800" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhed5v4t6l4lO-EDsUv2WR7d17YhrkrP1b21IwijZshT8YqRJ51CMShl-ESZjdMH65caEDU6TiIDSI_B5p5juTrnjaFmFOCYIbn0ZFxKgdUJs2Xo8u51TLTbalAIrWagkoMxogQ/s320/Safety1.png" width="320" /></a></div><p>そもそも、製品全体の構成要素の信頼性を高めることで安全性を確保しようとする設計は個別最適の発想(フォールト・アボイダンス)であり、ソフトウェアの規模が増大し、複雑化した現代では、まったくもって古い考え方である。1960年代の主流だった発想だ。</p><div>今では、左図の緑枠にあるように、製品の安全は「フェールセーフ」「フォールトトレランス」「エラー・プルーフ」といった、個々の構成要素に故障がバグがあっても安全側に倒れるようにしたり、冗長性を持たせたり、操作者は必ずミスをするという前提で設計するといった全体最適の発想を行うことが求められている。これが IEC 62304 で求められているリスクベースアプローチ(患者危害に至る危険状態が起こる要因を分析して、重大な危害が起こらないような対策を行う手法)だ。</div><div><br /></div><div>だから、RTOSのような汎用部品が何の機器に組み込まれて、どのような機能や性能を実現するために使われるかが分からない状態で、安全性を評価することはできない。</div><div><br /></div><div>例えば、列車で事故が発生したら速やかに列車を止めることが求められるが、飛行機で事故が発生したら、近くの空港まで飛行機を飛ばし続けなければらならない。同じ移動手段でも前者は止める、後者は動き続けることが求められる。</div><div><br /></div><div>使用目的(意図する使用 = Intended Use)が定まらないと、リスク分析ができないと教えている。なぜなら、同じ材質、同じ形状をしていても何に使うのかによって、危険状態に至る可能性や発生する危害は変わるからである。</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnmmg6wN26rbW9K97pW0dF_XC9lrrh6kncTMEcLjTAtsfFCKbcN75L40CZXuxYm_dLoNSKqMy0m-wFlaWO-eigD074AwSoBea8-klz2rV3WDpwCC3LTwjn0XVFxNR3R2OkcW92/s800/Safety2.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="555" data-original-width="800" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnmmg6wN26rbW9K97pW0dF_XC9lrrh6kncTMEcLjTAtsfFCKbcN75L40CZXuxYm_dLoNSKqMy0m-wFlaWO-eigD074AwSoBea8-klz2rV3WDpwCC3LTwjn0XVFxNR3R2OkcW92/s320/Safety2.png" width="320" /></a></div>この図にあるように、細い木の棒は、アイスキャンディの棒かもしれないが、医師が口の中を診る際の舌圧子かもしれない。<div><br /></div><div>後者の場合は、医療機器となり滅菌や一つ一つの包装が求められる。</div><div><br /></div><div>同じ材質、同じ形状でも、意図する使用(Intended Use)によっては、リスクが変わるのだ。</div><div><br /></div><div>よって、汎用製品である リアルタイムOS について、規格の認証が取れているから安全性が高いと主張しているのは、間違っているし、意味がない。<br /><div><br /></div><div>下記の誤った記事を見て欲しい。IEC 62304 を機能安全規格と同じように扱っている。さらに、IEC 62304 のソフトウェア安全クラスは、機器の意図する使用によってリスク分析を行いその評価によってクラスが変わるはずなのに、なにに使われるのか分からない段階で、ソフトウェア安全クラスC であると言っている。一番高いクラスにしておけばいいでしょという考えならば、それはリスクベースアプローチの本質をまったく理解していないことになる。ようするに、IEC 62304 の規格趣旨が理解できていない証拠である。</div><div><p>【MONOist 組込み開発ニュース『<a href="https://monoist.atmarkit.co.jp/mn/articles/2011/30/news045.html" target="_blank">工業、自動車、医療機器の機能安全認証を取得した最新版RTOSを提供開始</a>』】より引用</p><p></p><blockquote><p>BlackBerryは2020年11月9日、機能安全認証を取得したリアルタイムOSの最新版「QNX OS for Safety 2.2」の提供を開始した。自動車や組み込みソフトウェア開発などにおいて、認証取得作業を軽減し、迅速なシステム開発を可能とする。</p><p>最新版のQNX OS for Safety 2.2は、「QNX Neutrino RTOS」をベースとする。第三者認証機関のテュフ ラインランドから、「IEC 61508 SIL3」(工業)、「ISO 26262 ASIL D」(自動車)、<span style="color: #2b00fe;">「IEC 62304 Class C」(医療機器)の機能安全認証を取得している。</span></p><p> さらに、「ISO 26262」「IEC 61508 TCL3/T3」の要件に準拠したC/C++ツールチェーンも採用している。これにより、QNXの機能安全性製品に安全認証取得済みのC++ランタイムライブラリが含まれることとなった。</p><p> 同社は、最新版のQNX OSを利用することで、開発期間を短縮しながら安全性や信頼性の高いシステムを開発し、開発費用の削減が可能になるとしている。</p><p></p></blockquote><p>【引用おわり】</p><p>一方で、富士ソフトは、IEC 62304 を医療機器のソフトウェア開発に適用する際に、支援を行うサービスも行っており、そのサービスを紹介したページでは、IEC 62304 の趣旨を正しく理解しているように見える。【<a href="https://www.fsi-embedded.jp/iomt/" target="_blank">対象ページ</a>】</p><p>なぜ、このような矛盾が生じるのか。理由は簡単だ。QNX が IEC 62304 に準拠したと宣伝に使っている部門と、IEC 62304 をコンサルテーションしますといっている部門が異なっており、前者は IEC 62304 の中身を読んでおらず(または読んでいても理解しておらず)規格適合したと表明すれば、他のRTOSと差別化ができ、規格の趣旨をよく理解できていないユーザから購入してもらえると考えているからだ。</p><p>そして、規格の内容や趣旨を熟知している 第三者認証機関が 機能安全ではない IEC 62304 を汎用ソフトウェア製品に対して適合証明してしまうのか、これも商売になるからだ。(規格適合を証明するには相当な費用がかかる)</p><p>規格を熟知した認証機関が誤った使い方をしていることを知っていながら、規格適合証明を出しているのだから、こっちの方が罪が重いと思う。</p><p><span style="color: #2b00fe;">このブログで必要に問題のあるソフトウェア製品について批判する記事を書くのは、これらの認証がエンドユーザの安全を目指して実施されているのではなく、単に商品を売りたいために認証を取っていると思うからだ。</span></p><p>ここで冒頭の blackberry QNX リアルタイムOS に 脆弱性が見つかり、米国FDA, 日本の厚労省が 医療機関や医療機器製造業者に対して注意喚起を行っているという件に話しを戻す。</p>blackberry QNX リアルタイムOS は 第三者認証機関のテュフ ラインランドから、「IEC<br />61508 SIL3」(工業)、「ISO 26262 ASIL D」(自動車)、「IEC 62304 Class C」(医療機器)の機能安全認証を取得している(IEC 62304は機能安全規格ではないので、この記述は誤り)と、富士ソフトはWEBサイトで、規格の認証を取得していて、他の製品より安全ですよと主張している。<p>揚げ足を取るつもりはないが、今回の脆弱性の発見で脆弱性を突かれると リアルタイムOSを使っている製品が悪用され、患者危害に至る可能性があるためパッチを当てる必要があることが分かった。</p><p>QNX は「信頼性が高いとされていた」ため、医療機器にも多く使用されていたので、米国や日本の規制当局が冒頭の注意喚起を出したわけだ。</p><p>QNXは自動車にも多く使われているようなので、自動車業界でも対応が求められているだろう。</p><p>ただ、QNXが対象システムのどこに、何に使われているのかによって、リスクの大きさは異なる。だから、製品ごとにリスク分析を行うことが重要なのであって、部品の製品開発のプロセスが規格に適合していることを主張するのはおかしいし、医療機器の場合、規格趣旨から特に間違っている。</p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisyKRNP6ivbRtRrbsedCGRMRRGKNTfuq75Th-6V5mL_uUzH0E0Gt-5oVrmOH3ADi5cBFcIHfKMHgBAD1lhMqoxrwl3gndUdfWmH-Q_HaoFUh_3TRN30nxCQcHJjxGCqpXfLUgw/s800/Safety1.png" style="clear: left; display: inline; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="530" data-original-width="800" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisyKRNP6ivbRtRrbsedCGRMRRGKNTfuq75Th-6V5mL_uUzH0E0Gt-5oVrmOH3ADi5cBFcIHfKMHgBAD1lhMqoxrwl3gndUdfWmH-Q_HaoFUh_3TRN30nxCQcHJjxGCqpXfLUgw/s320/Safety1.png" width="320" /></a>この図を再掲するが、個別最適で安全設計をする時代ではないのだ。全体最適の発想で、意図する使用を明確にして、その上でリスクを分析し、危害の重大度を考慮し、重大な危害に至るケースを優先して、対策を立てていることが、患者や利用者の被害を効率てきに低減することにつながる。</p><p>このリスクベースアプローチの考え方を理解せずに、規格適合を主張し、商品を売ろうとする者は、場合によっては、エンドユーザのリスクを高めてしまっている可能性さえある。</p><p>汎用ソフトウェア部品を利用する開発者は、ソフトウェア部品の開発プロセスの認証を気にするのではなく、そのソフトウェアがどのような検証を行ったのか、テストの網羅性やテストケースの設計はどうだったのかを精査するべきだ。</p><p>規格ビジネスの悪は、規格が求める内容を理解しないユーザにお墨付きをちらつかせて商品を売ろうとする側面を増長させる点にある。</p><p>単純な商品販売における競争のための手段ならまあ、無駄ではないし、それもありかと思うが、そこにユーザの健康や安全がかかっているとすれば、それは間違いだと言わなければかえって危ないと思っている。</p><p>セキュリティ上の脆弱性は市販後に見つかったら、粛々を対応することでよい。</p><p>だた、これを期に、汎用ソフトウェア製品の規格適合証明が製品の安全性で担保するのは間違いであるということを再認識して欲しい。</p><p></p></div></div>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-67276204522627278622021-07-07T09:05:00.006+09:002021-07-07T09:09:48.802+09:00医療機器プログラムの該当性のガイドラインが改訂され、非医療機器の範囲が広がった?(間違い)<p> 医療機器プログラムの該当性のガイドラインは 2021年3月31日に発行されたもので2014年に発行されたものから置き換わりました。(<a href="https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/0000179749_00004.html" target="_blank">厚労省のページ</a>)</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoZfEQKj50L2Z3STaowucGaE0kYhAK5lgkf_p1J5bl3G5O3_RG-GoBfm8Fd-EfZts07xAUAens11_DTdZHgXbvmgHRoFcgW8U0590oyKv_z_T4JV1sDh1ehwo_ebVZY-a-5Pkp/s800/GHS1.png" style="display: inline; margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="480" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoZfEQKj50L2Z3STaowucGaE0kYhAK5lgkf_p1J5bl3G5O3_RG-GoBfm8Fd-EfZts07xAUAens11_DTdZHgXbvmgHRoFcgW8U0590oyKv_z_T4JV1sDh1ehwo_ebVZY-a-5Pkp/w400-h240/GHS1.png" width="400" /></a></div><p></p><p>GHS(ヘルスソフトウェア推進協議会)にて、第3回ヘルスソフトウェアのリスク分析入門セミナー(オンライン)を 2021年8月23日に実施します。</p><p>このオンラインセミナーの「ヘルスソフトウェアー規制と規制対象外の境界の考え方」にて、今回改訂されたプログラム医療機器該当性のガイドラインについても解説します。</p><p><br /></p><p><b>ヘルスソフトウェアのリスク分析入門オンラインセミナー プログラム</b></p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><p>13:00~13:10 開講挨拶(スケジュール確認,連絡)</p><p>13:10~13:30 GHS と GHS 開発ガイドラインの紹介 </p><p><span style="color: #2b00fe;">13:30~14:00 ヘルスソフトウェア-規制と規制対象外の境界の考え方</span></p><p>14:00~14:15 休憩</p><p>14:15~15:00 ヘルスソフトウェアの周辺に存在するリスク(健康リスク)</p><p>15:00~16:00 リスク分析の考え方とリスク分析演習(仮想ヘルスソフトウェアを想定して)</p><p>16:00~16:15 質疑応答</p><p>16:15~16:30 アンケート記入・提出</p></blockquote><p><a href="https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/0000179749_00004.html" target="_blank">厚労省のページ(医療機器プログラムについて)</a>では、対象のソフトウェアが医療機器に該当するかしないかを判定した事例も随時 Excel 表にて提示されています。</p><p>また、厚労省は医療機器プログラムの早期実現推進を目的として、医療機器プログラムに関する相談を「医療機器プログラム総合相談」として一元的に受け付ける窓口をPMDAに設置しました。</p><p><a href="https://www.pmda.go.jp/review-services/f2f-pre/strategies/0011.html" target="_blank">SaMD一元的相談窓口(医療機器プログラム総合相談)</a></p><div>一方で、これまで医療機器の該当性の相談を都道府県の担当窓口にて受けてきましたが、今後、プログラムの医療機器該当性の相談については、厚生労働省医薬・生活衛生局監視指導・麻薬対策課にて一元的に行うこととなったようです。</div><div><br /></div><div>なお、医療機器に該当しないプログラムの広告相談につきましては、引き続き、都道府県にご相談とのことです。</div><div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNfZLrUW6Bb84mL-dpwMpUz_BL_Z3gHPkr54eMgYaA7EqZBz0hrJX67qj7VFJnWbeV5fmOTgXs4XKe5uJWW3NNKlzoxmUnTd0H_eqiIqfUPjdgWamdCcq2JLUG-FdbnapBlgb5/" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="" data-original-height="667" data-original-width="580" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNfZLrUW6Bb84mL-dpwMpUz_BL_Z3gHPkr54eMgYaA7EqZBz0hrJX67qj7VFJnWbeV5fmOTgXs4XKe5uJWW3NNKlzoxmUnTd0H_eqiIqfUPjdgWamdCcq2JLUG-FdbnapBlgb5/" width="209" /></a></div></div><div>医療機器プログラムの該当性のガイドライン が改定されたことで、非医療機器の範囲が拡大されたとミスリードして、下記のようなことを書いているサイトがありますが、これは間違いです。(厚労省確認ずみ)</div><div><div></div><blockquote><div><i><span style="color: #cc0000;">厚労省が今年3月31日より施行したプログラム医療機器のガイドラインによると、このような健康管理のためのプログラムは非医療機器としてリリースが可能とのこと。</span></i></div><div><i><span style="color: #cc0000;"><br /></span></i></div><div><i><span style="color: #cc0000;"><u>つまり非医療機器部分が拡大されたわけで、このガイドラインを活用すれば、非医療機器=薬事法の外でいろいろな仕掛を行うことが可能となります。</u></span></i></div></blockquote><div></div></div><p>米国もそうですが、医療機器と非医療機器の境界にあるヘルスソフトウェア、ヘルスアプリはどんどんリリースされてきており、各国の規制当局もそのソフトウェアが医療費の削減に貢献されるのであれば歓迎したいというスタンスで、厚労省も効果・効能があって、医療機器にするなら支援しますよといっています。</p><p>一方で、医療機器と非医療機器の違いや、健康被害に至るようなリスクがあるのかないのかといったリスクマネジメントについて、よく分からないままソフトウェアをリリースし、商品を売りたいがために、効果・効能的なことを謳ってしまって、広告規制に引っかかるといったケースも増えてくると思います。</p><p>GHSのリスク分析入門セミナーでは、規制と規制対象外の違いや、どんなリスクが想定されるのか、また、リスク分析とはどのようにやるのかについて解説します。</p><p>セミナーの詳細については、GHSの<a href="https://www.good-hs.jp/seminar.html" target="_blank">こちらのページ</a>からご確認ください。</p><p><br /></p>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-44499157585984064612021-03-23T14:42:00.003+09:002021-03-23T14:43:47.494+09:00人工呼吸器は不足したからといって簡単に作れるもんじゃない<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjotmz8Pig9dxLLz1EXar5mZsGktqGDyZwN7ZKjNifg-grezz_xzgF3FP7iPoW7WMkqO6_kLEk8lnT9bAeeFxD2Www16SaQVQZXjyd_laJg3A5LNpR1QRFaQPVwZ-3MOek1iCxF/s640/%25E4%25BA%25BA%25E5%25B7%25A5%25E5%2591%25BC%25E5%2590%25B8%25E5%2599%25A8640x363.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="363" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjotmz8Pig9dxLLz1EXar5mZsGktqGDyZwN7ZKjNifg-grezz_xzgF3FP7iPoW7WMkqO6_kLEk8lnT9bAeeFxD2Www16SaQVQZXjyd_laJg3A5LNpR1QRFaQPVwZ-3MOek1iCxF/s320/%25E4%25BA%25BA%25E5%25B7%25A5%25E5%2591%25BC%25E5%2590%25B8%25E5%2599%25A8640x363.png" width="320" /></a></div>『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2020/04/blog-post.html" target="_blank">他業種の医療機器製造業参入について(人工呼吸器そんなに簡単に作れるの?)</a>』の記事をおよそ1年前に書いた。<p></p><p>時は流れて最近、人工呼吸器の使い方を 病院の臨床工学士の皆さんに説明する場に立ち会う機会があった。</p><p>自分は人工呼吸器はあまり詳しくないので、初めて聞く内容ばかりだったが、かなり専門性のある内容であることは分かった。</p><p>例えば、マスクが外れたことを検知したときにアラームを鳴らして、いったん酸素の供給を止めるが、マスクを付け直したことを検知したら自動的に再稼働するとか、使用前点検の記録を各病院のルーティーンに合わせてカスタマイズできるとか。</p><p>そういった専門的で臨床使用する場合の仕様が人工呼吸には必要なんだということが分かったので、『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2020/04/blog-post.html" target="_blank">他業種の医療機器製造業参入について(人工呼吸器そんなに簡単に作れるの?)</a>』の記事を書いた頃の、「人工呼吸器不足しているので作ってみました」的な記事はいったい何だったのかと思った次第だ。</p><p>たぶん、臨床の現場では、それは役に立たない代物であり、実際には 睡眠時無呼吸症候群の治療用のCPAPの代用品にできるかどうかくらいだったのだろうと思う。</p><p><br /></p><p>医療機器ってそんなに簡単に参入できるもんじゃないよなということを再認識したとともの、医療機器を作るなら医療の現場をじっくり見て臨床的に何が行われているのかをちゃんと見ないとダメだと思った。</p>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-35133555071102870032020-07-07T08:57:00.000+09:002020-07-07T08:57:00.854+09:00組込みソフト開発とクラウドソフト開発の違い30年近く組込みソフトウェア開発に携わってきたが、ここに来てクラウドソフトウェアサービスの開発に関わっている。<br />
<br />
そこでだいぶ様子が違うことが分かってきた。今回はその違いについて書いてみたい。<br />
<br />
IoT機器(組込みソフトウェア機器)を無線/有線ネットワークでクラウドに接続し、クラウドアプリケーションソフトウェアでサービスを提供するというスタイルが増えつつある。<br />
<br />
かつて、組込みソフトウェアは出荷時のソフトウェア品質を担保するためウォーターフォール的な開発プロセスが取られてきたが、ソフトウェアの規模が増大するにつれて、組込みソフトウェアでも一部または全体にアジャイル的なプロセスが適用されるようになった。<br />
<br />
一方で、クラウドアプケーションソフトウェアの開発はどうだろう。クラウドアプリケーションソフトウェアの開発は DevOps だと言われる。<br />
<br />
DevOps については、『<a href="https://www.buildinsider.net/enterprise/devops/01" target="_blank">DevOpsとは何か? そのツールと組織文化、アジャイルとの違い</a>』の解説がわかりやすい。<br />
<blockquote class="tr_bq">
DevOpsとは「開発チーム(Development)と運用チーム(Operations)がお互いに協調し合うことで(図1参照)、開発・運用するソフトウェア/システムによってビジネスの価値をより高めるだけでなく、そのビジネスの価値をより確実かつ迅速にエンドユーザーに届け続ける」という概念である。</blockquote>
【引用おわり】<br />
<br />
ようするに、開発しながら運用も行うという、組込みソフトウェアを長年やってきたエンジニアとしては、ちょっと衝撃的な開発スタイルだ。<br />
<br />
これが実現可能となっているのは、クラウドサービス提供各社(Microsoft Azure や Amazon AWS等)のクラウドアプリケーションが、クラウド上での各種サービスアプリケーションの組み合わせで、目的を果たせるようになっているところにある。<br />
<br />
最終的なUI部分の作り込みは必要だが、IoT機器との接続や、アーカイブ、二次処理、データからのトリガー、セキュリティ確保等々、すでにあるサービスの組み合わせでかなりことができる。<br />
<br />
これらのサービスの組み合わせの開発もクラウド上で行うので、クラウドアプリの開発にはPCとインターネットがあれば、それだけでできてしまう。<br />
<br />
ただ、クラウドアプリの開発には、各社がクラウドサービスで提供するサービス群を使いこなすためのノウハウ(多くはWEBに情報があるが、使いこなすには経験が必要)をもったエンジニアが必要であり、この主の知識・スキルはかつての組込みソフトエンジニアが持っている知識・スキルとは異なると感じている。<br />
<br />
ちなみに、Microsoft は今後のもうけの種をIoT や PC に搭載する Windows OSの販売から、クラウドサービス(Azure)の使用料に大きく舵を切っている。今や、Microsoft Office も Microsoft 365 でクラウドサービスになりつつある。<br />
<br />
Microsoft は IoTのOSは Windows にこだわっておらず、Linux でもよいと考えている。だから、最新のWindows 10には WSL(Windows Subsystem for Linux)を追加できるし、Linux から Azure への接続もまったく問題にしていない。<br />
<br />
実際やってみてわかるのは、IoTからクラウドへの接続費用とクラウドサービスの使用料はそれなりにかかる。クラウドへの接続のセキュリティレベルを高くしようとすると、それだけ接続料は上がるし、クラウドサービスは使用するサービスの組み合わせでどんどん料金が上がっていく。<br />
<br />
エンドユーザは、さまざまなクラウドサービスが無償で提供されている気分になっているが、実際にはかなりのコストがかかっていて、商品の代金やサブスクリプション費用にそのコストが上乗せされている。<br />
<br />
商品の価格にクラウドサービスのコストを転嫁すると、商品を売り続けないとダメなので、各企業ともサブスクリプションでエンドユーザからお金をもらいたい。そのためには、Eコマースのサービスを導入する必要があり、その投資も馬鹿にならない。<br />
<br />
また、一度、クラウドサービスをエンドユーザに提供し始めると、そう簡単にはやめられなくなる。クラウド業者をスイッチするこは理論的には可能だが、各種提供されるクラウドサービスのインタフェースがまったく同じではないので、実質的には難しい。<br />
<br />
よって、クラウドサービス提供業者はクラウドサービスの利用企業を囲い込むことができる。クラウドサービスの提供にはかなりの費用がかかると思うが、それに見合った利益も確保できるので、おいしい商売だと感じる。<br />
<br />
さて、DevOps の話にもどると、クラウドサービスでエンドユーザにどんな価値が提供できるのかは、実際やってみないとわからない部分が多い。<br />
<br />
また、クラウドへアクセスする部分のUIは比較的簡単に変更可能であるため、ユーザの要望に応じて、運用しながら変更していくこともできる。<br />
<br />
そこが、組込みソフトウェアの開発との大きな違いだと感じる。組込みソフトウェアの場合、ネット経由でシステムソフトウェアのアップデートがやりやすくなったとはいえ、リリース時のソフトウェア品質の担保は必須であり、変更にもかなり気を遣うし、検証や妥当性確認の工数も必要だ。<br />
<br />
一方でクラウドアプリケーションの場合は、すでに完成されたサービスを組み合わせるため、個々のサービスの信頼性は確保されており、データの流れを変えていくようなイメージで変更ができる。<br />
<br />
同じことを組込みソフトウェアで実現することも、ソフトウェアアーキテクチャ次第で可能ではあるが、最初のシステムアーキテクチャの構築が難しい。クラウドアプリケーションの場合は、すでにシステムアーキテクチャが用意されている状態で利用を始めるので、最初の苦労はない。<br />
<br />
ちなみに、クラウドアプリケーションで提供される個々のサービスの完成度が高いからといって、試行錯誤的な開発をしていたのでは、エンドユーザの対する品質は担保できない。<br />
<br />
アジャイルを単純な試行錯誤的な開発開発スタイルだと思っているエンジニアはさすがに少数になったと思うが、ひょっとして今でもそれなりの数いるのではないかと疑っている。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih_lZs5SScA4BtiRKi53020_UY4SpNW_UEYBghg6OocWg4nnsQUrtXjm2UVDssnCwefocIpQctvT9m88BE38Xovc63lnk3Y-vOlhxM64Grkdfw7n_sDyhSXkD3s0CX3c7V06ur/s1600/AGAIL.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="499" data-original-width="347" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih_lZs5SScA4BtiRKi53020_UY4SpNW_UEYBghg6OocWg4nnsQUrtXjm2UVDssnCwefocIpQctvT9m88BE38Xovc63lnk3Y-vOlhxM64Grkdfw7n_sDyhSXkD3s0CX3c7V06ur/s320/AGAIL.jpg" width="222" /></a></div>
そういう方には、『<a href="https://amzn.to/2ZLun2b" target="_blank">アジャイル開発のプロジェクトマネジメントと品質マネジメント: 58のQ&Aで学ぶ</a>』を読むことをお勧めする。<br />
<br />
日立製作所でアジャイル開発の品質保証を実践してきた筆者らが、本当の意味での品質を担保したプロのアジャイル開発とは何かについてレクチャーしてくれている。<br />
<br />
自分もまだ全部腹に落ちておらず勉強中だが、クラウドアプリケーション開発において実践しないといけないと思っている。<br />
<br />
IoT(組込み)ソフトエンジニアとクラウドソフトエンジニア、この二種類のソフトウェアエンジニアが協力しないと、今どきのクラウドサービスが成り立たない。<br />
<br />
この二種類のエンジニアは似て非なる者だと思うので、これらの開発をうまくコーディネイトできる人材が成功の鍵となるのではと思っている。<br />
<br />
ソフトウェアとハードウェアのつなぎについても、両方の知識や経験をもった技術者(=組込みソフトエンジニア)の存在が重要だったが、IoT と クラウドについても両方の知識・スキルを持ったエンジニアがシステムの全体を俯瞰しながら、適宜最適となるようにソフトウェア開発プロセスを選択的に適用していく必要があるし、二つの文化の違いを理解した上で、それらを上手にマネジメントする必要がある。<br />
<br />
明らかに10年前、20年前とは、ソフトウェアの開発スタイルが変わりつつある。クラウドサービスに関しては、クラウドアプリを開発できるエンジニアをどれだけ増やせるかがクラウドサービス提供者の売り上げアップの鍵となるため、クラウドサービスの技術を学ぶための教育コンテンツが驚くほど豊富にWEB上に存在する。それもすべて無償だ。<br />
<br />
かつて組込みソフトエンジニアのための教育教材がないということで、<a href="http://www.sessame.jp/" target="_blank">SESSAME</a>が作られたのだが、クラウドエンジニアの教材は豊富に提供されている。このソフトウェアエンジニアのトレーニングという部分での進化もすさまじい。<br />
<br />
ただ、勉強することが山ほどあって、分業しないとやってられないという現実はある。だからこそコーディネータの役割は重要だと感じる。<br />
<br />
DevOpsを成功させるには、エンドユーザの対する価値と時代による価値の変化を敏感に感じ取るセンスも必要だし、価値をビジネスに結びつけるための戦略を考え、その戦略を実現するための技術が何であるかがわかるようでないとうまくいかない。<br />
<br />
組込むソフトウェアとクラウドソフトウェア、新しい時代のソフトウェアエンジニア像について、今後も考えていきたい。sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-70467800566012597482020-05-15T15:25:00.002+09:002020-05-15T16:02:11.406+09:00IoT(組込み系)のソフトウェア技術の e-Learning コンテンツが新型コロナウイルス感染症緊急対策で助成金を利用できます(東京都)<div style="text-align: center;">
<div style="text-align: left;">
<a href="http://www.sessame.jp/e-learning/index1.htm" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="523" data-original-width="453" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiCHXUyLVx90RRheLzrSonyGdW7lNYTcx092WVzo7XOixUZw_7N7aoJ_H9vzCz0TracUyi5lfZXrwh5YoMOPAEi3GSoKvG78E5J3W7mJAf6hzv8RKmHZQKP5WosUSe-TwvQSs7/s320/SESSAME_e-Learning003.png" /></a></div>
<div style="text-align: left;">
SESSAMEがリリースした 組込みソフトの e-Learning コンテンツについて、東京都が用意した新型コロナウイルス感染症緊急対策で、費用の4/5(上限32万円)の助成申請ができます。</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
東京都に事業所がある資本金3億円以下、従業員300人以下の企業であれば、<a href="https://www.hataraku.metro.tokyo.lg.jp/kansensyo/e-learning/index.html?fbclid=IwAR07ykkTG7Gk7dLxVtgyhDcCKCR1qpimSY3GZQRuXuhY-uQ_sA2P3ngmumw" target="_blank">新型コロナウイルス感染症緊急対策の中小企業人材オンラインスキルアップ支援助成金を使い、e-Learning 費用の4/5(上限32万円)の助成</a>を申請することができます。</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
SESSAMEの e-Learning WEBコンテンツは 月額3000円で見放題なので、およそ100名のエンジニアに下記のコンテンツを一か月間 約6万円の費用で受講させることができます。</div>
</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
現在リリースされているタイトル</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<table border="1" cellpadding="3" style="width: 528px;"><tbody>
<tr><td align="center" bgcolor="#00ffff"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">o.</span></b></td><td align="center" bgcolor="#00ffff"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">カテゴリ</span></b></td><td align="center" bgcolor="#00ffff"><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">講義タイトル</span></b></td><td align="center" bgcolor="#00ffff"><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">リリース時期</span></b></td><td align="center" bgcolor="#00ffff"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">詳細</span></b></td></tr>
<tr><td align="center"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">WB-01</span></b></td><td align="center" rowspan="2"><span class="font-small" style="font-size: 12px; line-height: 15.6px;"><b>初級</b></span></td><td><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;"><span style="font-family: "ms pゴシック"; font-size: 10pt;">プログラミング<span lang="EN-US">/</span>テストの基礎</span></span></b></td><td align="center"><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">2020年04月</span></b></td><td align="center" rowspan="2"><a href="http://www.sessame.jp/e-learning/BiginnersClassContents/index2.htm" target="_self"><img border="0" src="http://www.sessame.jp/e-learning/images/img_n006.gif" height="20" width="20" /></a></td></tr>
<tr><td align="center"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">WB-02</span></b></td><td><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;"><span style="font-family: "ms pゴシック"; font-size: 10pt;">構造化分析・設計の基礎</span></span></b></td><td align="center"><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">2020年04月</span></b></td></tr>
<tr><td align="center"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">WM-01</span></b></td><td align="center" rowspan="8"><span class="font-small" style="font-size: 12px; line-height: 15.6px;"><b>中級</b></span></td><td><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;"><span style="font-family: "ms pゴシック"; font-size: 10pt;">組込みシステム開発における知的財産権</span></span></b></td><td align="center"><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">2020年04月</span></b></td><td align="center" rowspan="8"> <a href="http://www.sessame.jp/e-learning/MiddleClassContents/index2.htm" target="_self"><img border="0" src="http://www.sessame.jp/e-learning/images/img_n006.gif" height="20" width="20" /></a></td></tr>
<tr><td align="center"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">WM-02</span></b></td><td><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;"><span style="font-family: "ms pゴシック"; font-size: 10pt;">構成管理(理論編<span lang="EN-US">/</span>実践編)</span></span></b></td><td align="center"><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">2020年04月</span></b></td></tr>
<tr><td align="center"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">WM-03</span></b></td><td><b><span style="font-family: "ms pゴシック"; font-size: 10pt;">リアルタイムシステム設計(理論編<span lang="EN-US">/</span>実践編)</span></b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;"><span style="font-family: "ms pゴシック"; font-size: 10pt;">プラットフォーム選定の観点(<span lang="EN-US">RTOS</span>編)</span></span></b></td><td align="center"><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">2020年04月</span></b></td></tr>
<tr><td align="center"><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">WM-04</span></b></td><td><b><span style="font-family: "ms pゴシック"; font-size: 10pt;">テスト・レビュー・インスペクション<span lang="EN-US"><o:p></o:p></span></span></b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;"><span style="font-family: "ms pゴシック"; font-size: 10pt;"></span></span></b></td><td align="center"><b> </b><b><span class="font-small" style="font-size: 12px; line-height: 15.6px;">2020年04月</span></b></td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
申請期間は第6回の最後が 9月21日なので、申請する企業はお早めに。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
------------- SESSAME の e-Learning コンテンツについて ----------</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
組込みソフトウェア管理者・技術者育成研究会(SESSAMEは) これまで CD-ROM で提供してきた SESSAME e-Learning Series のコンテンツを WEBコンテンツに移行しています。(すべてのコンテンツの移行が完了するまで、CD-ROMでの販売も継続します。) </div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
今回、初級コンテンツ2講座と中級コンテンツ 5講座を WEBコンテンツ化しました。これまで CD-ROM 1コンテンツ 5000円で、さらに、多人数で視聴する場合は上映権を設定していましたが、WEBコンテンツではひとりのユーザがすべてのリリースコンテンツを 1ヶ月3000円+税で視聴できるようになります。</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
これにより、短期集中的に組込みソフトウェアを学習したい方、長期に渡り学習したい方の両方にニーズに対応できるようになります。</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
この機会に是非 SESSAME e-Learning Series (WEBコンテンツ版)をご利用ください。</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<a href="http://www.sessame.jp/" target="_blank">SESSAME WEBサイト</a></div>
<div class="separator" style="clear: both;">
<a href="http://www.sessame.jp/e-learning/index1.htm" target="_blank">SESSAME e-Learning Series (WEB版)</a></div>
<div class="separator" style="clear: both;">
<br /></div>
sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-91997535688253661362020-04-21T13:45:00.000+09:002020-04-21T13:45:44.347+09:00『ソフトウェア系国際規格の認証の現状について』の記事に対するコメントと回答2019-10-20に投稿した『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/10/blog-post.html">ソフトウェア系国際規格の認証の現状について</a>』の記事に対して2020-02-10にコメントをもらっていて、確認&承認を忘れており、昨日気が付いて承認をしました。2ヶ月以上放置してしまい申し訳ありません。<br />
<br />
改めて、コメントの内容をここで紹介し、回答も書きたいと思います。<br />
<br />
ーーーーコメント ーーーー<br />
<br />
匿名 さんのコメント...<br />
いつも有益な記事をありがとうございます。<br />
汎用ソフトウェアが医療ソフトウェア規格の認証を受けることは意味が無いということは、ソフトウェアを含む医療機器開発には、汎用OSはもちろん、コンパイラが提供するライブラリも使用できないということですね?<br />
リアルいタイムOSはもちろん、Linuxのような巨大なOS相当も、意図する使用を考慮してフルスクラッチが必要であるということですね?もしくは、LinuxクラスのOSは使用してはいけないということですね?<br />
C言語ならいざ知らず、C++やJava 等の言語のメカニズムに相当する部位も汎用ソフトウェアと言えますから、それも使えないということですね?<br />
<br />
ーーーーコメントに対する回答 ーーーー<br />
<br />
さて、「汎用ソフトウェアが医療ソフトウェア規格の認証を受けることは意味が無いということは、ソフトウェアを含む医療機器開発には、汎用OSはもちろん、コンパイラが提供するライブラリも使用できないということですね?」のご質問に回答します。<br />
<br />
汎用ソフトウェア(OTS: Off The Shelf Software)は OTS として検証・評価を行います。IEC 62304 はリスクベースアプローチを採っているため、何に使うのかが定まっていない状態で、リスクベースアプローチのプロセス規格を適用することは意味がないと言っているのであり、医療機器にOTSを使用できないとは一言も言っていません。<br />
<br />
米 FDA は <a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents/shelf-software-use-medical-devices">医療機器に使用するOTSに対するガイダンス</a>を発行しており、このガイダンスでは「そのOTSを医療機器に使用したときの懸念レベルを定めて、ハザード分析すること」を医療機器の製造業者に求めています。また、OTSの検証・評価も必要です。これもリスクベースアプローチです。<br />
<br />
これについても勘違いしているOTSベンダーが多いのですが、OTSベンダーができるのはOTSの検証(=Verification)の部分であり、OTSが医療機器に使われたときの懸念レベルの推定やハザード分析は、医療機器製造業者が行います。正確には、その OTSを何に使うのか知っている医療機器製造業者しか、懸念レベルの推定やハザード分析はできないということです。<br />
<br />
もちろん、Windows や Linux を医療機器に使用することもできますが、それらOTSを医療機器に使用したときのリスクの分析(OTSに障害が起きたときの患者への危害の重大さや発生確率の分析と評価)がもとめらます。<br />
<br />
記事の中でも説明したつもりですが、機能安全のアプローチである認証が取れたOTSを使用することを求めるという考え方と、意図する使用(=Intended Use)を明確にした上で、リスクベースアプローチでOTSを使用するという考え方は、元のコンセプトが異なるということです。<br />
<br />
リスクベースアプローチの考え方であっても、OTSが使えないということはありません。OTSがどんな用途の医療機器に使用するのかを分析した上で、必要な検証、評価を求めています。<br />
<br />
また、コンパイラは 医療機器に組み込まれるソフトウェアではないものの、製品の品質に影響を与えるQMSソフトウェアであることから、そのリスクレベルに応じてバリデーションを求められます。(ISO 13495:2016 より)<br />
<br />
さらに、近年の医療機器規制の中のサイバーセキュリティ要求により、汎用ソフトウェアの脆弱性の監視とパッチ対応は医療機器製造業者に対する義務となりつつあります。<br />
<br />
いずれにせよ、汎用OSやコンパイラが医療機器に使えないということは一切ありません。<br />
<br />sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-91669789432361923692020-04-18T07:18:00.004+09:002020-04-18T07:53:32.889+09:00他業種の医療機器製造業参入について(人工呼吸器そんなに簡単に作れるの?)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7cXFw6T4qFT5kQ0wz9sDv3pb9d_Dyu0Px88vIdlLK3TCyvIgBaoih4uqYqdQS24-x84LrnXGIL3CsMFhqEP6VjGrU-wMINED9qoOQL2WDdj23otP3PpGpz2Gx6R_7DD8rzBQY/s1600/%25E4%25BA%25BA%25E5%25B7%25A5%25E5%2591%25BC%25E5%2590%25B8%25E5%2599%25A8640x363.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="363" data-original-width="640" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7cXFw6T4qFT5kQ0wz9sDv3pb9d_Dyu0Px88vIdlLK3TCyvIgBaoih4uqYqdQS24-x84LrnXGIL3CsMFhqEP6VjGrU-wMINED9qoOQL2WDdj23otP3PpGpz2Gx6R_7DD8rzBQY/s320/%25E4%25BA%25BA%25E5%25B7%25A5%25E5%2591%25BC%25E5%2590%25B8%25E5%2599%25A8640x363.png" width="320" /></a></div>
新型コロナウイルスの蔓延で人工呼吸器が足らなくなるかもしれないというニュースが駆け巡っている。<br />
<br />
それを受けて、自動車やその他の産業から、急遽医療機器の製造を支援したり、医療機器そのものを作りますといった発表も散見される。『<a href="https://monoist.atmarkit.co.jp/mn/articles/2004/15/news049.html" target="_blank">ホンダが新型コロナ軽症者の搬送車両を開発、陰圧状態の後部座席で飛沫感染防ぐ</a>』の記事中で、トヨタ自動車の豊田章男社長は、次のように述べている。<br />
<blockquote class="tr_bq">
人工呼吸器の生産に対しては「人命に直結するモノづくりは簡単ではない」(自工会 会長の豊田章男氏)とし、直接生産は行わない姿勢だ。</blockquote>
それはその通りなのだが、なぜ「人命に直結するモノづくりは簡単ではない」について解説したいと思う。<br />
<br />
医療機器は規制が厳しいので、実際にどのような規制要件があるのかを書いてみる。非常時なんだから、一次的に規制は緩和してもいいのではないかという意見もあると思うが、まずは、現状どんな規制があるのかを書く。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
法規制</h2>
</div>
日本では<a href="https://www.yakujihou.com/content/yakkihou.html" target="_blank">薬機法(旧:薬事法。正式名称:医薬品、医療機器等の品質、有効性及び安全性の確保等に関する法律)</a>がある。医療機器としての要件や、医療機器製造業や販売業に関する規定が含まれている。<br />
<br />
電気を使用する医療機器では IEC 60601-1 医用電気機器―第1部:基礎安全及び基本性能に関する一般要求事項 の規格に適合しなければならない。<br />
<br />
この規格は各種個別規格や副通則もあるので、医療機器の種別によって適合しなければならない規格は複数存在する。<br />
<br />
※医療機器には<a href="https://www.pmda.go.jp/medical_devices/2017/M20170824001/530381000_22900BZX00248000_D100_1.pdf.pdf" target="_blank">基本要件基準</a>が定められており、IEC 60601-1 は基本要件基準への適合を示すための規格の一つ。<br />
<br />
ソフトウェアの要件としては<a href="https://www.amazon.co.jp/dp/4840748780/" target="_blank"> IEC 62304(JIS T 2304)</a>もある。さらに、医療機器を製造するには <a href="https://www.jqa.jp/service_list/management/service/iso13485/" target="_blank">ISO 13485(ISO 9001 の医療機器版)</a>の認定も必要だ。<br />
<br />
どれ一つとってもハードルは高く、そのハードルの高さが、異業種からの医療機器業界への新規参入を阻んでいる。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
なぜ、そんなに規制が厳しいのか?</h2>
</div>
<a href="https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/kenkou_iryou/iyakuhin/koukokukisei/index.html" target="_blank">薬機法には公告規制</a>もある。要するに虚偽・誇大広告は法律で禁じられている。<br />
<blockquote class="tr_bq">
第六十六条 何人も、医薬品、医薬部外品、化粧品、医療機器又は再生医療等製品の名称、製造方法、効能、効果又は性能に関して、明示的であると暗示的であるとを問わず、虚偽又は誇大な記事を広告し、記述し、又は流布してはならない。</blockquote>
効果効能が明確でないのに、「癌が治る」とか「症状が軽減する」などと公告すると、一般市民が惑わされ害があるので規制されている。病気や健康は人々にとって強い関心事であるため、虚偽又は誇大な記事を規制しないとだまされる人が増えて社会が混乱する。<br />
<br />
医療機器についても同じで、効能、効果、性能が臨床的に立証されていない機器は売れないし宣伝もできない。<br />
<br />
規制がないと、製造業者が表明している機器の機能や性能が実際には十分でなかったり、リスクコントロールがないため事故が起こったりしてしまう。一般的な機器ならユーザがメーカにクレームを言えば済むかもしれないが、医療現場では取り返しがつかないような事態になるかもしれない。だから、医療機器は規制されている。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
ベネフィット・リスク分析</h2>
</div>
多くの薬には副作用がある。副作用があるけれども、効果効能を優先させるために服用が必要な場合もある。例えば、抗がん治療には副作用があるが、延命するためには治療はしなければならない。<br />
<br />
医療機器も同様で、リスクはあるがベネフィットが上回るため、ある条件下では使用すべきということが多々ある。<br />
<br />
生命維持装置や治療器には大抵リスクがあるので、どんなリスクがあり、それらのリスクを低減してリスクが受容できている状態にしておく必要がある。<br />
<br />
そのときに、リスクはあるがベネフィットが上回るので条件付きで使用させるというケースも出てくる。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm9TYpDT7XeINHaMy5xbVpOkp2GKfY6bMYxyAaMtkDm4_CFVGR40rqBdtNbXzqs8K_SsDZVmZcIvNAFiaSA82Vby-74V8JMaeUtSlRNy4K2N_LGV-KUeF046frvPLnMaOZofCU/s1600/Value.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="301" data-original-width="302" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm9TYpDT7XeINHaMy5xbVpOkp2GKfY6bMYxyAaMtkDm4_CFVGR40rqBdtNbXzqs8K_SsDZVmZcIvNAFiaSA82Vby-74V8JMaeUtSlRNy4K2N_LGV-KUeF046frvPLnMaOZofCU/s200/Value.png" width="200" /></a></div>
左図の上部は顕在的な価値、例えばカタログスペックに出てくるような目に見える価値で、下の部分は、表にはでてこないけれど安心や安全を担保する価値になる。当たり前品質とも言える。<br />
<br />
医療機器は、この潜在的価値の部分が脆弱だと、人の死に直結してしまう可能性がある。生命維持装置や治療器が期待通りに動かなければ、患者が死亡したり重傷を負ったりするかもしれない。<br />
<br />
よって、この潜在的価値の部分を担保するために、さまざまな規制があると言えるし、規制当局は取り締まりをすることで、国民の安全を確保している。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
緊急時にそんなこと言ってられない</h2>
</div>
世の中平温ならいざ知らず、今は、「もたもたしていたら、死者がどんどん増えてしまうではないか」という緊急事態かもしれない。<br />
<br />
だから、米FDA(食品医薬品局)は、COVID-19 に関連して、規制を緩和するガイダンスを次々に出してる。例えば、<a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents/enforcement-policy-telethermographic-systems-during-coronavirus-disease-2019-covid-19-public-health?utm_campaign=2020-04-16%20COVID-19%20Update%20New%20Policy%20for%20Thermography%20Devices&utm_medium=email&utm_source=Eloqua" target="_blank">これ</a>や<a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents/enforcement-policy-digital-health-devices-treating-psychiatric-disorders-during-coronavirus-disease?utm_campaign=2020-04-16%20CDRH-COVID-19%20Update%3A%20New%20Policy%20for%20Psychiatric%20Digital%20Health%20Devices&utm_medium=email&utm_source=Eloqua" target="_blank">これ</a>。<a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents" target="_blank">こちらのサイト</a>でCOVID-19をキーワードに検索すると27件ものガイダンスがヒットする。<br />
<br />
米国は、FDAにかなりの権限があり、規制に対する裁量権が認められているので、ガイダンスによって規制を緩和することができるようだ。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjh8lIk3Lg_TVYRjjsUEdYlnfGKDj6nQoVaEBhJbQRdcLhynyfkiT6OiTC4BzdZqliPel3t8eJ5vc3NwZbucbbeWFU8QqwEsXO8WrW-2osIT3IipyC1e6vmcVU31zn2culxZhuq/s1600/%25E8%25A6%258F%25E5%2588%25B6%25E5%25AF%25BE%25E8%25B1%25A1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="430" data-original-width="640" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjh8lIk3Lg_TVYRjjsUEdYlnfGKDj6nQoVaEBhJbQRdcLhynyfkiT6OiTC4BzdZqliPel3t8eJ5vc3NwZbucbbeWFU8QqwEsXO8WrW-2osIT3IipyC1e6vmcVU31zn2culxZhuq/s400/%25E8%25A6%258F%25E5%2588%25B6%25E5%25AF%25BE%25E8%25B1%25A1.png" width="400" /></a></div>
モバイルアプリに関しても、左図にあるように米国では、医療機器かもしれないが、FDAが執行裁量権を使って取りあえず規制しないというカテゴリーがあるが、日本では、法体系が違うためそのような曖昧なことはできない。<br />
<br />
1か0(医療機器か、そうでないか)を判定しないといけない。<br />
<br />
よって、現実的には、日本では薬機法を改訂しないかぎり、従来の規制を一次的に緩和することは難しい。<br />
<br />
特に、現実問題、医療機器の製造業・販売業の業の認定がない企業に、一次的ではあっても医療機器を製造したり、販売させることはできないだろう。<br />
<br />
米国も同じだが、審査の工程を簡素化したり、短縮したりすることはできるようだ。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
現実的には何が問題になるのか</h2>
</div>
法規制のことはいったん横においておいて、実際にこの緊急時に異業種の企業が人工呼吸器を作ることにどんな問題があるのだろうか。<br />
<br />
<a href="https://www.gizmodo.jp/2020/04/elon-musk-ventilators.html" target="_blank">コロナ最前線で戦う医療現場にTeslaが約束の「人工呼吸器」を送ったという記事</a>があった。<br />
<br />
ところが、この機器は、睡眠時無呼吸症候群の治療機機器であるCPAPの機器だったようだ。価格は800ドルで、侵襲型の人工呼吸器(約5万ドル)とは異なる。<br />
<br />
機能としては、CPAPも人工呼吸器も酸素を送り込むので似ているが、意図する使用/意図する目的(Intended Use)が異なる。<br />
<br />
臨床的に目的が異なるものを緊急で転用するならその違いを理解している人が機器を扱わないと事故が起こる危険があるし、人間は必ずミスをする(ヒューマンエラーはなくならない)ので、臨時の使い方を多くの人がするようになると気をつけないといけないことを怠って事故が起こる確率も徐々に上がっていくだろう。<br />
<br />
それも含めて緊急事態だからベネフィット・リスクを考えて、臨時的な使い方を許容するという選択肢もあるかもしれない。<br />
<br />
どちらを優先させるべきか悩ましいが、前提として臨床的に有効性のない機器を投入することは間違いだと言えるし、患者が死や重傷に至るようなリスクに対してリスクコントロールがされており、リスクが受容できているという確認(=バリデーション)は必ず必要だ。<br />
<br />
特に、医療機器の開発にあたっては、臨床的な知識や医療現場での機器の使われ方、治療や診断の実際について、開発者が十分に理解していることが重要だ。<br />
<br />
今、集中治療学会は、新型コロナウイルス感染症(COVID-19)の対応に関連して、<a href="http://square.umin.ac.jp/jrcm/news/news20200415.html" target="_blank">人工呼吸教育ビデオ</a>や、<a href="https://www.jsicm.org/news/upload/COVID-19-ventilator-V2.pdf">新型コロナウイルス肺炎患者に使用する人工呼吸器等の取り扱いについて(Ver.2.0)</a>などの情報を公開している。<br />
<br />
これを見るだけでも人工呼吸器は取り扱いに注意が必要で、十分なメインテナンスが必要な機器であることがわかる。<br />
<br />
「人工呼吸器の部品を3Dプリンタで作りました」などのニュースを見ると、作った部品は滅菌できるのかとか、つなぎ目から空気の漏れは起こらないのか、薬液耐性は大丈夫かとかといった疑問が沸く。<br />
<br />
人工呼吸器を本気で作ろうと考えている設計者は、まずは、臨床的な知識、治療の実際について理解してから、自分達が持っている技術がどの部分に活かせるのかを考える必要があると思う。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
総合的な感想</h2>
</div>
現在の医療機器規制は過去の事故の再発防止策などが積み重なって今に至っている。ただし、改めてそれらができていないと安全ではないのか、逆にそれらができていれば安全なのかという疑問がないわけではない。<br />
<br />
例えば、IEC 62304 はプロセス規格なので、この規格への適合と機器の安全は一体一ではない。機器としてのリスクを分析しており、リスクが受容できていることの確認はしている。でも、この規格の一つ一つの要求について、本当に必要か?という要求もないわけではない。<br />
<br />
再発防止策の積み重ねは40年以上続いているのでハードルはどんどん高くなっており、医療機器ドメインへの新規参入はかなり難しくなっている。<br />
<br />
でもハードルを下げれば、事故は増えるだろう。だからこそ、リスクの高い機器についてはハードルを上げざるを得ず、リスクの低い機器やヘルスソフトウェアのハードルは下げて上げるのが現実的であり、米FDAはそういうアプローチを採っている。<br />
<br />
では、人工呼吸器はどうか。生命維持装置なのでリスクが高い機器であることは間違いない。人工呼吸器が足らない状況にみんなが協力して打開しようとすることはとても良いことだが、よかれと思った取った行動が逆の結果を招くかもしれないのが、医療機器の怖さでもある。<br />
<br />
意図通りに動作すれば社会に貢献でき、高い満足感も得られるが、その裏側には大きな責任(=リスク回避の責任)もあるということだ。<br />
<br />
この危機的な状況にあっても、安易に実験的な機器を現場に投入するよりは、現存する機器の増産の可能性を探ることが現実的なような気がする。<br />
<br />
日本の自動車業界が医療機器製造業者に製造に関する支援を表明しているのはそういう理屈なのだろう。sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-54147890766619109412020-04-09T14:27:00.002+09:002020-04-09T14:27:30.463+09:00Raspberry Pi3を使ったリアル波形描画(10) アーキテクチャの設計思想について(2)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIxVZYjNktEpBmPQgEWP8jyS4S_T0aw739f5bi58CoPMEb9P13Oo4K4zVzCgkDtI-WVBkMIYzZbapZAXAEzf9TCDx801sAkrvCfmIVJAEWlG27A03PImWl1LVtSqgDI-X0-zOS/s1600/RaspberryPi_BlogTitle10.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="340" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIxVZYjNktEpBmPQgEWP8jyS4S_T0aw739f5bi58CoPMEb9P13Oo4K4zVzCgkDtI-WVBkMIYzZbapZAXAEzf9TCDx801sAkrvCfmIVJAEWlG27A03PImWl1LVtSqgDI-X0-zOS/s320/RaspberryPi_BlogTitle10.png" width="320" /></a></div>
本特集記事の「Raspberry Pi3を使ったリアル波形描画」を実現するにあたり、採用したアーキテクチャの設計思想を説明しようと思う。前回は、全体のシステムの中の入力部分の説明をした。<br />
<br />
今回は、このシステムの重要な要素(=商品価値=コアコンピタンスとなりうる部分)の説明をする。<br />
<br />
アイテム構成にうち、他社に真似できない商品価値となる部分(コアコンピタンス)のソフトウェアを再利用可能な資産にすることができれば、商品の価値となるソフトウェアアイテムをベースに派生製品を作ることができる。それらの商品群は個々の商品の競合力が高く、かつ、商品群としても強く、さらに、効率よく派生開発が可能となる。<br />
<br />
コア資産部分がUIやI/Fに依存していなければ、コア資産をベースにさまざまなI/FやUIを持った派生製品を作ることができる。汎用I/Fや、UIは時代とともにどんどん代わっていくので、それらに対応していき、コア資産の実力をじっくりと高めていけば、商品群は競争力を高いまま維持することができるはずだ。<br />
<br />
コア資産が他社の追随を許さない性能を持っている、または特許で知財が保護されていれば、競合しても勝つことができるし、仮に営業力で負けても、長いこと使っていればユーザのその性能の差に気が付き、戻ってくるだろう。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicG0V9J7E3S4Vki9ZFcEIa9ebA2rQRM7_f5WazlLpfa113XoRkwvlKDcOEu3EC30w9tBgtHcyG8ziuclXugtpFudHv6c1gLMbmzYCgDFz7mJhiSAmEeHO4zTwmZUm6Ogk5Dry4/s1600/RealWaveDisplay_1786x1509.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1352" data-original-width="1600" height="337" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicG0V9J7E3S4Vki9ZFcEIa9ebA2rQRM7_f5WazlLpfa113XoRkwvlKDcOEu3EC30w9tBgtHcyG8ziuclXugtpFudHv6c1gLMbmzYCgDFz7mJhiSAmEeHO4zTwmZUm6Ogk5Dry4/s400/RealWaveDisplay_1786x1509.png" width="400" /></a></div>
本システムは、基本的には、心電図を入力し、デジタルフィルタで波形を整えて、心電図のQRS(ピンと上に跳ねる部分)を検出して、心拍数を算出し、その結果や波形や付帯情報をディスプレイに表示します。<br />
<br />
先の一番下のレイヤーがデータソースレイヤーで心電図の入力部、真ん中がドメインレイヤーで、デジタルフィルタや心拍数計測部、一番上がプレゼンテーションレイヤーで結果を表示する部分です。<br />
<br />
今回は、重要な不整脈の解析などは入れていませんが、それがあればドメインレイヤーに含まれ、解析性能が良ければコアコンピタンスになります。<br />
<br />
ちなみに、デジタルフィルターやQRS検出の部分も、それなりにノウハウがあるはずなので、コアコンピタンスになります。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG_fifr17N612jijF3xPhjUgP-wDFBU-UqGGzakegXJAVa1SU3nkqTaw3udjyFQxG_fn3iq3HM0h-LRp0mL2fiEIZ-u085B5SH3WJcRxvo9O2rBG4SubEOPsyKobGbzOoZ46c4/s1600/DomainLayer1110x712.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="712" data-original-width="1110" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG_fifr17N612jijF3xPhjUgP-wDFBU-UqGGzakegXJAVa1SU3nkqTaw3udjyFQxG_fn3iq3HM0h-LRp0mL2fiEIZ-u085B5SH3WJcRxvo9O2rBG4SubEOPsyKobGbzOoZ46c4/s400/DomainLayer1110x712.png" width="400" /></a></div>
左記の緑のクラスがそれに相当します。<br />
<br />
EcgAcLineNoiseFilter クラスは、心電図に重畳する50Hzや60Hzの電源ノイズを除去するフィルターで、EcgDriftFreeFilter クラスは、呼吸やその他の基線変動要因を取り除き、心電図を見やすくし、心拍数計測の精度を高めるために必要なアイテムです。<br />
EcgHighCutFilter はアナログフィルターで取り除いてもなお、残っている40Hzより高域のノイズ成分を取り除くフィルターとなります。QrsDetectorTypeTest1 クラスは、心電図のQRSを検出するためのクラスで、このシステムの中ではもっとも複雑性が高く、システムの性能に寄与するアイテムです。TypeTest1としているのは、QRS検出のソフトウェアは試行錯誤しながら精度を高めていくことが多く、1回で完成することはなく、いろいろな試行を繰り返すことになるからです。<br />
<br />
このクラス図では、派生クラスにしていませんが、インタフェースを共通にしておいて派生させていろいろなタイプを作って差し替えながら、性能を検証していくのがよいと思います。<br />
<br />
また、デジタルフィルタについても、一度固まってしまえば変更することはあまりないと思いますが、こちらもベースクラスから派生させておいて、後々差し替えられるようにするのもよいと思います。<br />
<br />
実際、デジタルフィルタは C言語で数行で表現できてしまうケースもあるため、技術者研修ではわざわざクラスに分けたり、派生させたりしないことが多いようですが、商品としてまた、コアコンピタンスとしてデジタルフィルタを位置づけるのであれば、ソフトウェア資産として独立させて、再利用することに意味があります。<br />
<br />
そのソフトウェアシステムのうち、競争力を生み出すコア資産が何か、そのコア資産が再利用しやすくできているか、そこができているかどうかが、競争力の高い商品でかつ、効率のよい開発ができるかどうかの分岐点になります。<br />
<br />
詳しくは、『<a href="https://amzn.to/3aVy0XF" target="_blank">リアルタイムOSから出発して 組込みソフトエンジニアを極める[改装版]</a>』の第三章をお読みください。<br />
<br />sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-6783018931743097372019-11-06T14:21:00.001+09:002019-11-14T14:06:39.978+09:00『リコールを起こさないソフトウェアのつくり方』のKindle 版リリース<div class="separator" style="clear: both; text-align: center;">
<a href="https://amzn.to/2Khy3BB" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;" target="_blank"><img border="0" data-original-height="213" data-original-width="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG3o5imiBKao1DKCK3eP8_hF-fogQAaZ7tdlxwejeB9G8bslK_bAEAotRUQWnXkW13TImqQqCT9ioUumq5kwIeel7Ls6tH-WwcsBSdrEl2chwUkD7BobDGUQCG6eqrzfLWAs8F/s1600/recall_image_150.jpg" /></a></div>
『<a href="https://amzn.to/2Khy3BB" target="_blank">リコールを起こさないソフトウェアのつくり方</a>』のKindle 版が出ました。紙の本は絶版になってしまい、技術評論社から PDF版では買えたのですが、技術評論社の編集者にお願いして kindle 版もリリースしてもらいました。<br />
<br />
下記は、この本が最初に出版されたときのブログ記事の抜粋です。<br />
<br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">【『</span><a href="http://www.amazon.co.jp/gp/product/4774142166?ie=UTF8&tag=embeddedsoftw-22" style="background-color: #fefdfa; color: #7d181e; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px; text-decoration-line: none;">リコールを起こさないソフトウェアのつくり方</a><span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">』はじめにより】</span><br />
<blockquote style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">
日本のソフトウェア製品やソフトウェア搭載機器がグローバルマーケットで支持され続けるためには、「品質がよく割安感のある商品」を市場にアウトプットしていかなければいけないと思っています。リコールを繰り返すような品質の悪いソフトウェアではダメなのです。<br />
<br />
一方、ソフトウェア開発の側面を見ると、欧米で体系化されたソフトウェア品質改善の方法論の多くが日本のソフトウェアプロジェクトに紹介されています。ところが、日本のソフトウェア開発現場の多くでそれらが役に立っておらず形骸化しているように感じています。また、大部分の方法論は欧米で実践されているはずですが立ち遅れているといわれる日本のソフトウェア搭載製品のほうが品質が高いという事実があります。<br />
<br />
それはなぜなのでしょうか。それならば、日本のソフトウェアプロジェクトはこのままの方法で開発を続けていればよいのでしょうか。この命題を解明し、ソフトウェア工学をどのように日本のソフトウェアプロジェクトに適用すると有効なのかを示すことができなければ、日本のソフトウェアエンジニアは決して幸せにはなれないと思っています。これが本書を書こうと思った動機です。<br />
<br />
本書は、たとえば、次のような方に有用です。<br />
<ul style="line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="border: none; margin: 0px 0px 0.25em; padding: 0.25em 0px;"> ソフトウェア開発の初級者の方</li>
<li style="border: none; margin: 0px 0px 0.25em; padding: 0.25em 0px;"> 新人でこれから目指すべき道筋が見えていない方</li>
<li style="border: none; margin: 0px 0px 0.25em; padding: 0.25em 0px;"> ハードウェアエンジニアで「なぜ、ソフトウェアは問題を起こすのか」を常々疑問に思っている方</li>
<li style="border: none; margin: 0px 0px 0.25em; padding: 0.25em 0px;"> ソフトウェアプロジェクトマネージメントの技術を学んでいて、どうして自分のプロジェクトでうまくいかないのか悩んでいる方</li>
<li style="border: none; margin: 0px 0px 0.25em; padding: 0.25em 0px;"> 組織内でソフトウェア品質問題に頭を抱えている方</li>
</ul>
その他にも、ソフトウェアの品質管理、構成管理、再利用資産、安全設計などに興味を持っている方にもおもしろく読んでいただけると思います。 まず、ソフトウェアエンジニアの新人や初級クラスの方は、Part1のソースコードのケーススタディを見て、自分がいまどのレベルにいて、何を学ばないとまずいのかを考えてみてください。きっと答えが見つかるはずです。中堅、ベテランのエンジニアのみなさんは、Part1でソフトウェアの本質的な危うさを認識し、日本人の特性を理解したうえで、日本におけるプロジェクトマネージメントの適用方法を Part2で学んでください。<br />
<br />
そして、プロジェクトリーダーやソフトウェアアーキテクトとしての責務を負っている方は、ソフトウェア再利用資産の抽出方法を Part3で修得し、現行のソフトウェア製品群の開発効率と品質向上に役立ててください。<br />
最後に、自組織のソフトウェア製品やソフトウェア搭載製品が市場で問題を起こしており、その問題を解決する責務を負っている方は、本書の最初から最後までを通して読み、ソフトウェアと日本人の特徴を理解し、自組織において何に手をつければよいのかを理解してほしいと思います。<br />
本書が、初級や中級のソフトウェアエンジニア、アーキテクト、マネージャ、リーダーの方にソフトウェア品質の改善活動の参考書として役立つことを期待しています。<br />
<br />
2010 年 3月 酒井由夫</blockquote>
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">【引用終わり】</span><br />
<br style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">『</span><a href="http://www.amazon.co.jp/gp/product/4774142166?ie=UTF8&tag=embeddedsoftw-22" style="background-color: #fefdfa; color: #7d181e; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px; text-decoration-line: none;">リコールを起こさないソフトウェアのつくり方</a><span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">』目次</span><br />
<br style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" />
<b style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">Part1 ソフトウェアの危うさの本質を体感してみよう</b><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 1 ソフトウェアの危うさを知ろう</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 2 危ないソフトウェアのプログラム例とケーススタディ</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 3 ソフトウェアはなぜ危ないのか</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 4 ソフトウェアの品質を高く保持するために</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">coffee break アメリカ人と日本人</span><br />
<br style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" />
<b style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">Part2 日本的ソフトウェアプロジェクトの管理はここから</b><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 5 ソフトウェア開発の理想と現実</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 6 日本のソフトウェアプロジェクトに求められる取り組み</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 7 ソフトウェア構成管理</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 8 ソフトウェア変更管理</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 9 レビュー</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">coffee break 問題解決能力:自ら考え行動する力</span><br />
<br style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" />
<b style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">Part3 ソフトウェア資産化の技術がリコール防止につながる</b><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 10 ソフトウェア開発のプラットフォーム</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 11 ソフトウェアシステムとソフトウェア搭載機器の価値</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">coffee break 3 ものづくり戦略とソフトウェア品質:品質=Qualityの話</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 12 再利用資産を抽出するためのアプローチ</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 13 再利用資産を抽出する手順</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">coffee break 4 UML導入のススメ</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 14 再利用資産の抽出のケーススタディ</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 15 再利用資産の抽出後のアプローチ</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">coffee break 5 テストカバレッジ</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 16 安全性が求められるシステムに対するアプローチ</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 17 安全アーキテクチャの検討</span><br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">Chapter 18 ソフトウェアを資産化して品質と開発効率を高める</span>sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-88912090741659731522019-10-20T10:56:00.000+09:002019-10-20T19:49:17.293+09:00ソフトウェア系国際規格の認証の現状について機能安全規格の IEC 61508(Functional safety of electrical/electronic/programmable electronic safety-related systems) や ISO 26262 (Road vehicles — Functional safety )や、医療機器ソフトウェアのソフトウェアライフサイクルプロセス規格 IEC 62304(Medical device software - Software life cycle processes)に 「適合しました!」とか、「準拠しています!」といったニュースリリースをよく見る。<br />
<br />
しかし、ブログでは『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2017/03/iec-62304jis-t-2304.html" target="_blank">汎用ソフトウェア製品(製品開発プロセス)は IEC 62304(JIS T 2304) に適合できない</a>』で書いたように、医療機器ソフトウェアでは、汎用ソフトウェア製品や汎用ソフトウェア製品の開発組織に対して IEC 62304 は適用できないということを解説してきた。<br />
<br />
その趣旨は、医療機器業界では 医療機器ソフトウェアに対して主に患者のリスクを低減することを目的としてリスクベースアプローチを求めており、その考え方のもとにライフサイクルプロセスとタスクの要求を課しているため、どのような使用目的に使うのかが定まっていない汎用ソフトウェア製品に IEC 62304 を適用しようとすることは意味がないということであった。<br />
<br />
今年2019年7月にさらなる意味がないことを示すできごとがあったので、それを説明したい。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
IEC 62304 と医療機器規制との関係</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjICZ4itr7zKpfdF_RvxRRZZYF_nLyQxlv87cxCLOx1u22Ra5qPdBe5DJE_I7D0HQ68NeS77Bg8LJHbD0C38x9efgL9FrBswomBsq8dgFFCF8BfLAO4HZLx8BxyBicyFrG4Gv2p/s1600/IEC62304_A.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="449" data-original-width="640" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjICZ4itr7zKpfdF_RvxRRZZYF_nLyQxlv87cxCLOx1u22Ra5qPdBe5DJE_I7D0HQ68NeS77Bg8LJHbD0C38x9efgL9FrBswomBsq8dgFFCF8BfLAO4HZLx8BxyBicyFrG4Gv2p/s400/IEC62304_A.png" width="400" /></a></div>
まず、IEC 62304 医療機器ソフトウェア-ソフトウェアライフサイクルプロセス と医療機器規制との関係について整理しておきたい。<br />
<br />
左図にあるように、医療機器は日本の場合、医薬品医療機器等法(通称:薬機法)で規制されており、医療機器に搭載される、または、そのものが医療機器となるソフトウェアは IEC 62304(JIS T 2304)への適合が求められる。正確には法律で国際規格が指定されているのではなく、法律が省令を省令が通知をといったようにブレークダウンされた中で IEC 62304(JIS T 2304)が医療機器ソフトウェアの要件となっている。<br />
<br />
IEC 62304 はもちろん、医療機器製造業者が製品のソフトウェアに対して適合していることを示す必要がある。<br />
<br />
<span style="color: blue;">一方で、機能安全規格 IEC 61508 や ISO 26262 は、ソフトウェア部品やソフトウェア部品を供給するサプライヤーに対しても これらの規格の一部に適合することを推奨している。</span><br />
<br />
ここで注意して欲しいのは、標準規格には、強制規格と任意規格があり、ISO, IEC, JIS は任意規格であり、規制に使うかどうかは、各国の規制当局が決めるということだ。<br />
<br />
<span style="color: blue;">IEC 62304 は医療機器規制の中で規制に実質的に使われている。ちなみに、IEC 26262 は今のところ規制に使われていない。ISO 26262 への適合を求めているのは、自動車OEM(メーカ)がサプライヤに対して求めているのだ。規制当局ではないから、規制要件ではない。</span><br />
<br />
規格を規制に使うということは、別の見方をすれば、規格の適合を持って認可した規制当局にも責任が生じるということだ。医療機器の場合、規制当局は機器が患者危害に至るような問題を抱えていないかどうかが最大の関心事であるから、規格適合要件は、患者リスクが許容以下に低減されていることの証明でなければいけない。<br />
<br />
ところで、自動車業界は市場規模が大きいので、ISO 26262 が国際規格となった以降、規格認証ビジネスの市場が出来上がった。<br />
<br />
「ISO 26262 に適合しています!」というハードウェア部品やソフトウェア部品が増えてきて、ISO 26262 の適合証明を取ることが自動車業界で部品を売るための条件になりつつある。<br />
<br />
その際、部品メーカ、特にソフトウェア部品のメーカは ISO 26262 と IEC 61508 と IEC 62304 だいたい同じだろうと考え、いっぺんに3つのプロセス規格に適合してしまえば、それぞれの業界のアピールできると考えた。<br />
<br />
クリティカルなソフトウェアに対する規格は、どれも同じようなものだと考えた訳だ。そもそも、クリティカルなソフトウェアが安全であるかどうか確証を持って言えるわけがない。ソフトウェア起因の不具合の起こり方は特殊なので、プロセスをマネージメントして対応するしかないのだが、そのときに、どんな危害に至る可能性があるのかを想定して対応することが IEC 62304 では求められている。<br />
<br />
だから、IEC 62304 を安全規格と分類するのはおかしい。Medical device software - Software life cycle processes(医療機器ソフトウェアのソフトウェアライフサイクルプロセス)というタイトルにあるように、IEC 62304 は 医療機器向けのライフサイクルプロセス規格であり、製品安全規格ではない。(冒頭の図を参照のこと)<br />
<br />
ちなみに IEC 62304 は医療機器製造業者が適合を示す規格なので、ソフトウェア部品に適合証明を出すのはおかしいのに、ソフトウェア部品の製造業者に IEC 62304 の適合証明を出す 認証機関がいる。<br />
<br />
自分は、そのような認証機関は、規格趣旨を理解していないか、もしくは、規格趣旨を理解していながら、単に金儲けがしたいために認証書を出しているのだと考えている。<br />
<br />
そのような認証機関にはショックなできことが 2019年7月に起こった。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
IEC 62304 の認証に起こったできごと</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
IECEE ※1 が 2019年7月26日付けの通知で IEC 62304 をCBスキームから取り下げた(Withdrawal of standards)のだ。<br />
<br />
【※1 IECEE CBスキームについて <a href="https://home.jeita.or.jp/assess/pdf/005.pdf" target="_blank">JEITA資料</a>より引用】<br />
<br />
<blockquote class="tr_bq">
<b>IECEE CBスキームについて</b><br />
◆<b>IECEEとは?</b><br />
<ul>
<li>IEC電気機器・部品適合性試験認証制度の略称<span style="color: red;">(通称CBスキームと呼ばれる)</span></li>
</ul>
<ul>
<li>IEC規格に基づく1回の適合証明試験結果を加盟53カ国(MB*)の72認証機関(NCB*)で、重複試験無しに受入れることを目的としたデータの相互活用制度</li>
</ul>
<ul>
<li>制度はIECEE01(基本ルール)、IECEE02(手順ルール)及びIECEE03(CB-FCS)に 基づき運営され、これらは年1回開催されるCMC*会議にて承認のうえ改正される</li>
</ul>
<ul>
<li>IECEEスローガン:“One standard, one test performed anywhere, accepted everywhere !”</li>
</ul>
<b>◆IECEEの国際法上の位置づけは?</b><br />
<ul>
<li>WTO-TBT協定により;</li>
</ul>
<ul>
<li>強制・任意分野に関わらず、国際規格・制度を適合性評価手続きの基礎とする</li>
</ul>
<ul>
<li>上記手続きによって得られた評価結果は加盟国間で相互に認め合う</li>
</ul>
<ul>
<li>旨の規定があり、CB制度はこれを満足するメカニズムとして認知されている</li>
</ul>
<br />
<b>◆本制度における日本のプレゼンスは?</b><br />
<ul>
<li>日本は1981年にJISC(日本工業標準調査会)がMBとして加盟し、現在はJET、JQA、TUV-RhJ、UL Japanの4NCBが参加</li>
</ul>
<ul>
<li>日本はIECEE国内審議委員会(事務局:JEITA)が受け皿となり、日本の対処方針を 決定のうえCMC会議に参画し意見反映</li>
</ul>
</blockquote>
<br />
<br />
<div>
【引用終わり】</div>
<div>
<br /></div>
<div>
IEC 62304 は IECEEが発行する TRF(Test Report Form)を使用し、試験を実施して適合を示すことができた。(IEC 62304の TRF が廃止されたため過去形)</div>
<br />
IECEE が発行する TRF(Test Report Form)を使って、CB試験所が IEC 62304 の認証を行った場合、その CBレポートは 多くの国で規制要件適合の証明として受入れられてきた。<br />
<br />
ところが、IECEE は IEC 62304 の TRF を廃棄してしまった。なぜか。その理由は、CB認証のルールを定めた OD-2037(関係運用文書) には「証明書Product Standardsのみ記載する」というルールがあり、IEC 62366 や IEC 62304 は Product Standardではないため、CBスコープから外されたと想像される。(予想)<br />
<br />
そして、冒頭の図にある IEC 60601-1 医療電気機器-第1部:基礎安全及び基本性能に関する一般要求事項 の TRF Rev.N に IEC 62304 TRF の内容が組み込まれた。<br />
<br />
これによって、IEC 62304 単独の CBレポートは発行できなくなった。(医療機器の安全規格である IEC 60601-1 の試験を TRF で行うと自動的に IEC 62304 のTRF の要求も満たすことになる。)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeoEaKuOFWZIY5Q7mBHA2004fp7P3nDJNeR47whtwJkRrBklE-grSr9lWcqrdu1woOieiVM_1HG4vLfrFHJEW7gBPVPXVqkQZQ5QGaZ7T9tnukyYFK-dPrGs1rh6bl1fe4r1zZ/s1600/%25E9%2581%25A9%25E5%2590%2588%25E5%25A0%25B1%25E5%2591%258A.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="499" data-original-width="640" height="311" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeoEaKuOFWZIY5Q7mBHA2004fp7P3nDJNeR47whtwJkRrBklE-grSr9lWcqrdu1woOieiVM_1HG4vLfrFHJEW7gBPVPXVqkQZQ5QGaZ7T9tnukyYFK-dPrGs1rh6bl1fe4r1zZ/s400/%25E9%2581%25A9%25E5%2590%2588%25E5%25A0%25B1%25E5%2591%258A.png" width="400" /></a></div>
ハードウェアを含む医療機器が IEC 62304 への適合を示すには、IEC 60601-1 の TRF(現時点の最新版は Rev.N)を使用すればよい。<br />
<br />
ただし、ソフトウェアそのものが医療機器となる単独の医療機器ソフトウェア(SaMD)では、CBレポートが発行できなくなったので、左図のプライベートレポートを使うしかなくなった。<br />
<br />
実際、まったく独自のレポートを受け入れている国もあるので、大きな問題にはならないだろう。<br />
<br />
また、CBスキームではなく、ISO/IEC 17025 の認定を受けた試験所で作成したレポートを受け入れる国はある。(※現時点では、日本の医療機器規制では上図のどれも受け入れている。ISO/IEC 17025 は試験所認定があるので、実質的には CBスキームの TRFレベルの試験が行われる。)<br />
<br />
ただし、ISO/IEC 17025 の認定を受けた試験所も、IECEE が発行していた IEC 62304 のTRFを使っていたので、今後は、過去に発行されていた IEC 62304 の TRF を模倣した独自のレポートを使うことになるだろう。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
今後の IEC 62304 の認証</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
IECEE が IEC 62304 の TRFを破棄し、IEC 60601-1 の TRF Rev.N の附属書に取り込んだことにより、CBスキームによる IEC 62304 単独の認証ができなくなったので、ソフトウェア部品メーカが IEC 61508 と ISO 26262 と IEC 62304 への適合を3つ並べてニュースリリースするケースがなくなると思われる。<br />
<br />
そもそも、規格適合は 1. 実質的に安全や信頼が高いことを示す 2. 権威を示して売り上げを上げたい といった目的があり、規格適合を3つならべてニュースリリースしているの 2の目的だろうから、IEC 62304 が CBスキームから外れたことで、プライベート認証しかなくなり IEC 62304 単独の規格認証の権威はなくなったので、アピールもできなくなったはずだ。<br />
<br />
今後、IEC 62304 単独の認証証を掲げる ソフトウェア部品メーカが現れたあら、それはプライベート認証であり、Intended Use(意図する使用)が定義されていないのに、IEC 62304 箇条7 ソフトウェアリスクマネジメントプロセス に適合を出してしまっているとみた方がいい。「認証」ではなく「準拠」となっている場合、おそらく箇条7が適合できていないのだろうが、箇条7ができていないということはソフトウェア開発においてリスクベースアプローチができていることが確認されていないということだから、IEC 62304 適合の意味はない。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
IECEE のサイト(参照情報)</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<ul>
<li><a href="https://www.iecee.org/" target="_blank">IECEEのサイト</a></li>
<li><a href="https://www.iecee.org/dyn/www/f?p=106:42:0" target="_blank">CBテストラボのリスト</a></li>
</ul>
<br />
<br />sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com3tag:blogger.com,1999:blog-19350560.post-70453867672525854292019-08-09T16:08:00.000+09:002019-08-09T16:08:33.863+09:00Raspberry Pi3を使ったリアル波形描画(9) アーキテクチャの設計思想について<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBT7vP4eT0SQzlolQ9d9LvsJIZgoDzxCLaR63XaNVrP1vxtPkTVoWhBLM8qFz7WIFKJ79A8HOQnm71itUr0uZgMW3k1_GuAPyo-Gr_95QzVouVEu85cE6N73Ts74bej7538O7l/s1600/RealWaveDisplayTitle09_340x241.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="340" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBT7vP4eT0SQzlolQ9d9LvsJIZgoDzxCLaR63XaNVrP1vxtPkTVoWhBLM8qFz7WIFKJ79A8HOQnm71itUr0uZgMW3k1_GuAPyo-Gr_95QzVouVEu85cE6N73Ts74bej7538O7l/s320/RealWaveDisplayTitle09_340x241.png" width="320" /></a></div>
本特集記事の「Raspberry Pi3を使ったリアル波形描画」を実現するにあたり、採用したアーキテクチャの設計思想を説明しようと思う。<br />
<br />
なお、今回より、Qt で作成したリアル波形描画のシステム(基本フレームワークだけで、フィルタや心拍検出等の中身はスケルトンにしてある)について解説するのだが、実際に動いた実績のあるソースコードを見ながら解説を読んでもらった方がよいと思う。そこで、Qt でコンパイルできるソースファイル一式と Qt の設定画面を PDF にしたものを希望する方が入手できるようにした。(Qt の設定画面を付けたのは、同じ環境にするのは意外と大変なので)<br />
<div style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
リアル波形描画のソースコード入手方法</h2>
</div>
入手方法は第一回目の記事『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2018/07/raspberry-pi31.html" target="_blank">Raspberry Pi3を使ったリアル波形描画(1) イントロダクション</a>』で Windows で実行できるデモファイルを配布したときと同様に、Google Drive の共有設定で共有できるフォルダにパスワード付きの圧縮ファイルを格納してダウンロードできるようにし、パスワードはメールの自動返信機能で送るようにした。<br />
<br />
なお、最近、WEBブラウザのセキュリティが強化され、ファイルをダウンロードするときにWEBブラウザによっては、いろいろ聞いてくるようになったようだ。gmailのアドレスを持っていなくてもダウンロードできるはず。共有フォルダがからファイルをダウンロードする手順については IE11 と Microsoft Edge ではできることを確認したので、上手くいかなかったときは、これらのWEBブラウザで試して欲しい。<br />
<br />
<blockquote class="tr_bq">
【リアル波形描画のソースファイルの入手方法】<br />
次のメールアドレスに件名:ソースファイル送信 と書いてメールをお送りください。(件名は”ソースファイル送信”でなければ返信されません。メール本文は何でも構いません。<br />
メールアドレス:CriticalSoftwareConsulting[あっとまーく]gmail.com</blockquote>
<div style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
リアル波形描画のソースコードについて</h2>
</div>
本ソースコードは 2019年8月時点で Qt 5.12.2 / Qt creator 4.9.0 にてコンパイル・リンクし、Windows 10上で 動作しているものである。<br />
<br />
自分のパソコンに Qtをインストールし、コンパイル/リンクして、実際に動くことを確認した上で、どのようなソースコードで動いているのか確認してみて欲しい。<br />
<br />
どんな環境であれ、「実際に動いている」という実績は設計者に取って絶大な安心感につながる。裏返せば、ソフトウェアは一行どころか、1文字変更しただけで、システムが動かなくなるということもある。だから、一度、ちゃんと動いているという確信を得た上で、ソフトウェアを修正しては動作を確認しという作業を繰り返していれば、上手くいかなかったときに少しの後戻りでまたちゃんと動いていたところに戻ることができる。<br />
<br />
※設計せずにコーディングをするのはダメという金言をよく聞くが、小さい実験システムでも、まずは動くコードを押さえて安心した上で、コードも設計書もきれいにするというのが自分のスタイルだ。小さいながらも「動くコード」がない状態で、設計書だけを書き進めていって実装する壁にぶつかって止まるのはイヤだ。<br />
<br />
さて、「Raspberry Pi3を使ったリアル波形描画アプリ」のユーザーインターフェースは次のようになっている。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
画面の説明</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMBz_8hcv5WVF30e7NI4rcX6I30MAFoHpohBiZyOhaaEuw1wycsdZxVFfu_g_cZNnvJ48gpkyuZMIdootiOD5UbgCa0YAalnny23euohJ9vP2Pd12fatH5XFCqS7R8ff5HA_zR/s1600/RealWaveDisplay%25E7%2594%25BB%25E9%259D%25A2%25E8%25AA%25AC%25E6%2598%258E2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="629" data-original-width="986" height="408" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMBz_8hcv5WVF30e7NI4rcX6I30MAFoHpohBiZyOhaaEuw1wycsdZxVFfu_g_cZNnvJ48gpkyuZMIdootiOD5UbgCa0YAalnny23euohJ9vP2Pd12fatH5XFCqS7R8ff5HA_zR/s640/RealWaveDisplay%25E7%2594%25BB%25E9%259D%25A2%25E8%25AA%25AC%25E6%2598%258E2.png" width="640" /></a></div>
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTVV7of6inKkUszE074i5XIupOa6cF2z1WpVYtb-RurUUId3zURGygRhT2WEVTnJehi9-Z0XVfD1NSMFa3i79cUW_cCnkZSkYxecNRLzgxvWoBcyr7xdrly5YWxCKWTjeA36de/s1600/RealWaveDisplay201807A.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTVV7of6inKkUszE074i5XIupOa6cF2z1WpVYtb-RurUUId3zURGygRhT2WEVTnJehi9-Z0XVfD1NSMFa3i79cUW_cCnkZSkYxecNRLzgxvWoBcyr7xdrly5YWxCKWTjeA36de/s1600/RealWaveDisplay201807A.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a></div>
これがリアル波形描画のソフトウェアをWindows 上で実行したときの画面になる。<br />
<ol>
<li>波形表示領域:上部の3種類のデジタルフィルタを通した後の波形。</li>
<li>デバッグ用波形表示領域:内部処理が意図通りに動いているかどうかを確認するための表示領域。</li>
<li>入力ソースの切り替え(DEMO, A/D変換器, SIN波):画面に映っているのはDEMO用の三角波。</li>
<li>波形の切り替え(三角波1, 三角波2, 疑似心電図):三角波1 は心拍数が60になるように調節してある。入力ソースが DEMOのときのみ有効。</li>
<li>感度切り替え(×1/4, ×1/2, ×1, ×2, ×4)</li>
<li>波形掃引の開始/停止ボタン:4msインターバルと10msインターバルのスレッドを起動/終了している。</li>
<li>心拍数の表示:心電図のとがった部分(QRS波形)が1分間に何回計測したかをカウントして表示している。※マークはQRS波形検出時に200ms表示している。</li>
<li>電源ノイズフィルターON/OFF:心電図に重畳した電源ノイズ50Hz/60Hzを除去するためのデジタルフィルターのON/OFFスイッチ。ソースの中身は空となっている。(自分でフィルタを設計して実装する)</li>
<li>ドリフトフリーフィルタON/OFF:心電図は体動などの影響で基線動揺が起こる。基線が動揺すると画面からはみ出したりして見にくいので、ドリフトフリーフィルタ(ローカットフィルタ)を入れる。ソースの中身は空となっている。(自分でフィルタを設計して実装する)</li>
<li>ハイカットフィルターON/OFF:A/D変換前にアナログのハイカットフィルターを入れるが、それよりも低い周波数帯域のハイカットデジタルフィルター。ソースの中身は空となっている。(自分でフィルタを設計して実装する)</li>
<li>フィルタの遅れ時間:デジタルフィルタをかけると遅れ時間が生じる。特にドリフトフリーフィルタは遅れ時間が大きい。入力波形に対して表示している波形がどれくらい遅れているのか表示する。</li>
<li>入力波形:フィルタ後の入力波形。</li>
<li>心拍検出のためのスレッショルドレベルの変化の様子:心拍数を計測するために14のフィルタ出力値のピークを計測して、そのピークを階段状に下げていき、スレッショルドレベルを設定している。(簡易的なものを実装している。このスレッショルドレベルを超えた時が新たなQRSの起点となる。)</li>
<li>心電図波形の微分値:心拍数を計測するために、入力波形のうち心電図のとがった部分(QRS波形)だけを際立たせるようなフィルタ(現在はサンプルで入力波形を微分して、絶対値を取っている。暫定的なもの。)をかけている。</li>
</ol>
心拍検出部分とデジタルフィルタをスケルトン(メソッドと入出力のみ実装し、中身を空にしてある)にしているのは、そこに業務ドメイン上のノウハウがあると考えているからであり、その他の部分のソースコードを公開したのは、そのアーキテクチャ自体はドメインには特化していない技術であり、学ぼうと思えばデザインパターンの本など教材は入手する方法がいろいろあるからである。<br />
<br />
繰り返すが、もの作りをするソフトウェアエンジニアにとって、「実際に動いている」実績のあるソースコードは貴重で、「動いている」ことを確認した上で、自分自身で一から同じものを作り上げてみて、同じように「動いている」状態にまで仕上げることと、アーキテクチャを含めより理解が深まるし、自信につながる。<br />
<br />
こちらはPC上で波形表示を行ったデモ画像<br />
<div class="separator" style="clear: both;">
<iframe allow="autoplay; encrypted-media" allowfullscreen="" frameborder="0" height="270" src="https://www.youtube.com/embed/Kjs3WttJfvc" width="480"></iframe><br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both;">
こちらは 5インチのLCD上で波形表示を行ったデモ画像</div>
<iframe allow="autoplay; encrypted-media" allowfullscreen="" frameborder="0" height="270" src="https://www.youtube.com/embed/5e3vMUHzLYs" width="480"></iframe><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
アーキテクチャの目標</h2>
</div>
今回のソフトウェアのアーキテクチャの目標は次の通り。</div>
<ol>
<li>一発勝負ではなく、商品や商品群として10年間は骨格を変えずに使えるアーキテクチャにしたい。</li>
<li>変わりやすい部分(画面表示を含むUI)と変わりにくい部分(デジタルフィルタや心拍数検出の論理など)を分離したい。</li>
<li>心拍数計測等のアルゴリズムの改善作業を見越して、実際の生体信号の入力(A/D変換)ではなく、サンプルデータやSIN波を入力ソースとできるようにしたい。</li>
<li>デジタルフィルタや心拍数計測アルゴリズムが意図通りに働いているかどうかをデバッグ画面で確認できるようにしたい。</li>
<li>普段はPC上で検討を重ね、シミュレーションで上手くいくことが検証をかさね、その後、実機でバリデーションするようにしたい。(開発効率を高めるため)</li>
<li>タイマー制御、スレッド制御といったリアルタイム制御に関する部分は Qt で行い、作成するアプリケーションソフトウェアからはできるだけ隠蔽したい。</li>
</ol>
<div>
1回動くものができればいいという発想ではなく、商品群として長く保守や性能向上を継続し、開発効率が良く、競争力が高く、研究開発もでき、保守しやすいアーキテクチャを目指している。<br />
<br />
ただただ早く動くものを作りたいという考え方でソフトウェアの開発を続けていくと、開発効率は上がらず、過去の作ったソフトウェアの保守に追われるという悪循環から抜け出すことができない。<br />
<br />
そのような負のスパイラルから脱却するためには、長持ちして、競争力が高く、保守もしやすいアーキテクチャを目指す必要がある。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
実現の可能性(Feasibility Study)の結果</h2>
</div>
上記の目標を実現するのに重要な「実現可能性」のポイントは、Qt で正確なタイマ割り込みを発生させ、かつ、優先度の高いスレッドと低いスレッドを走らせることができるかどうかだった。<br />
<br />
Raspberry Pi3B+ のCPU は ARM Cortex-A53 1.4GHz でクワッドコア(CPU4つ)なので、4ms の定期割り込みの発生など、CPUスペックから考えれば楽勝と思えるのだが、そう簡単にはいかない。<br />
<br />
なにしろ、Linux はリアルタイムOSではないし、OSの制限もあり、msオーダーの定期割り込みを発生させるのは簡単ではない。<br />
<br />
さらに、このシステムを実現するには、マルチスレッドが必須であり、かつスレッド間のデータの受け渡しが必要で、これが意外に難しい。<br />
<br />
でも、Qt の SIGNAL/SLOT のしくみを使うことによって、マルチスレッドとイベントの伝達、データの受け渡しができることが分かった。<br />
<br />
ただ、できれば、CPUコアが4つあるので、4msインターバルの割り込み処理を行うスレッドは4つのコアのうち一つに割り当てたかったのだが、Qt 上でその設定ができなかった。<br />
<br />
その代わり、定期インターバルの起動間隔に大きなバラツキが発生したいないことは、常に確認できるようにした。<br />
<br />
10ms 間隔で起動されるスレッドで、システムタイマーの値を読み込んで、前回のタイマーの値との差分を printf で表示するようにしてある。下記は Windows で走らせたときの様子だ。これを Raspberry Pi3B+ で実行したときも、間隔に大きなずれがなければ、定期割り込みは成功していることになる。ちなみに、下記の例ではインターバル間隔に 0.5% 程度の誤差(ジッター)がある。この誤差がシステムとして許容できないようならば、Raspberry Pi3B+ の外側で発生させるか、Raspberry Pi3B+ にリアルタイムOS を搭載する。今回は、できる限り、ハードウェアの追加なしで実装したかったので、0.5%のジッターは許容したが、常にブレが大きくなっていないかどうかをWatchしておくことは重要だ。<br />
<br />
time: 1475803.318404771 CLOCK_REALTIME 09987 DIFF:uSec<br />
time: 1475803.328394707 CLOCK_REALTIME 09989 DIFF:uSec<br />
time: 1475803.338389771 CLOCK_REALTIME 09995 DIFF:uSec<br />
time: 1475803.348481033 CLOCK_REALTIME 10091 DIFF:uSec<br />
time: 1475803.358499317 CLOCK_REALTIME 10018 DIFF:uSec<br />
time: 1475803.368381897 CLOCK_REALTIME 09882 DIFF:uSec<br />
time: 1475803.378349216 CLOCK_REALTIME 09967 DIFF:uSec<br />
time: 1475803.388392228 CLOCK_REALTIME 10043 DIFF:uSec<br />
time: 1475803.398597482 CLOCK_REALTIME 10205 DIFF:uSec<br />
time: 1475803.408382657 CLOCK_REALTIME 09785 DIFF:uSec<br />
time: 1475803.418337612 CLOCK_REALTIME 09954 DIFF:uSec<br />
time: 1475803.428369466 CLOCK_REALTIME 10031 DIFF:uSec<br />
time: 1475803.438366942 CLOCK_REALTIME 09997 DIFF:uSec<br />
time: 1475803.448362910 CLOCK_REALTIME 09995 DIFF:uSec<br />
time: 1475803.458338070 CLOCK_REALTIME 09975 DIFF:uSec<br />
time: 1475803.468366909 CLOCK_REALTIME 10028 DIFF:uSec<br />
time: 1475803.478349608 CLOCK_REALTIME 09982 DIFF:uSec<br />
time: 1475803.488375431 CLOCK_REALTIME 10025 DIFF:uSec<br />
time: 1475803.498362352 CLOCK_REALTIME 09986 DIFF:uSec<br />
time: 1475803.508351083 CLOCK_REALTIME 09988 DIFF:uSec<br />
time: 1475803.518362431 CLOCK_REALTIME 10011 DIFF:uSec<br />
time: 1475803.528348146 CLOCK_REALTIME 09985 DIFF:uSec<br />
time: 1475803.538355272 CLOCK_REALTIME 10007 DIFF:uSec<br />
time: 1475803.548384713 CLOCK_REALTIME 10029 DIFF:uSec<br />
time: 1475803.558325194 CLOCK_REALTIME 09940 DIFF:uSec<br />
time: 1475803.568313623 CLOCK_REALTIME 09988 DIFF:uSec<br />
time: 1475803.578347889 CLOCK_REALTIME 10034 DIFF:uSec<br />
time: 1475803.588317923 CLOCK_REALTIME 09970 DIFF:uSec<br />
time: 1475803.598452309 CLOCK_REALTIME 10134 DIFF:uSec<br />
time: 1475803.608321620 CLOCK_REALTIME 09869 DIFF:uSec<br />
time: 1475803.618302208 CLOCK_REALTIME 09980 DIFF:uSec<br />
<br />
ちなみに、この部分を実験したのが『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/05/raspberry-pi36-qt.html" target="_blank">Raspberry Pi3を使ったリアル波形描画(6) Qtでマルチスレッド処理をやってみる</a>』の記事になる。
この実験によって、およそQt上で4ms と 10ms の間隔のタイマー割り込みを発生させ、マルチスレッドで優先度の高いスレッドにタイマー割り込み処理を任せることができた。(目標6) その確認なくして、Qtを使ったリアル波形描画 の構想はありえないし、意味がない。<br />
<br />
また、Qt そのものの特長により、マルチプラットフォームでの開発と、UI部分の開発効率を高めることができることも分かった。(目標2,5)
以前の記事でアーキテクトは「実現の可能性(Feasibility Study)」について「いける!」という感覚をつかめるかどうかが重要だと言うことを書いた。
「実現の可能性(Feasibility Study)」について「いける」のか「いけないのか」を判断するには、その商品に対して求められている要求と要求の優先度が頭の中に入っており、その要求を実現するための実現方法の引き出しをたくさん持っている必要がある。<br />
<br />
要求はさまざまあり、全部実現しようとするとコストが上がったり、開発の時間が足りなくなったりするので、競争力の高い商品にするためには、どの部分に独自の研究開発のリソースをつぎ込んで、どの部分はすでにある技術や市販のソフトウェアで補うのか、一番いいバラインスポイントを探す必要がある。<br />
<br />
それには深いドメイン知識と、広いソフトウェアエンジニアリングの技術、豊富なソリューションの引き出しを持っていることが大事だ。<br />
<br />
ちなみに、オブジェクト思考設計のコンサルタントは「広いソフトウェアエンジニアリングの技術」、「豊富なソリューションの引き出し」を持っているが、「深いドメイン知識」はない。一般的に組込みソフトウェア製品の企業のエンジニアは「深いドメイン知識」を持っているが、「広いソフトウェアエンジニアリングの技術」と「豊富なソリューションの引き出し」を持っている者は少ない。<br />
<br />
よって、長持ちして、競争力が高く、保守もしやすいアーキテクチャを目指すためには、両者が協力するか、企業のエンジニアががんばって知識やスキルを身につける必要がある。<br />
<br />
なお、ドメイン知識として、ユーザーまたは業務ドメインにおける市場要求の分析は、製品企業側で分析しておく必要がある。お客さんの声を吸い上げることができるのは、製品を設計販売している企業であり、そこに実現すべき機能や性能のもととなる要求がある。<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghu9tBepd5Y3MMOZiHD8prTG3YQbSMM_VUN5DLJXz3ERvDgaTIbYdqWUbHlj_bmxoppROzp7yX0L_9VxAJPA6f2tspgw70t-6wWQ4JNK3y02fltCeFP6NE1FVDmc0uR0yz2cEP/s1600/QFD.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="419" data-original-width="878" height="152" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghu9tBepd5Y3MMOZiHD8prTG3YQbSMM_VUN5DLJXz3ERvDgaTIbYdqWUbHlj_bmxoppROzp7yX0L_9VxAJPA6f2tspgw70t-6wWQ4JNK3y02fltCeFP6NE1FVDmc0uR0yz2cEP/s320/QFD.png" width="320" /></a></div>
<div>
要求の整理についてはQFD(品質機能展開。左図が一例)などを使うとよい。または、マインドマップなどで整理してもよい。
それらの要求が実現可能かどうかは、さまざまな条件(コスト、リソース、エンジニアが使いこなせるかどうか等々)があるので、単純ではない。なにしろ幅広い知識(引き出し)と、最新の情報にアンテナを張っていることが必要になる。
今の世の中情報はあふれかえっているので、やりたいこと、実現したいことは常に頭の中に記憶しておいて、やりたいことの実現に関係ある情報を見つけたら、その情報をクリップしておいて掘り下げるという習慣を付けておく必要がある。
働き方改革で、オンとオフをキッチリ分けて休むときは休んでエネルギーを充電するのはいいと思うが、アンテナはオフのときも立てておいて、実現可能性の種がピピッときたらメモっておくぐらいのとをやっていないと、なかなか競争には勝てない。
<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
静的構造の説明(3層構造)</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiOi-VGZyhHliYWpb8fOYTsdjaAlFNzMrUE-vPlp47EpeP1TjJO44U4SsF_m5hrW8PhmnxMqxY4vvQVSQ9Kt8KFaw7b0OGNGwsBTslShfpwDSXxXzqNOxizYm03OfgppEi4m6_/s1600/RealWaveDisplay_1786x1509.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1352" data-original-width="1600" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiOi-VGZyhHliYWpb8fOYTsdjaAlFNzMrUE-vPlp47EpeP1TjJO44U4SsF_m5hrW8PhmnxMqxY4vvQVSQ9Kt8KFaw7b0OGNGwsBTslShfpwDSXxXzqNOxizYm03OfgppEi4m6_/s400/RealWaveDisplay_1786x1509.png" width="400" /></a></div>
<br />
<br />
さて、「Raspberry Pi3を使ったリアル波形描画」のアーキテクチャ(静的な構造、クラス図)について説明していこうと思う。 なお、このアーキテクチャについては今回記事の冒頭でソースコードを入手できるようにしてあるので、ソースコードを見ながらクラス図を眺めて欲しい。<br />
<br />
デジタルフィルタと心拍数検出のアルゴリズムについては、それぞれソースコードはインタフェースだけ用意してあり、中身は空または簡易的なものにしてある。(ここが最も重要なノウハウ=コア資産と考えているため)<br />
<br />
この部分の性能を高めることができれば、他社に対する競合力となり、その資産は組織の財産となる。また、その資産が真似しにくい若しくは特許で保護されていれば、商品群のコア資産として商品の価値を生み出す宝となりうる。<br />
<br />
このアーキテクチャは プレゼンテーションレイヤー、ドメインレイヤー、データソースレイヤーの3層構造となっている。 プレゼンテーションレイヤーは、ユーザーとのユーザインタフェースを担う部分であり、表現方法は商品群の中でも変わりやすい(ハイエンド製品は大画面、ローエンド機器は小画面など)。逆に言えば、プレゼンテーションレイヤー部分を変えることで、ラインナップを揃えたり、マイナーチェンジをして商品を新しく見せることができる。<br />
<br />
仕向け地や特別なユーザー用にカスタマイズすることもあるかもしれない。 プレゼンテーションレイヤーは変わりやすく、変化に柔軟に対応できるようにしておく必要がある。<br />
<br />
プレゼンテーションレイヤーの部分の変化に対する対応は Qt Creator を使うことで、簡便にいろいろな画面を実現することが可能だ。<br />
<br />
また、ドメインレイヤーは、その商品あるいはその商品群に特有の資産を配置している。ドメインに特化しているため、その商品の本質的な機能や性能を実現していることが多い。別な言い方をすれば「本業の強み」を実現する部分だ。場合によってはソフトウェアだけでなくハードウェアも含めてコア資産となる場合もある。 基本、このドメインは「変わりにくい部分」であり、ノウハウとなり得る。<br />
<br />
なお、今回のケースでは、黄色背景のタイマー処理とスレッドのクラスもドメインレイヤーに配置した。これらはドメインに特化したクラスではないものの、プレゼンテーションレイヤーやデータソースレイヤーとも異なり、リアルタイムシステム実現のための要素でり、システム実現の根幹と考えたからである。<br />
<br />
データソースレイヤーはその名の通り、システムが使用する入力データの元となるレイヤーであり、ここは、 EcgAcquirer (心電図の受入れ者)から派生させた、3つのクラスを実装している。 その意図は、入力クラスのインタフェースを共通にしておき、入力元の実態を A/D変換器と、サンプルデータと sin波 の3種類で切り替えることができるようにしている。 信号処理アルゴリズムの設計、性能分析、性能向上を検討するためには、リファレンスとなる波形データや、問題が起こったときの 波形データをファイルから読み込んでシミュレーションでさまざまな確認を行うことが重要となる。<br />
<br />
アルゴリズムを変更したときなど、今まで動いていた機能や性能が、意図通りに動いているかどうかを確認することはとても重要であり、その確認・検証には、検証に使うシミュレーション用のデータがあるとよい。そのための入力切り替えでもある。<br />
<br />
また、デジタルフィルタの効き具合を確かめるのに、シミュレーションでsin波を入力できると都合がよい。 入力の切り替えのしくみは、C言語でも条件コンパイルを駆使したりして実現は可能だが、オブジェクト指向言語であるC++を使えば、スマートに実現できるし、クラス図でその設計思想を表現するのもやりやすい。<br />
<br />
実際、このクラス図も、Qtで設計して上手くいくことを確認したC++のソースファイルを UMLツールである Enterprise Architect に読み込ませて、整えることでクラス図にした。 そうすれば、実際のソースコードの設計思想を正確にクラス図で表現できるからだ。 入力の切り替えは、紫背景のQt Creator で作成したボタンの押下をトリガーにして、緑背景の EcgMonitor で入力のオブジェクトインスタンスを入れ替えることで、簡単に切り替えることができる。 これができると非常に気持ちがいい。また、入力のインタフェースが変わらなければ、さらに別の入力例えば、既存の心電図データベースを追加することもできる。<br />
る。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
Qt Creator の画面</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwkk-HBQj3Ztl-t_TkAm2jQT9HMXAswPPiBZ0qdrqpgzgvRxYIIgBAWWde9b_-JJFU-ZWkaLDtZVkLLtJ7SRL8w-4WRfzXpeKf5ROXgiER4Ghteb1W9XvbxyBUIhqy8XnBa2uG/s1600/QtCreator%25E7%2594%25BB%25E9%259D%25A2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1240" data-original-width="1024" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwkk-HBQj3Ztl-t_TkAm2jQT9HMXAswPPiBZ0qdrqpgzgvRxYIIgBAWWde9b_-JJFU-ZWkaLDtZVkLLtJ7SRL8w-4WRfzXpeKf5ROXgiER4Ghteb1W9XvbxyBUIhqy8XnBa2uG/s400/QtCreator%25E7%2594%25BB%25E9%259D%25A2.png" width="330" /></a></div>
左記が QtCreator で RealWaveDisplay01 のプロジェクトファイルを開いたときの画面である。ざっと、ソースファイルの説明をしておく。<br />
<br />
まず、頭に ap_ がついているファイルは、リアル波形描画特有のアプリケーションを意味する。<br />
<br />
qt_ がついているファイルは、Qt に特化した部分、今回は周期起動するスレッド処理。<br />
<br />
qcustomplot.h と qcustomplot.cpp はオシロスコープのように右から左に波形を流すために使っているソースで、『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2018/07/raspberry-pi33-qt-qcustomplot.html" target="_blank">Raspberry Pi3を使ったリアル波形描画(3) Qt + QCustomPlot で静止グラフを描いてみる</a>』の記事の一番下に使い方の解説動画がある。<br />
<br />
main.cpp は Qt のお決まりの入り口関数で、mainwindow.h と mainwindow.cpp は Qt のメインウインドウの画面の初期化やら、画面で使っている変数や、ボタンが押されたときの処理のメソッドなどが入っている。<br />
<br />
アプリケーションのソフトウェアのファイルの説明は次の通り。<br />
<ul>
<li>ap_EcgAcquirorFromSampleData.cpp :DEMO波形のデータ</li>
<li>ap_EcgAcquirorFromADConvertor.cpp :A/Dコンバータからの入力(現在スケルトン)</li>
<li>ap_EcgAcLineNoiseFilter.cpp :電源ノイズフィルター(現在スケルトン)</li>
<li>ap_EcgHighCutFilter.cpp :ハイカットフィルター(現在スケルトン)</li>
<li>ap_EcgDriftFreeFilter.cpp :ドリフトフリーフィルタ(現在スケルトン)</li>
<li>ap_EcgMonitor.cpp:波形計測の中心となるクラス(各種オブジェクトの生成も行う)</li>
<li>ap_EcgAcquirorFromSinWave.cpp:SIN波発生</li>
<li>ap_EcgDetectQrsTypeTest1.cpp:QRS検出(簡易的なアルゴリズムにしている)</li>
</ul>
<div>
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
mainwindow.cpp の説明</h2>
</div>
mainwindow.cpp 内の MainWindow クラスは QMainWindow クラスから派生したクラスでヘッダは次のようになっている。<br />
<br />
<pre><span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple;">MainWindow</span><span style="color: silver;"> </span>:<span style="color: silver;"> </span><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: purple;">QMainWindow</span></pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">Q_OBJECT</span></pre>
<pre><span style="color: olive;">public</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">コンストラクタ</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">explicit</span><span style="color: silver;"> </span><span style="color: #00677c;">MainWindow</span>(<span style="color: purple;">QWidget</span><span style="color: silver;"> </span>*<span style="color: #092e64;">parent</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: olive;">nullptr</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">デストラクタ</span></pre>
<pre><span style="color: silver;"> </span>~<span style="color: #00677c; font-style: italic;">MainWindow</span>();</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">グラフ初期化</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">intializeGraph</span>();</pre>
<pre></pre>
<pre><span style="color: olive;">private</span><span style="color: silver;"> </span><span style="color: navy;">slots</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Run/Stop</span><span style="color: silver;"> </span><span style="color: green;">ボタンを押された時の処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">on_pbt_run_clicked</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">波形タイプボタンを押された時の処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">on_pbt_wavetype_clicked</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">電源ノイズフィルターボタンが押された時の処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">on_pbt_ac_line_filter_clicked</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ドリフトフリーフィルタボタンが押された時の処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">on_pbt_drift_free_filter_clicked</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ハイカットフィルタボタンが押されたときの処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">on_pbt_hicut_filter_clicked</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">表示感度ボタンが押された時の処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">on_pbt_displaygain_clicked</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">入力ソースボタンが押されたときの処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">on_pbt_input_type_clicked</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">周波数スピンボックスの値が変化したときの処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">on_doubleSpinBox_frequency_valueChanged</span>(<span style="color: olive;">double</span><span style="color: silver;"> </span><span style="color: #092e64;">arg1</span>);</pre>
<pre></pre>
<pre><span style="color: olive;">public</span><span style="color: silver;"> </span><span style="color: navy;">slots</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">4ms周期処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">work4msPeriodicOnMainWindow</span>(<span style="color: olive;">void</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">10ms周期処理</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c;">work10msPeriodicOnMainWindow</span>(<span style="color: olive;">void</span>);</pre>
<pre><span style="color: olive;">private</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">Ui</span>::<span style="color: purple;">MainWindow</span><span style="color: silver;"> </span>*<span style="color: maroon;">ui</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: blue;">CyclicThread *mpCyclicThread4ms = new CyclicThread; // 周期起動のスレッドオブジェクト(プライベートメンバ変数)</span></pre>
<pre><span style="color: blue;"> CyclicThread *mpCyclicThread10ms = new CyclicThread; // 周期起動のスレッドオブジェクト(プライベートメンバ変数)</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mTimekey_wave</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>; <span style="color: green;">// 波形表示間隔</span><span style="color: silver;"> </span><span style="color: green;">(s)</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mWave_data</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>; <span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">波形データ</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mAdd_data</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0.1F</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mTimekey_debugwave</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">デバッグ用波形表示間隔</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mQrsFilterWave_data</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">QRSフィルt出力用波形データ</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mThresholdLevel_data</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">スレッショルドレベルデータ</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: maroon;">mDisplayCounter</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ディスプレイ用のカウンタ(10msの倍数で表示する)</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: maroon;">mRunStopFlag</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: olive;">false</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">Start/Stop</span><span style="color: silver;"> </span><span style="color: green;">フラグ</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: maroon;">mEcgDemoCounter</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">心電図デモカウンター</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: maroon;">mDemoWaveType</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">デモ波形タイプ0:三角波</span><span style="color: silver;"> </span><span style="color: green;">HR60</span><span style="color: silver;"> </span><span style="color: green;">1:三角波</span><span style="color: silver;"> </span><span style="color: green;">HR300</span><span style="color: silver;"> </span><span style="color: green;">2:疑似心電図,);</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mMaxWave</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">最大波形</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mMinWave</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">最小波形</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">float</span><span style="color: silver;"> </span><span style="color: maroon;">mPreviousPlotData</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">前回のプロットデータ</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: maroon;">mRealWaveFlag</span>=<span style="color: olive;">false</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">リアル波形<->デモ波形スイッチ</span></pre>
</div>
</div>
<pre></pre>
<pre><span style="color: blue;"> // 心電図モニタクラスを生成</span></pre>
<pre><span style="color: blue;"> EcgMonitor *mpEcgMoniter = new EcgMonitor; // 心電図モニタクラス</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: maroon;">mAcLineFilterFlag</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">電源ノイズファルタフラグ</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: maroon;">mDriftFreeFilterFlag</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ドリフトフリーフィルタフラグ</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: maroon;">mHicutFilterFlag</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ハイカットフィルターフラグ</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: maroon;">mHRDisplayCounter</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ハートレート表示用カウンタ(1秒)</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: maroon;">mQrsMarkDislpayCounter</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">QRSマーク表示用カウンタ</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">bool</span><span style="color: silver;"> </span><span style="color: maroon;">mQrsMarkDislpayFlag</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">QRSマーク表示用フラグ</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: maroon;">mDisplayGain</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">表示用の感度変数</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">char</span><span style="color: silver;"> </span><span style="color: maroon;">mGainText</span>[<span style="color: navy;">5</span>][<span style="color: navy;">6</span>]={(<span style="color: green;">"x1/4"</span>),<span style="color: silver;"> </span>(<span style="color: green;">"x1/2"</span>),(<span style="color: green;">"x1</span><span style="color: silver;"> </span><span style="color: green;">"</span>),(<span style="color: green;">"x2</span><span style="color: silver;"> </span><span style="color: green;">"</span>),(<span style="color: green;">"x4</span><span style="color: silver;"> </span><span style="color: green;">"</span>)};</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: maroon;">mInputType</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">入力種別</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">char</span><span style="color: silver;"> </span><span style="color: maroon;">mInputTypeText</span>[<span style="color: navy;">3</span>][<span style="color: navy;">18</span>]={(<span style="color: green;">"Demo</span><span style="color: silver;"> </span><span style="color: green;">"</span>),</pre>
<pre><span style="color: silver;"> </span>(<span style="color: green;">"A/D</span><span style="color: silver;"> </span><span style="color: green;">Convertor</span><span style="color: silver;"> </span><span style="color: green;">"</span>),</pre>
<pre><span style="color: silver;"> </span>(<span style="color: green;">"Sin</span><span style="color: silver;"> </span><span style="color: green;">Wave</span><span style="color: silver;"> </span><span style="color: green;">"</span>)};</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">double</span><span style="color: silver;"> </span><span style="color: maroon;">mFrequency</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">sin波の周波数</span></pre>
<br />
<pre>};</pre>
<br />
頭が on_pbt_・・・ となっているメソッドは、画面上でボタンが押されたときに、呼ばれるメソッドとなる。<br />
<br />
各種変数の定義と初期化、4msと10msの周期起動のスレッドの生成、心電図モニタメインクラスの生成などを行っている。(青字部分)<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
入力の切り替え</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHtanSKzwHeJjQPosSp3Oa9P08j2YZfBWjIpYSRkoKIpxgLtSiwfStvGph93Pcfwztq4OoIMSjiytWmWO7dCOEsgEZE1M4F6Ixw2Vnm13cv6kigITj-wIyZsAdcgcVNTDbqj3w/s1600/%25E5%2585%25A5%25E5%258A%259B%25E3%2581%25AE%25E5%2588%2587%25E3%2582%258A%25E6%259B%25BF%25E3%2581%2588.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1127" data-original-width="931" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHtanSKzwHeJjQPosSp3Oa9P08j2YZfBWjIpYSRkoKIpxgLtSiwfStvGph93Pcfwztq4OoIMSjiytWmWO7dCOEsgEZE1M4F6Ixw2Vnm13cv6kigITj-wIyZsAdcgcVNTDbqj3w/s640/%25E5%2585%25A5%25E5%258A%259B%25E3%2581%25AE%25E5%2588%2587%25E3%2582%258A%25E6%259B%25BF%25E3%2581%2588.png" width="528" /></a></div>
<br />
入力の切り替え部分を説明する。登場人物の説明<br />
<ul>
<li>EcgAcquirorクラス:心電図入力の基底クラスで実態を持たない。</li>
<li>EcgAcquirorFromADConvertor:EcgAcquirorクラスから派生したクラスで、A/D変換器からの入力を意図している。(公開ソースでは、スケルトンにしてある)</li>
<li>EcgAcquirorFromSampleData:EcgAcquirorクラスから派生したクラスで、データで定義したサンプルデータ(三角波二種類と疑似心電図データ)を供給することを意図している。</li>
<li>EcgAcquirorFromSinWave:EcgAcquirorクラスから派生したクラスで、SIN波のデータをEcgMonitorクラスに供給することを意図している。</li>
</ul>
EcgAcquiror は 心電図入力の基底クラスで getEcgWaveData() を純粋仮想関数にして、心電図波形データの入力ソースを切り替えられるようにしている。<br />
<br />
EcgAcquiror 入力のインタフェースを固定しておき、EcgAcquiror クラスから 派生させた入力ソースのクラスから、さまざまなデータを EcgMonitor クラスに共有する。<br />
<br />
EcgAcquirorFromADConvertorクラス以外は、実機(製品)では使わないのだが、デジタルフィルタや心拍計測アルゴリズムの検証したり、デモンストレーションしたりするときに、EcgAcquirorFromSampleDataクラスや、EcgAcquirorFromSinWaveクラスはあると便利だ。<br />
<br />
また、例えば、実際にA/D変換して取り込んだ心電図データや、いろいろな心電図のデータライブラリをファイルから読み込むような時には、EcgAcquirorクラスから派生させたクラスを新たに作成して、EcgMonitor クラスに持たせれば 簡単かつ、安全に入力ソースを追加することができる。<br />
<br />
この「簡単かつ安全に追加できる」ということがオブジェクト指向言語である C++ を使う目的であり、組込みソフトウェアでも C言語にこだわっている時代ではないと思う理由だ。C言語でも同じことはできると思うが、「簡単かつ安全に追加する」ためにはC++を使った方がよいと思う。<br />
<br />
具体的には EcgMonitor クラス のメソッドに 心電図入力オブジェクトのポインタ変数を作っておき、派生させた3つのクラスを new で作成してそれらのポインタをポインタ変数に格納している。<br />
<br />
<pre><span style="color: olive;">protected</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">心電図入力オブジェクトのポインタ(メンバ)をする</span></pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">EcgAcquiror</span><span style="color: silver;"> </span>*<span style="color: maroon;">mpEcgAcquiror</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">EcgAcquirorFromSampleData</span><span style="color: silver;"> </span>*<span style="color: maroon;">mpEcgAcquirorDemo</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">EcgAcquirorFromSampleData</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">EcgAcquirorFromADConvertor</span><span style="color: silver;"> </span>*<span style="color: maroon;">mpEcgAcquirorADC</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">EcgAcquirorFromADConvertor</span>;</pre>
<br />
<pre><span style="color: silver;"> </span><span style="color: purple;">EcgAcquirorFromSinWave</span><span style="color: silver;"> </span>*<span style="color: maroon;">mpEcgAcquirorSin</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">EcgAcquirorFromSinWave</span>;</pre>
<br />
<br />
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">EcgMonitor</span>::<span style="color: #00677c; font-weight: 600;">activateEcgDemoMode</span>(<span style="color: olive;">void</span>)</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">心電図入力オブジェクトにデモ波形オブジェクトを設定して、デモタイプを三角波にする</span></pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mpEcgAcquiror</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: maroon;">mpEcgAcquirorDemo</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mpEcgAcquirorDemo</span>-><span style="color: #00677c;">setEcgDemoType</span>(<span style="color: navy;">0</span>);</pre>
<br />
<pre>}</pre>
<pre></pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">EcgMonitor</span>::<span style="color: #00677c; font-weight: 600;">activateEcgAdcMode</span>(<span style="color: olive;">void</span>)</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">心電図入力オブジェクトにADCオブジェクトを設定する</span></pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mpEcgAcquiror</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: maroon;">mpEcgAcquirorADC</span>;</pre>
<br />
<pre>}</pre>
<pre></pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">EcgMonitor</span>::<span style="color: #00677c; font-weight: 600;">setEcgDemoType</span>(<span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: #092e64;">type</span>)</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: silver;"> </span><span style="color: #092e64;">type</span><span style="color: silver;"> </span>><span style="color: silver;"> </span><span style="color: navy;">2</span>)<span style="color: silver;"> </span><span style="color: #092e64;">type</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">3以上だったら強制的に</span><span style="color: silver;"> </span><span style="color: green;">0:ECGにする</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">波形種別を設定する。</span></pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mpEcgAcquirorDemo</span>-><span style="color: #00677c;">setEcgDemoType</span>(<span style="color: #092e64;">type</span>);</pre>
<br />
<pre>}</pre>
<pre></pre>
<pre></pre>
そして、入力モードの切り替えが指示されたら、mpEcgAcquiror に各、入力ソースのポインタをセットしてあげればよい。<br />
<br />
それだけで、その後の処理は何も変える必要がない。<br />
<br />
<pre><span style="color: silver;"> </span><span style="color: green;">//----------------------------------------------</span></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">内容:疑似心電図三角波</span></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">サンプリング:</span><span style="color: silver;"> </span><span style="color: green;">4ms</span></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">データ数:</span><span style="color: silver;"> </span><span style="color: green;">250</span></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">振幅:1000</span></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//----------------------------------------------</span></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">HR</span><span style="color: silver;"> </span><span style="color: green;">=</span><span style="color: silver;"> </span><span style="color: green;">60のデータ</span></pre>
<pre><span style="color: silver;"> </span>{</pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.000</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.010</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.020</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.030</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.040</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.050</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.060</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.070</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.080</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.090</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.100</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">100</span>,<span style="color: silver;"> </span><span style="color: navy;">200</span>,<span style="color: silver;"> </span><span style="color: navy;">300</span>,<span style="color: silver;"> </span><span style="color: navy;">400</span>,<span style="color: silver;"> </span><span style="color: navy;">500</span>,<span style="color: silver;"> </span><span style="color: navy;">600</span>,<span style="color: silver;"> </span><span style="color: navy;">700</span>,<span style="color: silver;"> </span><span style="color: navy;">800</span>,<span style="color: silver;"> </span><span style="color: navy;">900</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.110</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">1000</span>,<span style="color: silver;"> </span><span style="color: navy;">900</span>,<span style="color: silver;"> </span><span style="color: navy;">800</span>,<span style="color: silver;"> </span><span style="color: navy;">700</span>,<span style="color: silver;"> </span><span style="color: navy;">600</span>,<span style="color: silver;"> </span><span style="color: navy;">500</span>,<span style="color: silver;"> </span><span style="color: navy;">400</span>,<span style="color: silver;"> </span><span style="color: navy;">300</span>,<span style="color: silver;"> </span><span style="color: navy;">200</span>,<span style="color: silver;"> </span><span style="color: navy;">100</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.120</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.130</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.140</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.150</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.160</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.170</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.180</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.190</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.200</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.210</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.220</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.230</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<pre><span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span>,<span style="color: silver;"> </span><span style="color: navy;">0</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">No.240</span><span style="color: silver;"> </span><span style="color: green;">~</span></pre>
<br />
<pre><span style="color: silver;"> </span>},</pre>
<br />
サンプルデータはこんな感じでデータが定義されている。<br />
<br />
そして、このような切り替え可能な構造になっていいることは、作成したソースコードを UML ツールに読み込んで、整形して クラス図にすることで、モデルで確認することができる。<br />
<br />
それが、上記のクラス図だ。クラス図を描いてからソースコードを作ったり、ソースコードをリバースエンジニアリングしてクラス図を作ったりを繰り返していると、だんだん派生のしくみや、クラス図どおりに実装するにはどうすればよいかが分かってくる。<br />
<br />
次回以降は、入力部以外のアーキテクチャを解説していく。
sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-46340740895024797102019-06-10T15:22:00.000+09:002019-06-10T15:22:43.163+09:00Raspberry Pi3を使ったリアル波形描画(8) アーキテクトの腕の見せどころ<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ROfAPejouYP4CLw5kcShFICr5cy6zeDWEioT-L5BGBAtZXdUqcAxYf5dy7iaqjJHakwB8wn6GYGlXOSbt8M1Pvt77VotJAKdiSorhgakSRPxNhOBfhGfyAc7_GwImIR_R4BG/s1600/RealWaveDisplayTitle08_340x241.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="340" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ROfAPejouYP4CLw5kcShFICr5cy6zeDWEioT-L5BGBAtZXdUqcAxYf5dy7iaqjJHakwB8wn6GYGlXOSbt8M1Pvt77VotJAKdiSorhgakSRPxNhOBfhGfyAc7_GwImIR_R4BG/s320/RealWaveDisplayTitle08_340x241.png" width="320" /></a></div>
この特集記事とは別に『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/05/blog-post.html" target="_blank">ソフトウェアアーキテクチャとは何かを考える</a>』という記事を書いた。<br />
<br />
ここで説明したのはリアル建築で例えれば「どんな生活をしたいのか」「家主の要望は何か」「予算はどれくらいか」などによって,家の構造設計は変わるということだ。<br />
<br />
ソフトウェアのアーキテクチャも何をしたいのか,どんな困りごとを解決したいのかによって,ソフトウェアシステムのアーキテクチャは変わる。ソフトウェアのアーキテクチャの重要なポイントは「設計思想」だと思う。設計思想こそが「アーキテクトの腕の見せどころ」のポイントなのだ。<br />
<br />
『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/05/blog-post.html" target="_blank">ソフトウェアアーキテクチャとは何かを考える</a>』にも書いたが,ソフトウェアの場合は,「大改造!!劇的ビフォーアフター」のようにリフォーム後に アーキテクトの仕事の成果を顧客とともに見て回り,リフォームのできに感動してもらうといったシーンがない。ソフトウェアは見えないから,アーキテクチャの善し悪しは分かる人にしか分からない。そこがなんとも悲しいところなのだが,だからこそ,アーキテクトはそのシステムのアーキテクチャの設計思想を他人にキチンと説明できるようにしておかないとダメなのだろう。<br />
<br />
そう思い,今回の記事では 『Raspberry Pi3を使ったリアル波形描画』の取り組みの中で採用しようとしているアーキテクチャの設計思想を説明しておきたいと思う。<br />
<br />
考え方はInterface誌 2003年1月号に投稿した記事『<a href="https://www.cqpub.co.jp/interface/contents/2003/200301.htm" target="_blank">オブジェクト思考を使ったリアルタイム信号計測システムの開発</a>』と同じなので,まずは,この記事で想定した 1ch のデジタルオシロスコープを例に説明しようと思う。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_jVPleA04afL7UrBN_B3TP7gQjY_6ZeVKeehEivc1LAkGt84ijIb8pLj5VIbZtTQ4fPXQ1c0xWzr645yD-U2bS07BzzzC6DqYQpHITexoTcAmryJJItoeoxs9hEVO9j4X4mhz/s1600/1ch%25E3%2582%25AA%25E3%2582%25B7%25E3%2583%25AD%25E3%2582%25B9%25E3%2582%25B3%25E3%2583%25BC%25E3%2583%2597.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="308" data-original-width="883" height="138" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_jVPleA04afL7UrBN_B3TP7gQjY_6ZeVKeehEivc1LAkGt84ijIb8pLj5VIbZtTQ4fPXQ1c0xWzr645yD-U2bS07BzzzC6DqYQpHITexoTcAmryJJItoeoxs9hEVO9j4X4mhz/s400/1ch%25E3%2582%25AA%25E3%2582%25B7%25E3%2583%25AD%25E3%2582%25B9%25E3%2582%25B3%25E3%2583%25BC%25E3%2583%2597.png" width="400" /></a></div>
ここに 1ch のデジタルオシロスコープの完成予想図がある。この機器の目的は,電気回路の信号をピックアッププローブで拾って,高周波のノイズを取り除いて,目的の信号だけを見えるようにして,結果をUSB経由でPCに保存するというものだ。<br />
<br />
この製品のソフトウェアシステムを設計したい。設計の前に解決したい問題を確認しておこうと思う。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
解決したい問題</h2>
</div>
この商品の開発の前提として,この商品は単発の商品とするのではなく,商品ラインナップにして,基本の機能はさまざまなオシロスコープ製品群に使いたいと思っている。<br />
<br />
この商品の基本機能はノイズを除去するためのデジタルフィルターであり,ハイエンド製品では,さまざまな,フィルターを搭載できるようにしたり,切り替えたりできるようにしたい。よいデジタルフィルターを設計し,搭載することができれば,それがこの商品群のコア資産となり,その資産が他社の商品と競合したときのアドバンテージとなる。<br />
<br />
したがって,アーキテクチャの第一の目的は「コア資産となるデジタルフィルタのソフトウェアモジュール」の再利用しやすく設計し,さまざまな商品群にソフトウェアにまったく手を加えることなく<span style="color: blue; font-size: x-small;">※1</span>,利用できるようにすることである。<br />
<br />
<span style="color: blue; font-size: x-small;">※1 コア資産の主要部分(パラメータ設定以外)についてはソースコードを1行も変更しないで複数の製品に使用できることを「再利用」と言っている。ソフトウェアは簡単に変更することができ,1行変更しただけで動かなくなったり,デグレードしたりするので「再利用」は基本,ソースコードの変更はなしでできることが前提。</span><br />
<br />
それがうまくいけば「競争力の高いソフトウェア資産」使って,さまざまな商品展開ができ,顧客満足が高まり,商売も儲かる。<br />
<br />
また,「競争力の高いソフトウェア資産」に問題があり,それが市場で発覚すると,組織に大きなダメージを与えるため,コア資産となるソフトウェアの信頼性は十分に確認しておきたい。これらの要求をまとめると次のようになる。<br />
<ol>
<li>コア資産となるデジタルフィルタのモジュールを再利用可能な資産(ソフトウェア本体にまったく手を入れることなく再利用可能)にする。</li>
<li>コア資産となるデジタルフィルタはさまざまなバリエーションを持たせる。</li>
<li>新しいフィルタを開発することと,採用するフィルタの妥当性確認(バリデーション)をしやすくするために,実機ではなくPC上でフィルタ効果を確認できるようにしたい。</li>
<li>フィルタの入力は信号ピックアッププローブから入力するだけでなく,検証用に持っている信号データや,擬似的に作成したデータを入力できるようにしたい。</li>
<li>データの保存はUSB経由を想定しているが,将来は Wi-Fi や ブルートゥース経由でPCへ保存できるようにしたい。</li>
</ol>
<div>
ちなみにソフトウェアの「再利用」ではなく「流用」ということばを使っている技術者をよく見かけるが,自分は「流用」ということばは絶対に使わない。「流用」ということばの響きに「再利用のための設計思想はありません」というニュアンスを感じるからだ。</div>
<div>
<br /></div>
<div>
設計思想のないアーキテクチャには将来ろくな事がないと思う。設計思想なく「流用」されたソフトウェアは,最初に設計したときの思想が伝わることなく,別のシステムにはめ込まれ,予想もしなかったような不具合が起きることがある。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-rvdo2YH6iK7ouYodha9QilWztdvYI-gWcUQpjyp_Nhpl9qwRA96EI4RUT0H5YMO3oX2weBGyjpBO1bEAJHaIJVBGVj4SiLelCmJpq5ef2T1KTXHJfa9_EV_oWgMkXLrgPsxd/s1600/%25E3%2582%25AA%25E3%2582%25B7%25E3%2583%25AD%25E3%2582%25B9%25E3%2582%25B3%25E3%2583%25BC%25E3%2583%2597%25E6%25A7%258B%25E6%2588%2590%25E5%259B%25B3.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="455" data-original-width="485" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-rvdo2YH6iK7ouYodha9QilWztdvYI-gWcUQpjyp_Nhpl9qwRA96EI4RUT0H5YMO3oX2weBGyjpBO1bEAJHaIJVBGVj4SiLelCmJpq5ef2T1KTXHJfa9_EV_oWgMkXLrgPsxd/s320/%25E3%2582%25AA%25E3%2582%25B7%25E3%2583%25AD%25E3%2582%25B9%25E3%2582%25B3%25E3%2583%25BC%25E3%2583%2597%25E6%25A7%258B%25E6%2588%2590%25E5%259B%25B3.png" width="320" /></a></div>
<div>
さて,これらの要求を実現するための概念的な構造を図で表してみると左図のようになる。(設計の思想)</div>
<div>
<br /></div>
<div>
入力は製品では信号ピックアッププローブから入力(A/D変換)するが,実験,検証のために信号データファイルからも入力できるようにしたい。</div>
<div>
<br /></div>
<div>
この入力の切り替えは簡単にスイッチできるようにしたいし,その後のソフトウェア(デジタルフィルタやディスプレイ表示やデータ保存)には影響を与えたくない。(1行もソフトウェアを変えないで済むようにしたい)</div>
<div>
<br /></div>
<div>
信号処理部のデジタルフィルターは,さまざまなものをラインナップし,こちらも簡単に切り替えられるようにしたい。新しいフィルタも簡単に試せるようにしたい。</div>
<div>
<br /></div>
<div>
波形の出力は 小さなLCDディスプレイに表示するが,このLCDディスプレイは商品によってサイズや解像度が変わる。また,後継機種を出す際にはLCD部品が変わる可能性が高いので,これらの変化に柔軟に対応できるようにしたい。</div>
<div>
<br /></div>
<div>
さらに,データの出力機能としては,当初は USB I/FでデータをPCに送るが,将来はWi-Fi や ブルートゥース経由でデータを格納できるようにしたい。</div>
<div>
<div style="background-color: #fefdfa; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
このシステムにおけるコア資産は何か?変わりない部分と変わりやすい部分</h2>
</div>
この商品または商品群における「コア資産」はデジタルフィルタA, B, ・・・ Z である。これらは有効性が確かめられれば,今後,ずっと代えることなく使い続けることのできる資産である。長い間変わりのない部分となる。そして,ずっと変わらず性能がよければ他社との競争力の源泉にもなる。これらのコア資産を最大限活かすことが,今回のアーキテクトの設計思想(腕の見せどころ)だ。<br />
<br />
なお,出力部のLCDディスプレイは変更となる可能性が高い。また,出力の I/F は時代とともに新たなものが増えていく。ようするに,将来の商品開発を見据えて長い目でみれば,変わりやすい部分と言える。<br />
<br />
変わりやすい部分の影響を受けて,コア資産にも変更が加わるようにはしたくない。ソフトウェアアーキテクチャ上,信号処理部と出力部はキッチリ分けて,信号処理部から出力部へのデータ渡しの I/F はできるだけ変わらないようにしたい。<br />
<br />
また,入力部の信号ピックアッププローブと信号データファイルについても,その後ろの工程からみたらその差について気にしないですむようにしたい。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy7ltdvKVccheYsrb3EWY3P33-rS67IQ5QDjwGy71i4wLK0KIRXvbx-npVV04kKahyphenhyphennsvubblYbKpULXwYzgEwMtZKw95GLrEW17WSEq7CIhrh0-ovTE4zuT58zIA91VwozlRg/s1600/%25E5%25AE%259F%25E3%2582%25B7%25E3%2582%25B9%25E3%2583%2586%25E3%2583%25A0%25E3%2581%25A8%25E4%25BB%25AE%25E6%2583%25B3%25E3%2582%25B7%25E3%2582%25B9%25E3%2583%2586%25E3%2583%25A0.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="297" data-original-width="503" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy7ltdvKVccheYsrb3EWY3P33-rS67IQ5QDjwGy71i4wLK0KIRXvbx-npVV04kKahyphenhyphennsvubblYbKpULXwYzgEwMtZKw95GLrEW17WSEq7CIhrh0-ovTE4zuT58zIA91VwozlRg/s400/%25E5%25AE%259F%25E3%2582%25B7%25E3%2582%25B9%25E3%2583%2586%25E3%2583%25A0%25E3%2581%25A8%25E4%25BB%25AE%25E6%2583%25B3%25E3%2582%25B7%25E3%2582%25B9%25E3%2583%2586%25E3%2583%25A0.png" width="400" /></a></div>
<br />
信号ピックアッププローブと信号データファイルの切り替えのイメージはこのような感じとなる。<br />
<br />
製品では A/D変換器から取り込んだ信号でデータにデジタルフィルタをかけ,結果を表示する。<br />
<br />
これをリアルシステムとすれば,バーチャルシステム(仮想システム)では,信号データはファイルたか取り込んで,デジタルフィルタをかけ,その結果を開発マシンのPCのディスプレイ上に表示したい。<br />
<br />
「バーチャルシステムでコア資産の性能を検証し,商品として使えそうであること(有効性)が確認でき次第,コア資産のソフトウェアに手を加えることなく,リアルシステムで動かす」これが,今回のシステムの設計思想となる。<br />
<br />
ちなみに,コア資産は変わりにくいとはいえ,一度作ったら終わりということにはならない。競合他社と競争しているわけだから,日々改善,性能向上をしていく必要もある。そのき,改善したコア資産の中身だけを入れ替えて,コア資産の入力と出力のI/Fを代えなくて済めば,安全に性能向上のバージョンアップができる。<br />
<br />
コア資産の改善と,入出力の仕様の変化の対応を同じレベルで考えてはいけない,コア資産の改善は,その商品や商品群の屋台骨を強くするための取り組みであり,入出力の仕様の変化に対応するのは,ユーザインタフェースの改善が目的である。後者は商品の本質的な価値に関係し,後者は商品の(表面的な)魅力に関係する。どちらも,商品が売れるためには必要だが,コア資産は他社にまマネできない競争力の源泉であり,後者は他社が真似しようと思えば真似できる。だから,コア資産は機能や性能を確認し,信頼性が十分に高い状態を維持し,ユーザインタフェースの部分は時代に合わせて素早く変化できるよにしておくことが重要となる。<br />
<br />
コア資産の性能向上を検討したときに,デグレード(今までできていたことができなくなったり,性能が落ちたりすること)してはまずいので,これまでできていたことの検証もできるようにしておきたい。<br />
<br />
そのとき,実機でさまざまな入力信号を再生して,結果を確認するのは多大な工数を必要とする。だから,この検証部分は バーチャルシステムで網羅性の高い確認を行い,最後にリアルシステムでサンプル検証する方法を採りたい。<br />
<br />
これらができると飛躍的に開発効率が高まる。<br />
<ul>
<li>新しい性能(今回はフィルタの特性)の確認が実機なしで確認できる。</li>
<li>さまざまな入力データを新しいコア資産に通した結果をシミュレーション環境で確認できる。</li>
<li>ソフトウェアをいじることなく,かつ,安全に新しいコア資産をリアルシステムに実装できる。</li>
<li>フィールドで問題が起きたとき(例えば,結果が期待通りにならないケース)入力データを記録できれば,そのデータを繰り返しシミュレーション環境で再現できる。</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7cpHlqI0vlViKmxvnLLgVzstR4opmhFBaCuMUOB2yyYx5SQTOpcdc6pOqUNJuVjxrh81aCzF-dFVrqAEhS_XGKSbas0qmv6neU_iAf8z1WiG9GFbRhJIa2t4UZiJ1CZOG8BuU/s1600/%25E4%25BB%25AE%25E6%2583%25B3%25E3%2581%258B%25E3%2582%2589%25E7%258F%25BE%25E5%25AE%259F%25E3%2581%25B8.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="486" data-original-width="636" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7cpHlqI0vlViKmxvnLLgVzstR4opmhFBaCuMUOB2yyYx5SQTOpcdc6pOqUNJuVjxrh81aCzF-dFVrqAEhS_XGKSbas0qmv6neU_iAf8z1WiG9GFbRhJIa2t4UZiJ1CZOG8BuU/s400/%25E4%25BB%25AE%25E6%2583%25B3%25E3%2581%258B%25E3%2582%2589%25E7%258F%25BE%25E5%25AE%259F%25E3%2581%25B8.png" width="400" /></a></div>
これを図で示すとこんな感じとなる。<br />
<br />
仮想システムでコア資産となるデジタルフィルタにサンプルデータを流し込み,開発環境のPCのディスプレイに表示する。<br />
<br />
このとき,デバッグ用に内部データをPCに表示することも可能。<br />
<br />
そして,さまざまな入力データで網羅性の高い検証を行ったのち,リアルシステムにスイッチして実機環境にて,シミュレーション環境と結果が同じになることを確認して実装を完了する。<br />
<br />
今回のシステムでやりたいことは,こういったことだ。<br />
<br />
ここまでの説明でお分かりかと思うが,ソフトウェアのシステムアーキテクチャの設計にあたって,対象の商品や商品群,提供するサービス,顧客の要望,開発効率を妨げていることなどの情報が必要となる。<br />
<br />
そして,商品や商品群のコア資産が何か,そのコア資産を再利用して効率よくまた,安全に派生開発できるようにするには,どんなアーキテクチャが最適かを考える。<br />
<br />
ソフトウェア開発を単発で考えているとこの発想にはならない。製品のソフトウェアを外部の協力会社に丸投げしているようなプロジェクトでは,およそこういった発想にはならないだろう。商品開発とソフトウェアの再利用,開発の効率化,安全性信頼性の向上を頭にいれたアーキテクチャ設計が必要になる。<br />
<br />
5年とか10年,また,複数の商品,商品群で共通に利用するコア資産をベースにした再利用開発を想定したアーキテクチャ設計を行う,これがソフトウェアアーキテクトの腕の見せどころとなる。<br />
<br />
このようなシステムを実現するためのソフトウェアアーキテクチャは具体的にどう設計するのかを次回以降解説する。<br />
<br />
今回の記事には書かなかったが『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/05/raspberry-pi36-qt.html" target="_blank">Raspberry Pi3を使ったリアル波形描画(6) Qtでマルチスレッド処理をやってみる</a>』に書いたように,マルチスレッドによる正確なタイムインターバルの実現と,タイマーイベントとデジタルフィルタのモジュールはパッシブに(『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/05/blog-post.html" target="_blank">ソフトウェアアーキテクチャとは何かを考える</a>』で解説したデータ結合のような疎結合状態)つながるようにしないといけない。<br />
<br />
また,デバッグ用の画面も含めたユーザインタフェースはゼロから作るのは効率が悪い。今の時代,さまざまなお助けツールがある。<br />
<br />
今回の特集記事で Qt を使った事例を書いているのは,ここまで説明してきたアーキテクチャの基本設計の方針を Qt を使うと上手に実現できそうだということが分かったからだ。(特にユーザインタフェースの部分は相当お助けになる)<br />
<br />
波形描画やボタンなどのユーザインタフェースは自分で作ると結構時間がかかる。しかも,UIは時代とともにどんどん変わっていくし,ユーザもリッチなUIに慣れてきているので,プアーなUIだと中身の性能が良くても,商品として評価が低くなるかもしれない。<br />
<br />
だから,Qt を使うことでユーザインタフェースは最大限作業を省くことができたし,デバッグ用の内部のデータ表示なども,サクッと作ることができた。<br />
<br />
そして,PC上で表示した画面をソースコードを変えることなく,そのまま,Raspberry Pi3 上で使えるのも魅力的だった。<br />
<br />
さらに,4ms の正確なタイムインターバルを発生させて,Qt のSIGNAL/SLOTのしくみをつかって,他のコア資産にイベントを伝達できることも分かった。<br />
<br />
ソフトウェアアーキテクチャの設計思想がよくても,実現の方法や条件が満たされていないと上手くいかない。さまざまな制約条件をクリアしつつ,目的のアーキテクチャを設計思想通りに実現する,これがソフトウェアアーキテクトの腕の見せどころなのだ。<br />
<br />
制約があればあるほど,燃えるのがプロの職人であり,そのためには,数多くの経験とソフトウェア設計に関する多くの引き出しがないといけない。いろいろな制約条件がある中で,設計思想にぴったりくるアーキテクチャが見つかったときに「いける!」と感じる瞬間がある。<br />
<br />
それは,開発の相当初期の段階で,実現可能性の検討段階(フィージビリティ・スタディ)のときでないとまずい。作り始めてしまったあとに,最初の設計思想が実現できないことがわかり,妥協していくと,グダグダになってプロの仕事でなくなってしまう。<br />
<br />
制約条件をクリアしながら,価値の高い商品を効率良く生み出していくアーキテクチャ,これを実現するのがプロのソフトウェアアーキテクトだと思う。<br />
<br />
今回,ソフトウェア自体(ソースコードやクラス図など)に一切触れなかったのは,アーキテクチャを決定するのに,いかに設計思想が重要かということを理解してもらいたかったからだ。<br />
<br />
プログラマーとしてプロならば,デザインパターンなどの定石や手筋が習得できているだけでいいのかもしれないが,ソフトウェアアーキテクトしてプロの仕事をするのならば,効率良く儲かる,ユーザにも高い満足を与えることができる設計が必要だ。<br />
<br />
リアル建築に例えれば,一級建築士の資格をもって,個人事務所を持ち,限られた予算でさまざまな要求を持つ顧客を満足させる家を実現するために最適な図面を書き,設計思想どおりに家ができるようにコントロールする役割が求められる。<br />
<br />
同じ要求のユーザはほとんどいない。業務ドメインによって,求められる構造も,制約条件も変わる。今回紹介しているリアル波形描画のシステムにしても,ドメインに依存しており,処理の時間制約が厳しいという条件に特化していると言える。<br />
<br />
だから,このアーキテクチャはどの業務ドメインにも使えるというわけではない。しかし,だからこそ,アーキテクトは幅広い見識と経験,多くの引き出しが必要だ。銀の弾丸はなく,どのドメインにも最適な解はない。<br />
<br />
なお,『<a href="https://amzn.to/2XrppVL" target="_blank">リアルタイムOSから出発して 組込みソフトエンジニアを極める[改装版]</a>』は,全編 仮想の電子レジスター 商品群をテーマに,今回書いているようなことを解説している。<br />
<br />
今回の特集記事は,この本で書いたことを,実機で実現できると証明するために書いた。机上の空論と言われたくなかったからだ。<br />
<br />
次回からは,実際にどのような構造にすると実現できるのかを説明していく。<br />
<br />
大規模・複雑化している組込みソフトウェアにC言語だけで取り組んでいるエンジニアに,オブジェクト指向設計やC++などのオブジェクト指向言語を使うと,開発がこんなに楽になるよと伝えたいというのも,この特集記事を書いている理由だ。</div>
sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-3223394388526387582019-05-31T16:01:00.002+09:002019-05-31T16:01:21.941+09:00Raspberry Pi3を使ったリアル波形描画(7) デジタル信号処理の基本を理解する<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYQtfIO4-39pH4RHUdA_UHgm2L4g1vbgMvEMEy7Y6MLg8NMUgXkVEsLKAezEJNJWXhS57KZalZKWDKwF74rpddPrBIxxSolKjttnpasKeXC8SddWl29OI6p09GrQEIGIJeOtSS/s1600/RealWaveDisplayTitle07_340x241.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="340" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYQtfIO4-39pH4RHUdA_UHgm2L4g1vbgMvEMEy7Y6MLg8NMUgXkVEsLKAezEJNJWXhS57KZalZKWDKwF74rpddPrBIxxSolKjttnpasKeXC8SddWl29OI6p09GrQEIGIJeOtSS/s320/RealWaveDisplayTitle07_340x241.png" width="320" /></a></div>
本特集は「Raspberry Pi3を使ったリアル波形描画」がテーマだが,もちろん「描画すること」が目的ではない,何らかのアナログ信号をA/D変換して,その波形を描画したり,二次処理することがしたい。<br />
<br />
そのためには,デジタル信号処理の基本を理解しておく必要がある。前回の特集記事『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/05/raspberry-pi36-qt.html" target="_blank">Raspberry Pi3を使ったリアル波形描画(6)Qtでマルチスレッド処理をやってみる で</a>』4msぴったりのサンプリングにこだわっていたのは,例えば,心電図などのデジタル信号処理としてブレのない(ジッターのない)信号サンプリングは必須の条件だからだ。<br />
<br />
Raspberry Pi3 ではアナログの信号を取り込む際,多くの場合 A/D変換器は外付けで用意することになる。<br />
<br />
実際の工作については『<a href="https://qiita.com/shiraco/items/8c2587ae5a647b4f9803" target="_blank">はじめてのAD変換(RaspberryPi3で試すアナログ・デジタル変換)</a>』の記事を参考にしていただきたい。<br />
<br />
問題は,A/D変換器に対して,定期的なA/D変換のタイミングを作るのは誰か?ということだ。例えば,部屋の温度が何度なんかを知りたいのならば,A/D変換のタイミングはかなり遅くて適当(例えば5分おきとか)でもいいだろう。もともとの信号の変化がそんなに早くないからだ。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVz1ildjdq-qSrEHAoSG6zcEpphSYcgtDPQan-UL70dedtXEPQC_vrdJxLg5rpC8_wobNYEl5IDsKS5Ei3jAGwhVaWmq4-NkxK48YrFcfKKaSueR9Ddm0aWI1G8AkoFNzp5eHb/s1600/256px-SinusRhythmLabels.svg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="254" data-original-width="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVz1ildjdq-qSrEHAoSG6zcEpphSYcgtDPQan-UL70dedtXEPQC_vrdJxLg5rpC8_wobNYEl5IDsKS5Ei3jAGwhVaWmq4-NkxK48YrFcfKKaSueR9Ddm0aWI1G8AkoFNzp5eHb/s1600/256px-SinusRhythmLabels.svg.png" /></a></div>
一方で,例えば生体信号である心電図などを計測する際には,早いサンプリングが必要となる。なぜなら,心電図の変化,例えば,心臓がドクンとしたときの急峻な立ち上がりの部分(左図のQRS波形)はおよそ幅が10msくらいなので,それよりも早いサンプリングでないとこのQRS波形をA/D変換器で取り込んで再現することができなくなる。<br />
<br />
QRS波形の幅が10msなのに10msでサンプリングしていたら,タイミングによってはQRS波形をすっぽり取りこぼしてしまうかもしれない。<br />
<br />
だから心電図をA/D変換するならば最低でも4msのサンプリング間隔(250Hz)は必要と言われる。<br />
<br />
そして,そのサンプリング間隔にブレ(ジッター)があると,本当の心電図が正確に再現できないということは容易に想像できるだろう。<br />
<br />
したがって,A/D変換器に対して,例えば心電図の取り込みならば,正確に4ms間隔の割り込みを発生させる必要がある。4ms, 3ms, 5ms, 4ms というような感じではだめだ。ブレは 4ms ± 10μs (0.25%)ぐらいには押さえたい。<br />
<br />
このタイムインターバルのトリガーを Raspberry Pi3 の外側で発生させるのであれば,水晶発振子で定期的な割り込みを発生させれば,相当正確なサンプリング間隔を作れる。(数十キロHz~)<br />
<br />
ただ『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/05/raspberry-pi36-qt.html" target="_blank">Raspberry Pi3を使ったリアル波形描画(6) Qtでマルチスレッド処理をやってみる</a>』の記事に書いたように,Raspberry Pi3自身で(ある程度)正確なサンプリング間隔を作れるのであれば,わざわざ外部でサンプリングの間隔を作る回路は必要なくなるので都合がよい。Raspberry Pi3 で4ms間隔のタイミングを作ることができれば,それをトリガーにして,外部のA/D変換器から GPIOを経由して,SPI通信やI2C通信を使って A/D変換した値を取り込む例はいろいろな資料で公開されている。<br />
<br />
外付けのA/D変換器とアナログアンプと電極があれば,心電図を取り込むこと自体はそう難しいことではない。<br />
<br />
ただし,デジタル信号処理の基本を理解していないと,正しい計測はできない。<br />
<div style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
デジタル信号処理の基本</h2>
</div>
デジタル信号処理の基本を理解するのに『<a href="https://amzn.to/2K4GZew" target="_blank">ディジタル信号処理の基礎</a>』がいいと思ったのだが,なんとこの本は絶版になってしまっている。(最近,よいと思う本が絶版になってることがよくあり寂しい)<br />
<br />
そこで,この本に書いてあることの一部を紹介していこうと思う。こちらの記事『<a href="http://www.picfun.com/dsPIC/dspsw/dspprog01.html" target="_blank">アナログ信号のサンプリング処理</a>』も参照されたし。<br />
<br />
まず,アナログとデジタルの違いについて。<br />
<br />
【アナログとデジタル】<br />
<ul>
<li>アナログとは連続的に変化する信号を無段階に表すことを指し、デジタルとはある値を離散的な数値によって表すことを指します。組込み機器では一般に、アナログデータをセンサによって電流や電圧などに変換し、その変化をADC(アナログ-デジタル変換器)などでデジタルデータにして処理を行います。変換されたデジタルデータはデジタルのまま利用されたり、DAC(デジタル-アナログ変換器)などで再度アナログデータに変換したりします。</li>
<li><span style="color: blue;">アナログシステムでは使用する部品の性能に誤差があるため、温度などの周辺の環境が変わっても同じような動作をさせるためには誤差を見込んだ設計や、機器生産時の調整や校正を行う必要があります。</span></li>
<li><span style="color: blue;">これに対してデジタルシステムでは、安定した動作、高再現性、変更のしやすさなどのメリットがあり、最近の組み込みシステムではセンサからのアナログ出力をできるだけ早い段階でデジタルに変換して処理や制御に用いるケースが多くなっています。</span></li>
<li>しかしながら、デジタルシステムでは量子化時の誤差やプロセッサの処理速度の限界などがあるため、システムのリアルタイム性や連続性、コストメリットなどを考慮すると要求仕様をアナログシステムで実現した方がよい場合もあります。</li>
</ul>
デジタル信号処理を行うにあたっては,シャノンのサンプリング定理を理解しておく必要がある。<br />
<br />
【シャノンのサンプリング定理】<br />
<ul>
<li>関数 f(t) がW Hz 以上の周波数を含まないとき、その関数は(1/2W)秒間隔で抽出した標本値により完全に表現できる。</li>
</ul>
<br />
<div>
たぶん,これだけ読んでも直感的に理解できないと思うので,『<a href="https://amzn.to/2K4GZew" target="_blank">ディジタル信号処理の基礎</a>』の図(p40 図3.8)を使って説明したい。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn5wfx3VuJACeme0Rtmp_EJL_KMg_3S1lP-M55LUPfjKp0rE_aNBcBGc_8aNh83FRj_pPcL1o71BYLA_kcr_hXZ05QWIF_fqe7uZCOVdmlAtns7c0CoRKtWrnbfwDGpqJXa44T/s1600/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586001.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="840" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn5wfx3VuJACeme0Rtmp_EJL_KMg_3S1lP-M55LUPfjKp0rE_aNBcBGc_8aNh83FRj_pPcL1o71BYLA_kcr_hXZ05QWIF_fqe7uZCOVdmlAtns7c0CoRKtWrnbfwDGpqJXa44T/s400/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586001.png" width="400" /></a></div>
<div>
シャノンのサンプリング定理を簡単に言えば「計測したい信号の周波数の倍以上の周波数でサンプリングしないと元の信号を正しく再現できない」ということになる。</div>
<div>
<br /></div>
<div>
これを理解するために左図の右上の波形を見て欲しい。</div>
<div>
<br /></div>
<div>
右上の実線のsin波に対して,□のポイントでサンプリングしている。(見た目,サンプリングが遅い!)元波形(実線のsin波)を再現しようとすると,点線のsin波もまったく同じ□の点を通っていることが分かる。</div>
<div>
<br /></div>
<div>
これがいわゆる「エリアシング」という現象で,A/D変換する前に元波形からこのような高調波を取り除いてあげなければ,元にはなかったはずの波形が「ゴースト」のように現れてしまうのだ。(音声ではビート音,画像ではモアレ)<br />
<br />
まとめると</div>
<div>
<ul>
<li>アナログ信号を正確に表現するためには、最低サンプリング周波数は原信号の最高周波数の2倍に等しいか、それ以上でなければならない。</li>
<li>サンプリング周波数の1/2の周波数をナイキスト周波数と呼ぶ。</li>
<li>ナイキスト周波数を超える周波数成分は標本化した際に折り返し(エリアシングとも言う)という現象を生じ、再生時に元の信号として忠実には再現されない。</li>
</ul>
</div>
<div>
ということになる。実際には,上図の左下のように元波形の周波数のちょうど倍くらいのサンプリングにすることはなく,上図の右下のようにターゲットとなる波形の早い周波数成分の数倍の周波数でサンプリングをすることが多い。</div>
<div>
<br /></div>
<div>
なお,それでもシャノンのサンプリング定理は生きているので,必ずサンプリング周波数の1/2以上の周波数(ナイキスト周波数)を超える周波数成分はA/D変換する前に限りなくゼロにしておく必要がある。</div>
<div>
<br /></div>
<div>
これはアナログフィルタで取り除くしかない。このフィルタを「アンチエリアシングフィルタ」という。</div>
<div>
<br /></div>
<div>
デジタル信号処理を行うにあたっては,シャノンのサンプリング定理は必ず知っていないといけないし,A/D変換器の前にアナログのアンチエリアシングフィルタは必要だ。</div>
<div>
<br /></div>
<div>
それを知らないでいると 元波形にはなかった「ゴースト波形」に悩まされることになる。ソフトウェアエンジニアだからといってデジタル信号処理やアナログ回路のことは知らなくてもいい訳ではなく,何をやりたいかによっては,広い範囲の知識や原理原則を知る必要がある。(手段そのものの理解ではなく,目的と目的を実現する原理と,目的を実現するための方法を理解しないと,原理から外れた変更をしてしまい失敗したりする)</div>
<div>
<br /></div>
<div>
シャノンのサンプリング定理やアンチエリアシングフィルタのことは,ハード屋さんが考えることだと決めつけていると,ソフトウェア技術者がよかれと思ってサンプリング周波数を早くしたり,遅くしたりしたときに,アンチエリアシングフィルタとの相性が合わない事態になり,そのことに気が付かず,「ゴースト波形」が出て「なぜ?」と悩むことが起こる。</div>
<div>
<br /></div>
<div>
デジタル信号を扱うのならばデジタル信号の基礎は,ハード屋さんも,ソフト屋さんも知っている必要がある。</div>
<div>
<br /></div>
<div>
なお,本当に人間の心電図を計測するならば,電気安全対策は必ず理解して実施しておかないと危ないのでこちらの記事<a href="http://www.neo-tech-lab.jp/Sensor/Electrocardiograph.htm#Page1" target="_blank">【トランジスタ技術2006年01月号】 投稿記事『心電計の製作』</a>をよく読んでおくべし。</div>
<div>
<div style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
デジタル信号処理の流れ</h2>
</div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAjvDmk3mB4slRZGSGQ_W9IcKU-Vo-7WTvKS97RbIcKc7O8Y3X6OXHmXHLLeHijS2fWd2TifPSR5AQ35yItZ3mPdYYg9V7HoKS01jb38mRfyUpBGfhXTTxEuyXSxy-IL-ZJZKF/s1600/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586002.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="469" data-original-width="885" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAjvDmk3mB4slRZGSGQ_W9IcKU-Vo-7WTvKS97RbIcKc7O8Y3X6OXHmXHLLeHijS2fWd2TifPSR5AQ35yItZ3mPdYYg9V7HoKS01jb38mRfyUpBGfhXTTxEuyXSxy-IL-ZJZKF/s400/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586002.png" width="400" /></a></div>
<div>
<br /></div>
<div>
『<a href="https://amzn.to/2K4GZew" target="_blank">ディジタル信号処理の基礎</a>』の図(p70 図3.55) を引用してデジタル信号処理の流れを説明する。</div>
<div>
<br /></div>
<div>
【デジタル信号処理の流れ】</div>
<div>
<ol>
<li>まず,低域通過フィルタ(「アンチエリアシングフィルタ」)にて,サンプリング周波数の1/2以上の周波数をカットする。</li>
<li>A/D変換器で A/D変換する間アナログ信号をサンプル・ホールドする。(最近のA/D変換器はサンプル・ホールドも込みでやってくれる場合が多い)</li>
<li>A/D変換したデータをCPU(上図ではDSP)に取り込む。(Raspberry Pi3 では,GPIOを経由して,SPI通信やI2C通信で取り込むのが簡単)</li>
<li>取り込んだデジタルデータに対して,デジタルフィルタなどの信号処理を行う。</li>
<li>加工が済んだら,デジタルデータをD/A変換する。(加工データを外部にアナログ出力する場合)</li>
<li>D/A変換したアナログ信号に対して,低域通過フィルタをかける。</li>
</ol>
<div>
4の,デジタルフィルタや信号処理のところで,何をするのかは,何の信号を取扱い,その信号で何をしたいのかによって,いろいろ変わる。</div>
</div>
<div>
<br /></div>
<div>
例えば,心電図を取り扱うのであれば,次のようなことをソフトウェアで実施することになる。(<a href="http://www.neo-tech-lab.jp/Sensor/Electrocardiograph.htm#Page1" target="_blank">【トランジスタ技術2006年01月号】 投稿記事『心電計の製作』</a>を参照のこと)</div>
<div>
<ul>
<li>目的の周波数成分(エリアシングフィルタよりも低い周波数成分)だけを取り出すために,デジタルフィルタでハイカット(低域通過)フィルタをかける。(ノイズ除去フィルタ)</li>
<li>電源ノイズ(関東:50Hz,関西:60Hz)だけを取り除く,フィルタ(電源ノイズ除去フィルタ)をかける。</li>
<li>基線のゆっくりした動揺を取り除くための ローカット(高域通過)フィルタをかける。</li>
<li>心拍数を計測するためには,心電図波形のQRS波形をカウントする必要がある。QRS波形をカウントするには,QRSを強調するようなデジタルフィルタをかけて,その上でスレッショルドレベルを設定して,スレッショルドを超えたらQRS波形としてカウントする。</li>
</ul>
<div>
なお,上記のハイカットフィルタやローカットフィルタ(ドリフトフリーフィルタ)をかけたことにより,もとの心電図波形が大きくひずんでしまっては,元も子もないので,目的に合った「有限インパルス応答」(FIR)フィルタを適用することが重要となる。</div>
</div>
<div>
<div style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
デジタルフィルタとリングバッファ</h2>
</div>
</div>
<div>
A/D変換した信号に継続的にデジタルフィルタをかける場合,データを格納する領域は有限なので,データを格納するためにリングバッファを用意する。『<a href="https://amzn.to/2K4GZew" target="_blank">ディジタル信号処理の基礎</a>』の図(p103 図4.33) </div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiDBcSRNi-7TYKS9as_ky_ACZAaQ5si9aW_e1s4vVElPy2ERvXHHCGi0WKgKdUeRksqxzw7v9FSpbbcyZ1a9ugLYpDeKHxzM51671tvFf2GxciM4CDcLQizsaqz5CSNiSdGvYo/s1600/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586003.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="469" data-original-width="452" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiDBcSRNi-7TYKS9as_ky_ACZAaQ5si9aW_e1s4vVElPy2ERvXHHCGi0WKgKdUeRksqxzw7v9FSpbbcyZ1a9ugLYpDeKHxzM51671tvFf2GxciM4CDcLQizsaqz5CSNiSdGvYo/s320/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586003.png" width="308" /></a></div>
<div>
<br /></div>
<div>
図はリング上になっているが,メモリ領域はリング上にはなっていないので,データの格納ポイントをインクリメントしていってバッファの範囲を超えたらポインタを元に戻すという処理が必要になる。</div>
<div>
<br /></div>
<div>
リングバッファ処理やデジタルフィルタはサンプリング毎に実施しなければいけないため,いくら今どきのCPUの処理スピードが早くなったとはいえ,4ms以下で毎回やらなければいけない処理はできるだけ軽くしておいた方がよい。</div>
<div>
<br /></div>
<div>
蛇足だが,整数と浮動小数点の違いを意識せずに,処理時間があまりない中で浮動小数点の演算をバンバン気にせずにやってしまうソフトウェアの新人技術者をよく見かける。CやC++で書いたソースコードが機械語に翻訳されたコードの量を見たことがないのだろう。浮動小数点の演算を専用のプロセッサを使わずに行うとものすごく機械語のコードが増えるので,それを知っていると,できるだけ整数演算で済ませられないかといつも考えるようになる。</div>
<div>
<br /></div>
<div>
さて,リングバッファを用意する際には,バッファサイズは2のn乗であると都合がよい。</div>
<div>
<br /></div>
<div>
リングバッファのポインタは,バッファの上限を超えたら,バッファ数ぶん引かないとポイントが誤った位置を指し示してしまう。バッファサイズは2のn乗であれば,簡単な計算で知りたいポインタの位置を知ることができる。</div>
<div>
<br /></div>
<div>
そのことを説明しよう。</div>
<div>
<br /></div>
<div>
例えばバッファサイズが8で、ポインタが現在 5 で、+4 の位置を知りたいなら</div>
<div>
i = (( i + 4 ) & 0x07 ) を計算すればよい。 答え (5 + 4)- 8 = 1</div>
<div>
<br /></div>
<div>
ポインタが現在 5 で、-6 の位置を知りたいなら</div>
<div>
i = (( i - 6 ) & 0x07 )を計算すればよい。 答え (5 - 6) + 8 = 7</div>
<div>
<br /></div>
<div>
この計算ならば処理が高速で,意味さえ理解できれいればコーディングミスが少ない。</div>
<div>
<br /></div>
<div>
欲しいビットフィールドを1にしてANDを取る意味を考えてみよう。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoz839YaNDm9znNxYmWkWysLl5ftpgabH776Bo-X2n6HdxZDvXaJYrkNekJXOxAyUJznYbzlezmaCwOUIrrW7dl80PiKEICfV1hIlN4FAdt1gd5HbljUEZzqAKnkkVqxefq2Wx/s1600/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586004.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="783" data-original-width="400" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoz839YaNDm9znNxYmWkWysLl5ftpgabH776Bo-X2n6HdxZDvXaJYrkNekJXOxAyUJznYbzlezmaCwOUIrrW7dl80PiKEICfV1hIlN4FAdt1gd5HbljUEZzqAKnkkVqxefq2Wx/s400/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586004.png" width="203" /></a></div>
<div>
<div>
<b>( Index + i ) & 0x07 で 5 + 4 → 1 になるしくみ</b></div>
<div>
<br /></div>
<div>
10進数の5は2進数なら <span style="white-space: pre;"> </span>0101</div>
<div>
10進数の4は2進数なら <span style="white-space: pre;"> </span>0100</div>
<div>
足すと 9 <span style="white-space: pre;"> </span>1001</div>
<div>
10進数の7(8-1)は2進数なら<span style="white-space: pre;"> </span>0111</div>
<div>
(1001 を 0111=7でマスクする。すなわちANDを取る)</div>
<div>
0001 = 10進数の1 になる。</div>
</div>
<div>
<br /></div>
<div>
<div>
<b>( Index + i ) & 0x07 で 5 - 6 → 7 になるしくみ</b></div>
<div>
<br /></div>
<div>
10進数の5は2進数なら <span style="white-space: pre;"> </span>0101</div>
<div>
10進数の6は2進数なら <span style="white-space: pre;"> </span>0110</div>
<div>
引くと -1 <span style="white-space: pre;"> </span>1111</div>
<div>
10進数の7(8-1)は2進数なら<span style="white-space: pre;"> </span>0111</div>
<div>
(1111 を 0111=7でマスクする。すなわちANDを取る)</div>
<div>
0111 = 10進数の7 になる。</div>
</div>
<div>
<br /></div>
<div>
このように,バッファサイズが 2のn乗ならば,現在のポインタに対して 欲しい相対位置を足したり引いたりして,バッファサイズ-1 と AND を取ると 正しい絶対位置を計算できる。</div>
<div>
<br /></div>
<div>
これを,バッファサイズが2のn乗でないときと,2のn乗のときのC言語のコードの違いは次のようになる。</div>
<div>
<br /></div>
<div>
<div>
signed short<span style="white-space: pre;"> </span>TempIndex1:</div>
<div>
unsigned short<span style="white-space: pre;"> </span>TempIndex2:</div>
<div>
<br /></div>
<div>
InputBuffer[index] = InputData;</div>
<div>
<br /></div>
<div>
<span style="color: blue;">// バッファサイズが2のn乗でない=13などのとき</span></div>
<div>
TempIndex1 = (signed short)(index - 12);</div>
<div>
<br /></div>
<div>
if ( TempIndex1 >= BUFFER_SIZE ) (</div>
<div>
TempIndex1 = TempIndex1 - BUFFER_SIZE;</div>
<div>
)</div>
<div>
else if ( TempIndex1 < 0 ) (</div>
<div>
TempIndex1 = TempIndex1 + BUFFER_SIZE;</div>
<div>
)</div>
<div>
<br /></div>
<div>
<span style="color: blue;">// バッファサイズが2のn乗=8のときの例</span></div>
<div>
TempIndex2 = ( (signed short)Index + 4 ) & 0x07;</div>
<div>
TempIndex2 = ( (signed short)Index - 6 ) & 0x07;</div>
</div>
<div>
<br /></div>
<div>
ちょっとした違いなのだが,下の方がずっといいと思うのは自分だけだろうか?<br />
この計算をマクロに登録しておくと,すごくスッキリしたコードになる。</div>
<div>
<div>
<div style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
デジタルフィルタの効果を視覚的に確認する</h2>
</div>
</div>
</div>
<div>
今度は,Interface誌 2003年1月号に投稿した記事『<a href="https://www.cqpub.co.jp/interface/contents/2003/200301.htm" target="_blank">オブジェクト思考を使ったリアルタイム信号計測システムの開発</a>』の記事から引用する。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0G6PItZA_RFYmeinrtPxpzMvZ3SDUm0WGKf1Ojl9B0nP50PSB3dmGTyTvl0bnqIpQ9mRGsbUg-DVJ_x6JiWti6Yo6RgN3WHfIqgNsxdVXJBrsS4alu7SvJpdVTtYwufWfanYh/s1600/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586005.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="386" data-original-width="598" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0G6PItZA_RFYmeinrtPxpzMvZ3SDUm0WGKf1Ojl9B0nP50PSB3dmGTyTvl0bnqIpQ9mRGsbUg-DVJ_x6JiWti6Yo6RgN3WHfIqgNsxdVXJBrsS4alu7SvJpdVTtYwufWfanYh/s400/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586005.png" width="400" /></a></div>
<div>
左図は 1Hz のsin波に10Hzのノイズに見立てた sin波を重畳させた波形だ。</div>
<div>
<br /></div>
<div>
デジタルフィルタを作成して 10Hz のノイズだけを取り除いてみる。</div>
<div>
<br /></div>
<div>
このとき Filter A と Filter B を試してみて,その結果を画面上で確認してみたのが次の図になる。</div>
<div>
<br /></div>
<div>
デジタルフィルタがいいのは,こういった「試しにやってみる」の効果を確認するのが簡単でできることだ。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCFl-fD7CChS8UNt0ULEwfyn8RE2Sf5aVSmfOO9tb11V4ycTXebERF67abjg39fWxAwfnS-jq6L1y824OPq50EvZaoGCV1z5kaefm_xwynw_1LIGAnt0jg6ls6MOps8LIfXvmH/s1600/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586006.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="572" data-original-width="894" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCFl-fD7CChS8UNt0ULEwfyn8RE2Sf5aVSmfOO9tb11V4ycTXebERF67abjg39fWxAwfnS-jq6L1y824OPq50EvZaoGCV1z5kaefm_xwynw_1LIGAnt0jg6ls6MOps8LIfXvmH/s400/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586006.png" width="400" /></a></div>
<div>
左図の左側がノイズを重畳させた元波形とカットオフ周波数 8.4Hz のハイカットフィルタを通した結果の波形(赤色)で,右波形が元波形とカットオフ周波数4.3Hzのハイカットフィルタを通した波形(グリーン)だ。</div>
<div>
<br /></div>
<div>
ちなみに,カットオフ周波数(遮断周波数)とは,その周波数を越えると(あるいは下回ると)回路の利得が通常値の 3 dB 低下する値のことである。(<a href="https://ja.wikipedia.org/wiki/%E9%81%AE%E6%96%AD%E5%91%A8%E6%B3%A2%E6%95%B0" target="_blank">Wikipediaの解説</a>)</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJNzUCsfTt7OwijTtdJ4EBDhggHPVKzHxwxOc7GVzRwsF50W450ZB5JK6PReen4oSxT-W8hYOBuo2SLl43TkcN7xzB9b29jvsNsednmJCM0DGd3EfHDwLLXtqaAlkpA-oRW2oF/s1600/640px-Butterworth_response.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="640" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJNzUCsfTt7OwijTtdJ4EBDhggHPVKzHxwxOc7GVzRwsF50W450ZB5JK6PReen4oSxT-W8hYOBuo2SLl43TkcN7xzB9b29jvsNsednmJCM0DGd3EfHDwLLXtqaAlkpA-oRW2oF/s400/640px-Butterworth_response.png" width="400" /></a></div>
<div>
ようするに欲しい周波数帯域におけるsin波の振幅を1としたときに,ハイカットフィルタをかけると,周波数高域になるにしたがって振幅が小さくなってくる。(フィルタの特性によっては単調に減少するとは限らない)</div>
<div>
そのときに,振幅1に対して-3dB(およそ 0.73)になる周波数をカットオフ周波数という。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiake4QdwrZEWg_eDtptSkUslB0n3PEIVN7OrtTIVPc6SP6MRpll4IYheCBe3-1rbx2XwuqItfVN_6rpS5WWqRKLfem-LRhRVXsW1dUxPxsnT3sA8UHBW_3MjZnF8Z0LALqkcDA/s1600/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586007.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="538" data-original-width="867" height="247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiake4QdwrZEWg_eDtptSkUslB0n3PEIVN7OrtTIVPc6SP6MRpll4IYheCBe3-1rbx2XwuqItfVN_6rpS5WWqRKLfem-LRhRVXsW1dUxPxsnT3sA8UHBW_3MjZnF8Z0LALqkcDA/s400/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586007.png" width="400" /></a></div>
左図は,青が1Hzに10Hzを重畳させた元波形で,10Hzの sin波が 1Hz で上下している。<br />
<br />
紫の波形が Filter A(カットオフ周波数 8.4Hz)をかけた結果で,10Hzのノイズは低減しているものの取り切れていない。<br />
<br />
一方,黄色の波形は Filter B(カットオフ周波数 4.3Hz)をかけた結果で,10Hzのノイズは奇麗に取れて 1Hzの sin波だけが残っている。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG7UbK04fYqbqyDCemzwa7sF19-eUIHBw14Tu_94dfJ43icJ9-cR5patMA1zkJNT3-ylg8CnfLbzwLn20BQl5e-y3H8PsCS_25vIpoOkKBLN_tbf5MJkwJ-4qAFJJfA0FeOyLu/s1600/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586008.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="545" data-original-width="875" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG7UbK04fYqbqyDCemzwa7sF19-eUIHBw14Tu_94dfJ43icJ9-cR5patMA1zkJNT3-ylg8CnfLbzwLn20BQl5e-y3H8PsCS_25vIpoOkKBLN_tbf5MJkwJ-4qAFJJfA0FeOyLu/s400/%25E3%2583%2587%25E3%2582%25B8%25E3%2582%25BF%25E3%2583%25AB%25E4%25BF%25A1%25E5%258F%25B7%25E5%2587%25A6%25E7%2590%2586008.png" width="400" /></a></div>
<div>
左図は,5Hzの sin波を Filter A と Filter B に通したときに,どれくらい時間遅れが発生しているかを見たものだ。</div>
<div>
<br /></div>
<div>
元波形に対して 振幅が減衰し,波形のピーク点が僅か左にずれていることが分かる。</div>
<div>
<br /></div>
<div>
位相ひずみがないフィルタ(FIRフィルタ)をかけると,時間遅れが発生する。ドリフトフリーフィルタ(高域通過フィルタ)などでは,この時間遅れが数百msec にもなる場合があるので,どれくらい遅れているのかが分かるようにしておくもとも重要だ。</div>
<div>
<br /></div>
<div>
次回は,Interface誌 2003年1月号に投稿した記事『<a href="https://www.cqpub.co.jp/interface/contents/2003/200301.htm" target="_blank">オブジェクト思考を使ったリアルタイム信号計測システムの開発</a>』をベースに,波形の入力を A/D変換器や サンプルデータやファイルデータに 簡単に切り替えるオブジェクト指向設計を使った事例を紹介する。<br />
<br />
デジタル信号処理のポイントは次のようなことになる。<br />
<br />
<ul>
<li>入力したい信号の最高周波数を調べる。</li>
<li>シャノンのサンプリング定理を理解し,サンプリング周波数を定め,アンチエリアシングフィルタにて,サンプリング周波数の1/2以上の周波数成分をアナログフィルタで取り除く。</li>
<li>正確なサンプリング間隔を作り,デジタルデータを取り込む。</li>
<li>デジタルデータをバッファリングして,デジタルフィルタをかける。</li>
<li>その他,二次処理を行う。</li>
</ul>
<div>
そして,デジタル信号処理のシステムの保守性や再利用性を高め,新しい機能を安全に追加できるようにするためには,ソフトウェアのアーキテクチャを工夫する必要がある。</div>
<div>
<br /></div>
<div>
C言語でゴリゴリ書いてしまい「動くソフトウェア」を作ることはできる。しかし,それは,『<a href="https://embeddedsoftwaremanufactory.blogspot.com/2019/05/blog-post.html" target="_blank">ソフトウェアアーキテクチャとは何かを考える</a>』の記事で書いたように,丸太組工法で高級マンションを建てようとしているように思える。</div>
<div>
<br /></div>
<div>
どのようにスマートに設計するか,できるのかを次回説明しようと思う。</div>
</div>
sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-50437872560907800582019-05-25T16:07:00.000+09:002019-05-27T11:05:25.112+09:00Raspberry Pi3を使ったリアル波形描画(6) Qtでマルチスレッド処理をやってみる<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjhgriJDryZ-7MEv9rQ_2veT47XzpAy7s9kAWnH7TmWCOZnpo4xOfm70GI7syzGtgykRvYv4Dx4qJ3-PKjQQ5igzkEv2yWhWuuyDipPUYfS34PF2PgvHTdj4kg7MzaEFq07fY0/s1600/RealWaveDisplayTitle06_340x241.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="340" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjhgriJDryZ-7MEv9rQ_2veT47XzpAy7s9kAWnH7TmWCOZnpo4xOfm70GI7syzGtgykRvYv4Dx4qJ3-PKjQQ5igzkEv2yWhWuuyDipPUYfS34PF2PgvHTdj4kg7MzaEFq07fY0/s320/RealWaveDisplayTitle06_340x241.png" width="320" /></a></div>
今回はリアル波形描画で必須となるマルチスレッド処理を Qt でやってみたいと思う。<br />
<br />
ちなみに Raspberry Pi3 には,DebianベースのRaspberry Pi用の小規模な開発者向けのLinuxであるRaspbianを搭載することを想定している。(ラズパイの入門書でもRaspbianをインストール例が多い)<br />
<br />
その場合,OS は Linux なのでマルチタスクでスレッドに優先度は付けられるものの,リアルタイムOSではないので インターバルの短いスレッド(RTOSならタスク)を正確に起動するのが難しい。<br />
<br />
リアル波形を取り込む場合,正確なインターバルでA/D変換することが非常に重要になる。正確なインターバルでA/D変換ができないと正確な波形の再現ができない。<br />
<br />
例えば,心電図をA/D変換するならば,4msインターバル(250Hz)程度のサンプリングはしたいところだ。しかし,いかに1.2GHzのマルチコアのCPUを搭載しているRaspberry Pi3と言えども,Raspbian の標準設定では 4ms以下の定時起動のスレッドを作るのは難しい。<br />
<br />
そこで,マルチスレッドを実装する前に,リアルタイムOSとマルチタスクOSの違いについて考えてみたい。<br />
<br />
この後説明するのは,もう何十年も前に CQ出版社の Interface に載っていたリアルタイムマルチタスクを理解するための示されていた例だ。参照元を書こうと思ったのだが,あまりにも古くで検索しても見つからない。自分の記憶だけで解説を再現する。<br />
<div>
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
昔の風呂焚きの作業をリアルタイムシステムとして考える</h2>
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBbx9jHlsxCbuVWEzoxTHfrlV6BdNhXmpmUJYWcUNBubnmONWa-7KWg4WxtNjaQGTJX3FZaSjkE7KDXui3ktpEXM0_7dTm-mR-F7QAPmZhm4ahpyPu5CAhm66aPaH_1mnoU12a/s1600/%25E4%25BA%2594%25E5%258F%25B3%25E8%25A1%259B%25E9%2596%2580%25E9%25A2%25A8%25E5%2591%2582.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1024" data-original-width="768" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBbx9jHlsxCbuVWEzoxTHfrlV6BdNhXmpmUJYWcUNBubnmONWa-7KWg4WxtNjaQGTJX3FZaSjkE7KDXui3ktpEXM0_7dTm-mR-F7QAPmZhm4ahpyPu5CAhm66aPaH_1mnoU12a/s320/%25E4%25BA%2594%25E5%258F%25B3%25E8%25A1%259B%25E9%2596%2580%25E9%25A2%25A8%25E5%2591%2582.jpg" width="240" /></a></div>
昔の五右衛門風呂の風呂焚きの作業をリアルタイムシステムとして考えてみる。<br />
<br />
今どき風呂焚きはボタン一発なので,「なにそれ」と思うかもしれないが,まあ,原始的な風呂焚きはそうなんだと思って欲しい。<br />
<br />
原始的な,五右衛門風呂を沸かす手順は次の通りだ。<br />
<br />
<ol>
<li>風呂釜を洗い栓をして水を注ぐ。</li>
<li>約15分たったら水を止める。</li>
<li>水がいっぱいになったら薪を燃やす。</li>
<li>約40分たったら湯加減をみてちょうど良ければ火を消す。</li>
</ol>
<div>
ポイントは次の通り。</div>
<div>
<ul>
<li>複数の作業を自分一人でこなさなければいけない。</li>
<li>時間を含む限られた資源を有効に使いたい。</li>
<li>水を止めそびれると水が溢れてしまう。</li>
<li>火を消し忘れると火事になるかもしれない。</li>
<li>水を入れているとき,風呂を沸かしている間は他のことをしいてもよい。</li>
</ul>
<div>
Inerface の特集記事では,確か,風呂を沸かしている間に原稿を書いたり,電話に出たりするという設定だったと記憶している。</div>
</div>
<div>
<br /></div>
<div>
これらのイベント/タスクを時間経過をX軸に,優先順位をY軸にとって書くと次のようになる。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNpXKZ7NSB2QOVZ2Q0TLENgQLPF0-2BmGGOarJDbETXFqDPKj5hTMQtdjp0CKdlf4nY0y7R5jLVht29qPVzqYP-0d-0BBDBw5quZ3DWRAhQtWHQI9MXttzGL0OURBlESZOGNd_/s1600/%25E9%25A2%25A8%25E5%2591%2582%25E6%25B2%25B8%25E3%2581%258B%25E3%2581%2597%25E3%2581%25AE%25E6%2589%258B%25E9%25A0%25861.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="429" data-original-width="600" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNpXKZ7NSB2QOVZ2Q0TLENgQLPF0-2BmGGOarJDbETXFqDPKj5hTMQtdjp0CKdlf4nY0y7R5jLVht29qPVzqYP-0d-0BBDBw5quZ3DWRAhQtWHQI9MXttzGL0OURBlESZOGNd_/s400/%25E9%25A2%25A8%25E5%2591%2582%25E6%25B2%25B8%25E3%2581%258B%25E3%2581%2597%25E3%2581%25AE%25E6%2589%258B%25E9%25A0%25861.png" width="400" /></a></div>
<div>
<br /></div>
<br />
「水を止める」「火を消す」いったタスクは,すぐにやらないと水が溢れたり,火事になったりするので優先度が高い。<br />
<br />
一方で,原稿を書いたり,風呂に入ったりするタスクの優先度は低く,空き時間があるときにやればよい。<br />
<br />
タスクの優先度と時間経過の関係を図にしたのが左の図となる。水張り15分後の「水を止める」や風呂焚き40分後の「火を消す」はタイムアウトのイベント発生後,他のタスク(例えば原稿書き)が動いていても,そのタスクを中断して,実施すなければならないタスクである。<br />
<br />
このようにイベントが発生して優先度の高いタスクにリソースを割り当てなければいけないのたリアルタイムシステムであり,それを実現するためのOSがリアルタイムOSである。<br />
<br />
CPUがシングルコアの時代,発生したイベントによってすぐさま優先度の高いタスクに切り替える必要があるようなイベントドリブンのリアルタイムシステムではリアルタイムOSを使う必要があった。<br />
<br />
Raspberry Pi3 はマルチコアのCPUである Cortex-A53 (4コア)を搭載しているので,個々のコアにスレッドを割り当てることができれば,リアルタイムOSでなくてもいいのだが,Qt で用意されているスレッドのライブラリで コアの割り当てる方法は分からなかった。(おそらく,まだないと思う)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEwiIwWBxOjgBnv_pXp-ovI1-Jkc9oFb6kALje2i2MLgYiqICIIM_NekekaiyI9SU7Jte-VW_SK3O1jLcMKANZnd81xZ5iJY8T_bH9dno-YaOEN6K7qElSRs9bB8V3fu9lSCjb/s1600/%25E3%2583%25AA%25E3%2582%25A2%25E3%2583%25AB%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A0_%25E9%259D%259E%25E3%2583%25AA%25E3%2582%25A2%25E3%2583%25AB%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A0.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="432" data-original-width="600" height="287" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEwiIwWBxOjgBnv_pXp-ovI1-Jkc9oFb6kALje2i2MLgYiqICIIM_NekekaiyI9SU7Jte-VW_SK3O1jLcMKANZnd81xZ5iJY8T_bH9dno-YaOEN6K7qElSRs9bB8V3fu9lSCjb/s400/%25E3%2583%25AA%25E3%2582%25A2%25E3%2583%25AB%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A0_%25E9%259D%259E%25E3%2583%25AA%25E3%2582%25A2%25E3%2583%25AB%25E3%2582%25BF%25E3%2582%25A4%25E3%2583%25A0.png" width="400" /></a></div>
リアルタイムシステムのマルチタスクと非リアルタイムのマルチタスクの違いを左図に示す。<br />
<br />
リアルタイムシステムの場合,イベントが発生するとただちに優先度の高いタスクに切り替わるが,非リアルタイムシステムの場合,一定時間ごとにタスク(スレッド)が切り替わるので,イベントが発生した後,待ち時間が発生する可能性がある。<br />
<br />
最近の組込み系のCPUも待ち時間が気にならないほど,切り替えは早くなっているが,msオーダーのイベントでは追随できないこともある。<br />
<br />
各タスクに処理の順番が回ってくる周期が遅いと,風呂焚きの例でいえば,水が溢れたり,湯が熱くなりすぎたりするということになる。<br />
<br />
非力なCPUの時代の Windows では,ウインドウをたくさん開くとマウスのレスポンスが悪くなるような現象を経験したことはないだろうか。これは,ウインドウを開けば開くほど,一つのウインドウに処理が回ってくるインターバルが長くなるからだ。<br />
<div>
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
非リアルタイムシステムで4msインターバルのマルチスレッドを作成してみる</h2>
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
では,本題に戻るとして,メインのスレッドとは別に4msインターバルで動くスレッドを Qt で実現してみる。<br />
<br />
Qtでマルチスレッドを実現するには QtConcurrent や QTread を使う。<br />
<br />
実際 Qt で実現するのに次の記事を参考にした。<br />
<br />
QtConcurrent に関する記事 『<a href="https://qiita.com/hermit4/items/d949160c8108d61cf744" target="_blank">QtConcurrentでマルチスレッドに挑戦</a>』<br />
QTread に関する記事 『<a href="https://qiita.com/hermit4/items/1606750332d1d2685bdb" target="_blank">Qtでスレッドを使う前に知っておこう</a>』</div>
<br />
QTread から定期的に必要な処理を起動するしくみは『<a href="http://freeplanets.ship.jp/Qt/Tutor/Tutor4_Thread_and_SignalSlot/Qt_Thread_signal.html" target="_blank">スレッドを使った並列処理</a>』を参照している。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipcdJU2PinN5XVyNtkLb-DAVXpE77W7wtkM7YFH2ssQYdiTZGfisSTF5y235izlXI1nCHUH1wY75Wwc-gf83rZdWI7P0WKWiXlGNpUErY8-SiGDpjliGS8ehKcoHoxhrgzPOGG/s1600/MultiThread_w769.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="194" data-original-width="769" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipcdJU2PinN5XVyNtkLb-DAVXpE77W7wtkM7YFH2ssQYdiTZGfisSTF5y235izlXI1nCHUH1wY75Wwc-gf83rZdWI7P0WKWiXlGNpUErY8-SiGDpjliGS8ehKcoHoxhrgzPOGG/s400/MultiThread_w769.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
クラス図でそれぞれの関係を示すと上図のようになる。メインウインドウのクラス MainWindow は QThead のクラス MyTread を持ち,MyTread は Qtimer のクラスtimer を持っている。<br />
<br />
信号処理において正確なサンプリングができることは極めて重要で,サンプリング間隔が揺れてしまうと,波形がひずんでしまう。例えばもとの波形が sin波であっても,再現した 波形が奇麗な sin波でなくなってしまう。<br />
<br />
よって,システムタイマーによる割り込みをスレッド処理で実現したら,正確にインターバルが取れているかどうか,常に確認しておきたい。この例では,4msのタイムインターバルがどれくらい正確に実現できているかどうかをインターバル間隔を表示することで確認している。<br />
<ul>
<li>SIGNAL/SLOT の設定</li>
<li>periodic_work の処理を設定</li>
<li>ボタンの押下でスレッドの開始/終了を行う</li>
</ul>
<ul>
<li>スレッドが始まるときに呼ぶ run() メソッドを作成する。</li>
<li>run() でタイマーを生成し,タイムアウトしたときに Qtの SIGNAL/SLOT で timerHit()が呼ばれるようにする。</li>
<li>run() でタイマーを指定時間に設定する。(ms単位)</li>
<li>exec()を実行してスレッド動作を開始する。</li>
<li>なお,スレッドが終了すると exec()以下が実行される。</li>
<li>スレッド終了後に timer を停止する。</li>
<li>タイマーがタイムアウトしたら timerHit() が呼ばれる。</li>
<li>timerHit()が呼ばれたら Qt のシグナル data_update を発生させて,SLOT で受ける。</li>
</ul>
<div>
4msインターバルのスレッドを起動するときのボタンをウインドウがこれ。</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMt63c-pBoaGw_EYkHYbZOB_cvnRIfMLsubNuQDX995HVODdXKQ3FxuRYkwC7PnUlMAEYOlTWKC-M0zMs_D8-ZwnByZmSAdwG2Yk_W0ozm4IFek12rDgYLwCsMIg8P_sC9H_Ch/s1600/%25E3%2582%25B9%25E3%2582%25BF%25E3%2583%25BC%25E3%2583%2588%25E3%2583%259C%25E3%2582%25BF%25E3%2583%25B3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="219" data-original-width="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMt63c-pBoaGw_EYkHYbZOB_cvnRIfMLsubNuQDX995HVODdXKQ3FxuRYkwC7PnUlMAEYOlTWKC-M0zMs_D8-ZwnByZmSAdwG2Yk_W0ozm4IFek12rDgYLwCsMIg8P_sC9H_Ch/s1600/%25E3%2582%25B9%25E3%2582%25BF%25E3%2583%25BC%25E3%2583%2588%25E3%2583%259C%25E3%2582%25BF%25E3%2583%25B3.png" /></a></div>
<br /></div>
<div>
MainWindows と MyThead の関係を示した図が下になる。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG4WBah4hjriX9EEPhcoKykhSUXYaLes4VDivN75cWS3DakSvNnyKdNaoux330ik-3BVNo0IRUkg0GPc1p6lyoZ_XLYxUS6SBtN6YZXGOXjC2Zzgk_F_F2nHq-I6ZjI4xRmy76/s1600/%25E3%2583%259E%25E3%2583%25AB%25E3%2583%2581%25E3%2582%25B9%25E3%2583%25AC%25E3%2583%2583%25E3%2583%2589%25E9%2596%25A2%25E4%25BF%2582%25E5%259B%25B3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="524" data-original-width="600" height="279" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG4WBah4hjriX9EEPhcoKykhSUXYaLes4VDivN75cWS3DakSvNnyKdNaoux330ik-3BVNo0IRUkg0GPc1p6lyoZ_XLYxUS6SBtN6YZXGOXjC2Zzgk_F_F2nHq-I6ZjI4xRmy76/s320/%25E3%2583%259E%25E3%2583%25AB%25E3%2583%2581%25E3%2582%25B9%25E3%2583%25AC%25E3%2583%2583%25E3%2583%2589%25E9%2596%25A2%25E4%25BF%2582%25E5%259B%25B3.png" width="320" /></a></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
<b>main.cpp のソース</b></h2>
</div>
<span style="font-family: MS ゴシック;">#include "mainwindow.h"<br />
#include <QApplication><br />
<br />
int main(int argc, char *argv[])<br />
{<br />
QApplication app(argc, argv);<br />
MainWindow testwindow;<br />
<br />
testwindow.show();<br />
<br />
return app.exec();<br />
}</span><br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
<b>mainwindow.cpp のソース</b></h2>
</div>
#include "mainwindow.h"<br />
#include "ui_mainwindow.h"<br />
#include <QThread><br />
<br />
MainWindow::MainWindow(QWidget *parent) :<br />
QMainWindow(parent),<br />
ui(new Ui::MainWindow)<br />
{<br />
ui->setupUi(this); <br />
//----------------------------------------------------------<br />
// Sendar :my_thread Signal :data_upda<br />
// Receiver :MainWindows Slot :periodic_work<br />
//----------------------------------------------------------<br />
QObject::connect(&my_thread, SIGNAL(data_update(int)), this, SLOT(periodic_work(int))
);<br />
<br />
}<br />
<br />
MainWindow::~MainWindow()<br />
{<br />
my_thread.quit();<br />
my_thread.wait();<br />
delete ui;<br />
}<br />
<br />
void MainWindow::periodic_work( int data){<br />
char str[256];<br />
static int i=0;<br />
// sprintf(str,"i=%d",i++);<br />
<br />
i++;<br />
<br />
// デバッグ用の表示文字列を作成<br />
sprintf(str,"No= %6d Interval: %d [uSec]",i, data);<br />
<br />
// ウインドウにカウンタを表示<br />
ui->textBrowser->append( QString::fromLocal8Bit(str) ); // カウンタを追記表示<br />
<br />
}<br />
<br />
<br />
void MainWindow::on_pushButton_clicked()<br />
{<br />
static int flag_run=0;<br />
<br />
// push ボタンがクリックされて,スタートならスレッドをスタートする。<br />
if(flag_run==0){<br />
flag_run = 1;<br />
ui->pushButton->setText(QString::fromLocal8Bit("Stop thread"));<br />
<br />
// QTread の最優先度を設定する<br />
my_thread.setPriority(QThread::HighestPriority);<br />
my_thread.start();<br />
<br />
// push ボタンがクリックされて,ストップなら,スレッドを抜ける<br />
}else{<br />
flag_run = 0;<br />
ui->pushButton->setText(QString::fromLocal8Bit("Run thread"));<br />
my_thread.quit();<br />
<br />
}<br />
}<br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
<b>mytread.cpp のソース</b></h2>
</div>
<br />
#include "mythread.h"<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <time.h><br />
<br />
<br />
MyThread::MyThread(QObject *parent) :<br />
QThread(parent)<br />
{<br />
}<br />
<br />
void MyThread::run(){<br />
QTimer timer; // Qtimer オブジェクト timer を生成<br />
<br />
//----------------------------------------------------------<br />
// Sendar :timer Signal :timerのタイムアウト<br />
// Receiver :このスレッド Slot :timeHit関数<br />
//----------------------------------------------------------<br />
// timerをスタートさせ,指定時間のタイムアウトが発生したら,Qt の SIGNAL/SLOT を使ってtimerHit関数を呼ぶ<br />
//----------------------------------------------------------<br />
connect(&timer, SIGNAL(timeout()), this, SLOT(timerHit()), Qt::DirectConnection
);<br />
<br />
timer.setInterval(4); // Qtimerオブジェクトの timerの 時間間隔を 4ms に設定する<br />
timer.start(); // Qtimerオブジェクト timer をスタートする。<br />
<br />
printf("debug : Thread Starts\n"); fflush(stdout);<br />
exec(); //Start event loop<br />
printf("debug : Thread Stops\n"); fflush(stdout);<br />
<br />
timer.stop();<br />
}<br />
<br />
void MyThread::timerHit(){<br />
<br />
// システムのタイマーの構造体の変数を作成する<br />
struct timespec ts; // 現在のシステム時間を格納する構造体<br />
static struct timespec ts_before; // 前回のシステム時間を格納する構造体<br />
long diff = 0; // 前回と今回の差分を格納する変数<br />
<br />
// システムクロックをgetする<br />
clock_gettime(CLOCK_REALTIME, &ts);<br />
// 前回のシステム時間と今回のシステム時間の差分ナノ秒単位で計算し,ミリ秒単位に変換する<br />
diff = (long(ts.tv_nsec) - long(ts_before.tv_nsec))/1000;<br />
<br />
// 次回のために今回取得したシステムクロックを格納する<br />
ts_before = ts;<br />
<br />
// システムの実時間を秒とナノ秒に分けて表示し,前回と今回の差をミリ秒で表示する。<br />
printf("time: %10ld.%09ld CLOCK_REALTIME %05ld DIFF:uSec\n",
ts.tv_sec, ts.tv_nsec, diff);<br />
<br />
// emit で前回との時間差(ms) を Qt の SIGNAL/SLOT で受け渡す<br />
emit data_update( int(diff) ); //emit signal<br />
}<br />
<br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
<b>mainwindow.h のソース</b></h2>
</div>
#ifndef MAINWINDOW_H<br />
#define MAINWINDOW_H<br />
<br />
#include <QMainWindow><br />
#include "mythread.h"<br />
#include <stdio.h><br />
<br />
namespace Ui {<br />
class MainWindow;<br />
}<br />
<br />
class MainWindow : public QMainWindow<br />
{<br />
Q_OBJECT<br />
<br />
public:<br />
explicit MainWindow(QWidget *parent = 0);<br />
~MainWindow();<br />
<br />
public slots:<br />
void periodic_work( int i);<br />
<br />
private slots:<br />
void on_pushButton_clicked();<br />
<br />
private:<br />
Ui::MainWindow *ui;<br />
MyThread my_thread;<br />
};<br />
<br />
#endif // MAINWINDOW_H<br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<h2 class="heading" style="background-color: white; border-bottom: 1px solid transparent; border-left: 5px solid rgb(128, 128, 255); color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 14px; font-stretch: normal; line-height: 1.8; margin: 20px 0px; padding: 15px 0px 15px 10px; position: relative;">
<b>mytread.h のソース</b></h2>
</div>
<br />
#ifndef MYTHREAD_H<br />
#define MYTHREAD_H<br />
<br />
#include <QThread><br />
#include <QTimer><br />
<br />
class MyThread : public QThread<br />
{<br />
Q_OBJECT<br />
public:<br />
explicit MyThread(QObject *parent = nullptr);<br />
<br />
void run();<br />
<br />
signals:<br />
void data_update(int i);<br />
<br />
public slots:<br />
<br />
private slots:<br />
void timerHit();<br />
};<br />
<br />
#endif // MYTHREAD_H<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiRHgGNLjB5u4BJyn8PHRyGpHB03nMJsqub9ozGKjeqvh1xS0pdmaXllP_BEW-fWsUVbFbn0_CRQnDdQHPtLSy9UMNC5r_U_LFaSbpKrWPjLsXYzzo8aqKxTXE6tXQxcfhiMg4/s1600/%25E3%2582%25B9%25E3%2583%25AC%25E3%2583%2583%25E3%2583%2589%25E5%25AE%259F%25E6%2596%25BD%25E4%25BE%258B.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="440" data-original-width="343" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiRHgGNLjB5u4BJyn8PHRyGpHB03nMJsqub9ozGKjeqvh1xS0pdmaXllP_BEW-fWsUVbFbn0_CRQnDdQHPtLSy9UMNC5r_U_LFaSbpKrWPjLsXYzzo8aqKxTXE6tXQxcfhiMg4/s1600/%25E3%2582%25B9%25E3%2583%25AC%25E3%2583%2583%25E3%2583%2589%25E5%25AE%259F%25E6%2596%25BD%25E4%25BE%258B.png" /></a></div>
スレッドをWindows上で実施した例。インターバル間隔が,ぴったり4msではなくわずかにずれている(数μs程度)ことが分かる。<br />
<br />
まあ,この程度なら実験としては問題ない範囲だろう。</div>
sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-52522512063198562802019-05-20T17:35:00.000+09:002019-06-20T12:47:59.359+09:00ソフトウェアアーキテクチャとは何かを考える<div class="separator" style="clear: both; text-align: center;">
</div>
最近,協力会社に開発を任せていてソフトウェアの中身が分からず,意図した動きにならない(レスポンスが遅いとか,画面が思ったように遷移しないとか)という話を聞いた。<br />
<br />
また,「ソフトウェアを継ぎ足し続けた結果,肥大化・複雑化して,原因を追及しにくい不具合が発生して困っている。リファクタリングしたい」という話も聞いた。<br />
<br />
どちらも,ソフトウェアアーキテクチャ(構造設計)ができていない,把握できていないのではないかと思う。また,現在のアーキテクチャがシステムの用途・目的に合っていないのではないかと思う。<br />
<br />
ソフトウェア設計のプロセス的に言えば,要求分析や実現可能性の実験(フィージビリティ・スタディ)や機能要件・非機能要件を考慮したアーキテクチャ設計ができていないとかなんだろうが,一言で言えば「アーキテクト不在」という問題が一番大きい。<br />
<br />
アーキテクト(=建築士)不在ということが,どういうことなのかを,住宅の設計の例で考えてみたいと思う。<br />
<br />
【<a href="https://kensetsutenshokunavi.jp/c/content/job_guide/job_guide_01/" target="_blank">建設転職ナビより転載</a>】<br />
<br />
<b>一級建築士について</b><br />
<span style="color: blue;">一級建築士とは</span>、国土交通大臣から認可を受けた国家資格です。家屋、学校や体育館、商業施設や病院など、ありとあらゆる建造物の設計をします。街や村など人々の生活を豊かにしていく、私達には欠かせない大切な仕事を担っています。 <span style="color: blue;">安全性を考慮して建物の設計図を書き、それを元に工事を進めていきます。</span><br />
<br />
試験の受験資格の面でも、一級建築士の場合は実務経験がないと受験資格を得られないという決まりがあります。二級までは、建築学部などで履修科目を学んでいれば実務経験がなくても受験資格を得ることができます。<span style="color: blue;">十分な経験を積み、高い知識を持ちあわせている人だからこそ、一級建築士になれるのです。</span><br />
<br />
<b>一級建築士にできること</b><br />
<span style="color: blue;">一級建築士は、一級というだけあり、建築できる建造物に制限がありません。</span><br />
二級建築士までだと、建物の高さや面積により建築できる建造物に制限があります。 <span style="color: blue;">二級建築士は、主に戸建住宅などの小規模な建造物のみを設計・建築できます。</span> また、木造建築士においては、木造の建物かつ2階建てまでの建物しか取り扱うことができませんが、一級建築士の場合、高さや構造に制限がないため、学校や病院、商業施設など大規模な設計・建築に携わることができます。<br />
<br />
【転載終わり】<br />
<br />
ようするに,建築士の資格を持ったものが,さまざまが建物の設計図を書き,それに基づいて工事が進められる。自分は,「<a href="https://www.asahi.co.jp/beforeafter/" target="_blank">大改造!!劇的ビフォーアフター</a>」というリフォーム番組が好きでよく見ている。この番組では,いろいろな悩みを持った依頼主が,さまざまな得意スキルを持った一級建築士に家のリフォームを一任し,依頼主の悩みを解決して家を新しくする様を見る番組だ。<br />
<br />
建て直すわけではなく骨格は残すので,大元の家の骨組みは残すが,部屋割りや構造の補強など,建築士のアイデアで大改造を行う。<br />
<br />
ソフトウェアで言えば,ソフトウェアアーキテクト(一級建築士)がユーザの悩み事や要望を聞いて,システムのアーキテクチャをリファクタリングすることになる。<br />
<br />
リアル建築との違いがあるとすれば,「大改造!!劇的ビフォーアフター」の場合は,リフォームした家(リファクタリングが完了したシステム)を眺めて,その出来映えや使いやすくなったところをユーザと共有し共感することができることだ。一方,悲しいかなソフトウェアの方はリファクタリングが完了しても,ユーザとその出来映えを共有・共感することは難しい。<br />
<br />
「すばらしいアーキテクチャに変わりましたね」という感想がユーザだけでなく,プロジェクトメンバからも口々に語られることは,おそらくない。リファクタリング後に,ソフトウェアの修正が楽になったとか,デグレードが発生しなくなったとか,派生製品を作るときの開発期間が短くなったという感想は聞けるかもしれないが,しばらく時間がたたないとそういった感想にはならない。<br />
<br />
例えば,アーキテクチャを意識せず,または,設計当初はアーキテクチャの設計思想があったのに,その後の度重なる修正によりアーキテクチャが崩れてしまった場合,各ソフトウェアモジュール間の結合が強くなり,また凝集性が弱くなることで,テストケースが爆発的に増え,デグレードや欠陥の漏れが多くなる。<br />
<br />
ソフトウェアモジュール間の結合度が小さく,凝集が強いということは,責務が明確で他のモジュールとの関係性が小さいということだから,修正が他のモジュールに与える影響は小さくなり,また,どこに影響が及ぶかが分かり易い。(凝集が強く,責務が明確なので,その機能に責任を持っているモジュールがどこなのかがすぐに分かる)<br />
<br />
ソフトウェアのアーキテクチャが度重なる修正により崩れていくと,納期を急ぐあまり,自分の責務ではない機能をソフトウェアモジュールに入れ込んでしまったりして,テストが終わらなくなる。納期を急いでいるため時間切れとなり,テストされていない箇所が残り後に不具合となって現れる。<br />
<br />
ソフトウェアは見えないだけに,悪い状態もよくなったことも,分かりにくい。だから,まずは「アーキテクチャとは何か」についてイメージだけでも押さえてもらいたいと思う。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIP1GBcXmAs6L1fmgTLrGD9e4oMYso35Rv6xMCDyax3VVQUP7Tnn5hAXLujKVL2ac_btyM9WFuLkzXB7BQguaDBS1kam6lnR1KWwlTaahsJgt12M-nYF3cJsV5yJMsh1xNTvZH/s1600/Archtectures1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="305" data-original-width="600" height="162" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIP1GBcXmAs6L1fmgTLrGD9e4oMYso35Rv6xMCDyax3VVQUP7Tnn5hAXLujKVL2ac_btyM9WFuLkzXB7BQguaDBS1kam6lnR1KWwlTaahsJgt12M-nYF3cJsV5yJMsh1xNTvZH/s320/Archtectures1.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizLG7p0F6tewZ0o15xWRhyLaVNjOEVeTLit_jlT0-5s-vCKgma4lGKaRzc5HshaFUgactidkSqI4aMIJfgJ3ojPtGaXo60TbaFipbPxI12Lujc4x5WfSqHamJlGseb7o59tvHj/s1600/Archtectures3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="310" data-original-width="600" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizLG7p0F6tewZ0o15xWRhyLaVNjOEVeTLit_jlT0-5s-vCKgma4lGKaRzc5HshaFUgactidkSqI4aMIJfgJ3ojPtGaXo60TbaFipbPxI12Lujc4x5WfSqHamJlGseb7o59tvHj/s320/Archtectures3.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdGuHzJfVmsvFmci9pZxMV9TqyXOGp7xp8uaPkmneajavMmtabxTU7JKsoetloXHlovKpyg3Izy2FOrmDGXVlaN_RcWGQbunGjFuiLBAkwzQxQ-kjNC-H1Sg44ESqdLohhA2MN/s1600/Archtectures2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="295" data-original-width="600" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdGuHzJfVmsvFmci9pZxMV9TqyXOGp7xp8uaPkmneajavMmtabxTU7JKsoetloXHlovKpyg3Izy2FOrmDGXVlaN_RcWGQbunGjFuiLBAkwzQxQ-kjNC-H1Sg44ESqdLohhA2MN/s320/Archtectures2.png" width="320" /></a></div>
<br />
まず,実際の住宅の構造(アーキテクチャ)にいろいろな種類があることを理解しよう。住宅の構造だけでも,木造在来工法や2×4工法,軽量鉄骨を使った鉄骨軸組工法,ユニット工法などさまざまな工法がある。<br />
<br />
それぞれの工法には特徴があって,コストや施工の早さや,間取りの柔軟性等々,ユーザの要求や懐事情によって基本構造(アーキテクチャ)も変わる。<br />
<br />
リアル住宅の場合も完成してしまうと,構造(アーキテクチャ)がどうなっているかは外からは分かりにくい。(丸太組工法などは例外)<br />
<br />
例えば3階建てにしたいとか,地下室が欲しいとか,間取りにこだわりがあるとか,地震に強くしたいとかいったユーザの要望によって,建築士は構造(アーキテクチャ)を選択する。<br />
<br />
別荘に丸太組工法のログハウスを提案することはあっても,普段生活をするための住宅に丸太組工法を提案することはあまりないだろう。<br />
<br />
問題は,ソフトウェアの場合は,丸太組工法しか知らないソフトウェアエンジニアが丸太組工法で一般住宅や雑居ビルを作ってしまうケースがあるということである。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-sA9cRfanXr8KjoTulrGtA2jKEUX06sPfP9icrgkXfizMxxep1IkFKUHRNkSjVGDGTuGY9vNFI00psbRRGKpp_JEnewVZPg4PMLTH5zU3N09zYeLMDHXgyabSloGWz5j2sgD/s1600/a968763d.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="551" data-original-width="397" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-sA9cRfanXr8KjoTulrGtA2jKEUX06sPfP9icrgkXfizMxxep1IkFKUHRNkSjVGDGTuGY9vNFI00psbRRGKpp_JEnewVZPg4PMLTH5zU3N09zYeLMDHXgyabSloGWz5j2sgD/s320/a968763d.jpg" width="230" /></a></div>
<br />
また,よくありがちなのは,狭い敷地に雑居ビルがひしめき合っているようなソフトウェアの作りにしてしまうケースや,老舗の旅館に別館や新館を建てまして迷路のようになってしまうケースだ。<br />
<br />
収容できるお客は増えるのだが,泊まり客へのサービスはしにくいし,メインテナンスもたいへんだ。<br />
雑居ビルもごちゃごちゃしていて,ビルメインテナンスがしにくい。<br />
<br />
そういうソフトウェアになってしまうのは,設計を開始する際に建築士が要求に対して適切な設計図(アーキテクチャ)を作成していないからではないだろうか。<br />
<br />
ただ,そういった場合であっても「大改造!!劇的ビフォーアフター」のように,リファクタリングをすることは不可能ではない。<br />
<br />
ユーザの困りごとやシステムに対する要求,シリーズ製品のラインナップ等々を調査した上で,何をどう変更するのかを考える。<br />
<br />
その際に,何に困っているのか,どんなシステム要求があるのか,ソフトウェアが動くプラットフォームの性能などの情報がないと,適切な工法を選ぶことができない。<br />
<br />
【この後『<a href="https://amzn.to/2JsA4MG" target="_blank">C/C++による組み込みソフトウェア開発技法 オブジェクト指向を取り入れた理論と実践</a>』から適宜参照。ソフトウェアアーキテクチャを基本から学びたい方は是非読んで欲しい。】<br />
<br />
ソフトウェアのアーキテクチャを考える上で,構造化設計の基本を押さえておく必要がある。言わば,設計士の資格を得るための基礎知識といったところ。<br />
<br />
構造化設計では、モジュールごとに固有の機能が割り当てられているソフトウェア構造であるほど、開発や修正が容易となる。<br />
<br />
ソフトウェア構造が適切に分割されているか判定するために、エドワード・ヨードンとラリー・コンスタンチンが,著書“Structured Design”において、モジュールの結合度(Coupling)と呼ばれる基準を考案した。<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivcG6NysPjR7ReSb0mD8bmX7znD_aAqCE6QD9FRa0R0zQ7vei7KnDcRmwUsM0Kjl4LQJAN6qS9Vb3LlSTU0AwP17NppgV_TjaoSL4z57UtP1II8OvI8bVVA1-A5zoE99S2Byeh/s1600/%25E3%2583%25A2%25E3%2582%25B8%25E3%2583%25A5%25E3%2583%25BC%25E3%2583%25AB%25E7%25B5%2590%25E5%2590%2588%25E5%25BA%25A6.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="413" data-original-width="600" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivcG6NysPjR7ReSb0mD8bmX7znD_aAqCE6QD9FRa0R0zQ7vei7KnDcRmwUsM0Kjl4LQJAN6qS9Vb3LlSTU0AwP17NppgV_TjaoSL4z57UtP1II8OvI8bVVA1-A5zoE99S2Byeh/s320/%25E3%2583%25A2%25E3%2582%25B8%25E3%2583%25A5%25E3%2583%25BC%25E3%2583%25AB%25E7%25B5%2590%25E5%2590%2588%25E5%25BA%25A6.png" width="320" /></a></div>
<div>
左図にモジュールの結合度と特徴を示す。ソフトウェア内のモジュール間の結合度が低いほど、独立した機能と処理を担当するソフトウェア構造を持っていることを示す。</div>
<div>
<br /></div>
<div>
多くのモジュールが結合度の小さいデータ結合になっていればよいが,実際にはそうはなっていない。</div>
<div>
<br /></div>
<div>
モジュールの結合度と,後述するモジュールの凝集度は意識してソフトウェアを設計しなければ,なかなかそうはならない。ようするに,ソフトウェアアーキテクチャを「高凝集」「疎結合」なモジュールで構築しようという設計思想がなければ自然にはそうならない。まれに,直感で修正しやすいソフトウェアを作ろうとして「高凝集」「疎結合」なモジュールを作れるソフトウェアエンジニアもいるかもしれないが少数だろう。</div>
<div>
<br /></div>
<div>
だから,多くのソフトウェアエンジニアは,ソフトウェアモジュール同士の関係が「高凝集」「疎結合」とはどんなことかを頭に入れておいて,できるだけモジュール間の結合を疎に,役割や責務を集約するようにしようと常に考えておく必要がある。</div>
<div>
<br /></div>
<div>
下記に上記のモジュール結合度のタイプ6種類を示す。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkN1grrQTAbomGjk-ujZnQuP8hBOJYjsZBkdeWZmYCx9nusxg3a9mnexC8Mu9cmdgNJZWQb11xqhBB1QRGXLd1pQwDJL3hDMGwMWLOh11SxSyQ-2tbq0UhbBLL4_qKXpNgiYkt/s1600/1_%25E3%2583%2587%25E3%2583%25BC%25E3%2582%25BF%25E7%25B5%2590%25E5%2590%2588.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="417" data-original-width="600" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkN1grrQTAbomGjk-ujZnQuP8hBOJYjsZBkdeWZmYCx9nusxg3a9mnexC8Mu9cmdgNJZWQb11xqhBB1QRGXLd1pQwDJL3hDMGwMWLOh11SxSyQ-2tbq0UhbBLL4_qKXpNgiYkt/s320/1_%25E3%2583%2587%25E3%2583%25BC%25E3%2582%25BF%25E7%25B5%2590%25E5%2590%2588.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ1gWD0w3lXtfIF5t3gymmGgSuXwo4BceAYyfQnCdUFTjHZWuOFzENmPfnHSIuOoBvVX5w4dpxw6AECLlUerSFtcmSBjDj_Iet9G73IA3IV4T6Mxqob8Rjfdkg-d-p9r6RNGDv/s1600/2_%25E3%2582%25B9%25E3%2582%25BF%25E3%2583%25B3%25E3%2583%2597%25E7%25B5%2590%25E5%2590%2588.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="363" data-original-width="600" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ1gWD0w3lXtfIF5t3gymmGgSuXwo4BceAYyfQnCdUFTjHZWuOFzENmPfnHSIuOoBvVX5w4dpxw6AECLlUerSFtcmSBjDj_Iet9G73IA3IV4T6Mxqob8Rjfdkg-d-p9r6RNGDv/s320/2_%25E3%2582%25B9%25E3%2582%25BF%25E3%2583%25B3%25E3%2583%2597%25E7%25B5%2590%25E5%2590%2588.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuYzfwSWPxCVeYUFql0iOgILBuwWAsqGJ_uoJ2jHCaTdGJeasXpPQynhn7vr2jCVr6SfelMn_oW1fr5QgCZp9GevRFQ9aNU0qJq6xiSvPYw7jEelL2v0PYXG1qX9nflLZ1BxoB/s1600/3_%25E5%2588%25B6%25E5%25BE%25A1%25E7%25B5%2590%25E5%2590%2588.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="553" data-original-width="893" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuYzfwSWPxCVeYUFql0iOgILBuwWAsqGJ_uoJ2jHCaTdGJeasXpPQynhn7vr2jCVr6SfelMn_oW1fr5QgCZp9GevRFQ9aNU0qJq6xiSvPYw7jEelL2v0PYXG1qX9nflLZ1BxoB/s320/3_%25E5%2588%25B6%25E5%25BE%25A1%25E7%25B5%2590%25E5%2590%2588.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifmRHOH2otScfkWHky5UmLjxg6MPgaCQGU0uByZY0iZa7RVwYeh9lD_6TA3iyXuxkPP5uuTYYPJLeV2mHiH4h8AxVwoK-sgVB_PGO6apiQJJFF8z6prayqFcPr1_lOwB0a54Lu/s1600/4_%25E5%25A4%2596%25E9%2583%25A8%25E7%25B5%2590%25E5%2590%2588.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="414" data-original-width="600" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifmRHOH2otScfkWHky5UmLjxg6MPgaCQGU0uByZY0iZa7RVwYeh9lD_6TA3iyXuxkPP5uuTYYPJLeV2mHiH4h8AxVwoK-sgVB_PGO6apiQJJFF8z6prayqFcPr1_lOwB0a54Lu/s320/4_%25E5%25A4%2596%25E9%2583%25A8%25E7%25B5%2590%25E5%2590%2588.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaNxj4pe2cLzAy0cH2nVXtSh0fnaz-XWWHkwz_LXDnwIl_pK6GKboQxvATrbPpdn9gm7tWBdb1VrtLBuOj21kmEZSTiEV7yk_P30s0KCpcfZ9Dwq89hsI8wrMlxU5ax0BLsZ0z/s1600/5_%25E5%2585%25B1%25E9%2580%259A%25E7%25B5%2590%25E5%2590%2588.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="423" data-original-width="600" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaNxj4pe2cLzAy0cH2nVXtSh0fnaz-XWWHkwz_LXDnwIl_pK6GKboQxvATrbPpdn9gm7tWBdb1VrtLBuOj21kmEZSTiEV7yk_P30s0KCpcfZ9Dwq89hsI8wrMlxU5ax0BLsZ0z/s320/5_%25E5%2585%25B1%25E9%2580%259A%25E7%25B5%2590%25E5%2590%2588.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTkmxc8P8Oac6mrIvG_Bmy2F-2HjdoTTXtt6Ow6rqYkoXxOsJYD_l3iAWZtcfSX6C_Pw0CB_88uvBL6P2zxVMN-pKhLxVaAsswSq4Ohe20VKMi5FK5BnWrJa0fy22P4dtj6OHV/s1600/6_%25E5%2586%2585%25E5%25AE%25B9%25E7%25B5%2590%25E5%2590%2588.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="402" data-original-width="600" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTkmxc8P8Oac6mrIvG_Bmy2F-2HjdoTTXtt6Ow6rqYkoXxOsJYD_l3iAWZtcfSX6C_Pw0CB_88uvBL6P2zxVMN-pKhLxVaAsswSq4Ohe20VKMi5FK5BnWrJa0fy22P4dtj6OHV/s320/6_%25E5%2586%2585%25E5%25AE%25B9%25E7%25B5%2590%25E5%2590%2588.png" width="320" /></a></div>
<div>
<br /></div>
<div>
理想的には①データ結合,②スタンプ結合,③制御結合ですべてのソフトウェアモジュールが構成されているのがよいが,特にC言語で作っていると④外部結合や⑤共有結合や⑥内容結合になってしまう傾向がある。</div>
<div>
<br /></div>
<div>
C++のようなオブジェクト指向言語を使えば,言語仕様からして④外部結合,⑤共有結合,⑥内容結合は作りにくくなる。</div>
<div>
<br /></div>
<div>
次にモジュールの凝集度について説明する。</div>
<div>
<br /></div>
<div>
<div>
ソフトウェアの凝集度(Cohesion)は、エドワード・ヨードンとラリー・コンスタンチン、ウェイン・スティーブンス、グレンフォード・メイヤーズらによって考案されたソフトウェア機能の固有性の尺度で,凝集度が高いモジュールは、明確な責任を持ち、シンプルで独立性の高い機能を実装していることを示す。</div>
<div>
<br /></div>
<div>
この指標はオブジェクト指向設計の目標と一致する。</div>
<div>
一般的に凝集度が高いソフトウェアほど保守性や拡張性が高く、再利用も容易な傾向がある。<br />
<br />
ソフトウェアの新人技術者の教育をやっていると,機能の実現を関数を積み重ねることで作り上げていき,システムの規模が大きくなっても,そのやり方を続ける者が多い。<br />
<br />
システムの規模が大きくなったときは,機能の実現というよりも,責務の分割という視点で設計した方が圧倒的に保守性,拡張性,再利用性が高いという実感がある。<br />
<br />
ソフトウェアエンジニアはどこかの時点でその考え方のシフトが必要なんだと思う。そのことを『<a href="https://amzn.to/2wqDpTP" target="_blank">リアルタイムOSから出発して組込みソフトエンジニアを極める</a>』に書いたつもり。</div>
</div>
<div>
<br />
さて,ソフトウェアの凝集度(Cohesion)について見てみよう。<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWSswjnxycCZHQLmP9S7SZvMCA8cZqZonwlyfF3_GjOgFcMg-kGbEEgkDm76VNDglydDAh40E1zLr6Ic0GAUrIyNRq9m0R73j2OckXrpjSy8-nXuTeG8aYEGOV46hiS3buoHCd/s1600/%25E3%2583%25A2%25E3%2582%25B8%25E3%2583%25A5%25E3%2583%25BC%25E3%2583%25AB%25E5%2587%259D%25E9%259B%2586%25E5%25BA%25A6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="509" data-original-width="600" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWSswjnxycCZHQLmP9S7SZvMCA8cZqZonwlyfF3_GjOgFcMg-kGbEEgkDm76VNDglydDAh40E1zLr6Ic0GAUrIyNRq9m0R73j2OckXrpjSy8-nXuTeG8aYEGOV46hiS3buoHCd/s320/%25E3%2583%25A2%25E3%2582%25B8%25E3%2583%25A5%25E3%2583%25BC%25E3%2583%25AB%25E5%2587%259D%25E9%259B%2586%25E5%25BA%25A6.png" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b>①暗号的凝集/偶発的凝集(Coincidental Cohesion)</b></div>
<div>
<ul>
<li>互いに関連のない複数の機能を含むモジュールの凝集度を指す。</li>
<li>たまたまタイマイベントによってメッセージ表示とファイル書き込みの処理が開始するため1つの関数内に両方を実装した場合などに、このような構造が現れる。</li>
<li>機能同士はタイミングも、処理内容も、種別もまったく関連がない。そのため修正や機能追加の影響範囲が広いうえに可読性が低く、保守や修正が困難なソフトウェア構造。</li>
</ul>
</div>
<b>②論理的凝集(Logical Cohesion)</b><br />
<ul>
<li>実際の内容は異なるが、同じカテゴリに属する処理を集めたモジュールの凝集度。</li>
<li>たとえばLCD表示を処理する関数に、アイコンの制御とメッセージ表示と背景画像の描画処理を実装している場合などが該当する。</li>
<li>ひとたび論理的凝集状態にあるモジュールを実装すると、関連する機能を追加する場合に分離が難しくなる。</li>
<li>LCD制御の処理やデータがすでに集まっている関数がある場合に新たに時計表示を追加しようとすると、既存処理を利用するには同じ関数内に実装せざるをえないことなる。</li>
<li>このため機能は膨れあがり、次第に修正と保守が困難になる。</li>
</ul>
<br />
<b>③時間的凝集(Temporal Cohesion)</b><br />
<ul>
<li>同じタイミングで実行される処理を集めたモジュールの凝集度。</li>
<li>カーナビゲーションシステムで目的地に到着したタイミングでメッセージ表示と音声再生と画像更新を実行するために、一つの関数にこれらの処理を実装した場合などに発生する。</li>
<li>機能的関連がないため共通化や修正が難しい。</li>
</ul>
<br />
<b>④手続き的凝集(Procedural Cohesion)</b><br />
<ul>
<li>一連の処理を実行するために必要な機能を集めたモジュールの凝集度。</li>
<li>内蔵チップを初期化する機能として、初期化開始処理・初期化完了待ち処理・初期値のデータ設定処理などを1つのモジュールに実装した場合などに発生する。</li>
<li>ひとまとまりの処理として実行されるだけで、機能同士の関連が弱いため、ある箇所を修正すると次の処理にも影響が及ぶ結果となり保守性が低下する。</li>
</ul>
<br />
<b>⑤通信的凝集(Communicational Cohesion)</b><br />
<ul>
<li>同じデータを扱う処理を集めた凝集度。</li>
<li>処理に順序性がなくデータの共通性によって結びついているため、データ構造の変更が複数の箇所に影響する可能性がある。</li>
<li>クラスによっては最適な設計の結果が通信的凝集の状態になる場合もある。</li>
</ul>
<br />
<b>⑥逐次的凝集(Sequential Cohesion)</b><br />
<ul>
<li>同じデータを扱う処理を、順序性を持たせて集約したモジュールの凝集度。</li>
<li>ある処理の出力が次の処理の入力となり、処理を分離してもソフトウェアの構造が単純化されない(またはかえって複雑となる)ような機能を持つ状態を指す。</li>
</ul>
<b>⑦機能的凝集(Functional Cohesion)</b><br />
<ul>
<li>1つの関数やモジュールが単一の役割と目的を持っており、固有の機能を実装する状態の凝集度。</li>
<li>クラス設計においても独立したシンプルなクラスとすることができます。</li>
<li>すべてのモジュールを機能的凝集度で実装することはできないが、可能な限りこのレベルに近づけるように検討すべき。</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
</div>
次に,すでに機能の積み重ねで作ってしまい大規模・複雑化してしまったシステム,バグが多く混在する未熟な組込みシステムから,システムの中で価値の高いコア資産を分離する(高凝集,疎結合にする)イメージを示す。<br />
<br />
<a href="https://www.slideshare.net/xxsakai/ss-131547905" target="_blank">2005年のESEC専門セミナーで講演した内容</a>からの抜粋。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbePhG6hE7BPUw94gvDAmyeKZ9uC92i4A4TUGgWuE2ICRMSV5MdvLepB_5Vb1dL_gFJVoWiXhJh-GXj-c0MVXiSkCmXOq3muewQqQuLWD2uIl_hGr8YGI0UsYycTvGVcfmsuZd/s1600/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="377" data-original-width="600" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbePhG6hE7BPUw94gvDAmyeKZ9uC92i4A4TUGgWuE2ICRMSV5MdvLepB_5Vb1dL_gFJVoWiXhJh-GXj-c0MVXiSkCmXOq3muewQqQuLWD2uIl_hGr8YGI0UsYycTvGVcfmsuZd/s320/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B01.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCJ4gW0PQV99mc21niX3fB4QRyPxUmnqkbiSpwesJhWCLV8EHy9De8qN0-6-R_e0WpwnnGvd_SfblRt2v5BisJbcJToVKMSJkVxPbmcXXjpTLsM5fiSMzVYxk36yV7okPjCwO4/s1600/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="375" data-original-width="600" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCJ4gW0PQV99mc21niX3fB4QRyPxUmnqkbiSpwesJhWCLV8EHy9De8qN0-6-R_e0WpwnnGvd_SfblRt2v5BisJbcJToVKMSJkVxPbmcXXjpTLsM5fiSMzVYxk36yV7okPjCwO4/s320/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B02.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDI6syMRti7Nd7_Htal_jcvpH3X0BA31LwK8dx36_m3Wk0PxRUG2c0YMh3WxQV4tC0ivYA0CiOmxFvlp1VSPdZ8NWYbrdIZRFCg18Ya_1e5JM8TKyG6EmRc67mYhAj90frbSPp/s1600/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="354" data-original-width="600" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDI6syMRti7Nd7_Htal_jcvpH3X0BA31LwK8dx36_m3Wk0PxRUG2c0YMh3WxQV4tC0ivYA0CiOmxFvlp1VSPdZ8NWYbrdIZRFCg18Ya_1e5JM8TKyG6EmRc67mYhAj90frbSPp/s320/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B03.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdCV_bnS_edE_V9BK0xSxqW6OuT-q2pdys7io2dJTCptzPEyVBz3mFV-zaewAkCu-uTWJ4cAqJW-mGhCcqtUBosxFBsXS354iVg231InOibcHvY8oY849ivfix9HvJk5HeWPGr/s1600/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="386" data-original-width="600" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdCV_bnS_edE_V9BK0xSxqW6OuT-q2pdys7io2dJTCptzPEyVBz3mFV-zaewAkCu-uTWJ4cAqJW-mGhCcqtUBosxFBsXS354iVg231InOibcHvY8oY849ivfix9HvJk5HeWPGr/s320/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B04.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtdxSq6apd4-iTSBd2b1TOgn29CA0BRjAk_VVDLLiTXk5IYT2AQy5BQokaygEfIB8S2oWAyVGO50pHtE8N_9Eo1KxhPuwQVN0uSRMWY1yskxfxTsgsVsMI0MDrjVdWjG6WQVht/s1600/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="363" data-original-width="600" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtdxSq6apd4-iTSBd2b1TOgn29CA0BRjAk_VVDLLiTXk5IYT2AQy5BQokaygEfIB8S2oWAyVGO50pHtE8N_9Eo1KxhPuwQVN0uSRMWY1yskxfxTsgsVsMI0MDrjVdWjG6WQVht/s320/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B05.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL57imH1FGbLrf9KshsghBrwC1I0jVJk4TBg_lPQptUgKHUJvms1aohaU2uzeA4RrH8sz9PZbxA45q-oSfM9bLcpc_uQobPq90YhSbltDKc9kt_vEz0LahbLjlmvk53wbxQvHf/s1600/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="399" data-original-width="600" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL57imH1FGbLrf9KshsghBrwC1I0jVJk4TBg_lPQptUgKHUJvms1aohaU2uzeA4RrH8sz9PZbxA45q-oSfM9bLcpc_uQobPq90YhSbltDKc9kt_vEz0LahbLjlmvk53wbxQvHf/s320/%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2582%25AF%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B06.png" width="320" /></a></div>
<br />
あくまでもイメージであり,実際のソフトウェアのリファクタリングはそんなに簡単ではないが,まずはどうなっていればいいかというイメージを持つことが重要だ。<br />
<br />
ソフトウェアシステムのソフトウェア開発に携わるソフトウェアエンジニアは,まず,ソフトウェアのモジュールを作成する際には「高凝集」「疎結合」とすべきであることを常に認識しておく。作成したモジュールが結合の分類,凝集の分類のどれに当たるのかを把握しておくとよいだろう。<br />
<br />
そしてソフトウェアシステムのアーキテクチャを考えるアーキテクトは,システムに対する要求や条件,実現の可能性等を考慮して,どのような構造(アーキテクチャ)にするのが最適であるかを考える。その際には,今回対象の製品だけでなく,製品群で共通に使用するコアとなる資産が何になるのかを意識した方がよい。コア資産となるソフトウェアモジュールほど,高凝集,疎結合であった方が再利用性が高くなり,保守もしやすい。<br />
<br />
リアル建築士のように,ソフトウェアのアーキテクトも必要な知識やスキルがあるかどうかを検定して一級,二級といったソフトウェアアーキテクトの資格を作った方がいいのかもしれない。<br />
<br />
アーキテクト不在のソフトウェアシステムは恐ろしいので,ソフトウェア開発には少なくとも一人はアーキテクトを含めるようにした方がよいだろう。<br />
<br />
「ソフトウェアアーキテクトなんかいない」という組織やプロジェクトではどうすればいいのか。それは,外部の協力会社のアーキテクトをプロジェクトに引き入れたり,メンターとなってくれるコンサルタントに支援を要請する。<br />
<br />
ちなみに,ソフトウェアアーキテクトの素養のある人は,ソフトウェアエンジニア20人に1人くらいの割合だろうと言われている。みんながみんな一級建築士になれるわけではないのは,リアル建築と同じだ。<br />
<br />
ちなみに,実感として,ソフトウェアアーキテクトの素養のある人が,その能力を適正に評価されているようには思えない。ソフトウェアの構造(アーキテクチャ)が良い,美しいことは,外側からはよく分からないからだろう。<br />
<br />
「大改造!!劇的ビフォーアフター」のように依頼者が涙を流して,アーキテクトに感謝してくれるといったシーンが,ソフトウェアの世界では期待できない。<br />
<br />
そこがソフトウェアアーキテクトの悲しいところだ。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW68bj-eLDSTOYc-uQ-JR9QzfxzaufCuCubgfwWmGPrkxK5MC-IxsSJooS8BkIMNgcE2zP2WyH1O6Qvuv9T-Xcc12JnuMRvw-CBm2unTppkmeLQ9G35vGRJoZTq0JxF1wtLPim/s1600/%25E3%2582%25A2%25E3%2583%25BC%25E3%2582%25AD%25E3%2582%25A8%25E3%2582%25AF%25E3%2583%2581%25E3%2583%25A3%25E3%2581%25AE%25E5%2596%2584%25E3%2581%2597%25E6%2582%25AA%25E3%2581%2597%25E3%2581%25AE%25E4%25BE%258B.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="701" data-original-width="1171" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW68bj-eLDSTOYc-uQ-JR9QzfxzaufCuCubgfwWmGPrkxK5MC-IxsSJooS8BkIMNgcE2zP2WyH1O6Qvuv9T-Xcc12JnuMRvw-CBm2unTppkmeLQ9G35vGRJoZTq0JxF1wtLPim/s400/%25E3%2582%25A2%25E3%2583%25BC%25E3%2582%25AD%25E3%2582%25A8%25E3%2582%25AF%25E3%2583%2581%25E3%2583%25A3%25E3%2581%25AE%25E5%2596%2584%25E3%2581%2597%25E6%2582%25AA%25E3%2581%2597%25E3%2581%25AE%25E4%25BE%258B.png" width="400" /></a></div>
ソフトウェアもリファクタリングは可能と書いたが,現実にはすでに出来上がってしまったソフトウェアシステムを静的な構造として解析すると(どのクラス,どのモジュールがお互いを呼び出している関係)左図の左のようになっていたりして,リファクタリングはそう簡単ではない。<br />
<br />
全体的なリファクタリングは諦めて,後継機種を開発するときに着手しようという結果になることも多い。<br />
<br />
本来ならば,上から下へといった呼び出し関係(上図の右)となるような,レイヤードアーキテクチャになっていた方が,保守性が高まるが,そういうアーキテクチャにしようという意図なく開発していたら,そうそう,作り直すのは簡単ではない。<br />
<br />
最初の問題提起に戻ると,ソフトウェア開発する際に「アーキテクト不在」では何事もうまくいかず,失敗プロジェクトになってしまう可能性が高まる。sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-55827321171575762382019-05-13T10:48:00.001+09:002019-08-09T15:34:06.342+09:00Raspberry Pi3を使ったリアル波形描画(5) スタートレックゲームの一部を作ってみる<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHEWnnsACwLHUuOw3uDzHS5hXisWqcgk5K53b6AJZCqKlhihjuSsLEnzk_pb6m33NZv2fiNM9fV6bRb7xetf2Q4OrJCBB8yVIzqMjF5I2USl3O4ahyyz4KilkoEdzFIVtqFjKO/s1600/RealWaveDisplayTitle05_340x241.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="340" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHEWnnsACwLHUuOw3uDzHS5hXisWqcgk5K53b6AJZCqKlhihjuSsLEnzk_pb6m33NZv2fiNM9fV6bRb7xetf2Q4OrJCBB8yVIzqMjF5I2USl3O4ahyyz4KilkoEdzFIVtqFjKO/s320/RealWaveDisplayTitle05_340x241.png" width="320" /></a></div>
今回はテキストで遊ぶスタートレックゲームのほんの一部分を c++ で書いてみる。<br />
オリジナルのスタートレックゲームはテキストのゲームでありながら,自分がスタートレック号にのって宇宙を移動しながらクリンゴンを倒していく雰囲気を十分に味わうことができた。<br />
<br />
iPhone を持っている人は App Store に Old Trek という名前で登録がある。(120円)<br />
詳しくは<a href="https://www.tab-log.net/post-114/" target="_blank">こちら</a>を参照のこと。<br />
<br />
スタートレックゲームについてより詳しく知りたい方はこちらを参照のこと。<br />
<br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;">※</span><a href="https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%83%AC%E3%83%83%E3%82%AF_(%E3%83%9E%E3%82%A4%E3%82%B3%E3%83%B3%E3%82%B2%E3%83%BC%E3%83%A0)" style="background-color: #fefdfa; color: #d52a33; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" target="_blank">スタートレックシミュレーションゲーム(Wikipedia)</a><br />
<br style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;" />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;"><スタートレックゲームのオリジナルの動画></span><br />
<ol style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px;">
<li style="margin: 0px 0px 0.25em; padding: 0px;"><a href="http://d.hatena.ne.jp/gust_notch/20110614/p1" style="color: #7d181e; text-decoration-line: none;" target="_blank">スタートレックゲームのソースコードと解説</a></li>
<li style="margin: 0px 0px 0.25em; padding: 0px;"><a href="https://www.youtube.com/watch?v=j3CvJPqMGfU" style="color: #7d181e; text-decoration-line: none;" target="_blank">MZ-80 でスタートレックゲームを遊んでいる動画</a></li>
<li style="margin: 0px 0px 0.25em; padding: 0px;"><a href="https://www.youtube.com/watch?v=D9U57Q5y17o" style="color: #7d181e; text-decoration-line: none;" target="_blank">Apple II でスタートレックゲームを遊んでいる動画</a></li>
</ol>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEaCzi5xgkhKPOcpcXmdccg3fqTR55vDPRnCunGL7Oa5fLRczDpWoJx6xeQFbQmY8eNHmaKRTX-9CH0SbspqjP1O-2Lheyld_9UqydsYwpSBmDRwSfJmdsw70rgR9v5MAoMoiL/s1600/startrek.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="281" data-original-width="341" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEaCzi5xgkhKPOcpcXmdccg3fqTR55vDPRnCunGL7Oa5fLRczDpWoJx6xeQFbQmY8eNHmaKRTX-9CH0SbspqjP1O-2Lheyld_9UqydsYwpSBmDRwSfJmdsw70rgR9v5MAoMoiL/s320/startrek.png" width="320" /></a>スタートレックゲームのイメージは概ねこんな感じだ。左下の8×8のマスがショートレンジセンサーの結果で,上の8×8のマスがロングレンジセンサーのマップになる。<br />
<br />
ショートレンジセンサーの8×8のエリアが64個ぶん広がっている宇宙があるという設定だ。ロングレンジセンサー[517]の数字の意味は,5つの敵=K,1つの基地=B,7つの星=※があるという意味。ショートレンジセンサーのマップのEがエンタープライズ号を示している。Bの基地まで移動するとエネルギーを補給できる。<br />
<br />
クリンゴンは光子魚雷(Photon Torpedos)か,フェーザー砲(Fire Phaser)で攻撃する。フェーザー砲はエネルギー値を設定でき範囲攻撃ができる。光子魚雷は当たればクリンゴンを破壊できる。クリンゴンから攻撃を受けることもある。移動は短距離はインパルスエンジン,長距離はワープエンジンを使用する。<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVTYLbUnjVLdjY60mCwU8VBH3VmCQ4eVUuCgwmqvKgyw0rRU05nJxeZ-x7FEqMn1WFSaVUtOWCDN1_enMq96LIFKz-PviX2LxXby3d9uERgNbGUToLM6kMqmZLr90JzudfUldT/s1600/TtarTrek1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="194" data-original-width="264" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVTYLbUnjVLdjY60mCwU8VBH3VmCQ4eVUuCgwmqvKgyw0rRU05nJxeZ-x7FEqMn1WFSaVUtOWCDN1_enMq96LIFKz-PviX2LxXby3d9uERgNbGUToLM6kMqmZLr90JzudfUldT/s1600/TtarTrek1.png" /></a>今回は,8×8のショートレンジセンサーのレンジを用意し,ランダムにクリンゴンと星とエンタープライズ号を配置し,エンタープライズ号をインパルスエンジンで移動するプログラムを作ってみる。<br />
<br />
移動だけで,攻撃とかワープとか補給などはできない。前回のタートルクラスを参考にして(派生させて),エンタープライズ号とクリンゴンと星のオブジェクトを生成して,それぞれのオブジェクトを動かせるようにしてみる。<br />
<br />
方向は0~360° で方向を指定する。これは亀(タートルクラス)のときと同じ。<br />
<br />
0°<br />
↑<br />
270° ← 亀 → 90°<br />
↓<br />
180°<br />
<br />
オブジェクト思考設計をする意味は,前回も述べたようにソフトウェアを再利用可能な資産にして,毎回ゼロから作り直すようなことをしない点にある。<br />
<br />
今回のような仕様のソフトウェアはいろいろな方法で作成することができるが,エンタープライズ号とクリンゴンと星はどれも同じような特長(移動方法など)があるので,これらをオブジェクト指向設計でうまく設計すれば効率的にソフトウェアを作ることができる。<br />
<br />
<b>事前準備</b><br />
<br />
<ul>
<li>タートルクラス(x,yの位置情報を持ち,向きの変更と前進ができる)を応用して,宇宙船クラスを作成。</li>
<li>小宇宙クラスを作成し 8x8 のマップを作成。</li>
<li>クリンゴン(2個以上5個以下)と,惑星(4個以上7個以下)をランダムにマップに配置。</li>
<li>エンタープライズ号を配置。</li>
<li>エンタープライズ号を移動できるようにして,マップを表示させる。</li>
<li>これらをテキスト表示で行う。</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAPSv9AN5CRd69gMFhzspSXY06N3KRx1VkltTJgXGHZ4te7E97l-f-wtolMiQ-hSgvkXtrCyo9wnAn3dCKXNb_HtixH4cMBSet34EvRBkTn32Q7Jmha5hmSpzh0_2epDvaltQL/s1600/StarTrek_Class2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="302" data-original-width="1016" height="118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAPSv9AN5CRd69gMFhzspSXY06N3KRx1VkltTJgXGHZ4te7E97l-f-wtolMiQ-hSgvkXtrCyo9wnAn3dCKXNb_HtixH4cMBSet34EvRBkTn32Q7Jmha5hmSpzh0_2epDvaltQL/s400/StarTrek_Class2.png" width="400" /></a></div>
<br />
<div>
</div>
<br />
Spaceship クラスは,方向とX座標とY座標を内部変数として持っている。そして,前進,右向き,左向き,任意の位置に移動などのサービスを提供する。<br />
<br />
このクラスから実態となる宇宙船,クリンゴン,惑星を生成しマップに配置する。<br />
<br />
【ap_smallspace.h のソース】<br />
<br />
<pre>#<span style="color: navy;">ifndef</span><span style="color: silver;"> </span><span style="color: navy;">AP_SMALLSPACE_H</span></pre>
<pre>#<span style="color: navy;">define</span><span style="color: silver;"> </span><span style="color: navy;">AP_SMALLSPACE_H</span></pre>
<pre></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_spaceship.h"</span></pre>
<pre></pre>
<pre></pre>
<pre><span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple; font-weight: 600;">smallspace</span></pre>
<pre>{</pre>
<pre><span style="color: olive;">public</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">smallspace</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">deployPlanets</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">num</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">deployKlingons</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">num</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">deployEnterprise</span>(<span style="color: olive;">void</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">short</span><span style="color: silver;"> </span><span style="color: maroon;">mSpaceMap</span>[<span style="color: navy;">8</span>][<span style="color: navy;">8</span>];</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span><span style="color: silver;"> </span><span style="color: maroon;">Enterprise</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span><span style="color: silver;"> </span><span style="color: maroon;">Klingons</span>[<span style="color: navy;">8</span>];</pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span><span style="color: silver;"> </span><span style="color: maroon;">Planets</span>[<span style="color: navy;">8</span>];</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: maroon;">KlingonsNum</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: maroon;">PlanetsNum</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">displayMap</span>(<span style="color: olive;">void</span>);</pre>
<pre><span style="color: olive;">private</span>:</pre>
<pre></pre>
<pre>};</pre>
<pre></pre>
<br />
<pre>#<span style="color: navy;">endif</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">AP_SMALLSPACE_H</span></pre>
<br />
【ap_spaceship.h のソース】<br />
<br />
<pre>#<span style="color: navy;">ifndef</span><span style="color: silver;"> </span><span style="color: navy;">AP_SPACESHIP_H</span></pre>
<pre>#<span style="color: navy;">define</span><span style="color: silver;"> </span><span style="color: navy;">AP_SPACESHIP_H</span></pre>
<pre></pre>
<pre><span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple; font-weight: 600;">Spaceship</span></pre>
<pre>{</pre>
<pre><span style="color: olive;">public</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">Spaceship</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">turnleft</span>();<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">左を向く</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">turnright</span>();<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">右を向く</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">forward</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">distanse</span>);<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">前進する</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">getXPosition</span>(<span style="color: olive;">void</span>);<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">現在のX軸の位置を得る</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">getYPosition</span>(<span style="color: olive;">void</span>);<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">現在のY軸の位置を得る</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">getDiraction</span>(<span style="color: olive;">void</span>);<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">現在の向きを得る</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">setDiraction</span>(<span style="color: olive;">int</span>);<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">方向を設定する</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">resetPosition</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">warp</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">x</span>,<span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">y</span>);</pre>
<pre></pre>
<pre><span style="color: olive;">private</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: maroon;">mX</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">X座標</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: maroon;">mY</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">y座標</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: maroon;">mD</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">向き</span></pre>
<pre>};</pre>
<pre></pre>
<pre></pre>
<pre>#<span style="color: navy;">endif</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">AP_SPACESHIP_H</span></pre>
<pre><span style="color: green;">
</span></pre>
<pre></pre>
【ap_stertrekgame.h のソース】<br />
<br />
<pre>#<span style="color: navy;">ifndef</span><span style="color: silver;"> </span><span style="color: navy;">AP_STARTREKGAME_H</span></pre>
<pre>#<span style="color: navy;">define</span><span style="color: silver;"> </span><span style="color: navy;">AP_STARTREKGAME_H</span></pre>
<pre></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_smallspace.h"</span></pre>
<pre></pre>
<pre><span style="color: olive;">class</span><span style="color: silver;"> </span><span style="color: purple; font-weight: 600;">startrekgame</span></pre>
<pre>{</pre>
<pre><span style="color: olive;">public</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">startrekgame</span>();</pre>
<pre><span style="color: silver;"> </span>~<span style="color: #00677c; font-weight: 600;">startrekgame</span>();</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">惑星・エンタープライズ号・クリンゴンを配置</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">initStarTrekGame</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">小宇宙のマップを表示</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">displaySpaceMap</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">コマンド受け付け</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">inputCommand</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">コマンド実行</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">execCommand</span>();</pre>
<pre></pre>
<pre><span style="color: olive;">private</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">smallspace</span>*<span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">小宇宙ポインタ</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: maroon;">mCommand</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">コマンド</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: maroon;">mFunction</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ファンクション</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">inputMoveFunction</span>();</pre>
<pre>};</pre>
<pre></pre>
<br />
<pre>#<span style="color: navy;">endif</span><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">AP_STARTREKGAME_H</span></pre>
<br />
【ap_smallspace.cpp のソース】<br />
<br />
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_smallspace.h"</span></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><<span style="color: green;">stdio</span>.<span style="color: green;">h</span>></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><<span style="color: green;">stdlib</span>.<span style="color: green;">h</span>></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><<span style="color: green;">time</span>.<span style="color: green;">h</span>></pre>
<pre></pre>
<pre></pre>
<pre><span style="color: purple;">smallspace</span>::<span style="color: #00677c; font-weight: 600;">smallspace</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: silver;"> </span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">i</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: #092e64;">i</span><<span style="color: navy;">8</span><span style="color: silver;"> </span>;<span style="color: #092e64;">i</span>++){</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: silver;"> </span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">j</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: #092e64;">j</span><<span style="color: navy;">8</span>;<span style="color: silver;"> </span><span style="color: #092e64;">j</span>++){</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">i</span>][<span style="color: #092e64;">j</span>]=<span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">smallspace</span>::<span style="color: #00677c; font-weight: 600;">deployPlanets</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">num</span>)</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">i</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">posX</span>,<span style="color: silver;"> </span><span style="color: #092e64;">posY</span>;</pre>
<pre><pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">現在時刻を元に乱数の種を</span><span style="color: silver;"> </span><span style="color: green;">srand</span><span style="color: silver;"> </span><span style="color: green;">関数で生成する。unsgined</span><span style="color: silver;"> </span><span style="color: green;">int</span><span style="color: silver;"> </span><span style="color: green;">に明示的にキャストしておく</span></pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">srand</span>(<span style="color: olive;">static_cast</span><<span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">int</span>>(<span style="color: #00677c;">time</span>(<span style="color: olive;">nullptr</span>)));</pre>
<pre> <span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">3から7の間の乱数を作成する</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: #092e64;">num</span>==<span style="color: navy;">0</span>)<span style="color: silver;"> </span><span style="color: #092e64;">num</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: #00677c;">rand</span>()<span style="color: silver;"> </span>%<span style="color: silver;"> </span><span style="color: navy;">4</span><span style="color: silver;"> </span>+<span style="color: silver;"> </span><span style="color: navy;">3</span>;</pre>
</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">PlanetsNum</span>=<span style="color: #092e64;">num</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">while</span><span style="color: silver;"> </span>(<span style="color: #092e64;">i</span><(<span style="color: #092e64;">num</span>))<span style="color: silver;"> </span>{</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">posX</span><span style="color: silver;"> </span>=<span style="color: #00677c;">rand</span>()<span style="color: silver;"> </span>%<span style="color: silver;"> </span><span style="color: navy;">8</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">posY</span><span style="color: silver;"> </span>=<span style="color: #00677c;">rand</span>()<span style="color: silver;"> </span>%<span style="color: silver;"> </span><span style="color: navy;">8</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">posX</span>][<span style="color: #092e64;">posY</span>]==<span style="color: navy;">0</span>){</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">posX</span>][<span style="color: #092e64;">posY</span>]=<span style="color: navy;">100</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">Planets</span>[<span style="color: #092e64;">i</span>].<span style="color: #00677c;">warp</span>(<span style="color: #092e64;">posX</span>,<span style="color: #092e64;">posY</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">i</span>++;</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">smallspace</span>::<span style="color: #00677c; font-weight: 600;">deployKlingons</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">num</span>)</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">i</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">posX</span>,<span style="color: silver;"> </span><span style="color: #092e64;">posY</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">srand</span>(<span style="color: olive;">static_cast</span><<span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">int</span>>(<span style="color: #00677c;">time</span>(<span style="color: olive;">nullptr</span>)));</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: #092e64;">num</span>==<span style="color: navy;">0</span>)<span style="color: silver;"> </span><span style="color: #092e64;">num</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: #00677c;">rand</span>()<span style="color: silver;"> </span>%<span style="color: silver;"> </span><span style="color: navy;">3</span><span style="color: silver;"> </span>+<span style="color: silver;"> </span><span style="color: navy;">2</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">KlingonsNum</span>=<span style="color: #092e64;">num</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">while</span><span style="color: silver;"> </span>(<span style="color: #092e64;">i</span><(<span style="color: #092e64;">num</span>))<span style="color: silver;"> </span>{</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">posX</span><span style="color: silver;"> </span>=<span style="color: #00677c;">rand</span>()<span style="color: silver;"> </span>%<span style="color: silver;"> </span><span style="color: navy;">8</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">posY</span><span style="color: silver;"> </span>=<span style="color: #00677c;">rand</span>()<span style="color: silver;"> </span>%<span style="color: silver;"> </span><span style="color: navy;">8</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">posX</span>][<span style="color: #092e64;">posY</span>]==<span style="color: navy;">0</span>){</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">posX</span>][<span style="color: #092e64;">posY</span>]=<span style="color: navy;">10</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">Klingons</span>[<span style="color: #092e64;">i</span>].<span style="color: #00677c;">warp</span>(<span style="color: #092e64;">posX</span>,<span style="color: #092e64;">posY</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">i</span>++;</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">smallspace</span>::<span style="color: #00677c; font-weight: 600;">deployEnterprise</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">i</span>=<span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">posX</span>,<span style="color: silver;"> </span><span style="color: #092e64;">posY</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">srand</span>(<span style="color: olive;">static_cast</span><<span style="color: olive;">unsigned</span><span style="color: silver;"> </span><span style="color: olive;">int</span>>(<span style="color: #00677c;">time</span>(<span style="color: olive;">nullptr</span>)));</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">while</span><span style="color: silver;"> </span>(<span style="color: #092e64;">i</span><<span style="color: navy;">1</span>)<span style="color: silver;"> </span>{</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">posX</span><span style="color: silver;"> </span>=<span style="color: #00677c;">rand</span>()<span style="color: silver;"> </span>%<span style="color: silver;"> </span><span style="color: navy;">8</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">posY</span><span style="color: silver;"> </span>=<span style="color: #00677c;">rand</span>()<span style="color: silver;"> </span>%<span style="color: silver;"> </span><span style="color: navy;">8</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">posX</span>][<span style="color: #092e64;">posY</span>]==<span style="color: navy;">0</span>){</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">posX</span>][<span style="color: #092e64;">posY</span>]=<span style="color: navy;">1</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">Enterprise</span>.<span style="color: #00677c;">warp</span>(<span style="color: #092e64;">posX</span>,<span style="color: silver;"> </span><span style="color: #092e64;">posY</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">i</span>++;</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">smallspace</span>::<span style="color: #00677c; font-weight: 600;">displayMap</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">x</span>,<span style="color: silver;"> </span><span style="color: #092e64;">y</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"\n"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"</span><span style="color: silver;"> </span><span style="color: green;">1</span><span style="color: silver;"> </span><span style="color: green;">2</span><span style="color: silver;"> </span><span style="color: green;">3</span><span style="color: silver;"> </span><span style="color: green;">4</span><span style="color: silver;"> </span><span style="color: green;">5</span><span style="color: silver;"> </span><span style="color: green;">6</span><span style="color: silver;"> </span><span style="color: green;">7</span><span style="color: silver;"> </span><span style="color: green;">8</span><span style="color: silver;"> </span><span style="color: green;">\n"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: silver;"> </span>(<span style="color: #092e64;">y</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: #092e64;">y</span><<span style="color: navy;">8</span>;<span style="color: silver;"> </span><span style="color: #092e64;">y</span>++){</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span>(<span style="color: silver;"> </span><span style="color: green;">"%2d</span><span style="color: silver;"> </span><span style="color: green;">"</span>,<span style="color: silver;"> </span><span style="color: #092e64;">y</span>+<span style="color: navy;">1</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">for</span><span style="color: silver;"> </span>(<span style="color: #092e64;">x</span>=<span style="color: navy;">0</span>;<span style="color: silver;"> </span><span style="color: #092e64;">x</span><<span style="color: navy;">8</span>;<span style="color: silver;"> </span><span style="color: #092e64;">x</span>++){</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">x</span>][<span style="color: #092e64;">y</span>]==<span style="color: navy;">0</span>)<span style="color: silver;"> </span><span style="color: #00677c;">printf</span>(<span style="color: green;">"</span><span style="color: silver;"> </span><span style="color: green;">.</span><span style="color: silver;"> </span><span style="color: green;">"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">x</span>][<span style="color: #092e64;">y</span>]==<span style="color: navy;">100</span>)<span style="color: silver;"> </span><span style="color: #00677c;">printf</span>(<span style="color: green;">"</span><span style="color: silver;"> </span><span style="color: green;">*</span><span style="color: silver;"> </span><span style="color: green;">"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">x</span>][<span style="color: #092e64;">y</span>]==<span style="color: navy;">10</span><span style="color: silver;"> </span>)<span style="color: silver;"> </span><span style="color: #00677c;">printf</span>(<span style="color: green;">"</span><span style="color: silver;"> </span><span style="color: green;">K</span><span style="color: silver;"> </span><span style="color: green;">"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">x</span>][<span style="color: #092e64;">y</span>]==<span style="color: navy;">1</span><span style="color: silver;"> </span>)<span style="color: silver;"> </span><span style="color: #00677c;">printf</span>(<span style="color: green;">"</span><span style="color: silver;"> </span><span style="color: green;">E</span><span style="color: silver;"> </span><span style="color: green;">"</span>);</pre>
<pre><span style="color: silver;"> </span>};</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"\n"</span>);</pre>
<pre><span style="color: silver;"> </span>};</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"\n"</span>);</pre>
<pre>}</pre>
<br />
<pre></pre>
【ap_spaceship.cpp のソース】<br />
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_spaceship.h"</span></pre>
<pre></pre>
<pre><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">Spaceship</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">resetPosition</span>();</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">turnleft</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: maroon;">mD</span>-<span style="color: navy;">90</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mD</span><span style="color: silver;"> </span><<span style="color: silver;"> </span><span style="color: navy;">0</span>)<span style="color: silver;"> </span><span style="color: maroon;">mD</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: maroon;">mD</span>+<span style="color: navy;">360</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">turnright</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: maroon;">mD</span>+<span style="color: navy;">90</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mD</span>><span style="color: navy;">360</span>)<span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: maroon;">mD</span>-<span style="color: navy;">360</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">forward</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">distanse</span>)</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mD</span>==<span style="color: navy;">0</span>)<span style="color: silver;"> </span><span style="color: maroon;">mY</span>=<span style="color: maroon;">mY</span>-<span style="color: #092e64;">distanse</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mD</span>==<span style="color: navy;">180</span>)<span style="color: silver;"> </span><span style="color: maroon;">mY</span>=<span style="color: maroon;">mY</span>+<span style="color: #092e64;">distanse</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mD</span>==<span style="color: navy;">90</span>)<span style="color: silver;"> </span><span style="color: maroon;">mX</span>=<span style="color: maroon;">mX</span>+<span style="color: #092e64;">distanse</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mD</span>==<span style="color: navy;">270</span>)<span style="color: silver;"> </span><span style="color: maroon;">mX</span>=<span style="color: maroon;">mX</span>-<span style="color: #092e64;">distanse</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">getXPosition</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">mX</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">getYPosition</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">mY</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">getDiraction</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">mD</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">setDiraction</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">d</span>)</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">switch</span><span style="color: silver;"> </span>(<span style="color: #092e64;">d</span>)<span style="color: silver;"> </span>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">0</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">break</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">90</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: navy;">90</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">break</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">180</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: navy;">180</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">break</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">270</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: navy;">270</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">break</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">default</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">break</span>;</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">resetPosition</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mX</span>=<span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mY</span>=<span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mD</span>=<span style="color: navy;">0</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span>::<span style="color: #00677c; font-weight: 600;">warp</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">x</span>,<span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">y</span>)</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">resetPosition</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">turnright</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">forward</span>(<span style="color: #092e64;">x</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">turnright</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">forward</span>(<span style="color: #092e64;">y</span>);</pre>
<pre>}</pre>
<pre></pre>
【ap_stertrekgame.cpp のソース】<br />
<br />
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_startrekgame.h"</span></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_smallspace.h"</span></pre>
<pre></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><<span style="color: green;">stdio</span>.<span style="color: green;">h</span>></pre>
<pre></pre>
<pre><span style="color: purple;">startrekgame</span>::<span style="color: #00677c; font-weight: 600;">startrekgame</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">smallspace</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">initStarTrekGame</span>();</pre>
<pre>}</pre>
<pre></pre>
<pre></pre>
<pre><span style="color: purple;">startrekgame</span>::~<span style="color: #00677c; font-weight: 600;">startrekgame</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">startrekgame</span>::<span style="color: #00677c; font-weight: 600;">initStarTrekGame</span>()</pre>
<pre>{</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: #00677c;">deployKlingons</span>(<span style="color: navy;">0</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: #00677c;">deployPlanets</span>(<span style="color: navy;">0</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: #00677c;">deployEnterprise</span>();</pre>
<pre></pre>
<pre><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">printf</span><span style="color: silver;"> </span><span style="color: green;">("x1:%3d</span><span style="color: silver;"> </span><span style="color: green;">,</span><span style="color: silver;"> </span><span style="color: green;">y1:%3d\n",</span><span style="color: silver;"> </span><span style="color: green;">mSmallspace->Enterprise.getXPosition()+1,</span><span style="color: silver;"> </span><span style="color: green;">mSmallspace->Enterprise.getYPosition()+1);</span></pre>
<pre></pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">startrekgame</span>::<span style="color: #00677c; font-weight: 600;">displaySpaceMap</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: #00677c;">displayMap</span>();</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: purple;">startrekgame</span>::<span style="color: #00677c; font-weight: 600;">inputCommand</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mCommand</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">コマンドを入力</span></pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"COMMAND</span><span style="color: silver;"> </span><span style="color: green;">(-1:quit</span><span style="color: silver;"> </span><span style="color: green;">0:map</span><span style="color: silver;"> </span><span style="color: green;">1:move)</span><span style="color: silver;"> </span><span style="color: green;">?</span><span style="color: silver;"> </span><span style="color: green;">"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">scanf</span><span style="color: silver;"> </span>(<span style="color: green;">"%d"</span>,<span style="color: silver;"> </span>&<span style="color: maroon;">mCommand</span>);</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: maroon;">mCommand</span>;</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">startrekgame</span>::<span style="color: #00677c; font-weight: 600;">execCommand</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">switch</span><span style="color: silver;"> </span>(<span style="color: maroon;">mCommand</span>)<span style="color: silver;"> </span>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">0</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: #00677c;">displayMap</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">break</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">case</span><span style="color: silver;"> </span><span style="color: navy;">1</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">inputMoveFunction</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">break</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">default</span>:</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">break</span>;</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre>}</pre>
<pre></pre>
<pre><span style="color: olive;">void</span><span style="color: silver;"> </span><span style="color: purple;">startrekgame</span>::<span style="color: #00677c; font-weight: 600;">inputMoveFunction</span>()</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">distance</span>=<span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">direction</span>=<span style="color: navy;">0</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">x1</span>,<span style="color: silver;"> </span><span style="color: #092e64;">y1</span>,<span style="color: silver;"> </span><span style="color: #092e64;">x2</span>,<span style="color: silver;"> </span><span style="color: #092e64;">y2</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">Spaceship</span><span style="color: silver;"> </span><span style="color: #092e64;">tempSpaceship</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: maroon;">Enterprise</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">x1</span>=<span style="color: #092e64;">tempSpaceship</span>.<span style="color: #00677c;">getXPosition</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">y1</span>=<span style="color: #092e64;">tempSpaceship</span>.<span style="color: #00677c;">getYPosition</span>();</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"direction</span><span style="color: silver;"> </span><span style="color: green;">?</span><span style="color: silver;"> </span><span style="color: green;">"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">scanf</span><span style="color: silver;"> </span>(<span style="color: green;">"%d"</span>,<span style="color: silver;"> </span>&<span style="color: #092e64;">direction</span>);</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: #092e64;">direction</span>>=<span style="color: navy;">0</span><span style="color: silver;"> </span>&&<span style="color: silver;"> </span><span style="color: #092e64;">direction</span><<span style="color: navy;">360</span>){</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">tempSpaceship</span>.<span style="color: #00677c;">setDiraction</span>(<span style="color: #092e64;">direction</span>);</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"distance</span><span style="color: silver;"> </span><span style="color: green;">?</span><span style="color: silver;"> </span><span style="color: green;">"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">scanf</span><span style="color: silver;"> </span>(<span style="color: green;">"%d"</span>,<span style="color: silver;"> </span>&<span style="color: #092e64;">distance</span>);</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">x1</span>=<span style="color: #092e64;">tempSpaceship</span>.<span style="color: #00677c;">getXPosition</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">y1</span>=<span style="color: #092e64;">tempSpaceship</span>.<span style="color: #00677c;">getYPosition</span>();</pre>
<pre></pre>
<pre><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">printf</span><span style="color: silver;"> </span><span style="color: green;">("x1:%3d</span><span style="color: silver;"> </span><span style="color: green;">,</span><span style="color: silver;"> </span><span style="color: green;">y1:%3d</span><span style="color: silver;"> </span><span style="color: green;">\n",</span><span style="color: silver;"> </span><span style="color: green;">x1+1,</span><span style="color: silver;"> </span><span style="color: green;">y1+1);</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">tempSpaceship</span>.<span style="color: #00677c;">forward</span>(<span style="color: #092e64;">distance</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">x2</span>=<span style="color: #092e64;">tempSpaceship</span>.<span style="color: #00677c;">getXPosition</span>();</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">y2</span>=<span style="color: #092e64;">tempSpaceship</span>.<span style="color: #00677c;">getYPosition</span>();</pre>
<pre></pre>
<pre><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">printf</span><span style="color: silver;"> </span><span style="color: green;">("x2:%3d</span><span style="color: silver;"> </span><span style="color: green;">,</span><span style="color: silver;"> </span><span style="color: green;">y2:%3d\n",</span><span style="color: silver;"> </span><span style="color: green;">x2+1,</span><span style="color: silver;"> </span><span style="color: green;">y2+1);</span></pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: silver;"> </span>(<span style="color: #092e64;">x2</span><<span style="color: navy;">0</span>)<span style="color: silver;"> </span>||<span style="color: silver;"> </span>(<span style="color: #092e64;">x2</span>><span style="color: navy;">7</span><span style="color: silver;"> </span>)<span style="color: silver;"> </span>||<span style="color: silver;"> </span>(<span style="color: #092e64;">y2</span><<span style="color: navy;">0</span>)<span style="color: silver;"> </span>||<span style="color: silver;"> </span>(<span style="color: #092e64;">y2</span>><span style="color: navy;">7</span>)<span style="color: silver;"> </span>){</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"Out</span><span style="color: silver;"> </span><span style="color: green;">of</span><span style="color: silver;"> </span><span style="color: green;">range!\n\n"</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">return</span>;</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: maroon;">mSmallspace</span>-><span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">x2</span>][<span style="color: #092e64;">y2</span>]==<span style="color: navy;">0</span>){</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">x1</span>][<span style="color: #092e64;">y1</span>]-=<span style="color: navy;">1</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: maroon;">mSpaceMap</span>[<span style="color: #092e64;">x2</span>][<span style="color: #092e64;">y2</span>]+=<span style="color: navy;">1</span>;</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: maroon;">Enterprise</span>.<span style="color: #00677c;">setDiraction</span>(<span style="color: #092e64;">direction</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: maroon;">Enterprise</span>.<span style="color: #00677c;">forward</span>(<span style="color: #092e64;">distance</span>);</pre>
<pre><span style="color: silver;"> </span><span style="color: maroon;">mSmallspace</span>-><span style="color: #00677c;">displayMap</span>();</pre>
<pre><span style="color: silver;"> </span>}<span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span>{</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"Can</span><span style="color: silver;"> </span><span style="color: green;">not</span><span style="color: silver;"> </span><span style="color: green;">move!\n\n"</span>);</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre></pre>
<pre><span style="color: silver;"> </span>}<span style="color: silver;"> </span><span style="color: olive;">else</span><span style="color: silver;"> </span>{</pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"Input</span><span style="color: silver;"> </span><span style="color: green;">0-360!\n\n"</span>);</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre>}</pre>
<br />
<pre></pre>
【main.cpp のソース】<br />
<br />
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><<span style="color: green;">QCoreApplication</span>></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_spaceship.h"</span></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_smallspace.h"</span></pre>
<pre>#<span style="color: navy;">include</span><span style="color: silver;"> </span><span style="color: green;">"ap_startrekgame.h"</span></pre>
<pre></pre>
<pre><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #00677c; font-weight: 600;">main</span>(<span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">argc</span>,<span style="color: silver;"> </span><span style="color: olive;">char</span><span style="color: silver;"> </span>*<span style="color: #092e64;">argv</span>[])</pre>
<pre>{</pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">QCoreApplication</span><span style="color: silver;"> </span><span style="color: #092e64;">app</span>(<span style="color: #092e64; font-style: italic;">argc</span>,<span style="color: silver;"> </span><span style="color: #092e64;">argv</span>);</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ゲームを作成</span></pre>
<pre><span style="color: silver;"> </span><span style="color: purple;">startrekgame</span>*<span style="color: silver;"> </span><span style="color: #092e64;">startrekgameA</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: olive;">new</span><span style="color: silver;"> </span><span style="color: purple;">startrekgame</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">マップを表示</span></pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">startrekgameA</span>-><span style="color: #00677c;">displaySpaceMap</span>();</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">int</span><span style="color: silver;"> </span><span style="color: #092e64;">command</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: navy;">0</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">終了コマンドが入力されるまで繰り返し</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">while</span><span style="color: silver;"> </span>(<span style="color: #092e64;">command</span><span style="color: silver;"> </span>>=<span style="color: navy;">0</span><span style="color: silver;"> </span>){</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">コマンドを入力</span></pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">command</span><span style="color: silver;"> </span>=<span style="color: silver;"> </span><span style="color: #092e64;">startrekgameA</span>-><span style="color: #00677c;">inputCommand</span>();</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">コマンドを実行</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">if</span><span style="color: silver;"> </span>(<span style="color: #092e64;">command</span>>=<span style="color: navy;">0</span>){</pre>
<pre><span style="color: silver;"> </span><span style="color: #092e64;">startrekgameA</span>-><span style="color: #00677c;">execCommand</span>();</pre>
<pre><span style="color: silver;"> </span>}</pre>
<pre><span style="color: silver;"> </span>};</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ゲームを終了する</span></pre>
<pre><span style="color: silver;"> </span><span style="color: #00677c;">printf</span><span style="color: silver;"> </span>(<span style="color: green;">"\nGame</span><span style="color: silver;"> </span><span style="color: green;">End.\n"</span>);</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: green;">//</span><span style="color: silver;"> </span><span style="color: green;">ゲームを消去</span></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">delete</span><span style="color: silver;"> </span><span style="color: #092e64;">startrekgameA</span>;</pre>
<pre></pre>
<pre><span style="color: silver;"> </span><span style="color: olive;">return</span><span style="color: silver;"> </span><span style="color: #092e64;">app</span>.<span style="color: #00677c;">exec</span>();</pre>
<pre>}</pre>
<br />
<pre></pre>
前回 Turtleクラス を作成し,方向転換や前進できるようなクラスを作り,それを応用して スタートレックゲームの一部の部分を作ってみた。<br />
<br />
オブジェクト思考設計で大事なのは,なぜ,オブジェクト思考設計をするのかという目的を常に忘れないことだ。<br />
<br />
自分が楽になる,開発期間を短縮する,毎回一から作り直さない ようにするには,ソフトウェアの再利用が必ず必要となる。ただ,コピペするのではなく,作り直しをできるだけ少なくして,目的を達成するためにはどうすればよいかを考える。<br />
<br />
Qt は非常に便利だが,C++ やオブジェクト指向設計を理解していないと,なぜ,それができるのかが分からず,商品化まで到達するのは難しいと思う。<br />
<br />
次回は,リアル波形を表示するために必要なマルチスレッド処理をQtでやってみる。<br />
<br />
P.S.<br />
<br />
今回紹介した超簡易版スタートレックゲームの Qtプロジェクトを含むソースファイルを入手できるようにしました。<br />
<br />
【スタートレックゲームのソースファイルの入手方法】<br />
次のメールアドレスに件名:スタートレックソースファイル送信 と書いてメールをお送りください。(件名は”スタートレックソースファイル送信”でなければ返信されません。メール本文は何でも構いません。<br />
メールアドレス:CriticalSoftwareConsulting[あっとまーく]gmail.comsakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-36188372287740943872019-02-20T22:20:00.002+09:002019-02-20T22:20:35.823+09:00商品の顕在的な価値と潜在的価値<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm9TYpDT7XeINHaMy5xbVpOkp2GKfY6bMYxyAaMtkDm4_CFVGR40rqBdtNbXzqs8K_SsDZVmZcIvNAFiaSA82Vby-74V8JMaeUtSlRNy4K2N_LGV-KUeF046frvPLnMaOZofCU/s1600/Value.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="301" data-original-width="302" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm9TYpDT7XeINHaMy5xbVpOkp2GKfY6bMYxyAaMtkDm4_CFVGR40rqBdtNbXzqs8K_SsDZVmZcIvNAFiaSA82Vby-74V8JMaeUtSlRNy4K2N_LGV-KUeF046frvPLnMaOZofCU/s200/Value.png" width="200" /></a></div>
商品の価値を表すのにいつもこの図を使っている。表に見えている顕在的な価値はカタログやCMなどで強調され,商品の機能や性能としてアピールされる。<br />
<br />
一方で潜在的な価値は水の下で見えないのだが,ここが脆弱だと風が吹いただけでひっくり返ってしまう。<br />
<br />
第8回 組込みシステム開発技術展(ESEC) 2005年6月29日~7月1日 専門セミナー で 「高信頼性を確保するソフトウェア開発手法と実践」というテーマでプレゼンをした。もう,14年も前の話だ。でも,今一度中身を見直してみたが,そう陳腐化していないように思う。<a href="https://www.slideshare.net/xxsakai/ss-131547905" target="_blank">SlideShare にアップ</a>したので興味のある方はご覧下さい。<br />
<br />
さて,組織の中で商品の潜在的価値が重要だ!と叫ぶことはできるが,多くの組織では顕在的な価値の向上が優先される。それは何事もなければ,売り上げに直接貢献するのは顕在的な価値だからだ。<br />
<br />
潜在的な価値は,インシデント(事件)が発生したときに「大変だ!」と気が付く。<br />
<br />
潜在的な価値を高める技術も,歴史的に見ればインシデントが発生した後に前進している。FTAは1961年にアメリカで開発されたミニットマンミサイルの信頼性評価・安全性解析を目的として、その協力先であるベル研究所のH・A・ワトソンのグループが考案し、その後ボーイング(BOEING)社により完成された。(<a href="https://embeddedsoftwaremanufactory.blogspot.com/2012/10/iso-26262-14-ftafmea.html" target="_blank">こちらを参照のこと</a>)<br />
<br />
FMEAは1940年代にアメリカ陸軍が開発,採用した。STAMP/STPA を2012年に発表したマサチューセッツ工科大学(MIT) 教授のナンシー・レブソン(Nancy Leveson)が有名になったのは,放射線機器 Thearc-25 の事故と,スペースシャトル チャレンジャーの事故の調査分析の実績が認められたからだ。<br />
<br />
残念ながら,潜在的価値を向上させる技術は,その業界でインシデントやアクシデントが発生して,ニュースとして共有されないと振り向かれない。<br />
<br />
発生したインシデントやアクシデントの再発を防止しようという意思,モチベーションが高まり,かつ,リソース(人,物,金)が組織から投入されたときに初めて,潜在的価値を向上させる技術が発展する。<br />
<br />
別な角度で言えば,インシデントやアクシデントが発生しないと,どんなに潜在的価値を向上させる技術を説いても響かない。<br />
<br />
ソフトウェア品質についてもそうだが、サイバーセキュリティも、何事か事件が起きないと、組織はリソースを投入しようとはしないことが多い。<br />
<br />
最近は,そういうもんだとあきらめている。sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-82520570089620971072018-12-27T09:44:00.002+09:002018-12-27T09:49:59.989+09:00ヘルスケアドメインの最新技術動向をゲットするセミナー開催(2019年2月20日:東京代々木にて)JIETA ヘルスケアインダストリ部会/医療用ソフトウェア専門委員会が 2019日2月20日に東京代々木の国立オリンピック記念青少年総合センターにて,「医療機器ソフトウェアの最新技術動向セミナー」を開催します。募集定員は300名です。<br />
<br />
ヘルスケアドメインに新規参入を検討している企業や,クリティカルソフトウェアのリスベースアプローチの実際について知りたい方に参考になると思います。医療機器業界では,現在「リスクマネジメント」「ユーザビリティ(使いやすさというよりは,有効性を高め,危険状態になりにくい機器の使い方)」「サイバーセキュリティリスクマネジメント」などについて規制要求があり,本セミナーでそれらの最新情報をゲットできるような内容となっています。<br />
<br />
ヘルスアプリや遠隔医療,介護ロボットなど,さまざまな新サービスが世の中に出てきていますが,その延長線上には規制対象の医療機器になるかもしれないという未来があると思います。そうなる前に,現状で医療機器ソフトウェアにどんな要求が求められているのかを知っておくことは重要です。<br />
<br />
下記,主催の <a href="https://home.jeita.or.jp/cgi-bin/page/detail.cgi?n=1100&ca=570&fbclid=IwAR0pIjyu9GOO69zIVPQQdZ_4HWJ6oaArJa6ZBUg233I5OV5e-xFvzW9aMi4" target="_blank">JEITA ヘルスケアインダストリ部会のページ</a>より転載します。<br />
<br />
<h2 style="background-color: white; color: #333333; font-family: "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", メイリオ, Meiryo, "MS Pゴシック", sans-serif; font-size: 24px; line-height: 1.6; margin: 0px 0px 1em; padding: 0px;">
医療機器ソフトウェアの最新技術動向セミナー(2019/2/20)</h2>
<div class="section" style="background-color: white; clear: both; color: #333333; font-family: "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", メイリオ, Meiryo, "MS Pゴシック", sans-serif; font-size: 12.8px; margin: 0px 0px 1em; padding: 0px; zoom: 1;">
<div style="line-height: 1.6; margin-bottom: 1em; padding: 0px;">
</div>
<table align="CENTER" border="0" style="border-collapse: collapse; border-spacing: 0px; width: 600px;"><tbody>
<tr><td style="line-height: 1.6; margin: 0px; padding: 0px;"><center>
<table cellpadding="0" cellspacing="0" style="border-collapse: collapse; border-spacing: 0px; border: 2px solid rgb(95, 127, 255);"><tbody>
<tr><td bgcolor="#5f7fff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#6f8fff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#7f9fff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#8fafff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#9fbfff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#afcfff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#bfdfff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#cfefff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#ffffff" style="line-height: 1.6; margin: 0px; padding: 0px;"><br />
<div style="margin: 0px; padding: 6px; zoom: 1;">
<span style="color: #333333; font-size: large;"><b>医療機器ソフトウェアの最新技術動向セミナー</b></span><b><br /><br /><span style="color: #333333; font-size: medium;">〜セキュリティ・ユーザビリティ・リスクマネジメント〜</span></b><br />
<br />
<span style="color: #333333; font-size: small;"><b>日時:2019年2月20日(水) 10:00〜16:00 (受付開始 9:30〜)<br />会場:国立オリンピック記念青少年総合センター カルチャー棟 小ホール<br /><small>(東京都渋谷区代々木神園町3-1)</small></b></span></div>
</td></tr>
<tr><td bgcolor="#cfefff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#bfdfff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#afcfff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#9fbfff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#8fafff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#7f9fff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#6f8fff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
<tr><td bgcolor="#5f7fff" height="2" style="line-height: 1.6; margin: 0px; padding: 0px;"></td></tr>
</tbody></table>
</center>
<br />
<br />
医療機器ソフトウェアを取り巻く環境は、急速に変化しつつあります。日本においても平成26年11月に医薬品医療機器法が施行され、医療機器ソフトウェアが「プログラム」として法規制の対象になり、平成29年11月24日まで経過措置となっていた最新の技術に基づく開発ライフサイクルの適用が始まりました。<br />
当セミナーでは、まず医療機器ソフトウェアに関連のある規格の最新動向を解説します。これは毎回のセミナーで行っているもので、毎年の変化、動向をいち早く掴めるようにしています。IEC 62304,IEC 82304-1,ISO 14971,IEC 80001シリーズ、さらに現在策定中の規格についても説明を行います。さらに医療機器の必須となるリスクマネジメントについては、ISO 14971の理解、考え方、そして実践に向けての対応について説明を行います。<br />
サイバーセキュリティ関連については、2015年4月厚生労働省より「医療機器におけるサイバーセキュリティの確保について」、続いて2018年7月には、「医療機器のサイバーセキュリティの確保に関するガイダンス」は発出されました。さらに2018年10月にはFDAより「Content of Premarket Submissions for Management of Cybersecurity in Medical Devices」のドラフトガイダンスが公開されました。近年より重要度が増している内容であり、当セミナーでもより時間をあて、説明を行います。当セミナーでは、初めての内容となるユーザビリティについてIEC 62366-1の理解と考え方と題して、説明を行います。また規格・ガイダンスは毎日のように公開、発出されており、これらを網羅することもなかなかできません。今まで当セミナーで取り上げたことない初めての試みとなりますが、「規格・ガイダンスとの上手なつきあいかた」と題して、我々が意識すべきことを説明させていただきます。<br />
医療機器に係わる企業の経営者、設計開発、海外法規・薬事、品質保証、安全管理、標準化、規格適合試験等の業務に従事される方はもちろんのこと、医療情報ベンダー、医療機器分野に新規参入する方々にも有益なセミナーになると考えております。<br />
皆様のご参加をお待ちしております。<br />
<br />
<br />
<hr />
<span style="color: #666666;"><b>■ プログラム ■</b></span><br />
<div align="right" style="margin: 0px; padding: 0px; zoom: 1;">
<b>司会・進行</b> 医療用ソフトウェア専門委員会 委員長 松元 恒一郎(日本光電工業株式会社)</div>
<table align="center" border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse; border-spacing: 0px; width: 600px;"><tbody>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;" width="90">10:00-10:10</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;" width="300"><b>開会挨拶</b><br />
医療用ソフトウェア専門委員会 幹事<br />
鹿妻 洋之(オムロンヘルスケア株式会社)</td></tr>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;">10:10-10:55</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;" width="300"><b>医療機器ソフトウェアを取り巻く規制の背景と標準化の最新動向<br />−IEC 62304,IEC 82304-1,ISO 14971,IEC 80001シリーズ−</b><br />
医療用ソフトウェア専門委員会 幹事<br />
中里 俊章(キヤノンメディカルシステムズ株式会社)</td></tr>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;">10:55-11:40</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;" width="300"><b>リスクマネジメント<br />−その理解と考え方,実践にむけて ISO 14971−</b><br />
医療用ソフトウェア専門委員会 委員<br />
飯島 直人(株式会社島津製作所)</td></tr>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;">11:40-12:40</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;">昼食</td></tr>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;">12:40-14:10</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;" width="300"><b>医療機器に必要なサイバーセキュリティ<br />−国内外その考え方,動向について 厚労省ガイダンス,MDS2−<br />−事例をあげて−</b><br />
医療用ソフトウェア専門委員会 幹事<br />
高橋 英成(オリンパス株式会社)<br />
酒井 由夫(日本光電工業株式会社)</td></tr>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;">14:10-14:25</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;">休憩(10分)</td></tr>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;">14:25-15:10</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;"><b>ユーザビリティ<br />−IEC 62366-1の理解と考え方−</b><br />
医療用ソフトウェア専門委員会 委員<br />
関水 英正(独立行政法人 医薬品医療機器総合機構)</td></tr>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;">15:10-15:45</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;"><b>規格・ガイダンスとの上手なつきあいかた</b><br />
医療用ソフトウェア専門委員会 委員<br />
前田 宗泰(日本アイ・ビー・エム株式会社)</td></tr>
<tr valign="top"><td bgcolor="#F5F5F5" style="line-height: 1.6; margin: 0px; padding: 0px;">15:45-16:00</td><td bgcolor="#FFFAFA" style="line-height: 1.6; margin: 0px; padding: 0px;" width="300"><b>閉会挨拶</b><br />
医療用ソフトウェア専門委員会 委員長<br />
松元 恒一郎(日本光電工業株式会社)</td></tr>
</tbody></table>
<small>※ 都合により、プログラム・講師が変更になる場合もございます。</small><br />
<span style="font-size: x-small;">主催:一般社団法人 電子情報技術産業協会(JEITA)/ヘルスケアインダストリ部会<br />企画・運営:医療用ソフトウェア専門委員会</span><br />
<hr />
<span style="color: navy;">【 日時 】</span><br />
2019年2月20日(水) 10:00〜16:00(受付開始 9:30〜)<br />
<span style="color: navy;">【 場所 】</span><br />
国立オリンピック記念青少年総合センター カルチャー棟 小ホール<br />
(東京都渋谷区代々木神園町3-1)(<a href="https://nyc.niye.go.jp/" style="color: #0066cc; cursor: pointer; line-height: 1.6; text-decoration-line: none;" target="_blank">公式WEB</a>)<br />
<small> 小田急電鉄小田原線「参宮橋駅」 ※徒歩約7分<br /> 東京メトロ千代田線「代々木公園駅」 ※4番出口より徒歩約10分</small><a href="https://nyc.niye.go.jp/train/" style="color: #0066cc; cursor: pointer; line-height: 1.6; text-decoration-line: none;" target="_blank">【地図はこちら】</a><br />
<span style="color: navy;">【 参加費 】</span><br />
JEITA会員:7,560円/一般:10,800円 (テキスト代・消費税含む)<br />
→ JEITA会員一覧 <a href="http://www.jeita.or.jp/cgi-bin/member/list.cgi" style="color: #0066cc; cursor: pointer; line-height: 1.6; text-decoration-line: none;" target="_blank">http://www.jeita.or.jp/cgi-bin/member/list.cgi</a><br />
<span style="color: navy;">【 定員 】</span><br />
300名 ※先着順とし定員に達し次第、締切りとさせていただきます。<br />
<span style="color: navy;">【 申込締切日 】</span><br />
<u>2019年2月18日(月)</u><span style="color: #666666; font-size: 12.8px;"><b>■ 申込要領 ■</b></span><br />
<table align="center" border="0" cellpadding="3" cellspacing="3" style="border-collapse: collapse; border-spacing: 0px; color: #333333; font-size: 12.8px; width: 600px;"><tbody>
<tr><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">(1)</td><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">下記の「受講申込フォーム」に必要事項をご記入の上、送信してください。<br />
(受付システムについては(株)ビズクリエイトのサービスを使用しているため、JEITA外部のサーバに移動します。)<br />
<center>
<table bgcolor="#e5ffcc" border="2" cellpadding="3" cellspacing="3" style="border-collapse: collapse; border-spacing: 0px; height: 80px; width: 420px;"><tbody>
<tr><td style="line-height: 1.6; margin: 0px; padding: 0px;"><center>
<b>[ <span style="font-size: small;"><a href="https://39auto.biz/jeita/touroku/190220.htm" style="color: #0066cc; cursor: pointer; line-height: 1.6; text-decoration-line: none;" target="_blank">受講申込み</a></span> ]</b></center>
</td></tr>
</tbody></table>
</center>
</td></tr>
<tr><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">(2)</td><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">お申込み内容の確認後、折り返し「参加申込完了メール」が送信されます。<u>メールをプリントアウトし、セミナー当日に会場受付へご提出ください。</u>(お持ちでない場合は、名刺を1枚頂戴いたします。)</td></tr>
<tr><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">(3)</td><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">受講料の「請求書」は<u>郵送</u>にてお申込者様宛にお送りいたします。金額・内容をご確認の上、ご入金をお願いいたします。<br />
☆ 受講料の振込手数料はお申込者様各位にてご負担願います。<br />
☆ 当日、現金の取り扱いは行いませんので、ご了承下さい。</td></tr>
<tr><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">(4)</td><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">ご登録後のキャンセル、参加費の払い戻しはお受けできませんので予めご了承ください。お申込者様が参加できない場合は、是非、代理の方のご参加をお願いいたします。</td></tr>
<tr><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">(5)</td><td style="line-height: 1.6; margin: 0px; padding: 0px;" valign="top">お申込みの締め切りは<u>2019年2月18日(水)</u>です。</td></tr>
</tbody></table>
<br style="color: #333333; font-size: 12.8px;" />
<span style="color: navy; font-size: 12.8px;">【 お問合せ先 】</span><br />
<span style="color: #333333; font-size: 12.8px;">一般社団法人 電子情報技術産業協会</span><br />
<span style="color: #333333; font-size: 12.8px;">IoT事業推進部 石川・遠藤</span><br />
<span style="color: #333333; font-size: 12.8px;">TEL : 03-6268-0003</span><br />
<span style="color: #333333; font-size: 12.8px;">〒100-0004 東京都千代田区大手町1-1-3 大手センタービル</span><u><br /></u></td></tr>
</tbody></table>
</div>
sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-41139184152528620062018-12-02T18:42:00.004+09:002018-12-05T10:24:34.626+09:00個別最適の時代は完全に終わった(ソフトウェア品質のパラダイムシフトについて考える)<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiePyAaYOWNBRlUIaQr03Il18Qv16OiP_Kp9-nlBVQqj0EheRIWmp_blNobD5h-pgNJh6UvdQPZJbQC0SKSzD7uJzuMkzrAw-1PwyXRn8xWQhykZHjQ7WABH_KpmAoCA-K1TA0j/s1600/%25E5%25B8%2582%25E8%25B2%25A9%25E5%25BE%258C%25E3%2581%25AE%25E8%2584%2586%25E5%25BC%25B1%25E6%2580%25A7%25E5%25AF%25BE%25E5%25BF%259C02.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="843" data-original-width="995" height="338" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiePyAaYOWNBRlUIaQr03Il18Qv16OiP_Kp9-nlBVQqj0EheRIWmp_blNobD5h-pgNJh6UvdQPZJbQC0SKSzD7uJzuMkzrAw-1PwyXRn8xWQhykZHjQ7WABH_KpmAoCA-K1TA0j/s400/%25E5%25B8%2582%25E8%25B2%25A9%25E5%25BE%258C%25E3%2581%25AE%25E8%2584%2586%25E5%25BC%25B1%25E6%2580%25A7%25E5%25AF%25BE%25E5%25BF%259C02.png" width="400" /></a></div>
サイバーセキュリティのことにクビを突っ込んでいると,ソフトウェア品質の概念が根底から変わったのではないかと感じる。<br />
<br />
今や製品にOTSソフトウェア(Off The Shelf Software: 即利用可能な商用ソフトウェア)やオープンソースのソフトウェアを使うのは当たり前になっている。<br />
<br />
組込みソフトウェアであっても何十万行にもなるソフトウェアにOTSを使わないケースはほとんどない。OSだってOTSだ。<br />
<br />
そして,OTSには長い間使っているとサイバーセキュリティ上の脆弱性が見つかる。ここでよく考えた欲しいのはセキュリティの脆弱性は,ソフトウェアのバグ(欠陥)なのかという点だ。<br />
<br />
脆弱性となった時点で修正が必要になるのだから,バグ(欠陥)と言えるかもしれないが,これまでソフトウェア品質の中で語られてきた決定論的原因故障(Systematic Failures) とは違うように思うのだ。<br />
<br />
<span style="background-color: #fefdfa; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 13px;"><b>Systematic Failures/Faults (決定論的原因故障/障害)</b></span><br />
<ul style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px; line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="border: none; margin: 0px 0px 0.25em; padding: 0.25em 0px;">ハードウェアの設計に起因するもの、ソフトウェアのバグやソフトウェアに起因する問題やユーザーオペレーションが原因で発生する障害発生率の予測が難しい故障/障害</li>
</ul>
<ul style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px; line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="border: none; margin: 0px 0px 0.25em; padding: 0.25em 0px;">出荷前の検査で発見することが難しく、出荷後に故障や障害が発生してから始めて分かることが多い。</li>
</ul>
<ul style="background-color: #fefdfa; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13px; line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="border: none; margin: 0px 0px 0.25em; padding: 0.25em 0px;">開発のプロセス(工程)、ライフサイクルの中で Systematic Failures/Faults の作り込みを防止し、検証や妥当正確認によって発見・除去する。</li>
</ul>
上記が決定論的原因故障(Systematic Failures) の定義となるが,脆弱性はソフトウェアに起因する問題ではあるがユーザーオペレーションが原因で発生するわけではない。出荷前の検査で発見することは難しく,出荷後に発生してから分かることが多いというのはそのとおりだが,検証や妥当性確認によって発見,除去できないものもある。<br />
<br />
なぜなら,脆弱性は悪意を持ったハッカーが意図的にソフトウェアの穴を見つけて,そこを攻撃し,<span style="color: blue;">その悪用が成功すると,そこが脆弱性になるからだ。</span>ようするに,仕様通りに作った設計通りのソフトウェアであっても,<span style="color: blue;">悪意をもったハッカーにより「正しく作ったソフトウェア」でも「脆弱性」にされてしまうことがある</span>ということだ。<br />
<br />
設計通りに作ったソフトウェアでも後々「脆弱性=欠陥」となってしまうのって,ソフトウェア品質を考える上でのパラダイムシフトではないかと思うのだ。どんなに頑張って信頼性を高めようとしても,ソフトウェアに穴を見つけようとするハッカーがいるかぎり「脆弱性=欠陥」は発生してしまう。これはソフトウェアに完成というゴールは存在しないということを意味する。<br />
<br />
組込み機器がIoTの流れに乗って,ネットワークにつながるようになると,ネットワーク越しに脆弱性を攻撃される危険にさらされる。世界の中にいる一流のハッカーやあるいは,各国の軍事組織が意図的に作成したマルウェアは,コピーできたり自分自身が増殖したりできるので,IoT機器がインターネットに接続されていれば,そのソフトウェアが市場に存在し続ける限り,脆弱性=欠陥が発生するリスクがある。リスクが発生する確率は確率論で測ることはできない。ハッカーが攻撃したいと思うかどうかだ。<br />
<br />
例えば,ハッカーがその製品の企業に気にくわない対応をされたのかもしれない。有名な企業やセキュリティがが高いとされている企業の鼻っぱしを折ってやろうという気になったのかもしれない。セキュリティインシデントを発生させて,わざと株価を低下させようと企んだのかもしれない。ようするに,悪用の可能性(Exploitability)は従来の確率(Probability)や起こりやすさ(Likelihood)の概念では測りきれないのだ。<br />
<br />
米国FDA(食品医薬品局)は,2018年10月に<a href="https://www.fda.gov/downloads/MedicalDevices/DeviceRegulationandGuidance/GuidanceDocuments/UCM623529.pdf" target="_blank">医療機器の市販前のサイバーセキュリティに関するドラフトガイダンス</a>を改訂して,医療機器に搭載されているCBOM(Cybersecurity Bills of Materials)のリストを提供することを求めている。サイバーセキュリティの脆弱性を監視する必要があるソフトウェアやハードウェアを搭載しているならば,それをリストにして提出せよと言っている。<br />
<br />
そしてCBOMは NIST の<a href="https://nvd.nist.gov/" target="_blank">NDB(NATIONAL VULNERABILITY DATABASE)</a>と相互参照することを求めている。<br />
<br />
NDBは過去の脆弱性の報告があったソフトウェアやハードウェアが全てデータベース化されている。そこに載っているハードウェアやソフトウェアを使っているならば,それをリストにして提出しなさいと言っている。<br />
<br />
そして,市販後の新たな脆弱性が見つかったら,脆弱性を含むOTSを搭載する該当製品に対してパッチを当てるように勧告するのだろう。<br />
<br />
ようするに,IoT機器のソフトウェアは,クリティカルなソフトウェアに限らず市販前に完成度の高いソフトウェアを作ってリリースしたら終わりにはならないのだ。これまでも,仕様変更やバグが見つかったら,ソフトウェアの改変を行っていたかもしれないが,仮に市販前に仕様通り作った完璧と思ってリリースしたソフトウェアであっても,製品が市場にある限りサイバーセキュリティの対応が終わらないということになってきた。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm9TYpDT7XeINHaMy5xbVpOkp2GKfY6bMYxyAaMtkDm4_CFVGR40rqBdtNbXzqs8K_SsDZVmZcIvNAFiaSA82Vby-74V8JMaeUtSlRNy4K2N_LGV-KUeF046frvPLnMaOZofCU/s1600/Value.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="301" data-original-width="302" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm9TYpDT7XeINHaMy5xbVpOkp2GKfY6bMYxyAaMtkDm4_CFVGR40rqBdtNbXzqs8K_SsDZVmZcIvNAFiaSA82Vby-74V8JMaeUtSlRNy4K2N_LGV-KUeF046frvPLnMaOZofCU/s200/Value.png" width="200" /></a></div>
サイバーセキュリティは商品の価値としては潜在的な価値に分類される。潜在的な価値は,カタログスペックには出てこないが,セキュリティインシデントが発生することで,その潜在的価値がクローズアップされる。<br />
<br />
サイバーセキュリティの堅牢性は当たり前品質であるとも言える。ユーザーにとってはできていて当たり前だが,普通に使ってるぶんにはその価値は見えてこない。セキュリティインシデントが発生したときにはじめて,その価値の重要性に気が付く。製造業者側としては,事前に仕込んでおかないといけない価値となる。<br />
<br />
メーカーとしては,そこにコストをかけたくないところだが,セキュリティインデントが発生すると,著しく企業価値が下がり,ダメージが大きいので対処しない訳にはいかない。難しいのは,セキュリティ対策には終わりがないので,どこまでやればいいかの線引きが非常に難しいのだ。だから,市販前の考え方としては,クリティカルな製品においては,セキュリティインシデントが発生したときのユーザーのリスクが許容できるかどうかで判断し,また,過去に発生したセキュリティインシデントが再発しないような対策を積み重ねていく。そして,その対応をしたからといって,製品をリリースして終わりではないという認識を持ってセキュリティに対応する。<br />
<br />
ユーザーにとってIoT時代はいろいろと便利なサービスが提供されるという点ではいいのだが,メーカーはその裏でサイバーセキュリティ対策をしないといけない。最終的にはそのコストはユーザーが負うことになる。ユーザーは便利の裏側でセキュリティのコストを払うことになるのだ。どこまでコストをかければいいのかはメーカーが判断しなければいけない。日々コストと戦っている製造業者には頭の痛い問題だ。しかも,ソフトウェアのバグの発見とはまた別の意味で,悪用の確率を予測しにくい「やから」が相手ときている。<br />
<br />
さて,ソフトウェア品質の話に戻ろう。これまでソフトウェアの品質の議論は,主にリリース前までにいかにバグを潰すかという論点で進んで来たが,今後は市販後も含めたソフトウェアのライフサイクル全体を考えなければいけなくなってきた。<br />
<br />
悪意を持ったハッカーはどんなに完成度が高いソフトウェアであっても(わざわざ,堅牢なソフトウェアの穴を見つけようとはしないだろうが)穴を見つけ出そうとする。そこには悪意があるから防ぎようがない。オープンソースのソフトウェアは便利だからみんな使っているが,脆弱性との戦いは一生終わらないと思った方がいいだろう。ソースコードをオープンにして脆弱性を見つけてくださいと言っているのと同じだからしょうがない。ハッカーがその気になるかならないかは,ハッカーの気分次第なのだ。ちなみに,悪意を持ったハッカーではない,善意のハッカーと称する者は,わざわざソフトウェアの穴となりうる脆弱性を見つけてセキュリティインシデントを発生させてみて「この商品は危ないですよ」とデモンストレーションして,多くの人の注目を浴びたいため?に脆弱性をわざわざ指摘してくれる。(脆弱性を見つけた時点で公表する前にOTSの製造業者にお知らせしてくれるが,製造業者としては脆弱性を見つけてくれない方がうれしいと思うのは自分だけだろうか?)<br />
<br />
自動車業界はサイバーセキュリティを多層防御で乗りきろうとしているかもしれない。しかし,本当にそれで乗りきれるだろうか。車載ソフトウェアでもどこかでOTSやオーブンソースのソフトウェアは使われているだろう。ナビゲーションシステムやAIのソフトウェアだって使うかもしれない。ナビゲーションシステムは自動車の制御ソフトウェアとつながるようになるかも知れない。そして,ナビゲーションシステムのソフトウェアに脆弱性が見つかってしまったらどうするのだろうか。脆弱性があっても多層防御しているから大丈夫ですと言い切るのだろうか。<br />
<br />
ソフトウェアの場合,弱いところがあることが分かってしまうと,どんなに発生確率が低いと説明しても「直せるのなら直せ」と言われ,直さざるを得ない宿命がある。だから,脆弱性が見つかったら,パッチを当てるしかないのだ。そのためには,ソフトウェアを安全にアップデートするしくみが必要になり,アップデートすることを前提にしてソフトウェアをリリースすることになる。<br />
<br />
このことは,「ソフトウェア製品はリリース時に完成しない」時代になったということではないか。リリース時にバグはないかもしれないが,潜在的な脆弱性や未来に脆弱性となってしまうソフトウェアが含まれている状態で出荷せざるを得ないのだ。<br />
<br />
このサイバーセキュリティを起因としたパラダイムシフトは,企業のソフトウェア開発の体制にも影響を与える。OTSの脆弱性を監視し,脆弱性が見つかったら対応するための組織 PCERT(Product Computer Emergency Response Team)が必要になる。<br />
<br />
そして,ソフトウェア品質はソフトウェア部品の信頼性を高めて,それを組み上げるといったアプローチの有効性が低下し,個別最適から全体最適の時代に完全に切り替わったのだと思う。<br />
<br />
ようするに,製品のリリース時点では,サイバーセキュリティの脆弱性は発生するという前提で市販後の対応をする必要があり,商品のリリース時には,対ユーザーリスクをなくすことはできないので,できるだけ小さくすることを考えることが必要になったのである。<br />
<br />
これはソフトウェアのテストについても同じことが言える。仕様通りに作っても脆弱性となってしまうケースがある以上,テストがソフトウェアの完成度を確認する手段なら,製品リリース時に完全なテストは実施できないことになる。ソフトウェアは一生完成しないという前提に立てば,完全なテストも存在しないと言えないか。完全なテストを行うことを目指すのではなく,ユーザーリスクが最小になるようなテスト,検証,バリデーションを設計しないといけない。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs9A75YugQiGE3IBk48KEvCJ_jkC7mQCkUhFtCw4E6vEadcUvSBIZFX8r4zqvsW05rFH-Luqew_HCDIq989xFCp9Xm5-Rb0SCNkTFdjGp6QRHg5Bovqc4mqo4RCIeqGbAcK9yC/s1600/%25E3%2582%25BB%25E3%2583%25BC%25E3%2583%2595%25E3%2583%2586%25E3%2582%25A3%25E3%2582%25A2%25E3%2583%25BC%25E3%2582%25AD%25E3%2583%2586%25E3%2582%25AF%25E3%2583%2581%25E3%2583%25A3.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="640" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs9A75YugQiGE3IBk48KEvCJ_jkC7mQCkUhFtCw4E6vEadcUvSBIZFX8r4zqvsW05rFH-Luqew_HCDIq989xFCp9Xm5-Rb0SCNkTFdjGp6QRHg5Bovqc4mqo4RCIeqGbAcK9yC/s320/%25E3%2582%25BB%25E3%2583%25BC%25E3%2583%2595%25E3%2583%2586%25E3%2582%25A3%25E3%2582%25A2%25E3%2583%25BC%25E3%2582%25AD%25E3%2583%2586%25E3%2582%25AF%25E3%2583%2581%25E3%2583%25A3.gif" width="320" /></a></div>
ソフトウェア開発のおいて,また,ソフトウェア品質向上施策において,ソフトウェア部品の信頼性やセキュリティを個別に高めて結合すれば,システムも安全で,高品質でセキュアであるという時代ではなくなった。<br />
<br />
ユーザーに対して商品に責任を持つ組織が,全体最適として商品の安全性や信頼性やセキュリティのリスクを最小限にする方策を考え実施し,そして商品が市場にある限り,ライフサイクル全体でOTSの脆弱性対応を含めたサービスを提供することが必要になってきた。<br />
<br />
工場で製品作って出荷することが製造業者のゴールではなくなったということだ。そして,そのサービスのコストが最終的には便利と引き換えにエンドユーザーが負うことになる。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAP6Vj12w0-76xA13KfYsXd13S1NH4Tp8CzDVHG73vBXAWS1ZwbUj-MMYY9jY0s2DCuwp9STUxJfgp-3NDg1U25Uvr3Wq0YFBNDRGoD9aJeuA31Lqtm_F8luiMMqZpAxhgVUbh/s1600/%25E5%25B8%2582%25E8%25B2%25A9%25E5%2589%258D%25E5%25B8%2582%25E8%25B2%25A9%25E5%25BE%258C%25E3%2581%25AE%25E5%25AF%25BE%25E5%25BF%259C03C.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="696" data-original-width="1600" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAP6Vj12w0-76xA13KfYsXd13S1NH4Tp8CzDVHG73vBXAWS1ZwbUj-MMYY9jY0s2DCuwp9STUxJfgp-3NDg1U25Uvr3Wq0YFBNDRGoD9aJeuA31Lqtm_F8luiMMqZpAxhgVUbh/s400/%25E5%25B8%2582%25E8%25B2%25A9%25E5%2589%258D%25E5%25B8%2582%25E8%25B2%25A9%25E5%25BE%258C%25E3%2581%25AE%25E5%25AF%25BE%25E5%25BF%259C03C.png" width="400" /></a></div>
<br />sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0tag:blogger.com,1999:blog-19350560.post-63332979124843116562018-11-28T17:32:00.002+09:002018-11-30T09:35:20.328+09:00情報系の論文投稿はもううんざりソフトウェアテストシンポジウム2019東京(JaSST'19 Tokyo)に共同執筆者として経験論文を投稿し採用された。<br />
<br />
採用されたのは大変ありがたいことだ。素直に感謝したい。<br />
<br />
シンポジウムは2019年3月27日(水)~28日(木)に開催予定なので,論文はリアルタイムOSのテストの関することで,論文の詳しい内容については触れられないが,毎度のことながら査読コメントにはげっそりさせられる。<br />
<br />
誤字や内容についての指摘はありがたく指摘を受け入れたいのだが,論文の査読コメントはなぜ,匿名なのだろうか。それってなんで隠すのだろうっていつも思う。<strike>投稿者は名乗るのに,</strike> <span style="font-size: x-small;">※1</span> 査読者は匿名なのはなぜなのか。<br />
<br />
<span style="font-size: x-small;">※1 JaSST では査読時は投稿者が誰か知らされていないという指摘があったため訂正。</span><br />
<br />
査読者がもしも知り合いだったら失礼になるので変なこともかけないのだが,査読者が誰だか分からないから遠慮すべきかどうかもまったくわからない。だから,失礼かもしれないが,言いたいことを言ってしまおうと思う。<br />
<br />
査読者が匿名なのは,おそらく投稿者である下々の者が,偉い先生方に対してコメントに反論するなど,あり得ない。受け付けないというということなのだろう。<span style="font-size: x-small;">※2</span> でも,論文査読時のその上から目線が大っ嫌いだ。査読者がそういうつもりでなくても,査読のシステムがそうなっている。査読者は名乗らない,査読に対する意見は受け付けないというシステムなのだ。<br />
<br />
<span style="font-size: x-small;">※2 投稿者/査読者 ともに匿名にすることで公平性を担保する意図があるそうです。</span><br />
<br />
そして,いつも「フン」と思うのは,論文の作法に則っていないという指摘だ。「最初に他の研究の問題点や違いが述べられていない」とか「考察が先,結論が後」とか,「参照する他の論文をもっと掲載せよ」といったコメントは,ごもっともなのだろうが,本質的な話じゃないなと思う。<br />
<br />
例えば,論文の投稿者はその学会やシンポジウムに観客を呼び込むための大切なネタ元であると考える。そうすると,学会やシンポジウムの主催者や査読者は次もその次も気持ち良く論文を投稿してもらう必要がある。ならば,論文査読コメントは次のような書きぶりにしたらどうだろうか。<br />
<br />
【論文査読結果のお知らせ】<br />
<br />
この度は,○○学会に論文をご投稿いただき,まことにありがとうございます。投稿いただいた論文を拝読だせていただきました。<br />
△△に関する研究は貴重であり,たいへん興味深い内容です。□□の結果はソフトウェアのーーを向上させることのつながると思います。<br />
なお,ーーの部分については,さらにーーのような掘り下げを行えば,さらなる展開が見られるのではないかと思います。<br />
:<br />
非常に形式的な指摘で恐縮ですが,ーーの部分は,ーーのようにした方がより論文として説得力が高まると思われます。また,本論文と同じような研究があれば,読者の参考となるため,ーーのデータベースで関連する論文を検索して,参照論文として掲載してはいかがでしょうか。<br />
:<br />
<br />
○○学会にて,本研究のご発表をお待ちしております。また,ーー様の更なる研究と投稿をお待ちしております。<br />
<br />
【例示終わり】<span style="font-size: x-small;">※査読がコメントがこんな感じになることはあり得ないけど。</span><br />
<br />
ソフトウェアのレビューにレビューワとして参加するときは,できるだけ本質的なことを重点的にディスカッションし,形式的な問題はレビューが終わったあとにこっそり指摘したり,メールでお知らせしたりして,プロジェクトメンバのモチベーションが下がらないように気を遣ったりしている。<br />
<br />
それは,レビューではエンドユーザーに対する価値向上につなげるために指摘をするのあって,ルールやシステムへの逸脱を是正することが最終目的ではないからだ。ルールやシステムに従うことはあくまでも<span style="background-color: white;"><b><span style="color: blue;">間接的に</span></b></span>エンドユーザーに対する価値向上につながっているのだということをすっかり忘れるソフトウェアの品質保証担当もいる。ルールを守ることが目的になっているケースだ。そういう組織では現場のエンジニアはゲンナリしていたり,QAとは建て前で接して本音を言うのはやめようと諦めてしまったりしている。<br />
<br />
だから,問題を解決したい,改善したい,世の中のためになりたいと思って論文という書き物をしているのに,形式的な指摘はイラッとすることがある。<br />
<br />
だから,自分は論文書いて査読コメントを受ける度に,論文ではなく本で勝負したいと思う。自分はアカデミアにはなれない,ならない思う。論文で偉い先生方に評価されるより,本で「役に立った」という評価を受ける方が100倍うれしい。<br />
<blockquote class="tr_bq">
アカデミアが学生を育てて教え子が社会に貢献するようになるのは,すごくやり甲斐があると思う・・・</blockquote>
ちなみに,アカデミアが論文に関して新規性や作法に関する指摘をする理由を知っている。学位を取るためには,学会で論文を採用されることが必要であり,論文採用の条件として過去の論文との違いや新規性が求められるからだ。<br />
<br />
でも,ソフトウェアの品質向上に関する分野で,役に立つか立たないかをさておき,新規性を最重要と見るのには,強い違和感を感じる。仮に,同じような研究や実証があったとしたって,それが現場の役に立つならいいじゃないかと思う。<br />
<br />
また,情報系のアカデミアが数学的に検証可能な論理が大好きなのも知っている。例えばフォーマルメソッドなどがその例だ。数式を使って論理の正しさを証明できると,いかにももっともらしい論文になるから,みんな好きなんだろう。<br />
<br />
でも,まってくれよと言いたい。ソフトウェアを作っているのはロボットじゃない人間だろって思う。人間の思考や振る舞いは数式で表すことができない。最近流行のAIだって,人間の脳神経系のしくみをシミュレートしているのだ。<br />
<br />
だから,情報系の論文はもっと心理学とか人間の行動学を取り入れていいはずだ。ソフトウェアのメトリックスで語りきれない部分に解決策があることも多い。<br />
<br />
GD3 コンサルティング代表/JMAC GD3 センター長 の吉村達彦はトヨタとGMはすでにどちらも90%以上の品質を実現できているが,GMがトヨタに数%勝てないのは「品質を心配する意識:Awareness : Worrying about Quality」の違いだと言った。詳しくは<a href="https://embeddedsoftwaremanufactory.blogspot.com/2008/10/usjapan.html" target="_blank">こちら</a>。<br />
<br />
「品質を心配する意識:Awareness : Worrying about Quality」はおそらく数値では表せない。でも,数値では表せないところを解明していかないと,最後の数%の品質は上がらないのではないか。そこをもっと研究しろよとアカデミアに言いたい。<br />
<br />
みなさんは「<a href="https://amzn.to/2SeyRc4" target="_blank">ソフトウェアエンジニアリング論文集 80's</a>」という本を読んだことがあるだどうか。<br />
<br />
これが,論文の形式に則った論文か?といったものばかりだ。超有名どころの論文だから許されるのか? いや,論文が主張するべきところが共感できるから,受け入れられているのではないか。<br />
<br />
最初に載っている論文はワインバーグの論文で,冒頭で宮本武蔵の五輪の書を紹介している。<br />
<br />
論文の書き出しはこうだ<br />
<br />
宮本武蔵は,五輪の書の中で次のように書いている。<br />
<blockquote class="tr_bq">
<span style="color: blue;">大きな所は見えやすし,ちいさき所は見えがたし,其子細大人数のことは即座にもとをりがたし,一人の事は心一つにてかわることはやきによつて,ちいさき所しる事得がたし。</span></blockquote>
<blockquote class="tr_bq">
<span style="color: blue;">「大きなところは見えやすく,小さいところは見えにくい。というのは,大人数でやることは急速に転換できないから容易に捕捉できるのに対し,個人のことはその人の心一つですぐ変化するから分かりにくい。」</span></blockquote>
ソフトウェア研究者の Barry Boehmは "Software Engineering Economics" の中で次のように書いている。<br />
<blockquote class="tr_bq">
<span style="color: blue;">へたくそな管理は,他のいかなる要因よりもソフトウェアのコストを急速に増大させる。<br /> :</span></blockquote>
ワインバーグだから許されるのかもしれないが,論文の作法はまったく無視している。この本に掲載されている論文はどれも「中身で勝負」という内容であるように思える。<br />
<br />
ソフトウェアの品質を向上させるためにメトリクスを取るというのもよくあるし,メトリクスに関する論文はよく見る。でも,ソフトウェアのメトリクスを取るにしても,それはプロジェクトメンバーがソフトウェアの品質を改善するためにメトリクスを取ろう!となれば,有効なデータとなるだろうが,いやいややらされている状態で有効なデータが取れないのではないか。<br />
<br />
それは,結局,ソフトウェアの品質問題はエンジニアという人の問題に帰着するからではないか。だから,数字だけを追っかけても改善するわけもなく,人の問題も同時に改善する気持ちがないと効果が上がらないのではないか。<br />
<br />
人の問題は数字にしにくいし,数学的論文にはならないから,人をテーマにした情報系の論文はほとんど見ない?が,それでは結局のところ,現場の改善にはつながらないのではと思う。<br />
<br />
P.S.<br />
人材の育成や現場の改善に尽力をつくしているアカデミアの方々には敬意を表します。<br />
アカデミアの友人もたくさんいるのでこの手の記事書くときには気を遣うなあ・・・sakaihttp://www.blogger.com/profile/13883404163009530229noreply@blogger.com0