hiro99ma blog

何か技術的なこと

android: Data Sources をそれっぽくしたい

2024/11/18

BLEアプリのテンプレートを作ってみたものの、アプリアーキテクチャ が期待する Data Sources というものをわかっていないので落ち着かない。
Data Sources のガイドラインなどあれば眺めておきたいところである。

Data Layer

Data Layer は Repositories と Data Sources から構成されている。
矢面に立つのは Repositories で、Data Sources は Repositories からしかアクセスされない。
私のイメージでは Data Sources がデバイスドライバ層で Repositories がミドルウェア層のような感じだ。
まあ、Repositories がビジネスロジックを持つようなので範囲がもうちょっと広いが。

その上にドメインレイヤというのもあるが、有名らしいクリーンアーキテクチャの定義とはちょっと違うかもしれないので注意しておくれと書いてあった。
私も名前くらいしか知らないので違いについては何とも言えないが、そういっているならそうなんだろう。

image

日本語の文章はちょっと変だが、これは自動翻訳だから仕方ない。
手動で日本語訳されていると文章は読みやすいのだが本家(たぶん英語)の更新に取り残されるので、それなら自動翻訳の方がありがたい。
しかし Google 翻訳だと自然な文章になるので Cloud Translation API はちょっと違うのだろうな。

いかん、話が逸れた。
そしてドメインレイヤはテストアプリでは不要だから今回は対象外だ。
検索していたら、違いについて書いてくれている人がいた。

そうなんよねー、アプリでそんなに複雑な構成にしたいことがあんまりないと思うのよねぇ。
ガイドの方も「Data Sources が 1つしかないなら Repositories で持つのもあり」とか書いてあったし、自由にすればよいと思う。
あくまで「推奨」に過ぎないので、推奨を形作るところまではいろいろ議論があっただろうけど、読むだけの人は「ふーん、そういうのもあるのね」でよいのだろう。

Data Sources

各データソース クラスは、ファイル、ネットワーク ソース、ローカル データベースなど、1 つのデータソースのみを処理する役割を担う必要があります。データソース クラスは、データ オペレーションのためにアプリとシステムの橋渡しをします。

単独のデータソースを処理する、というのはどの程度の単独さなのだろうか。
ここに載っているサンプルコードではこうなっている。

データベースはテーブルが複数あっても 1 つということだろう。
命名規則としては汎用的にするため “Local” / “Remote” のようにしたり、扱うデータを名称にしたりして具体的な名前を出さないようにする。

“Local” とした場合は RoomSQLite みたいなもの全般を扱うのだろうか。
役割として使い分けたいなら “Local” ではなく “NewsData” とか “UserData” とかにするのか。
Repositories の方も要件さえ満たしてくれれば細かい使い分けをしたいわけでもないだろうし “Local” でまとめてよい気がしてきた。
じゃあ “Local” と “Remote” はなんで分けるかというと、やっぱりアクセスのめんどくささとか依存度が全然違うからかな?

これをまねするとなると…..

私の中で、BLE の機能は変に分散させない方がよいということになったので 1つの Data Source の class にしてしまおう。
巻き取るなら Repositories の階層で行うことにする。

API

BLE でやることは Write, Read, Notify/Indicate くらい。
Read は値をコールバックでもらうし、Write は w/o Response でないなら書込み結果は同じくコールバックでの通知だ。
これが別々のコールバック関数で戻るならそれぞれ好きにやれば良いのだが、GATT 接続時のコールバック関数に全部戻ってくる。
引数に Characteristic があるので見分けることはできる。
これらはたぶん「ワンショットオペレーション」になるのだろう。
suspend関数にせよ、といっているので・・・あれ、どうしたらいいんだ?
やり方は分からないが、そうしないといけないということだ。
可能なら、TypeScript の async-await みたいに見た目同期にした方がよいのだろうか?

Notify/Indicate はデータ変更の通知になるので flow にせんといかんだろう。
しかし BluetoothGattCallback を直接渡すと Read や Write の結果を受けられないので、一度受け取って別のflowで返すような形になるのか。

あああ、スキャンもやらんといかんのだった。
ちょうどよい記事があった。参考にさせてもらおう。

おわりに

やり方はわからないが方向性は決まった。
あとは実装しながら修正していこう。

おまけ1

クリーンアーキテクチャって組み込みソフトウェアみたいな分野だとちょっと使えないよなあ、と思ったので検索すると “Clean Embedded Architecture” というのが出てきた。

普通のことが書いてあった。
いつもあの同心円の図を見るから全体的にそういう話をしているのかと思ったけど、そうでもないのね。

と最初しか読んでなかったけど結構ページが多い。
いや、そもそもネットで検索して出てきた PDF(↑とは別) はなんなのだ?
本が売られているけどブログに書いていたという話もあったので、そこから持ってきたのだろうか。
まあ、そこまで高いわけでもないので買ってよいのだけど、他にも読んでない本が多数あるので気が引ける。。。

おまけ2

stopScan() の引数になんでcallback がいるんだよ! と思って空のScanCallbackインスタンスを設定したのだが止めることができなかった。
あれをキーにしてスキャンを止めているのだな。

つまり、複数のアプリから同時にスキャンすることもできるということか。

< Top page