個人開発アプリの設計を見直してみた

image

初めに

最近はクリーンアーキテクチャとかドメイン駆動設計とか「変更に強い設計」がキーワードなような気がして、設計に強みを作っていきたい自分としてはどんどんそういう世界に飛び込んでいきたいです。 まずは可茂IT塾で関わったアプリを参考にしつつ、個人開発アプリの設計を改善していきます!

アプリの説明

今回扱ったアプリはアルバイト先の飲食店に向けて開発している、食材の発注作業を楽にするアプリです。
発注作業はしんどい作業です。 というのも、発注量を決める目安の数字があるにはあるものの、実際には色々な要件が絡み合っていて考えるべきことが多く、面倒な計算が求めらるからです。
とても面倒でつらいので、自動化を目指しています。。

扱う数字たち

このアプリでは主に3つの数字を扱います。

  • 売上予想額
  • 食材の在庫数
  • 食材の単位量あたりの売上見込み

具体例として牛肉の発注量を考えてみましょう。

  • 明日は3000円の売り上げ予想です。
  • 明日の朝イチの時点で、牛肉の在庫は5パック分あります。
  • 牛肉1パックあたり500円の売り上げが見込まれます。

この時、初めに明日の牛肉の出庫量を考えます。3000 / 500 = 6パックの消費が見込まれます。
牛肉は明日の朝イチ時点で5パック分しかないため、1パック不足します。
結果として、1パック分発注すれば足りそうです。

めちゃくちゃシンプルにするとこんな感じの計算をします。

実際には、1箱12パックで送られて来るので送料の無駄がないように牛豚鶏の合計が12の倍数になるように発注する、などの縛りがあります。。。
例)牛 3P, 豚 4P, 鶏 5P の合計12パック

見直す前の設計

売り上げの予想額を扱うSalesクラスと、食材の在庫数と単位あたり売上を扱うItemクラスを作り、providerで管理するような形にしていました。 Itemは品目ごとにproviderをハードコーディングし、Salesも今日、明日、明後日の三日分ハードコーディングでproviderを作っていました。

また、それぞれのproviderをwatchしたStoreクラスのproviderを使って統括的な処理をするようにしていました。

クラス図(before)

改善前の悪い所

providerがバラバラなため、処理やUIの記述もバラバラになってしまう。

苦肉の策で親からproviderを引数で渡す対応をしていました。。。
それでも結局こんな感じで個別に書く必要があってなんか違う。

Column(
  child: [
    ItemCard(porkProvider),
    ItemCard(beefProvider),
    ItemCard(chickenProvider),
  ],
)

全てのItemに対して処理をするのにもproviderごとに個別にやってあげる必要があり、複雑な実装に入るとぐちゃぐちゃのスパゲッティコードに。

StoreクラスでItemやSalesを持っていても、結局個別のproviderが必要になる。

今思えば、初めからStoreクラスのproviderだけを用意するようにして、ItemやSalesの変更に対しても全てStoreで処理するようにすれば動くようにはできたのかも。(それでも深い構造になって分かり辛そう。)
今回の設計では、StoreクラスのItemに対して変更を加えてもproviderに何の変更も通知されないので、結局個別のproviderを使ってあげないといけません。

//通知されない
for(final item in store.itemList){
  item.amount++;
}

処理してるつもりなのになんで通知されないんだと詰まるポイントになり得る。。

見直し後の設計

クラス図(after)

.family

今回の悩みに関しては、ほとんどこれのおかげで解決しました。 idとproviderを紐づけることができるので、idをリスト形式にして持っておけば、

for(final itemId in itemIds) {
  ref.read(itemProviderFamily(itemId).notifier).incrementAmount();
}
Column(
  children: itemIds.map((itemId) {
    final item = ref.watch(itemProviderFamily(itemId)).item;
    return ItemCard(item);
  }).toList();
)

こんな具合に全てのItemに対しての処理なんかも簡潔に書けます。 バラバラのproviderにガッツリ依存していた時期に比べ、providerとの結びつきを緩めることができました。

状態管理

状態管理は全てitem, salesで管理するようにしました。それぞれidを持っているので、UIにインスタンスさえ渡してしまえばidを使って目的のproviderに対して処理を通知できます。 各UIはItemやSales,もっと言えばidさえ持っていれば良くなったので、複雑さが抜けて直感的に分かりやすくなりました。

結果

idに紐付いたproviderを引っ張って来れば良くなったことで、データの流れが分かりやすくなりました。12の倍数問題もかなりいい感じにクリア。
Firestoreとの連携もしやすく、在庫状況などをFirestoreに保存する機能の追加などが実現しました。 自動化に向けて大きく前進です。

フォーム画面 発注画面

まとめ

直感的で分かりやすい状態管理が大事! 今後は凝集度、依存の方向とかにも気を配れるようになりたいです。

アプリに関して、今は単位あたり売上には手動計算したものを入れています。
今後は売り上げデータの保存機能や、出庫量の算出機能を実装して、そこの計算まで自動化したいです!

新しく勉強したことを個人開発に取り入れてみるのは良い勉強になっている気がしてます🙂

お知らせ

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More
U30可茂ITインターンハッカソン

U30可茂ITインターンハッカソン

12月28,29日開催。2日間でアプリ開発の企画から完成までを目指す!U30可茂ITインターンハッカソンを開催します。

Read More

タグ

Flutter (113)初心者向け (28)イベント (18)Google Apps Script (15)Nextjs (12)可茂IT塾 (9)Firebase (7)riverpod (6)React (6)ChatGPT (5)vscode (5)デザイン (5)新卒 (4)就活 (4)Figma (4)Dart (4)JavaScript (4)お知らせ (4)FlutterWeb (3)Prisma (3)NestJS (3)Slack (3)TypeScript (3)ワーケーション (3)インターン (3)設計 (2)線型計画法 (2)事例 (2)Git (2)Image (2)File (2)Material Design (2)画像 (2)iOS (2)アプリ開発 (2)React Hooks (2)tailwindcss (2)社会人 (2)大学生 (2)RSS (1)Google (1)Web (1)CodeRunner (1)個人開発 (1)Android (1)Unity (1)WebView (1)Twitter (1)フルリモート (1)TextScaler (1)textScaleFactor (1)学生向け (1)supabase (1)Java (1)Spring Boot (1)shell script (1)正規表現 (1)パワーポイント (1)趣味 (1)モンスターボール (1)CSS (1)SCSS (1)Cupertino (1)ListView (1)就活浪人 (1)既卒 (1)保守性 (1)iPad (1)シェアハウス (1)スクレイピング (1)PageView (1)画面遷移 (1)flutter_hooks (1)Gmail (1)GoogleWorkspace (1)ShaderMask (1)google map (1)Google Places API (1)GCPコンソール (1)Google_ML_Kit (1)Vercel (1)Google Domains (1)DeepLeaning (1)深層学習 (1)Google Colab (1)コード生成 (1)GitHub Copilot (1)オンラインオフィス (1)オブジェクト指向 (1)クラスの継承 (1)ポリモーフィズム (1)LINE (1)Bitcoin (1)bitFlyer (1)コミュニティー (1)文系エンジニア (1)Freezed (1)ヒーター (1)作業効率 (1) (1)Flutter実践開発 (1) (1)permission_handler (1)flutter_local_notifications (1)markdown (1)GlobalKey (1)ValueKey (1)Key (1)アイコン (1)go_router (1)debug (1)datetime_picker (1)Apple Store Connect (1)FlutterGen (1)デバッグ (1)Widget Inspector (1)VRChat (1)API (1)検索機能 (1)Shader (1)Navigator (1)メール送信 (1)FlutterFlow (1)Firebase App Distribution (1)Fastlane (1)Dio (1)CustomClipper (1)ClipPath (1)カスタム認証 (1)アニメーション (1)Arduino (1)ESP32 (1)経験談 (1)フリーランス (1)mac (1)csv (1)docker (1)GithubActions (1)Dialog (1)BI (1)LifeHack (1)ショートカット (1)Chrome (1)高校生 (1)キャリア教育 (1)非同期処理 (1)生体認証 (1)BackdropFilter (1)レビュー (1)getAuth (1)Algolia (1)コンサルティング (1)Symbol (1)

お知らせ

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More
U30可茂ITインターンハッカソン

U30可茂ITインターンハッカソン

12月28,29日開催。2日間でアプリ開発の企画から完成までを目指す!U30可茂ITインターンハッカソンを開催します。

Read More