2018-12-27

ヘルスケアドメインの最新技術動向をゲットするセミナー開催(2019年2月20日:東京代々木にて)

JIETA ヘルスケアインダストリ部会/医療用ソフトウェア専門委員会が 2019日2月20日に東京代々木の国立オリンピック記念青少年総合センターにて,「医療機器ソフトウェアの最新技術動向セミナー」を開催します。募集定員は300名です。

ヘルスケアドメインに新規参入を検討している企業や,クリティカルソフトウェアのリスベースアプローチの実際について知りたい方に参考になると思います。医療機器業界では,現在「リスクマネジメント」「ユーザビリティ(使いやすさというよりは,有効性を高め,危険状態になりにくい機器の使い方)」「サイバーセキュリティリスクマネジメント」などについて規制要求があり,本セミナーでそれらの最新情報をゲットできるような内容となっています。

ヘルスアプリや遠隔医療,介護ロボットなど,さまざまな新サービスが世の中に出てきていますが,その延長線上には規制対象の医療機器になるかもしれないという未来があると思います。そうなる前に,現状で医療機器ソフトウェアにどんな要求が求められているのかを知っておくことは重要です。

下記,主催の JEITA ヘルスケアインダストリ部会のページより転載します。

医療機器ソフトウェアの最新技術動向セミナー(2019/2/20)


医療機器ソフトウェアの最新技術動向セミナー

〜セキュリティ・ユーザビリティ・リスクマネジメント〜


日時:2019年2月20日(水) 10:00〜16:00 (受付開始 9:30〜)
会場:国立オリンピック記念青少年総合センター カルチャー棟 小ホール
(東京都渋谷区代々木神園町3-1)


 医療機器ソフトウェアを取り巻く環境は、急速に変化しつつあります。日本においても平成26年11月に医薬品医療機器法が施行され、医療機器ソフトウェアが「プログラム」として法規制の対象になり、平成29年11月24日まで経過措置となっていた最新の技術に基づく開発ライフサイクルの適用が始まりました。
 当セミナーでは、まず医療機器ソフトウェアに関連のある規格の最新動向を解説します。これは毎回のセミナーで行っているもので、毎年の変化、動向をいち早く掴めるようにしています。IEC 62304,IEC 82304-1,ISO 14971,IEC 80001シリーズ、さらに現在策定中の規格についても説明を行います。さらに医療機器の必須となるリスクマネジメントについては、ISO 14971の理解、考え方、そして実践に向けての対応について説明を行います。
 サイバーセキュリティ関連については、2015年4月厚生労働省より「医療機器におけるサイバーセキュリティの確保について」、続いて2018年7月には、「医療機器のサイバーセキュリティの確保に関するガイダンス」は発出されました。さらに2018年10月にはFDAより「Content of Premarket Submissions for Management of Cybersecurity in Medical Devices」のドラフトガイダンスが公開されました。近年より重要度が増している内容であり、当セミナーでもより時間をあて、説明を行います。当セミナーでは、初めての内容となるユーザビリティについてIEC 62366-1の理解と考え方と題して、説明を行います。また規格・ガイダンスは毎日のように公開、発出されており、これらを網羅することもなかなかできません。今まで当セミナーで取り上げたことない初めての試みとなりますが、「規格・ガイダンスとの上手なつきあいかた」と題して、我々が意識すべきことを説明させていただきます。
 医療機器に係わる企業の経営者、設計開発、海外法規・薬事、品質保証、安全管理、標準化、規格適合試験等の業務に従事される方はもちろんのこと、医療情報ベンダー、医療機器分野に新規参入する方々にも有益なセミナーになると考えております。
 皆様のご参加をお待ちしております。



■ プログラム ■
司会・進行 医療用ソフトウェア専門委員会 委員長 松元 恒一郎(日本光電工業株式会社)
10:00-10:10開会挨拶
 医療用ソフトウェア専門委員会 幹事
  鹿妻 洋之(オムロンヘルスケア株式会社)
10:10-10:55医療機器ソフトウェアを取り巻く規制の背景と標準化の最新動向
−IEC 62304,IEC 82304-1,ISO 14971,IEC 80001シリーズ−

 医療用ソフトウェア専門委員会 幹事
  中里 俊章(キヤノンメディカルシステムズ株式会社)
10:55-11:40リスクマネジメント
−その理解と考え方,実践にむけて ISO 14971−

 医療用ソフトウェア専門委員会 委員
  飯島 直人(株式会社島津製作所)
11:40-12:40昼食
12:40-14:10医療機器に必要なサイバーセキュリティ
−国内外その考え方,動向について 厚労省ガイダンス,MDS2−
−事例をあげて−

 医療用ソフトウェア専門委員会 幹事
  高橋 英成(オリンパス株式会社)
  酒井 由夫(日本光電工業株式会社)
14:10-14:25休憩(10分)
14:25-15:10ユーザビリティ
−IEC 62366-1の理解と考え方−

 医療用ソフトウェア専門委員会 委員
  関水 英正(独立行政法人 医薬品医療機器総合機構)
15:10-15:45規格・ガイダンスとの上手なつきあいかた
 医療用ソフトウェア専門委員会 委員
  前田 宗泰(日本アイ・ビー・エム株式会社)
15:45-16:00閉会挨拶
 医療用ソフトウェア専門委員会 委員長
  松元 恒一郎(日本光電工業株式会社)
※ 都合により、プログラム・講師が変更になる場合もございます。
主催:一般社団法人 電子情報技術産業協会(JEITA)/ヘルスケアインダストリ部会
企画・運営:医療用ソフトウェア専門委員会


【 日時 】
2019年2月20日(水) 10:00〜16:00(受付開始 9:30〜)
【 場所 】
国立オリンピック記念青少年総合センター カルチャー棟 小ホール
(東京都渋谷区代々木神園町3-1)(公式WEB
  小田急電鉄小田原線「参宮橋駅」 ※徒歩約7分
  東京メトロ千代田線「代々木公園駅」 ※4番出口より徒歩約10分
【地図はこちら】
【 参加費 】
JEITA会員:7,560円/一般:10,800円 (テキスト代・消費税含む)
 → JEITA会員一覧 http://www.jeita.or.jp/cgi-bin/member/list.cgi
【 定員 】
300名 ※先着順とし定員に達し次第、締切りとさせていただきます。
【 申込締切日 】
2019年2月18日(月)■ 申込要領 ■
(1)下記の「受講申込フォーム」に必要事項をご記入の上、送信してください。
(受付システムについては(株)ビズクリエイトのサービスを使用しているため、JEITA外部のサーバに移動します。)
受講申込み ]
(2)お申込み内容の確認後、折り返し「参加申込完了メール」が送信されます。メールをプリントアウトし、セミナー当日に会場受付へご提出ください。(お持ちでない場合は、名刺を1枚頂戴いたします。)
(3)受講料の「請求書」は郵送にてお申込者様宛にお送りいたします。金額・内容をご確認の上、ご入金をお願いいたします。
☆ 受講料の振込手数料はお申込者様各位にてご負担願います。
☆ 当日、現金の取り扱いは行いませんので、ご了承下さい。
(4)ご登録後のキャンセル、参加費の払い戻しはお受けできませんので予めご了承ください。お申込者様が参加できない場合は、是非、代理の方のご参加をお願いいたします。
(5)お申込みの締め切りは2019年2月18日(水)です。

【 お問合せ先 】
一般社団法人 電子情報技術産業協会
IoT事業推進部 石川・遠藤
TEL : 03-6268-0003
〒100-0004 東京都千代田区大手町1-1-3 大手センタービル

2018-12-02

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


2018-11-28

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

論文の書き出しはこうだ

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

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

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

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

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

2018-11-01

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1.2 方向

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






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

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

#ifndef AP_TURTLE_H
#define AP_TURTLE_H

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

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

#endif // AP_TURTLE_H

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

#include "ap_turtle.h"

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

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

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

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

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

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

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

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

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

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

    Turtle turtleA;
    Turtle turtleB;

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

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

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

    return a.exec();
}

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

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

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

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

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

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

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

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


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

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

2018-07-30

Raspberry Pi3を使ったリアル波形描画(3) Qt + QCustomPlot で静止グラフを描いてみる

Qt(キュート)とは何か。簡単に解説する。

【出典】
https://ja.wikipedia.org/wiki/Qt
https://www.sra.co.jp/qt/point/

Qt([kjuːt] キュート)とは、クロスプラットフォームアプリケーションフレームワークである。The Qt Company(英語版)とQt Project(英語版)によって開発されている。キュー・ティーと発音されることもあるが公式にはキュートである。
GUIツールキットとして広く知られているQtであるが、コンソールツールやサーバのような非GUIプログラムでも広く使用されている。

ライセンスには商用版とオープンソース版があり、現在のオープンソース版のライセンスはLGPLおよびGPLである。商用版を購入するとQt商用ライセンス(Qt Commercial License)でソフトウェアを開発することができる。LGPL版は、2009年3月にリリースされたQt 4.5から提供され始めた。これによりQtは営利企業にとってもより使いやすいライブラリーとなった。

QtはC++で開発されており、単独のソースコードによりX Window System(Linux、UNIX等)、Windows、macOS、組み込みシステムといった様々なプラットフォーム上で稼働するアプリケーションの開発が可能である。またコミュニティーにより多言語のバインディングが開発されており、JavaからQtを利用できるようにしたQt Jambi、さらにQtをRuby、Python、Perl、C#などから利用できるようにしたオープンソースのAPIが存在する。

このように開発が容易であり高速、スタイリッシュなQtはライセンスが多様なこともあり、KDEを始めとするオープンソースのアプリケーションに限らず、商業アプリケーションでの採用例も多く様々な分野で使用されている。

【開発元】
トロールテック (1991-2008)
ノキア (2008-2011)
ディジア(英語版) (2012-2014)
Qt Project(英語版) (2011-現在)

Qtを使用している主なソフトウェア

  • Autodesk Maya 2011 - 3DCGソフト
  • Avidemux - 動画編集ソフト
  • FreeCAD - CADソフト
  • Google Earth - 地球儀ソフト
  • KDE - デスクトップ環境
  • Muse - シーケンサ
  • MuseScore - 楽譜編集プログラム
  • Nuke - デジタル合成ソフト
  • ParaView - データ可視化ソフト
  • QGIS - GISソフト
  • Rosegarden - 楽譜編集プログラム
  • Skype - コミュニケーションソフト
  • モバイルWnn - 日本語入力システム
Google Earth や Skype が Qt で開発されていたとは知らなかった。

【Qt が開発効率を高める点】

  • Qt Creator を使うことで,GUI を直感的に設計することができる。(Visial Basic に似ている)
  • Qt Creator のテキストエディタが優れいて,必要なクラスやメソッドなどを予測入力(先頭の数文字入力すると候補を表示)してくれる。

Qt SIGNAL/SLOTの実践(値の連携)

Qt の重要な機能として SIGNAL/SLOT の機能がある。まずは、実際にどんなことができるのかやってみよう。

Qt Creator でQt ウィジェットアプリケーションのプロジェクトを作成する。





【下線部を入力する。】

#include "mainwindow.h"

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

    QSpinBox *spin = new QSpinBox();
    QDial *dial = new QDial();

    spin->setGeometry(200, 200, 100, 20);   // X座標,Y座標,横の長さ,縦の長さ
    dial->setGeometry(200, 300, 100,100);   // X座標,Y座標,横の長さ,縦の長さ

    spin->show();
    dial->show();

    return a.exec();
}

実行すると下記のように表示される。ダイアルとスピンボックス値は連動していない。


スピンボックスとダイアルの値を SIGNAL/SLOT で連携させる

下線部を追加する。スピンボックスの値が変化したら,ダイアルの値をセットし,ダイアルの値が変化したら,スピンボックスの値をセットするように,SIGNAL/SLOTをつなげる。

#include "mainwindow.h"

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

    QSpinBox *spin = new QSpinBox();
    QDial *dial = new QDial();

    QObject::connect(spin, SIGNAL(valueChanged(int)), dial, SLOT(setValue(int)));
    QObject::connect(dial, SIGNAL(valueChanged(int)), spin, SLOT(setValue(int)));

    spin->setGeometry(200, 200, 100, 20);   // X座標,Y座標,横の長さ,縦の長さ
    dial->setGeometry(200, 300, 100,100);   // X座標,Y座標,横の長さ,縦の長さ

    spin->show();
    dial->show();

    return a.exec();
}

これを実行すると,スピンボックスとダイアルが連動するようになる。
別々のオブジェクトが Qt の SIGNAL/SLOT のしくみでつながった例。

Qt のSIGNALとSLOTのしくみを理解する


SIGNALとSLOT
SIGNALとSLOTは、オブジェクト間の通信に使用されます。 SIGNALとSLOTのメカニズムはQtの中心的な機能であり、おそらく他のフレームワークが提供する機能と最も異なる部分です。 SIGNALとSLOTはQtのメタオブジェクトシステムによって可能になります。

前書き
GUIプログラミングでは、1つのウィジェットを変更すると、別のウィジェットに通知されることがよくあります。 より一般的には、あらゆる種類のオブジェクトがお互いに通信できるようにしたいと考えています。 たとえば、ユーザーが閉じるボタンをクリックすると、おそらくウィンドウのclose()関数が呼び出されます。

他のツールキットはコールバックを使用してこの種の通信を実現します。 コールバックは関数へのポインターなので、処理関数が何らかのイベントについて通知するようにするには、別の関数へのポインター(コールバック)を処理関数に渡します。 処理関数は、必要に応じてコールバックを呼び出します。 このメソッドを使用した正常なフレームワークは存在しますが、コールバックは直感的ではなく、コールバック引数の型の正確さを保証する上で問題が発生する可能性があります。

SIGNALとSLOT
Qtでは、コールバック手法の代わりにSIGNALとSLOTを使用します。 特定のイベントが発生すると、SIGNALが出力されます。 Qtのウィジェットにはあらかじめ定義されたSIGNALがたくさんありますが、ウィジェットをサブクラス化して独自のSIGNALを追加することができます。 SLOTは、特定のSIGNALに応答して呼び出される関数です。 Qtのウィジェットにはあらかじめ定義されたSLOTが多数ありますが、ウィジェットをサブクラス化して独自のSLOTを追加することで、関心のあるSIGNALを扱うことができます。


SIGNALと SLOTのメカニズムはタイプセーフです。SIGNALのシグネチャは、受信SLOTのシグネチャと一致する必要があります。 (実際には、余分な引数を無視することができるため、SIGNALは受け取ったSIGNALよりも短いシグネチャを持つ可能性があります)。シグネチャは互換性があるため、コンパイラは関数のポインタベースの構文を使用するときに型の不一致を検出するのに役立ちます。 文字列ベースのSIGNALおよびSLOT構文は、実行時に型の不一致を検出します。 SIGNALとSLOTは緩やかに結合されています。SIGNALを送信するクラスは、どのSLOTがSIGNALを受信するかを知らず、また気にもしません。 QtのSIGNALとSLOTの仕組みにより、SIGNALをSLOTに接続すると、適切なタイミングでSIGNALのパラメータでSLOTが呼び出されます。 SIGNALとSLOTは任意の種類の任意の数の引数を取ることができます。 彼らは完全にタイプセーフです。

QObjectまたはそのサブクラス(例えばQWidget )の1つを継承するすべてのクラスは、SIGNALとSLOTを含むことができます。 SIGNALは、他のオブジェクトにとって興味深い方法で状態を変更したときにオブジェクトによって放出されます。 これはすべてオブジェクトが通信するためのものです。 それは、何かがそれが放出するSIGNALを受信しているかどうかを知らない、または気にしない。 これは真の情報カプセル化であり、オブジェクトをソフトウェアコンポーネントとして使用できることを保証します。

SLOTはSIGNALを受信するために使用できますが、通常のメンバー機能でもあります。 オブジェクトがSIGNALを受信するかどうかをオブジェクトが知らないように、SLOTはSIGNALが接続されているかどうかを知りません。 これにより、本当に独立したコンポーネントをQtで作成できるようになります。

単一のSLOTに多くのSIGNALを接続することができ、SIGNALは必要な数のSLOTに接続することができます。 SIGNALを別のSIGNALに直接接続することも可能です。 (これは、最初のSIGNALが放射されるたびにすぐに2番目のSIGNALを放射します)。

SIGNALとSLOTが一緒になって、強力なコンポーネントプログラミングメカニズムを構成します。

SIGNAL
SIGNALは、オブジェクトの内部状態が何らかの方法で変化したときに、オブジェクトのクライアントまたは所有者にとって興味深い可能性のあるオブジェクトによって放出されます。 SIGNALはパブリック・アクセス関数であり、どこからでも送出することができますが、SIGNALとそのサブクラスを定義するクラスからのみ送出することをお勧めします。

SIGNALが放射されると、SIGNALに接続されたSLOTは通常、通常の関数呼び出しと同様にすぐに実行されます。 これが起こると、SIGNALとSLOTのメカニズムは、どのGUIイベントループからも完全に独立しています。 emit文に続くコードの実行は、すべてのSLOTが戻ったときに行われます。 キューに入れられた接続を使用する場合は、状況が少し異なります 。 そのような場合、 emitキーワードに続くコードは直ちに続き、SLOTは後で実行されます。

複数のSLOTが1つのSIGNALに接続されている場合、SIGNALが発信されたときに、接続されている順にSLOTが順次実行されます。

SIGNALはmocによって自動的に生成され、 .cppファイルに実装してはいけません。 彼らは決して戻り値の型を持つことはできません(つまりvoid使用しvoid )。

注記:私たちの経験によれば、SIGNALやSLOTは特別なタイプを使用しないと再利用可能です。 QScrollBar :: valueChanged ()が仮想QScrollBar :: Rangeなどの特殊な型を使用する場合、QScrollBar専用に設計されたSLOTにのみ接続できます。 異なる入力ウィジェットを一緒に接続することは不可能です。

SLOT
SLOTに接続されたSIGNALが放射されると、SLOTが呼び出されます。 SLOTは通常のC ++関数であり、通常呼び出すことができます。 その唯一の特殊な特徴は、SIGNALをそれらに接続できることです。

SLOTは通常のメンバ関数なので、直接呼び出されると通常のC ++の規則に従います。 しかし、SLOTとして、SIGNALSLOT接続を介して、アクセスレベルに関係なく、どのコンポーネントからでも呼び出すことができます。 これは、任意のクラスのインスタンスから発信されたSIGNALが、無関係のクラスのインスタンスでプライベートSLOTを呼び出させる可能性があることを意味します。

仮想SLOTを定義することもできますが、実際には非常に便利です。

コールバックと比較して、SIGNALとSLOTは、柔軟性が向上しているため、わずかに遅くなりますが、実際のアプリケーションの違いは重要ではありません。 一般に、いくつかのSLOTに接続されたSIGNALを放射することは、非仮想関数呼び出しを使用して、受信機を直接呼び出すよりも約10倍遅くなります。 これは、すべての接続を安全に反復する(つまり、後続の受信者が放出中に破棄されていないことを確認する)ために、接続オブジェクトの位置を特定するために必要なオーバーヘッドであり、パラメータを一般的な方法でマーシャルするために必要です。 10の非仮想関数呼び出しは多くのように聞こえるかもしれませんが、例えば、 new操作やdelete操作よりもはるかに少ないオーバーヘッドです。 シーンの背後にある文字列、ベクトルまたはリスト操作をnewまたはdeleteとすぐに、SIGNALとSLOTのオーバヘッドは、完全な関数呼び出しコストのごくわずかな部分しか原因としません。 SLOT内でシステムコールを行うたびにも同じことが言えます。 10以上の関数を間接的に呼び出すことができます。 SIGNALとSLOTのメカニズムのシンプルさと柔軟性は、ユーザーに気づかないほどのオーバーヘッドの価値があります。

signalsやslotsと呼ばれる変数を定義する他のライブラリは、Qtベースのアプリケーションとともにコンパイルされると、コンパイラの警告とエラーを引き起こす可能性があることに注意してください。 この問題を解決するには、問題のあるプリプロセッサシンボルを#undefします。

Qt Creator で SIGNAL SLOTを使ってみる

Qt Creator で新しいプロジェクトを作成する。
Qtコンソールアプリケーションを選択する。

プロジェクト名とプロジェクトパスを設定する。

プロジェクト名の例:SignalSlot4
パスの例:C:\Qt\Projects\SignalSlot



プロジェクトファイルと main.cpp が生成される。

ソースファイルに 新しい ヘッダと cpp ファイルを追加する。Sources のフォルダを右クリックして 「新しいファイルを追加」を選択する。

C++ クラスを選択する。

クラス名を Counter とし,基底クラスを QObject にする。次へ。

counter.h と counter.cpp が追加された。

counter.h を修正する。下線が追加した行。

#ifndef COUNTER_H
#define COUNTER_H

#include

class Counter : public QObject
{
    Q_OBJECT
public:
    explicit Counter(QObject *parent = nullptr);
    
    int value();

signals:
    void valueChanged(int newValue);

public slots:
    void setValue(int value);
    
private:
    int m_value;
};

#endif // COUNTER_H

int value()の value にカーソルを合わせ右クリック→リファクタリング→counter.cpp に定義を追加を選択


counter.cpp にて 下記下線部を追記する。

#include "counter.h"

Counter::Counter(QObject *parent) : QObject(parent)
{
    m_value = 0;
}

int Counter::value()
{
    return m_value;
}

counter.h に戻って,setValue() にカーソルを合わせ右クリック→リファクタリング→counter.cpp に定義を追加を選択する。


counter.cpp にて 下記下線部を追記する。

#include "counter.h"

Counter::Counter(QObject *parent) : QObject(parent)
{
    m_value = 0;
}

int Counter::value()
{
    return m_value;
}

void Counter::setValue(int value)
{
    if (value != m_value){
        m_value = value;
        emit valueChanged(value);
    }
}

main.cpp に移って 下記,下線部を追記する。

#include
#include "counter.h"
#include "stdio.h"

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

    Counter x, y;
    QObject::connect(&x, &Counter::valueChanged, &y, &Counter::setValue);

    x.setValue(12);     // x.value() == 12, y.value() == 12

    printf("x:%3d, y:%3d \n\n", x.value(), y.value());

    y.setValue(48);     // x.value() == 12, y.value() == 48

    printf("x:%3d, y:%3d \n\n", x.value(), y.value());


    return a.exec();
}

コンパイルして,正常終了することを確認する。(下記 かなづちのアイコンを押す)

緑の三角キーを押してプログラムを実行してみる。


プログラムの動きを図で確認してみる。

下記の SIGNAL/SLOT の設定により,Counter クラスオブジェクト x の setValue が呼ばれ,値が変わると valueChanged()が emit され,Counter クラスオブジェクト y の setValue が呼ばれて値が設定される。

    QObject::connect(&x, &Counter::valueChanged, &y, &Counter::setValue);

Counter クラスオブジェクト y の setValue が呼ばれても,SIGNAL/ SLOT でつながっていないので,x.value() の値は変わらない。
下記を追加すれば,x.value() の値も変わるようになる。

    QObject::connect(&y, &Counter::valueChanged, &a, &Counter::setValue);

Qt の SIGNAL/SLOT のしくみがだいたい分かっただろうか。SIGNAL/SLOT は QtCreator で作成した ボタンが押されたときのイベントで動作する ソフトウェアにするために頻繁に使用する。

以下で紹介するグラフ描画でももちろん使うので、どんなしくみでイベントが伝達されるのかをよく理解しておくとよい。

波形描画を行うために Qt に QCustomPlot を追加する

QCustomplot はグラフ描画のための無償提供されているツールで,qcustomplot.h と qcustomplot.cpp をプロジェクトに追加して,Qt Creator のプロジェクト設定に QT += core gui printsupport を追加すればよい。

他にもQtでグラフ描画する方法はあるらしいが、一番簡単そうだったのが QCustomplot を使う方法だった。

↓QCustomPlotダウンロードサイト
http://www.qcustomplot.com/index.php/download

QCustomplot でグラフを描いてみる

QCustomplot でグラフ描画を行うには、下記の動画のとおりにやってみるとよい。(英語だが非常に丁寧で分かりやすい)。

この動画の通りにやってみると Qt Creator の使い方も学ぶことができる。



今回は、ここまで。

2018-07-07

Raspberry Pi3を使ったリアル波形描画(2) 開発環境を整える

今回は開発環境の準備について解説する。

【用意するもの】
Raspberry Pi3 Model B(LCDディスプレイは別でも込みでもよいので用意する)
  • Micro SD カード(キットに含まれている場合もある)
  • 電源コードやHDMIケーブル、USBマウス、キーボードなと(キットで購入してもよい)
  • Windows PC(OS は7か10)
【参考書籍】
  • これ1冊でできる! ラズベリー・パイ 超入門 改訂第4版 (Raspberry Piをまったく始めて触る場合あったほうがよい)
  • 入門 Qt 4 プログラミング (Qt を使いこなしたい場合に必要)
  • 基礎からしっかり学ぶC++の教科書 (C++未経験者の場合)

  • Windows の環境を整える

    Qtの環境を構築するにはこちらの記事『(Windows)Qtの開発環境を構築(Qtのインストール)』を参照して欲しい。(インターネット環境だと多くの有益な記事を参照できるのでありがたい)

    Visual Studio 2017 Community版はこちらのサイトからダウンロードできる。
    ※Visial Studio 2017 Community版 をインストールするには数時間かかる場合があるので注意が必要。

     vs_Community.exe を実行する。左記のメニューが表示されるまで 5~10分くらい。

    左記のメニューを選択しインストールする。
    インストールが完了するまで約1時間かかる。

    ※Visual Studio 2017 Community版 は試用ならば一ヶ月使える。Microsoft のIDを取得(無料で個人で作成することは可能)してログインすれば,ずっと使い続けることができる。

    次に Qt の Windows版をインストールする。Qtには有料版と無料版があり、無料版はLGPLのライセンスによる使用制限があるが、今回のアプリ作成には無償版で十分に対応が可能。

    基本,こちらのサイトのインストール手順に従う。Raspberry Pi3には Qt 4.x をインストールするが、Windows版では Qt 4.x のインストールはもうできないので、Qt 5.x をインストールする。(互換性はあるので問題はない)

    Qt はパスに日本語が含まれるとコンパイルが上手くいかないので,インストール先は C:\Qt などのフォルダにインストールし,その配下で作業すること。

    下記は Qt 5.10.0 を Windows 7 のPC にインストールしたときのコンポーネントの選択例

    <選択が必須なコンポーネント>

    • Qt Creator 4.6.0-rc1
    • Qt 5.10.0
      • MSVC 2017 64-bit
      • MinGW 5.3.0 32bit
    • Tools
      • MinGW 5.3.0

    なお,Qt はインストール後も Qt Maintanance Tool を使って,コンポーネントの追加,削除,更新を行うことができる。


    Windows 7 64bit にインストールした Qt の「ビルドと実行」の設定内容。

    ビルドと実行で、コンパイラを CとC++ ともに MinGW 32bit を設定する。










    Raspberry Pi3 へQt をインストールする

    Raspberry Pi3にRaspbianをインストールする。この手順については入門書を参照するか、インターネットで探す。基本はwww.raspberrypi.org のダウンロードサイトからNOOBSをダウンロードし、フォーマットしたSDカードにコピーして、インストールする。

    Qt の最新バージョンは Qt 5.10 だが,Raspberry Pi向けの install イメージが配布されていないため,確実にインストール可能な Qt 4.8 をインストールする。(Qt 5.x のソースを Raspberry Pi上でコンパイルする方法も Web上で示されているが上手くいかなかった。)

    Qt 4.8 インストール手順(※参考リンク

    ① Raspberry Pi3上のコマンドラインから Qt4関連のソフトウェアをインストールする。
    -------------------------------------
    sudo apt-get install qt4-dev-tools
    sudo apt-get install qtcreator
    sudo apt-get install gcc
    sudo apt-get install xterm
    sudo apt-get install git-core
    -------------------------------------

    ②QTCreatorを起動してgccのコンパイラーを追加する。
    Tools/Options >ビルドと実行 > コンパイラ > 追加 > (GCCを選択)
    また、コンパイラのパスの参照で/usr/bin/arm-linux-gnueabihf-gcc-6に設定・適用する。(C++ も C も gcc 6 を設定する)

    左記はC++ のコンパイラを手動でgcc 6 に設定した様子。

    ③QTCreatorのビルドキットを設定する。

    Tools/Options >ビルドと実行 > キット>コンパイラをGCCに選択・適用する。






    ④ Qt Creator で新規プロジェクトを作成し,空の状態でコンパイル,実行してエラーがないことを確認する。


    その他 Qt に関する使用手順の解説はこちら




    今回のシステムのデモ動画(5インチLCDで動かしたもの)はこちら

    クロスプラットフォーム開発環境について

    大規模で複雑化したソフトウェアをゼロから開発するのは無理がある。Windows ベースのリッチなGUI(Graphic User Interface)を実現するには,グラフィックライブラリやソフトウェア開発のプラットフォームが必要で、開発の大部分をWindows PC上で行い,実装は Raspberry Pi などのターゲットボードにというスタイルが効率がよい。

    一般にはWindows と Linux , Mac OS では GUI に互換性がない。

    しかし、Qt は Windows , Linux, Mac OS などの OS,プラットフォームに依存することなく,GUI アプリケーションソフトウェアを構築することができる。

    Qt はライセンス条件を満たせば,無償で利用することが可能。

    Qt(キュート)について知りたい場合は商用のライセンスを提供している SRA のサイトを見るとよい。マルチプラットフォーム開発の有効性などが解説されている。

    Qtでできること

    • WindowベースのGUI をQt Creator を使って,簡単に設計できる。
    • Qt Creator で作成した 部品をアクセス(例えばクリック)したときに起動するソフトウェアを書くのが簡単。
    • 複数のソフトウェア(例えば,アナログ信号の取り込みと波形の描画)を並行して動作させるマルチスレッドを実現できる。
    ただし、Qt は C++で書かれており,C++ を理解していなければ,Qt を使いこなすことはできない。

    プログラミング言語の系譜についてはこちらを参照してほしい。

    Qt を使わないと 自力では難しいこと

    • マルチスレッド処理
      • 複数のスレッドをmsオーダーで正確に起動させることは難しい。
      • スレッド間の同期や連携,データの受け渡しが Qt がないと難しい。
    • 波形描画
      • リアル波形描画は Qt に Customplot を追加することで比較的簡単に実現することができる。
    • GUI と C++ アプリとの連携
      • GUI と C++ アプリを連携させる方法は通常 OS に依存するが,Qt を使えば,OSの違いを意識することなく,連携させることができる。

    Microsoft Visual Basic でもあらかじめ用意された各種のGUIパーツを配置して、それらのプロパティが変更されたり、マウスでクリックされたりするなどイベントが発生した場合の処理を記述してゆくことでアプリケーションプログラムを作成することができが、それは Windows OS上だけのことだ。

    しかし、Qt はそれと同等のことを OSに関係なく(Windows, Linux, Mac OS)できる。また、GUIのイベントの発生から、イベントをトリガーにして指定したメソッドへキックするしくみは、Qt でコンパイルする過程の中に隠蔽されるため、アプリケーションの作成者は特定のボタンがクリックされたときに飛んでくるので、該当するメソッド(関数)の中身を書くだけでよい。

    mainwindow.h に構築された関数定義の例

    private slots:
        // Run/Stop ボタンを押された時の処理
        void on_pbt_run_clicked();
        // 波形タイプボタンを押された時の処理
        void on_pbt_wavetype_clicked();
        // 電源ノイズフィルターボタンが押された時の処理
        void on_pbt_ac_line_filter_clicked();
        // ドリフトフリーフィルタボタンが押された時の処理
        void on_pbt_drift_free_filter_clicked();
        // ハイカットフィルタボタンが押されたときの処理
        void on_pbt_hicut_filter_clicked();
        // 表示感度ボタンが押された時の処理
        void on_pbt_displaygain_clicked();
        // 入力ソースボタンが押されたときの処理
        void on_pbt_input_type_clicked();
        // 周波数スピンボックスの値が変化したときの処理
        void on_doubleSpinBox_frequency_valueChanged(double arg1);

    Qt のこのしくみは Signal/Slot の関係を使っており、その概要については、以降の記事で説明したい。(各種 Qt の解説書にも詳しく書かれている)

    現在の Window GUIベースのアプリケーションソフトウェアでは、Window とボタンやダイアログ、テキスト表示領域、ダイヤルやスライダーなどのGUI部品から発生するイベントを受けて、何らかの処理を行い、その結果をまたGUI部品に反映させるといったやり取りの積み重ねとなる。

    また、そういったユーザインタフェースを伴うイベントの背後で、ファイルの入出力や定期的なインターバル割り込みイベントなどを処理する。

    これらのシステム上の役割を3つのレイヤーで表現したのが、左記のクラス図となる。

    一番上のレイヤーは ユーザーインターフェースを担う部分で Presentation Layer となる。

    ユーザーが直接インタフェースする部分であるため、この部分の見た目の良さが商品の付加価値となる。また、時代や商品のラインナップによって、変わりやすい、または、変えることで違いをだす部分である。

    Presentation Layer を構成するソフトウェア部品は環境が変わる(ディスプレイやプラットフォームが変わる、GUI部品の追加要求があるなど)ことを前提に、汎用的なGUIライブラリが使えるとよい。今回はそれが Qt となる。

    なお、プレゼンテーションレイヤーは付加価値にはなるが、また、外から丸見えなため真似されやすい部分でもある。だから、組織のコア・コンピタンスにはなりにくい。商品の付加価値にはなるが、真似されないソフトウェア資産にはなりにくいので、GUIライブラリやツールを使ってさっさとかたづけたい領域である。

    一番下のレイヤーは Data Source Layer で、データを取り込んだり、格納したりする役割を担っている。最近の機器は IoTのキーワードが示すように、ネットワークやポータブルメディアの I/F を持ち、それらの機能があるのが当たり前になりつつある。

    Raspberry Pi にも最初から LANや WiFi, Bluetooth , USB, SDのハードウェアI/Fが付いており、ドライバや関連ライブラリも用意されている。

    このレイヤーも必ず実装はしないといけない部分だが、汎用的なI/F とそれを扱うソフトウェアであるため、真似されないソフトウェア資産にはなりにくい。

    なお、今回の事例ではアナログ信号を取り入れるため、その部分のハードウェア、ソフトウェアはコア資産となりうる。信号の取り込み後は、多くの場合、デジタルフィルタなどの二次処理を行う。

    それらの二次処理は検証を行う必要があり、検証のたびにいちいちアナログ信号をA/D変換していたのでは効率が悪い。

    よって、取り込んだアナログ信号をA/D変換したデータは Data Source Layer を使って、ファイルの保存したり、アナログ信号の代わりにsin波や、疑似データを入力に使ったりしたい。

    それをC++の派生を使って実現しているのが、このクラス図となる。入力のI/Fは同じで、いろいろな入力クラスを派生させており、それを切り替えることで シミュレーションでデジタルフィルタの効き具合を確認したのち、アナログ信号をA/D変換したときにも期待された効果が出ているかどうかを確認することができる。

    このようなフレームワークが出来上がっていれば、いちいち実機を使わずとも、シミュレーション環境でかなりの検証作業を行うことができる。

    そして、もっとも重要なのが真ん中の Domain Layer となる。ドメインレイヤーは、そのドメインに特化したソフトウェア資産を配置する。

    ここでは黄色のスレッドとタイマーのクラスを置いた。これらのクラスは Qt にライブラリで提供されているもので、定期的な割り込みを発生させて、インターバル処理を行うために必要だった。リアルタイムな波形処理を行うためには必要なしくみだが、ドメインに特化した機能とも言える。

    そして、緑のクラスがこのシステムのコア資産となる部分だ。電源ノイズフィルタや、ドリフトフリーフィルタ、ハイカットフィルタは、信号処理の二次処理として必要なフィルタだが、そこにノウハウがある。だからこそ、今回の教育素材ではスケルトン(I/Fだけが用意されており、中が空)にしてある。そこはがんばって作成して欲しい。

    心拍を検出するクラスもコア資産だ。その部分の性能を高めるには、多くのデータを通してみて最適なアルゴリズムを検証する必要があるだろう。それを実現することができれば、他社に真似できないコア・コンピタンスになる。

    この3つのレイヤーのうち Domain Layer はもっとも寿命が長く、組織の利益の源泉になる資産である。

    一方、Presentation Layer と  Data Source Layer に配置されたソフトウェアは、商品の付加価値としては必要で、それがないと競争には勝てないのだが、時代や環境、ユーザーの要求とともにどんどん変わっていく宿命もある。

    変化に対応が可能である必要があるということだ。ユーザーインターフェースは時代とととにリッチになっていくので、GUI部分のソフトウェアは効率よく開発できる環境を持っていたい。そのためには、GUIライブラリが必要であり、今ではGUIライブラリの多くはオブジェクト指向言語で提供されている。

    データの入出力も同様にLAN, WiFi, Bluetooth, USB, SD などの I/Fが当たり前になっている現状では、それらのI/Fを必要に応じて使いこなせるプラットフォームが欲しい。

    組込みソフトウェアアーキテクトが意識すべきは、この3つのレイヤーの役割、寿命、ソフトウェア資産としての価値の違いである。

    その違いに応じて、必要なソフトウェア開発環境を用意し、効率がよく、かつ、商品群としての価値を最大に高めるアーキテクチャを用意する。

    それができれば、デスマーチではなく、ユーザーに満足してもらえるクリエイティブな商品開発ができると思う。

    P.S.

    永年組込みソフトウェアを開発してきたエンジニアが描くモデルで,実現する機能がクラスやパッケージになっているものをよく見かける。例えば,デバイスドライバとか,システム制御とか,データライブラリといったクラスが並んでいると,何がコアコンピタンスとなりうるソフトウェアの再利用資産なのか分かりにくい。

    今はそんなに規模が大きくなくても,いずれ訪れるソフトウェアの大規模化を想定して早いうちから組織的に重要となる再利用資産は何か,どれかを見極めておいた方がいい。

    そのためにはクラスやパッケージを責務で分割して,その再利用資産が手足として使用するストレージやUIのI/Fは時代とともに変わりゆくものだとして設計する。

    それができるようになると上記の 3 Layer にクラスやパッケージを分類することができるようになる。

    ※この記事に紹介した レイアードアーキテクチャについて、より深く知りたい方は『リアルタイムOSから出発して 組込みソフトエンジニアを極める』の3章 再利用の壁を越える をお読みください。

    2018-07-01

    Raspberry Pi3を使ったリアル波形描画(1) イントロダクション

    書籍『リアルタイムOSから出発して組込みソフトエンジニアを極める』の改装版を2016年5月にリリースしてから、この手の専門書にしてはそこそこ売れているようだ。

    2006年3月のこの本の初版を出版して以来、ずっと売れ行きをウォッチしているが、12年経った今の方がコンスタントに売れているような気がする。

    「それはなぜか?」とずっと自問自答している。10年前はまだ組込みソフトウェアの開発規模はそれほど大きくなく、本の需要もそれほどなかったが、2020年を目前とした現在では、組込みソフトもゼロから作るようなこともなく、組込みソフトウェアの開発者も不足してきており、ソフトウェアの再利用を行わないと立ちゆかなくなってきたというのが、今この本が売れている理由ではないかと考えている。


    この本が、他の本と違う点は、商品のビジネスモデルと組込みソフトウェアのアーキテクチャやソフトウェア技術を絡めて語っているところだと思う。ビジネスを成功させるためのソフトウェアアーキテクチャとは何かについて語っているつもりだ。

    簡単に言えば、組込みソフトウェアの製品を効率良く開発し、利益を高めるために必要な技術や考え方は何かを Step by Step で説明している。(最近は聞くことが少なくなった MOT:Management Of Technologyを意識しているつもり。)

    この本では 電子レジスターの商品群を想定して解説をしているのだけれども、ここ最近、この本を読んでくれている読者向けに、実物を使ってこの本に書いてあることを実践的に学ぶ教材があるといいなと考えるようになった。

    そんな折、Raspberry Pi3 が6000円くらいで手に入り、OSが Linuxベースではあるが(Linux は基本的にマルチタスクOSでリアルタイムOSではない) Qt(キュート:オープンソース版は無償)の開発環境を使うと、安価な学習環境を構築できることが分かった。

    そこで、この特集記事「Raspberry Pi3を使ったリアル波形描画」では、『リアルタイムOSから出発して組込みソフトエンジニアを極める』を実践的に理解するための教材(Qtを使い、Windows と Raspberry Pi のマルチプラットフォームで開発する教材)を紹介しながら、組込みソフトウェアの製品を効率良く開発し、利益を高めるために必要な技術や考え方を説明しようと思う。

    組込み機器のものづくりで必要な技術・スキルとは?

    ところで、技術系のソフトウェア研修を永年やってきて、ものづくりに必要な目に見えにくいスキルがあるなと感じる。それはものづくりを始めるにあたって「いける」かどうかが分かる、または「いける」かどうかを直感で感じる能力のことだ。別な言い方をするとものづくりを始める前に実現可能性があるかどうか、ものづくりを実現するために最も重要な要素やボトルネックを見分ける能力だ。それが出来る素養があることがものづくりのアーキテクトの素養があるかないかの違いだと思う。

    チームのメンバー全員が持っている必要はないが、アーキテクトとしての素養を持ったスキルを持った者がチームに一人はいないと製品開発が実現しない。

    アーキテクトの素養があるものは20人に1人と言われる。実際それくらいの割合だと感じる。アーキテクトの素養を持った者がいないチームで標準的な製品開発のプロセスを頭からなめさせると、ドキュメントは出来てきても、「もの」ができない。

    別な言い方をすると、アーキテクトのいないチームはフィージビリティスタディ※1 をしないまま、何も恐れることなく製品開発に突入しようとする。

    ※1 フィージビリティスタディ(feasibility study):プロジェクトの実現可能性を事前に調査・検討することで、「実行可能性調査」「企業化調査」「投資調査」「採算性調査」とも呼ばれる。

    組込みソフトウェア製品の場合、多くの場合は現在販売している製品があり、その製品の派生機種や後継機種を開発することが多いだろう。

    だから、フィージビリティスタディはすでに終わっている、技術的なかなめとなる部分はもう分かっていることが多い。左図の左側の調査研究の中のコンセプト開発・研究試作の部分だ。

    ただし、現行製品があるからといってコアな技術が資産化されているかどうかは分からない。ソースコードがあるからといって再利用可能な状態になっているとは限らないし、具体的なノウハウは1人の技術者の頭の中だけにあるかもしれない。

    自分達の組織のコアな技術が何かを知るには、Raspberry Pi のような汎用プラットフォームをまだドメイン知識のないエンジニアに渡し、それで売り物の製品相当のものを作れるかどうか試してみると分かる。

    今はインターネットでかなりの情報を収集できるから、未知の技術であっても大抵のことは調査できる。CQ出版のトラ技やインタフェースのバックナンバーなんかも有効な情報源だ。しかし、そういった情報を駆使しても、ドメイン知識のない技術者が製品相当のものを作れるとは限らない。

    そして、それを試したときに、どんなに優秀なソフトウェアエンジニアであってもどうしてても、実現できない機能や性能があれば、それがあなたの組織のコア・コンピタンス(「競合他社を圧倒的に上まわるレベルの能力」「競合他社に真似できない核となる能力」)だ。

    もちろん、コア・コンピタンスがメカやエレキのこともあるだろ。その場合、メカやエレキの技術が特許で守られていたり、流出しないように保護できていれば他社にまねされることもなくしばらくは安泰だ。

    ただ、今の時代、メカ・エレキだけがコア・コンピタンスであり、ソフトウェアは付帯機能だというケースは少なくなってきており、メカ・エレキ・ソフトの複合的な資産がコア・コンピタンスになっていることが多いと思う。

    そこで今回の特集記事では、メカ・エレキの機能や性能はあらかじめ提供されるという前提にして、ソフトウェアのコア資産を同構築していけばいいのかにフォーカスを当てて話を進めたいと思う。

    商品開発の実現可能性を嗅ぎ分ける能力を養うには?

    インターネットの情報でマネできる機能や性能は競争優位要因にはならない。真似できないコアな技術があってこそ、ビジネスで成功できる。汎用のソフトウェア資産を組み合わせただけではビジネスで優位に立つことはできない。

    リアルタイム性能の部分が競争優位要因になることはあるが、それだけでは苦しいだろう。リアルタイムとソフトウェア資産とビジネスを意識した再利用を実践してこそ、競争に勝てる商品になる。

    さて、新しい製品、これまでになかったサービスを実現しようとするとき、また、製品の内部を知り尽くしていた技術者がいなくなってしまい、既存システムのアーキテクチャが分からなくなってしまった場合、経験のない新たなメンバーで製品開発を実現させないといけない。

    そんなとき、自分は、何かを作ろうと思ったときに「実現可能性」について確信がないと、ものつくりに着手するのが怖いという感覚がる。せっかく、やり始めたのにやっぱり出来なかったという結果にはなりたくない。前述のアーキテクトの素養というやつだ。

    自分を成長させるためには失敗も必要だが、やはり成功体験を積み重ねる必要がある。時間には限りがあるし、ものづくりの成功はエンジニアとしてのモチベーションを高め、技術やスキルの吸収を加速する。『問題解決能力(Problem Solving Skills):自ら考え行動する力』の記事で書いたが、「問題解決キッズ」の成長スピードは「評論家くん」に比べて22倍速い。ようするに、問題を解決し、製品開発の成功を重ねるとものすごいスピードで成長する。(アーキテクトの素養が身につくと成長するスピードも格段に上がる。)

    それを繰り返すと、開発を着手する前に「実現可能性」の確証といいうか「いけそうだ」というあたり感がないとイヤだと感じるようになる。そして、そういった感覚を研ぎ澄ませていくと、「その製品やシステムを開発するために必要なコアな技術は何か」を探る能力が高まる。

    市販品を見るときにも、この製品のコア技術は何かをカタログから探ったり、分解記事をくまなく精査するようになる。

    そして、そういった感覚が研ぎ澄まされていくと、コアな技術はなんとしても習得したいと思うようになる。コア技術と汎用技術があったら、真っ先にコア技術を学びたいと思い、その後製品実現のために汎用技術を学ぼうと思う。

    この感覚はどんな簡単なものでもいいのだが、やはりものづくりの経験を積み重ねないと醸成されない。

    だから、既存のアプリを利用する経験しかないと、「これはどうやって実現しているのだろうか」という視点が育たない。

    そういった人たちを集めて、「さあ、何か作ってごらん」といってもなかなか難しい。プログラミングの研修にしても演習課題を繰り返すだけでなく、自分の考えで何かの目的を達成するプログラムを作るという経験を積み重ねさせる必要がある。

    OJTで与えられた仕様についてプログラミングしたり、変更の依頼を実装したりすることだけやっていると、その経験はなかなかできない。

    アーキテクトを養成するための研修教材が必要だと感じる。そういったこともあって、今回Raspberry Piを使ったリアル波形描画の教材を作ってみようと思った。

    今の世の中、生まれたときから便利なものだらけで、使う側に圧倒的に時間を使う若い世代には、ものづくりには不利かのかなあと思うところもある。

    でも、別な見方をすると Raspberry Pi のような安価でいろいろなことができるソフトウェア開発のプラットフォームも簡単に手に入る世の中になった。

    また、Raspberry Pi を使った開発環境も無償で、開発に関する情報もインターネットから入手できるようになった。

    ものをつくりたいというモチベーションがあるポテンシャルの高い人材なら、自力で実力を身につけることができる世の中になったとも言える。

    リアルタイムOSから出発して組込みソフトエンジニアを極める』がそこそこ売れているということは、そういった人材が少数だがいて、どうすればソフトウェアアーキテクトとしてのスキルを高めたいともがいているのではないだろうか。

    そういった人たちに、手を動かしながら学べる教材コンテンツを提供したいと思う。

    『リアルタイムOSから出発して組込みソフトエンジニアを極める』を振り返る

    リアルタイムOSから出発して組込みソフトエンジニアを極める』の概要は、初版を作成したときに気合いを入れて作った『組込みソフトエンジニアを極める(外伝)』を見てもらうと分かりやすい。(本を読んで「外伝」を見ていない人は、是非、登場人物5人の日記をザッピングしてもらうと面白いと思う)

    この本では「リアルタイムシステム」を開発するためのソフトウェア技術と、リアルタイムシステム上で開発効率を高めたり、再利用性を高めるための「オブジェクト思考設計」の技術を 組田鉄男という主人公の成長とともに説明している。

    技術的には、第一章の時間分割のハードルで、リアルタイムOSを使った設計技術を、第二章 の機能分割のハードルで、オブジェクト思考設計の技術を紹介し、第三章の再利用の壁で、商品群を開発する際のビジネスを成功するために必要なソフトウェアの再利用技術を紹介している。

    この教育コンテンツでは、「リアルタイム制約」「オブジェクト指向設計」「ビジネス成功のためのソフトウェア再利用」という3つの要件を、Raspberry Pi3 を使って疑似体験することを目的としている。

    今後、この特集記事の完結に時間がどれくらいかかるか分からないが、1年以内には完結させたいと考えている。

    この特集記事を読み続けるとよい人

    • C言語は書けるけれど,C++はまだやったことがなくC言語との違いや特徴を実機ベースで実感したい人
    • オブジェクト思考設計の必要性を感覚的に掴みたい人
    • 組込みソフトウェア開発の経験は長いが,オブジェクト思考設計に踏み出せないでいる人
    • 製品のソフトウェア規模が100万行を超えてきて,開発効率が上がらなくて困っている人
    • 『組込みソフトウェアエンジニアを極める』を読んだけれども,上手くいく実感が湧かない人
    • 競合力の高いソフトウェア製品の商品群を展開したい人。
    • 理論より実践でソフトウェアの再利用や効率的開発を学びたい人。
    • 未来の組込みソフトウェアエンジニアを育てたい人

    前提条件

    • ハードウェアプラットフォームに Raspberry Pi3 を使用する。
    • Raspberry Pi の OS はLinux Raspbian を使用する。
    • ソフトウェア開発の言語は C++ を使用する。
    • GUI 及び統合開発環境は Qt 5.10(Raspberry Pi上では Qt 4.8)を使用する。
    • Windows と Raspberry Pi のマルチプラットフォーム開発を行う。

     アナログアンプ、アナログフィルタ、A/D変換器の設計はしません。そのI/Fまでは設計するのでその部分は自作してください。
     デジタルフィルタや二次処理の部分はスケルトン(インタフェースは提供するが、実装コードは空の状態で紹介する)で提供します。

    つくるもの

    • A/D変換器でアナログ波形をRaspberry Pi3に取り込んで、ディスプレイに波形を表示させるソフトウェアを作成する。
    • 単にソフトウェアを実装するのではなく、「ビジネス成功のためのソフトウェア再利用」という観点で、ソフトウェアのアーキテクチャを考えながら設計を進める。
    こちらはPC上で波形表示を行ったデモ画像


    こちらは 5インチのLCD上で波形表示を行ったデモ画像



    完成したWindowsプラットフォームアプリ(Windows 上で動作する exe + QtのDLL。Raspberry Pi3上でも動作することは確認済み)をダウンロードしてご自分のPCで動かしてみたい方は次の手順でご依頼ください。

    【注意点】
    • Windows 7 と 10で動作することは確認しています。
    • Qt のプロジェクトファイルやソースコードは今の段階では公開していません。本特集記事を進めていく過程で公開方法を考えます。
    • 本アプリは心電図をRaspberry Pi3に取り込み、心拍数を計測することを想定した教材ですが、デジタルフィルタの中身は空(スケルトン)になっています。また、心拍の計測アルゴリズム等も教育用に簡易的に作成したもので実用に耐えうるものではありません。
    • 本当に心電図計測を行うためにはアルゴリズムの設計やデジタルフィルタの設計が必要です。
    • 本教材は、そういったアルゴリズムやデジタルフィルタのインタフェースを定め、カプセル化するとデバッグ効率や再利用性が高まり、ビジネスを成功に導くことができることを学ぶことを目的としています。
    • 本教材は再配布や有償セミナ等への二次利用はできません。(公共の教育機関の方が教材として使用されたい場合は個別にご相談ください。)
    • 圧縮ファイルとパスワードを受け取った方は、本注意点について許諾したことになります。
    【完成形を確認する Windowsアプリの入手方法】

    次のメールアドレスに件名:パスワード送信希望 と書いてメールをお送りください。(”パスワード送信希望”というキーワードが件名に含まれていないと返信されません。
    メールアドレス:CriticalSoftwareConsulting[あっとまーく]gmail.com

    折り返し、ファイルのダウンロード URL と パスワードをお送りします。
    なお、ファイルは パスワード付きのZIPファイルで約20Mバイトあります。

    本教育教材システムのクラス図
    P.S.

    CPUの性能が上がり、カラー液晶や有機ELが安価に手に入るようになった現在では、GUIのソフトウェアをゼロから作り上げるなど考えられないし、やはりWindowsやLinuxマシン上で表示の出来を確認して、そのままそのソースコードを実機で動かすことができれば開発効率が上がる。

    そういった開発環境を Qt は用意してくれる。ちょっとしたソフトウェアの exe を作成するだけでも容量が大きくなる(実際今回のアプリも20Mバイトだった)のが玉にきずだが、そこはマルチプラットフォーム開発ができるのだからがまんしたい。

    C++で提供されているQt の豊富なライブラリや機能を使っていると、なぜC言語ではなく、オブジェクト指向言語であるC++が必要なのかがよく分かる。

    再利用可能なライブラリをサクサク使い、どうやって実現しているのかよく分からなくてもやりたいことが実現できる、それこそがオブジェクト指向言語を使う理由だ。

    同様に、自分達が作ったソフトウェアを再利用して開発効率を高めたいのなら、C言語では難しいと思う。オブジェクト指向言語を使ってI/Fを定め、実現方法は隠蔽して、ソフトウェア資産を構築していかないと、ソフトウェアの採用の効率は上がらない。ちなみに、オブジェクト指向言語を使ったからといっても、再利用可能な資産になるとは限らない。

    その点をこの特集記事では解説していきたいと思っている。

    デモ動画を見てもらうとわかるが、波形をリアルタイムに右から左に流す(ムービング)の波形表示は LCDとLCDドライバとCPUのリソースでC言語でゼロから作ったら気が遠くなるような時間がかかる。

    それが QtQCustomPlotのライブラリ(無償)を使うと、簡単にPC上で実現でき、そのソースをそのまま Raspberry Pi3上で HDMI の I/Fを持つディスプレイで再現させることができる。

    Linux で正確なタイマー割り込みを発生させるかどうかちょっと不安だったが、なんとか大きなジッターなしに実現できた。

    感覚的には数ヶ月もかかる組込みソフトウェアシステムの開発が開発期間を数日で実現できた感じだ。実際にはRaspberry Pi、Qt、QCustomPlot 等を使うのが始めてだったので、それらを使いこなせるようになるには数ヶ月かかったが、実際に動くものが出来たときに、「これが、オブジェクト思考言語やオブジェクト思考設計を使う根拠になる」と思った。

    組込みではないけれども『猫でも分からないオブジェクト指向入門』を読むと、過去から現在に至るまでに、どうしてオブジェクト思考設計が必要になってきたのかが理解できる。

    永年C言語を使い続けてきて、いまさらC++やオブジェクト指向設計はハードルが高いと思っている方は、この特集記事を読み進んでもらって、オブジェクト思考設計とソフトウェアの再利用資産を使って効率よく組込みソフトウェアが開発できることを実感してもらいたい。