なぜプラットフォーム化するのか
っていうと、 アプリを変えたくない から。
デバイスが変わっても、「アプリはいじってません。デバイスが変わったので、ドライバ(とプラットフォーム)は変えざるを得ませんが、それだけです。 従ってテストは変更した部分の再検証のみでOKです。 」と言いたいから。
例えば、
-
ある基板で、UARTデバイスとして ST16C2552(Exar)が載っていた。
-
で、改版され、SC16IS740(NXP)になった。
I2Cになるので割とドラスティックな変更ですね。
ここで、アプリに、
/* 送信する */
ST16C2552_Send(send_data, send_len, ...);
と書いてあったら、デバイスが変わったら、
/* 送信する */
SC16IS740_Send(send_data, send_len, ...);
に変えないとダメでしょ?そこ変わってるんだったら、再検証しないとダメでしょ?
でなくて、
/* 送信する */
UART_Send(send_data, send_len, ...);
という、「アプリから見たら、具体的なデバイスはともかく、UARTっぽい何かに送信してるだけ」になっていれば、自信をもって アプリ変更してません(ドヤッ) と言えるでしょ?
……というのが、プラットフォーム化の理由だと思ってます。
抽象化しないと意味ないが、うっすらでいい
Linux、Windowsなどは、I/Oを「ファイル」にまで抽象化しているが、組み込みだとそこまでする必要はないと思います。分かりづらくなるし、処理時間や必要メモリが大きくなってしまう。
とはいえ、当然だが、ある程度は抽象化しないとプラットフォームの意味がない。
例えば、「DIO」(デジタルI/O、パラレルI/O)、「UART」(UART、シリアルI/O)程度でよいが、デバイスの名称そのままでなく、うっすら抽象化する。デバイスの匂いを消す。程度で良いと思います。
抽象化すると機能は減るが、それでいい
とあるデバイス固有で検出可能な異常などは、インターフェースに出さない。というか出せない。出そうと思うと、共通のインターフェースに出来なくなる。
SC16IS740になったら、I2Cなのだから、当然通信エラーとかの概念が入ってくるが、アプリから見たらそんなの知らん。
ひとまずインターフェース設計はこれでOK。
例えば以下。
/**
* @brief UART送信
* @param data 送信するデータ。
* @param len 送信するデータの長さ。
* @return 送信したデータ長。
*/
int32_t UART_Send(const void *data, int32_t len);
減らした機能へのサポート
とはいえ、検出可能な異常なのであるから、検出して活用したい。
結論として、異常な状態を 記憶・取得するだけの モジュールを準備し、プラットフォームやドライバの処理で検出可能な異常はそこに記憶しておく。
で、アプリ側で、必要なら記憶された異常を取得できるようにしておく。「何の異常だかよく知らんが、なんか出てるので出力できるようにしておく」程度の対応をしておく。
Windowsのイベントビューアーをイメージ。
なぜプラットフォーム化が進まないのか
経営者 は、コスト削減をしたい。
だからプラットフォーム化しろと言う。
被雇用者 は、自分の仕事が増えるのを嫌う。なるべく労働時間を減らしたい。(ただし、給料変わらずに)
通常、アプリを作るのは被雇用者だし、プラットフォームやドライバを作るのも被雇用者。
プラットフォーム設計者は、適切な設計をすればするほど、自分たちにしわ寄せが来てしまう。頑張り損。基板改変があると、 自分らだけ仕事が増えて(なのに給料変わらず) 、アプリ開発者ずるい。
アプリ改変にかかったはずの費用を、プラットフォーム化して削減できたなら、全部でなくとも、プラットフォーム開発者に還元する仕組みを作らないと、この問題は解消しない。
ちなみに、プラットフォーム化により削減される費用は永続的なので、ボーナスではなく、基本給に反映されるべき。
うまくいったら基本給増えるとなれば、そら頑張るわな。
大事なことなのでもう一度。
進まないのは、技術的な問題じゃない。技術なんて、上記で示したごく単純なテクニックだけ。
これは経営的な問題であり、変えられるのは経営者だけ。
プラットフォーム化を進めるもう一つの冴えたやり方
あるいは、仕事が増えて喜ぶ人にプラットフォームを任せる。
具体的に言うと、 被雇用者でない外注業者。 (自分のことで恐縮)
設計自体は社内でやるとしても、実装を任せる。
うまくオチた?そうでもない?HAHAHAHA!