Power Appsアプリの構造はどうしておくべき?
最近、Power Apps アプリ開発の初心者のチームメンバーの作成したアプリの構造レビューをしていました。
私もまだまだ勉強中なので、偉そうなことは言えませんが、その中で気がついたこと、自分が気をつけていることを踏まえて整理してみます。
この記事で伝えたいこと
- よくない設計パターンとその課題
- アプリの各種処理をどこに書いておくと良いのか?
前提
- Power Apps のCanvasアプリ
- 複数画面を行き来させながら処理をするケース
その画面の準備を呼び出し元のボタンで処理してしまう
アプリの構造レビューで気になった大きなことが1つ。その画面を表示するために必要な処理を、画面を呼び出すボタンのOnSelectで書いているです。
選択された項目の詳細情報を、次の詳細画面で表示したいケースはよくあります。
詳細画面で表示するためのデータを、それより前に整えておけば、
データが整うタイミングや順番も守られていて、確かに表示上は問題ないです。
項目のOnSelect
// ❌ OnSelectに遷移先の準備処理を書いてしまう例
// 1. 次の画面で表示する商品詳細の情報をコレクションから1つ抜き出してグローバル変数に格納
Set(
gblSelectedProduct,
LookUp(colProducts, ProductID = ThisItem.ProductID)
);
// 2. 特定した商品に関連する商品のコレクションを生成
ClearCollect(
colRelatedProducts,
Filter(
colProducts,
Category = gblSelectedProduct.Category
&& ProductID <> gblSelectedProduct.ProductID
)
);
// 3. データの準備完了。次の画面に遷移
Navigate(DetailScreen, ScreenTransition.None);
)
何が起きるか
しかし、この詳細画面にいろんな画面から遷移したいケースになったらどうでしょうか?
全体としてこのような構造になっていました。
DetailScreenの表示に必要な処理が複数に分散されていて、しかも全く同じです。
これでもアプリは問題なく動作しますが、次のようなケースで苦しくなってきます。
- この共通処理の部分に修正が入る度に、ミスなく両方に変更しないといけない。
- DetailScreenへの遷移元が増えた場合、同じ処理をそちらにも書かないといけない。
特に、共通で同じ処理をしたいはずなのに、書く場所が増える度にミスが生まれやすくなります。
ではどうしたら良いか?
その画面のことは、その画面自身に極力させるようにします。
つまり、その画面への遷移元では、「どの画面に行くのか?」という本来の目的だけを書くようにして、遷移先の画面では、画面表示に必要な処理を自分自身のOnVisibleで処理をするようにします。
このような構造にしておくことによって、DetailScreenの処理は、DetailScreen自身のOnVisibleで共通的に管理されることにより、
画面表示に必要な処理部分に修正が入ったり、複数の画面からの遷移動線が後から増えたとしても、比較的安全に対応することができます。
項目のOnSelect
// ✅ 遷移先の準備は遷移先に任せる。必要最小限な情報(どの商品?)だけを渡す
Navigate(
DetailScreen,
ScreenTransition.None,
// 次の遷移先にコンテキスト変数として渡せる
{ locSelectedProductID: ThisItem.ProductID }
);
DetailScreenのOnVisible
// ✅ DetailScreen.OnVisible
// 渡されたProductIDをもとに、この画面で必要なデータを自身で準備をする
Set(
gblSelectedProduct,
LookUp(colProducts, ProductID = locSelectedProductID)
);
ClearCollect(
colRelatedProducts,
Filter(
colProducts,
Category = gblSelectedProduct.Category
&& ProductID <> gblSelectedProduct.ProductID
)
);
ポイント
疎結合と密結合
ソフトウェア設計には「結合度(Coupling)」という考え方があります。1960年代後半にLarry Constantineが提唱し、1974年にStevens, Myers, Constantineの共著論文 "Structured Design"(IBM Systems Journal)で発表、1979年にYourdonとConstantineの共著書籍『Structured Design』で体系化された、ソフトウェア設計の基礎概念の一つと言われています。
- 密結合(Tight Coupling): モジュール同士が互いの内部実装に強く依存している状態。一方を変更すると、もう一方にも修正が必要になる
- 疎結合(Loose Coupling): モジュール同士の依存が最小限で、一方の変更がもう一方に波及しにくい状態
Power Appsに当てはめると、OnSelect側にDetailScreenの初期化処理を書くのは密結合にあたります。呼び出し側が「遷移先の画面が内部でどんな変数を使い、どんなデータ整形が必要か」を知っていなければ動かない構造だからです。導線が増えるたびに同じ知識が複数箇所にコピーされ、DetailScreenの仕様変更がすべての呼び出し元に波及します。
一方、初期化処理をDetailScreen自身のOnVisibleに寄せれば、呼び出し側は「DetailScreenに遷移する」という意思だけを伝えればよい。これが疎結合な構造であり、導線が増えてもDetailScreenの内部変更が呼び出し元に影響しない状態です。
参考文献
Stevens, W.P., Myers, G.J., Constantine, L.L. (1974). "Structured Design". IBM Systems Journal, 13(2), 115-139.
Yourdon, E., Constantine, L.L. (1979). Structured Design: Fundamentals of a Discipline of Computer Program and Systems Design. Prentice-Hall.
まとめ
今回の話をまとめると、「その画面のことは、その画面自身に任せる」 という考え方です。
処理が動くかどうかだけで見れば、OnSelectに書いてもOnVisibleに書いても結果は変わりません。
違いが出るのは、アプリが育っていく過程です。画面が増え、導線が増え、仕様変更が入ったとき、処理がどこにあるかによって修正のしやすさが大きく変わってきます。
**「とりあえず動く」から「安心して変更できる」**へ。その最初の一歩が、処理を書く場所を意識することだと最近考えています。
次回予告(その2)
今回の方針でOnVisibleに処理を寄せていくと、今度は別の課題が見えてきました。
画面によっては、遷移元に応じて処理を変えたいケースがあります。たとえば、初期表示なのか、検索結果からの戻りなのか、設定変更後の再表示なのか。これらをOnVisible内でどう整理するかが、後編のテーマです。


