{"id":25067,"date":"2025-11-24T22:41:44","date_gmt":"2025-11-24T22:41:44","guid":{"rendered":"https:\/\/pokecon.jp\/job\/?p=25067"},"modified":"2025-11-24T22:41:44","modified_gmt":"2025-11-24T22:41:44","slug":"state-driven-clean-architecture-flutter-riverpod%e3%81%a7%e8%80%83%e3%81%88%e3%82%8b%e7%8a%b6%e6%85%8b%e4%b8%ad%e5%bf%83%e8%a8%ad%e8%a8%88","status":"publish","type":"post","link":"https:\/\/pokecon.jp\/job\/25067\/","title":{"rendered":"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08"},"content":{"rendered":"\n<\/p>\n<div>\n<h2 id=\"%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB\" data-line=\"0\" class=\"code-line\">\n \u306f\u3058\u3081\u306b<\/h2>\n<p data-line=\"1\" class=\"code-line\">Flutter\u958b\u767a\u6b742\u5e74\u3067\u521d\u3081\u30660\u304b\u3089Flutter\u306e\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea\u3092\u4f5c\u3063\u3066\u307f\u3088\u3046\u3068\u601d\u3063\u305f\u6642\u306b\u3001\u3069\u3046\u3044\u3046\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u3092\u9078\u3076\u306e\u304c\u6700\u9069\u306a\u306e\u304b\u60a9\u307f\u307e\u3057\u305f\u3002<\/p>\n<p data-line=\"3\" class=\"code-line\">\u4eca\u307e\u3067\u643a\u308f\u3063\u3066\u3044\u305fFlutter\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u69cb\u6210\u306ffeature-first + MVVM\u3067\u3057\u305f\u304c\u3001\u3053\u306e\u69cb\u6210\u3067\u306f\u3001\u4e3b\u306b2\u3064\u306e\u8ab2\u984c\u304c\u3042\u308a\u307e\u3057\u305f\u3002<\/p>\n<ol data-line=\"4\" class=\"code-line\">\n<li data-line=\"4\" class=\"code-line\">ViewModel\u3068Riverpod\u306e\u8cac\u52d9\u304c\u91cd\u8907\u3057\u3066\u66d6\u6627\u306b\u306a\u308b\u3053\u3068\u3067\u3059\u3002\n<ul data-line=\"5\" class=\"code-line\">\n<li data-line=\"5\" class=\"code-line\">ViewModel\u304c\u72b6\u614b\u7ba1\u7406\u3084\u975e\u540c\u671f\u51e6\u7406\u306e\u30ed\u30b8\u30c3\u30af\u3092\u6301\u3064\u4e00\u65b9\u3067\u3001Riverpod\u3082\u540c\u69d8\u306e\u8cac\u52d9\u3092\u62c5\u3048\u308b\u305f\u3081\u3001\u3069\u3061\u3089\u3067\u72b6\u614b\u3092\u6271\u3046\u3079\u304d\u304b\u5224\u65ad\u304c\u96e3\u3057\u304f\u306a\u3063\u3066\u3044\u307e\u3057\u305f\u3002\u7d50\u679c\u3068\u3057\u3066\u3001\u51e6\u7406\u306e\u5206\u62c5\u3084\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\u304c\u4e0d\u660e\u77ad\u306b\u306a\u308a\u304c\u3061\u3067\u3057\u305f<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"6\" class=\"code-line\">feature-first\u69cb\u6210\u3068Flutter\u306e\u8a2d\u8a08\u601d\u60f3\u306e\u76f8\u6027\u306e\u554f\u984c\n<ul data-line=\"7\" class=\"code-line\">\n<li data-line=\"7\" class=\"code-line\">Flutter\u306f\u300c\u72b6\u614b\u4e2d\u5fc3\u300d\u3067\u69cb\u6210\u3055\u308c\u308b\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3067\u3042\u308a\u3001\u30a6\u30a3\u30b8\u30a7\u30c3\u30c8\u968e\u5c64\u3092\u57fa\u70b9\u306b\u72b6\u614b\u304c\u81ea\u7136\u306b\u6d41\u308c\u308b\u8a2d\u8a08\u306b\u306a\u3063\u3066\u3044\u307e\u3059<\/li>\n<li data-line=\"8\" class=\"code-line\">\u3057\u304b\u3057\u3001feature-first\u69cb\u6210\u3067\u306f\u7570\u306a\u308b\u6a5f\u80fd\u9593\u3067ViewModel\u3092\u8de8\u3044\u3067\u51e6\u7406\u3092\u547c\u3073\u51fa\u3059\u30b1\u30fc\u30b9\u304c\u5897\u3048\u3001\u5171\u901a\u5316\u3084\u4f9d\u5b58\u95a2\u4fc2\u306e\u6574\u7406\u304c\u96e3\u3057\u304f\u306a\u308a\u307e\u3057\u305f\u3002\u7d50\u679c\u3068\u3057\u3066\u3001\u300c\u76ee\u7684\u306e\u30e1\u30bd\u30c3\u30c9\u304c\u3069\u3053\u306b\u3042\u308b\u306e\u304b\u300d\u304c\u5206\u304b\u308a\u3065\u3089\u304f\u306a\u308a\u3001\u958b\u767a\u52b9\u7387\u306b\u3082\u5f71\u97ff\u3057\u3066\u3044\u307e\u3057\u305f<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p data-line=\"10\" class=\"code-line\">\u3053\u308c\u3089\u306e\u554f\u984c\u306f\u300cMVVM\u304c\u60aa\u3044\u300d\u300cfeature-first\u304c\u60aa\u3044\u300d\u3068\u3044\u3046\u8a71\u3067\u306f\u306a\u304f\u3001<br \/>\u305f\u3060\u3001Flutter\u3068\u3044\u3046\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u306e\u8a2d\u8a08\u601d\u60f3\u306b\u305d\u306e\u307e\u307e\u5f53\u3066\u306f\u3081\u308b\u306b\u306f\u7121\u7406\u304c\u3042\u308b\u3068\u611f\u3058\u307e\u3057\u305f\u3002<\/p>\n<p data-line=\"13\" class=\"code-line\">\u305d\u3053\u3067\u4eca\u56de\u3001Flutter\u306e\u7279\u5fb4\u3092\u8e0f\u307e\u3048\u305f\u3046\u3048\u3067\u3001\u3088\u308a\u81ea\u7136\u3067\u3001Flutter\u306b\u6700\u9069\u5316\u3055\u308c\u305f\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3 \u3092\u518d\u69cb\u7bc9\u3057\u307e\u3057\u305f\u3002<\/p>\n<p data-line=\"15\" class=\"code-line\">\u3053\u308c\u304b\u3089Flutter\u3067\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea\u3092\u8a2d\u8a08\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u308b\u65b9\u306b\u3001\u5c11\u3057\u3067\u3082\u53c2\u8003\u306b\u306a\u308c\u3070\u5e78\u3044\u3067\u3059\u3002<\/p>\n<h2 id=\"%E5%AF%BE%E8%B1%A1%E8%80%85\" data-line=\"17\" class=\"code-line\">\n \u5bfe\u8c61\u8005<\/h2>\n<p data-line=\"18\" class=\"code-line\">\u672c\u8a18\u4e8b\u306f\u3001Flutter\u3067\u65b0\u898f\u30a2\u30d7\u30ea\u30920\u304b\u3089\u8a2d\u8a08\u3057\u305f\u3044\u65b9\u3001Riverpod\u3092\u4f7f\u3063\u3066\u8cac\u52d9\u5206\u96e2\u3092\u660e\u78ba\u306b\u3057\u305f\u3044\u65b9\u3001MVVM\u3068\u306e\u9055\u3044\u3092\u6574\u7406\u3057\u305f\u3044\u65b9\u306b\u7279\u306b\u304a\u3059\u3059\u3081\u306e\u5185\u5bb9\u3067\u3059\u3002<\/p>\n<h2 id=\"%E5%89%8D%E6%8F%90%E3%81%A8%E3%81%AA%E3%82%8B%E6%8A%80%E8%A1%93%E8%A6%81%E7%B4%A0\" data-line=\"20\" class=\"code-line\">\n \u524d\u63d0\u3068\u306a\u308b\u6280\u8853\u8981\u7d20<\/h2>\n<p data-line=\"21\" class=\"code-line\">\u672c\u8a18\u4e8b\u3067\u7d39\u4ecb\u3059\u308b\u300c\u72b6\u614b\u99c6\u52d5\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u300d\u306f\u3001\u4ee5\u4e0b\u306e2\u3064\u3092\u4e2d\u6838\u3068\u3057\u305f\u69cb\u6210\u3092\u524d\u63d0\u3068\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<ol data-line=\"23\" class=\"code-line\">\n<li data-line=\"23\" class=\"code-line\">Riverpod\u306b\u3088\u308b\u72b6\u614b\u7ba1\u7406<\/li>\n<li data-line=\"24\" class=\"code-line\">go_router\u306b\u3088\u308b\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u304a\u3088\u3073\u30b9\u30bf\u30c3\u30af\u7ba1\u7406<\/li>\n<\/ol>\n<p data-line=\"26\" class=\"code-line\">\u306a\u304a\u3001\u300c\u72b6\u614b\u99c6\u52d5\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u300d\u3068\u3044\u3046\u540d\u79f0\u306f\u4e00\u822c\u7684\u306a\u7528\u8a9e\u3067\u306f\u306a\u304f\u3001\u672c\u8a18\u4e8b\u306b\u304a\u3044\u3066\u79c1\u304c\u5b9a\u7fa9\u3057\u305f\u72ec\u81ea\u306e\u6982\u5ff5\u3067\u3059\u3002<br \/>Flutter\u306e\u300cUI = f(state)\u300d\u3068\u3044\u3046\u8a2d\u8a08\u601d\u60f3\u3092\u8e0f\u307e\u3048\u3001\u72b6\u614b\u3092\u8ef8\u306b\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306e\u5404\u5c64\u3092\u518d\u69cb\u6210\u3057\u305f\u8003\u3048\u65b9\u3092\u6307\u3057\u307e\u3059\u3002<\/p>\n<h2 id=\"flutter%E3%81%AE%E8%A8%AD%E8%A8%88%E6%80%9D%E6%83%B3%E3%81%A8mvvm%E3%81%AE%E7%90%86%E8%A7%A3\" data-line=\"29\" class=\"code-line\">\n Flutter\u306e\u8a2d\u8a08\u601d\u60f3\u3068MVVM\u306e\u7406\u89e3<\/h2>\n<p data-line=\"30\" class=\"code-line\">Flutter\u306e\u8a2d\u8a08\u601d\u60f3\u3092\u8e0f\u307e\u3048\u3066\u3001MVVM\u304c\u3069\u306e\u3088\u3046\u306a\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u30d1\u30bf\u30fc\u30f3\u306a\u306e\u304b\u3092\u6574\u7406\u3057\u307e\u3059\u3002<br \/>\u8a73\u7d30\u306a\u89e3\u8aac\u306f\u4ee5\u4e0b\u306e\u8a18\u4e8b\u306b\u307e\u3068\u3081\u3066\u3044\u308b\u305f\u3081\u3001\u3053\u3053\u3067\u306f\u672c\u8a18\u4e8b\u3092\u8aad\u3080\u3046\u3048\u3067\u5fc5\u8981\u306a\u8981\u70b9\u306e\u307f\u5171\u6709\u3057\u307e\u3059\u3002<\/p>\n<h3 id=\"flutter%E3%81%AE%E8%A8%AD%E8%A8%88%E6%80%9D%E6%83%B3\" data-line=\"32\" class=\"code-line\">\n Flutter\u306e\u8a2d\u8a08\u601d\u60f3<\/h3>\n<p data-line=\"33\" class=\"code-line\">Flutter\u306f\u300cUI = f(state)\u300d\u3068\u3044\u3046\u660e\u78ba\u306a\u601d\u60f3\u306b\u57fa\u3065\u3044\u3066\u8a2d\u8a08\u3055\u308c\u3066\u3044\u307e\u3059\u3002<br \/>\u3064\u307e\u308a\u3001UI\u306f\u72b6\u614b\uff08state\uff09\u306e\u7d50\u679c\u3068\u3057\u3066\u63cf\u753b\u3055\u308c\u308b\u3082\u306e\u3067\u3042\u308a\u3001\u72b6\u614b\u306e\u5909\u5316\u306b\u5fdc\u3058\u3066UI\u3092\u518d\u69cb\u7bc9\u3059\u308b\u30ea\u30a2\u30af\u30c6\u30a3\u30d6\u306a\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3067\u3059\u3002<br \/>\u3053\u306e\u305f\u3081\u3001\u72b6\u614b\u306e\u6d41\u308c\u3092\u5358\u4e00\u65b9\u5411\u306b\u4fdd\u3061\u3001\u72b6\u614b\u3092\u3069\u3046\u7ba1\u7406\u3057UI\u306b\u53cd\u6620\u3059\u308b\u304b\u304c\u8a2d\u8a08\u306e\u4e2d\u5fc3\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<h3 id=\"mvvm%E3%81%A8%E3%81%AF\" data-line=\"36\" class=\"code-line\">\n MVVM\u3068\u306f<\/h3>\n<p data-line=\"37\" class=\"code-line\">MVVM\uff08Model\u2013View\u2013ViewModel\uff09\u306f\u3001UI\u3068\u30ed\u30b8\u30c3\u30af\u3092\u5206\u96e2\u3057\u3001\u8868\u793a\uff08View\uff09\u30fb\u72b6\u614b\u3068\u30d7\u30ec\u30bc\u30f3\u30c6\u30fc\u30b7\u30e7\u30f3\u30ed\u30b8\u30c3\u30af\uff08ViewModel\uff09\u30fb\u30c9\u30e1\u30a4\u30f3\uff0f\u30c7\u30fc\u30bf\uff08Model\uff09\u306e\u8cac\u52d9\u3092\u660e\u78ba\u306b\u3059\u308b\u305f\u3081\u306e\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u30d1\u30bf\u30fc\u30f3\u3067\u3059\u3002<br \/>\u30dd\u30a4\u30f3\u30c8\u306f\u300cUI\u306f\u72b6\u614b\u306e\u7d50\u679c\u3068\u3057\u3066\u63cf\u753b\u3055\u308c\u308b\u300d\u3068\u3044\u3046\u8003\u3048\u65b9\u306b\u7acb\u3061\u3001ViewModel\u304c\u5358\u4e00\u306e\u771f\u5b9f\u306e\u72b6\u614b\uff08Single Source of Truth\uff09\u3092\u63d0\u4f9b\u3059\u308b\u3053\u3068\u3067\u3059\u3002<\/p>\n<p data-line=\"40\" class=\"code-line\">\u53c2\u8003: <a target=\"_blank\" href=\"%5Bhttps:\/\/docs.flutter.dev\/%5D(https:\/\/zenn.dev\/assign\/articles\/bb4ff51d8e4c0c)\" target=\"_blank\">\u300cMVVM\uff1d\u53cc\u65b9\u5411\u30c7\u30fc\u30bf\u30d0\u30a4\u30f3\u30c7\u30a3\u30f3\u30b0\u300d\u3058\u3083\u306a\u3044\uff01Flutter\u3067\u6b63\u3057\u304f\u7406\u89e3\u3059\u308bMVVM<\/a><\/p>\n<h2 id=\"%E5%AE%9F%E8%A3%85%E4%BE%8B%E3%81%A7%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E5%95%8F%E9%A1%8C%E7%82%B9\" data-line=\"42\" class=\"code-line\">\n \u5b9f\u88c5\u4f8b\u3067\u78ba\u8a8d\u3059\u308b\u554f\u984c\u70b9<\/h2>\n<p data-line=\"43\" class=\"code-line\">\u307e\u305a\u306f\u8ab2\u984c\u611f\u306e\u30a4\u30e1\u30fc\u30b8\u3092\u6301\u3063\u3066\u3082\u3089\u3046\u305f\u3081\u306b\u3001\u5b9f\u969b\u306e\u30b3\u30fc\u30c9\u30d9\u30fc\u30b9\u3067\u78ba\u8a8d\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n<h3 id=\"%E5%85%B7%E4%BD%93%E4%BE%8B1%EF%BC%9Ariverpod-vs-viewmodel-%E2%80%94-%E8%B2%AC%E5%8B%99%E3%81%8C%E6%9B%96%E6%98%A7%E3%81%AB%E3%81%AA%E3%82%8B%E3%82%B1%E3%83%BC%E3%82%B9\" data-line=\"45\" class=\"code-line\">\n \u5177\u4f53\u4f8b1\uff1aRiverpod vs ViewModel \u2014 \u8cac\u52d9\u304c\u66d6\u6627\u306b\u306a\u308b\u30b1\u30fc\u30b9<\/h3>\n<p data-line=\"46\" class=\"code-line\">Flutter \u00d7 MVVM\u69cb\u6210\u3092\u63a1\u7528\u3057\u3066\u3044\u305f\u5f53\u521d\u306f\u3001StateProvider\u3084ChangeNotifierProvider\u306a\u3069\u3001\u72b6\u614b\u7ba1\u7406\u5c02\u7528\u306e Provider \u306b ViewModel \u3092\u7d44\u307f\u5408\u308f\u305b\u308b\u69cb\u6210\u304c\u4e00\u822c\u7684\u3067\u3057\u305f\u3002<br \/>\u3057\u304b\u3057\u3001AsyncNotifier \u3084 Notifier \u306e\u3088\u3046\u306b\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u3092\u76f4\u63a5\u6271\u3048\u308b Provider \u304c\u767b\u5834\u3057\u305f\u3053\u3068\u3067\u3001ViewModel \u306e\u5b58\u5728\u610f\u7fa9\u304c\u8584\u308c\u3064\u3064\u3042\u308b\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<h4 id=\"before%EF%BC%9Aviewmodel%E4%B8%AD%E5%BF%83%E3%81%AE%E6%A7%8B%E6%88%90%EF%BC%88changenotifier%E3%82%92%E4%BD%BF%E7%94%A8%EF%BC%89\" data-line=\"49\" class=\"code-line\">\n Before\uff1aViewModel\u4e2d\u5fc3\u306e\u69cb\u6210\uff08ChangeNotifier\u3092\u4f7f\u7528\uff09<\/h4>\n<div class=\"code-block-container\">\n<pre class=\"language-dart\"><code class=\"language-dart code-line\" data-line=\"51\"><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">UserViewModel<\/span> <span class=\"token keyword\">extends<\/span> <span class=\"token class-name\">ChangeNotifier<\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">final<\/span> _repository <span class=\"token operator\">=<\/span> <span class=\"token class-name\">UserRepository<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token class-name\">User<\/span><span class=\"token operator\">?<\/span> _user<span class=\"token punctuation\">;<\/span>\n  bool _isLoading <span class=\"token operator\">=<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token class-name\">User<\/span><span class=\"token operator\">?<\/span> <span class=\"token keyword\">get<\/span> user <span class=\"token operator\">=<\/span><span class=\"token operator\">&gt;<\/span> _user<span class=\"token punctuation\">;<\/span>\n  bool <span class=\"token keyword\">get<\/span> isLoading <span class=\"token operator\">=<\/span><span class=\"token operator\">&gt;<\/span> _isLoading<span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token class-name\">Future<\/span><span class=\"token generics\"><span class=\"token punctuation\"><span class=\"token keyword\">void<\/span><span class=\"token punctuation\">&gt;<\/span><\/span> <span class=\"token function\">fetchUser<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">{<\/span>\n    _isLoading <span class=\"token operator\">=<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token function\">notifyListeners<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n    _user <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> _repository<span class=\"token punctuation\">.<\/span><span class=\"token function\">fetchUser<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n    _isLoading <span class=\"token operator\">=<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token function\">notifyListeners<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span>\n<span class=\"token punctuation\">}<\/span>\n\n<span class=\"token keyword\">final<\/span> userViewModelProvider <span class=\"token operator\">=<\/span> <span class=\"token class-name\">ChangeNotifierProvider<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>_<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token class-name\">UserViewModel<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<\/span><\/code><\/pre>\n<\/div>\n<p data-line=\"71\" class=\"code-line\">\u3053\u306e\u6642\u4ee3\u306e\u69cb\u6210\u3067\u306f\u3001<br \/>\u2022\tViewModel\u304c\u72b6\u614b\uff08_user, _isLoading\uff09\u3092\u4fdd\u6301<br \/>\u2022\tUI\u306f\u305d\u306e\u72b6\u614b\u3092\u8cfc\u8aad\u3057\u3066\u63cf\u753b<br \/>\u3068\u3044\u3046\u3088\u3046\u306b\u3001\u72b6\u614b\u3068\u30ed\u30b8\u30c3\u30af\u304cViewModel\u306b\u96c6\u7d04\u3055\u308c\u3066\u3044\u307e\u3057\u305f\u3002<\/p>\n<h4 id=\"after%EF%BC%9Aasyncnotifier%E3%81%AB%E3%82%88%E3%82%8B%E7%9B%B4%E6%8E%A5%E7%9A%84%E3%81%AA%E7%8A%B6%E6%85%8B%E7%AE%A1%E7%90%86\" data-line=\"76\" class=\"code-line\">\n After\uff1aAsyncNotifier\u306b\u3088\u308b\u76f4\u63a5\u7684\u306a\u72b6\u614b\u7ba1\u7406<\/h4>\n<p data-line=\"78\" class=\"code-line\">Riverpod 2.0\u4ee5\u964d\u3001AsyncNotifier\u3084Notifier\u304c\u767b\u5834\u3057\u3001<br \/>\u72b6\u614b\u7ba1\u7406\u3068\u975e\u540c\u671f\u30ed\u30b8\u30c3\u30af\u3092Provider\u5358\u4f53\u3067\u5b8c\u7d50\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<div class=\"code-block-container\">\n<pre class=\"language-dart\"><code class=\"language-dart code-line\" data-line=\"81\"><span class=\"token keyword\">final<\/span> userNotifierProvider <span class=\"token operator\">=<\/span>\n    <span class=\"token class-name\">AsyncNotifierProvider<\/span><span class=\"token generics\"><span class=\"token punctuation\"><span class=\"token class-name\">UserNotifier<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">User<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">UserNotifier<\/span><span class=\"token punctuation\">.<\/span><span class=\"token keyword\">new<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">class<\/span> <span class=\"token class-name\">UserNotifier<\/span> <span class=\"token keyword\">extends<\/span> <span class=\"token class-name\">AsyncNotifier<\/span><span class=\"token generics\"><span class=\"token punctuation\"><span class=\"token class-name\">User<\/span><span class=\"token punctuation\">&gt;<\/span><\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">final<\/span> _repository <span class=\"token operator\">=<\/span> <span class=\"token class-name\">UserRepository<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token metadata function\">@override<\/span>\n  <span class=\"token class-name\">FutureOr<\/span><span class=\"token generics\"><span class=\"token punctuation\"><span class=\"token class-name\">User<\/span><span class=\"token punctuation\">&gt;<\/span><\/span> <span class=\"token function\">build<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">{<\/span>\n    \n    <span class=\"token keyword\">return<\/span> _repository<span class=\"token punctuation\">.<\/span><span class=\"token function\">fetchUser<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span>\n\n  <span class=\"token class-name\">Future<\/span><span class=\"token generics\"><span class=\"token punctuation\"><span class=\"token keyword\">void<\/span><span class=\"token punctuation\">&gt;<\/span><\/span> <span class=\"token function\">refresh<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">async<\/span> <span class=\"token punctuation\">{<\/span>\n    \n    state <span class=\"token operator\">=<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token class-name\">AsyncLoading<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n    state <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> <span class=\"token class-name\">AsyncValue<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">guard<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=<\/span><span class=\"token operator\">&gt;<\/span> _repository<span class=\"token punctuation\">.<\/span><span class=\"token function\">fetchUser<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span>\n<span class=\"token punctuation\">}<\/span>\n<\/span><\/span><\/span><\/span><\/code><\/pre>\n<\/div>\n<p data-line=\"101\" class=\"code-line\">\u3053\u3053\u3067\u306fViewModel\u304c\u4e0d\u8981\u3068\u306a\u308a\u3001<br \/>UI\u306f\u6b21\u306e\u3088\u3046\u306bProvider\u3092\u76f4\u63a5\u76e3\u8996\u3057\u3066\u63cf\u753b\u3057\u307e\u3059\u3002<\/p>\n<div class=\"code-block-container\">\n<pre class=\"language-dart\"><code class=\"language-dart code-line\" data-line=\"103\"><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">UserPage<\/span> <span class=\"token keyword\">extends<\/span> <span class=\"token class-name\">ConsumerWidget<\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token metadata function\">@override<\/span>\n  <span class=\"token class-name\">Widget<\/span> <span class=\"token function\">build<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">BuildContext<\/span> context<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">WidgetRef<\/span> ref<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\n    <span class=\"token keyword\">final<\/span> userState <span class=\"token operator\">=<\/span> ref<span class=\"token punctuation\">.<\/span><span class=\"token function\">watch<\/span><span class=\"token punctuation\">(<\/span>userNotifierProvider<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n    <span class=\"token keyword\">return<\/span> userState<span class=\"token punctuation\">.<\/span><span class=\"token function\">when<\/span><span class=\"token punctuation\">(<\/span>\n      data<span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">(<\/span>user<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token class-name\">Text<\/span><span class=\"token punctuation\">(<\/span>user<span class=\"token punctuation\">.<\/span>name<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span>\n      loading<span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token class-name\">CircularProgressIndicator<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span>\n      error<span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">(<\/span>error<span class=\"token punctuation\">,<\/span> _<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token class-name\">Text<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-literal\"><span class=\"token string\">'Error: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">$<\/span><span class=\"token expression\">error<\/span><\/span><span class=\"token string\">'<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span>\n    <span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span>\n<span class=\"token punctuation\">}<\/span>\n<\/code><\/pre>\n<\/div>\n<p data-line=\"118\" class=\"code-line\">\u5f93\u6765\u3001ViewModel\u306f\u300c\u72b6\u614b\u306e\u4fdd\u6301\u300d\u3068\u300c\u30d7\u30ec\u30bc\u30f3\u30c6\u30fc\u30b7\u30e7\u30f3\u30ed\u30b8\u30c3\u30af\u306e\u7ba1\u7406\u300d\u3068\u3044\u30462\u3064\u306e\u8cac\u52d9\u3092\u62c5\u3063\u3066\u3044\u307e\u3057\u305f\u3002<br \/>\u3057\u304b\u3057\u3001Riverpod\u306eNotifier\u7cfb\uff08<code>Notifier<\/code> \/ <code>AsyncNotifier<\/code>\uff09\u306e\u767b\u5834\u306b\u3088\u3063\u3066\u3001\u3053\u308c\u3089\u306e\u8cac\u52d9\u306e\u591a\u304f\u3092Provider\u5358\u4f53\u3067\u5b8c\u7d50\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u3063\u305f\u305f\u3081\u3001\u7d50\u679c\u7684\u306bViewModel\u306e\u5b58\u5728\u610f\u7fa9\u304c\u8584\u308c\u3064\u3064\u3042\u308b\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<p data-line=\"121\" class=\"code-line\">\u3082\u3057\u305d\u308c\u3067\u3082ViewModel\u3092\u6b8b\u3059\u5834\u5408\u3001\u8cac\u52d9\u306e\u5206\u96e2\u3068\u3057\u3066\u306f\u6b21\u306e\u3088\u3046\u306a\u69cb\u9020\u306b\u306a\u308b\u3068\u79c1\u306f\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<ul data-line=\"123\" class=\"code-line\">\n<li data-line=\"123\" class=\"code-line\">\n<strong>ViewModel<\/strong>\uff1a\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u3092\u62c5\u5f53\uff08\u30c9\u30e1\u30a4\u30f3\u5c64\u306b\u8fd1\u3044\u8cac\u52d9\uff09<\/li>\n<li data-line=\"124\" class=\"code-line\">\n<strong>Riverpod<\/strong>\uff1a\u72b6\u614b\u7ba1\u7406\u3068ViewModel\u306e\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u3092\u62c5\u3046\u30aa\u30fc\u30b1\u30b9\u30c8\u30ec\u30fc\u30b7\u30e7\u30f3\u5c64<\/li>\n<\/ul>\n<p data-line=\"126\" class=\"code-line\">\u305f\u3060\u3057\u3053\u306e\u69cb\u6210\u3067\u306f\u3001<br \/>ViewModel\u304c\u30d7\u30ec\u30bc\u30f3\u30c6\u30fc\u30b7\u30e7\u30f3\u30ed\u30b8\u30c3\u30af\u3092\u3001Riverpod\u304c\u72b6\u614b\u7ba1\u7406\u3092\u305d\u308c\u305e\u308c\u90e8\u5206\u7684\u306b\u62c5\u3046\u5f62\u3068\u306a\u308a\u3001\u7d50\u679c\u3068\u3057\u3066\u3001\u672c\u6765ViewModel\u304c\u4e00\u8cab\u3057\u3066\u62c5\u3046\u3079\u304d\u300c\u72b6\u614b\u300d\u3068\u300c\u30d7\u30ec\u30bc\u30f3\u30c6\u30fc\u30b7\u30e7\u30f3\u30ed\u30b8\u30c3\u30af\u300d\u306e\u8cac\u52d9\u3092\u5358\u4f53\u3067\u5b8c\u7d50\u3067\u304d\u3066\u3044\u306a\u3044\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<p data-line=\"129\" class=\"code-line\">\u305d\u306e\u7d50\u679c\u3001Flutter + Riverpod\u74b0\u5883\u306b\u304a\u3044\u3066\u306f\u3001MVVM\u3068\u3044\u3046\u69cb\u9020\u3092\u7dad\u6301\u3059\u308b\u5fc5\u7136\u6027\u304c\u4f4e\u4e0b\u3057\u3001MVVM\u3092\u63a1\u7528\u3057\u305f\u5834\u5408\u3001\u4f3c\u305f\u8cac\u52d9\u3092\u6301\u3064\u5c64\u304c\u4e8c\u91cd\u306b\u5b58\u5728\u3059\u308b\u72b6\u614b\u304c\u751f\u307e\u308c\u3084\u3059\u304f\u306a\u308a\u3001\u958b\u767a\u8005\u306e\u6df7\u4e71\u3084\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u6027\u306e\u4f4e\u4e0b\u306b\u3064\u306a\u304c\u308b\u8981\u56e0\u3068\u306a\u308b\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<h3 id=\"%E5%85%B7%E4%BD%93%E4%BE%8B2%EF%BC%9Afeature-first-vs-ui-%3D-f(state)\" data-line=\"131\" class=\"code-line\">\n \u5177\u4f53\u4f8b2\uff1afeature-first vs UI = f(state)<\/h3>\n<p data-line=\"132\" class=\"code-line\">Flutter\u306f\u300cUI = f(state)\u300d\u3001\u3059\u306a\u308f\u3061UI\u306f\u72b6\u614b\u306e\u7d50\u679c\u3068\u3057\u3066\u63cf\u753b\u3055\u308c\u308b\u3068\u3044\u3046\u8a2d\u8a08\u601d\u60f3\u306b\u57fa\u3065\u3044\u3066\u3044\u307e\u3059\u3002<br \/>\u3053\u306e\u601d\u60f3\u306e\u3082\u3068\u3067\u306f\u3001\u300c\u72b6\u614b\u304c\u3069\u3053\u306b\u3042\u308a\u3001\u3069\u306e\u3088\u3046\u306bUI\u3078\u4f1d\u64ad\u3059\u308b\u304b\u300d\u3092\u5358\u7d14\u306b\u4fdd\u3064\u3053\u3068\u304c\u91cd\u8981\u3067\u3059\u304c\u3001feature-first\u69cb\u6210\u3067\u306f\u6a5f\u80fd\u5358\u4f4d\u3067\u30d5\u30a9\u30eb\u30c0\u3092\u5206\u3051\u308b\u3053\u3068\u3092\u512a\u5148\u3059\u308b\u3042\u307e\u308a\u3001\u72b6\u614b\u3084\u30ed\u30b8\u30c3\u30af\u304c feature\u3092\u8de8\u3044\u3067\u4f9d\u5b58\u3059\u308b\u3088\u3046\u306b\u306a\u308a\u3001\u3053\u306e\u72b6\u614b\u306e\u6d41\u308c\u304c\u5206\u6563\u3057\u3001UI\u304c\u72b6\u614b\u3092\u76f4\u63a5\u53c2\u7167\u3067\u304d\u306a\u304f\u306a\u308b\u30b1\u30fc\u30b9\u304c\u591a\u767a\u3057\u307e\u3059\u3002<\/p>\n<div class=\"code-block-container\">\n<pre class=\"language-plaintext\"><code class=\"language-plaintext code-line\" data-line=\"135\">lib\/\n \u251c\u2500 features\/\n \u2502   \u251c\u2500 user\/\n \u2502   \u2502   \u251c\u2500 user_view_model.dart\n \u2502   \u2502   \u2514\u2500 user_repository.dart\n \u2502   \u251c\u2500 chat\/\n \u2502   \u2502   \u251c\u2500 chat_view_model.dart\n \u2502   \u2502   \u2514\u2500 chat_repository.dart\n \u2502   \u2514\u2500 common\/\n \u2502       \u2514\u2500 widgets\/\n<\/code><\/pre>\n<\/div>\n<p data-line=\"147\" class=\"code-line\">\u305f\u3068\u3048\u3070\u3001\u30c1\u30e3\u30c3\u30c8\u6a5f\u80fd\u306e\u753b\u9762\u3067\u30e6\u30fc\u30b6\u30fc\u60c5\u5831\u3092\u53c2\u7167\u3057\u305f\u3044\u5834\u5408\u3001<br \/>ChatViewModel \u304c UserViewModel \u306b\u4f9d\u5b58\u3059\u308b\u3088\u3046\u306a\u69cb\u9020\u304c\u751f\u307e\u308c\u307e\u3059\u3002<\/p>\n<div class=\"code-block-container\">\n<pre class=\"language-dart\"><code class=\"language-dart code-line\" data-line=\"149\">\n<span class=\"token keyword\">final<\/span> user <span class=\"token operator\">=<\/span> ref<span class=\"token punctuation\">.<\/span><span class=\"token function\">read<\/span><span class=\"token punctuation\">(<\/span>userViewModelProvider<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>currentUser<span class=\"token punctuation\">;<\/span>\n<span class=\"token keyword\">final<\/span> messages <span class=\"token operator\">=<\/span> <span class=\"token keyword\">await<\/span> _repository<span class=\"token punctuation\">.<\/span><span class=\"token function\">fetchMessages<\/span><span class=\"token punctuation\">(<\/span>user<span class=\"token punctuation\">.<\/span>id<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\nstate <span class=\"token operator\">=<\/span> <span class=\"token class-name\">AsyncData<\/span><span class=\"token punctuation\">(<\/span>messages<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<\/code><\/pre>\n<\/div>\n<p data-line=\"155\" class=\"code-line\">\u3053\u306e\u3088\u3046\u306b\u300cChat\u306e\u72b6\u614b\u3092\u4f5c\u308b\u305f\u3081\u306bUser\u306e\u72b6\u614b\u304c\u5fc5\u8981\u300d\u306b\u306a\u308b\u3068\u3001<br \/>UI\u304c chatState \u3060\u3051\u3067\u5b8c\u7d50\u305b\u305a\u3001\u4ed6\u306e feature \u306e\u72b6\u614b\u3092\u6a2a\u65ad\u7684\u306b\u53c2\u7167\u3059\u308b\u69cb\u9020\u306b\u306a\u308a\u307e\u3059\u3002<br \/>\u305d\u306e\u7d50\u679c\u3001\u72b6\u614b\u9593\u306e\u4f9d\u5b58\u95a2\u4fc2\u304c\u8907\u96d1\u5316\u3057\u3001\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\u304c\u591a\u6bb5\u5316\u3059\u308b\u3053\u3068\u3067\u3001\u3069\u306e Provider \u304c\u6700\u7d42\u7684\u306a\u72b6\u614b\u3092\u4fdd\u6301\u3057\u3066\u3044\u308b\u306e\u304b\u304c\u5206\u304b\u308a\u306b\u304f\u304f\u306a\u308a\u3001\u610f\u56f3\u3057\u306a\u3044\u4e0d\u5177\u5408\u304c\u767a\u751f\u3057\u3084\u3059\u3044\u69cb\u9020\u306b\u306a\u308b\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<h2 id=\"flutter%E3%81%AB%E6%9C%80%E9%81%A9%E5%8C%96%E3%81%97%E3%81%9F%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%A8%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E6%88%90\" data-line=\"159\" class=\"code-line\">\n Flutter\u306b\u6700\u9069\u5316\u3057\u305f\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u30d1\u30bf\u30fc\u30f3\u3068\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u69cb\u6210<\/h2>\n<p data-line=\"160\" class=\"code-line\">Flutter\u306e\u601d\u60f3\u3092\u524d\u63d0\u306b\u3059\u308b\u3068\u3001\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u3092\u63a1\u7528\u3059\u3079\u304d\u3060\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<h3 id=\"clean-architecture%E3%81%A8%E3%81%AF\" data-line=\"162\" class=\"code-line\">\n Clean Architecture\u3068\u306f<\/h3>\n<p data-line=\"163\" class=\"code-line\">Flutter\u306b\u6700\u9069\u5316\u3057\u305f\u69cb\u6210\u3092\u8aac\u660e\u3059\u308b\u524d\u306b\u3001<br \/>\u307e\u305a\u300cClean Architecture\u300d\u3068\u306f\u4f55\u304b\u3001\u305d\u306e\u57fa\u672c\u7684\u306a\u8003\u3048\u65b9\u3092\u7c21\u5358\u306b\u6574\u7406\u3057\u307e\u3059\u3002<\/p>\n<p data-line=\"166\" class=\"code-line\">Clean Architecture\u306f\u3001Robert C. Martin\uff08\u901a\u79f0 Uncle Bob\uff09\u304c\u63d0\u5531\u3057\u305f\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u30d1\u30bf\u30fc\u30f3\u3067\u3001\u4f9d\u5b58\u65b9\u5411\u3092\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3084UI\u3001DB\u30a2\u30af\u30bb\u30b9\u306a\u3069\u306e\u6280\u8853\u7684\u306a\u8a73\u7d30\u304b\u3089\u3001\u30d3\u30b8\u30cd\u30b9\u30eb\u30fc\u30eb\uff08\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u3084\u30e6\u30fc\u30b9\u30b1\u30fc\u30b9\uff09\u3078\u5411\u3051\u308b\u3053\u3068\u3092\u539f\u5247\u3068\u3057\u3066\u3044\u307e\u3059\u3002<br \/>\u3053\u308c\u306b\u3088\u308a\u3001\u5916\u90e8\u6280\u8853\uff08\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3001UI\u3001DB\uff09\u306b\u4f9d\u5b58\u3057\u306a\u3044\u3001\u72ec\u7acb\u3057\u305f\u30c9\u30e1\u30a4\u30f3\u30ed\u30b8\u30c3\u30af\u3092\u4fdd\u3064\u3053\u3068\u3092\u76ee\u7684\u3068\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p data-line=\"169\" class=\"code-line\">\u3053\u306e\u30a2\u30d7\u30ed\u30fc\u30c1\u306e\u6700\u5927\u306e\u30e1\u30ea\u30c3\u30c8\u306f\u3001\u300c\u5909\u5316\u306b\u5f37\u3044\u69cb\u9020\u300d\u3092\u5b9f\u73fe\u3067\u304d\u308b\u70b9\u3067\u3059\u3002<br \/>UI\u30c7\u30b6\u30a4\u30f3\u3084\u5916\u90e8API\u306e\u4ed5\u69d8\u5909\u66f4\u3068\u3044\u3063\u305f\u5916\u5074\u306e\u8981\u7d20\u304c\u5909\u308f\u3063\u3066\u3082\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u4e2d\u6838\u3067\u3042\u308b\u30c9\u30e1\u30a4\u30f3\u30ed\u30b8\u30c3\u30af\u306f\u5f71\u97ff\u3092\u53d7\u3051\u306b\u304f\u304f\u306a\u308a\u307e\u3059\u3002<br \/>\u7d50\u679c\u3068\u3057\u3066\u3001\u4fee\u6b63\u7bc4\u56f2\u304c\u660e\u78ba\u306b\u306a\u308a\u3001\u6a5f\u80fd\u8ffd\u52a0\u3084\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u306e\u969b\u306b\u30d0\u30b0\u304c\u767a\u751f\u3057\u306b\u304f\u3044\u5b89\u5b9a\u3057\u305f\u69cb\u9020\u3092\u7dad\u6301\u3067\u304d\u307e\u3059\u3002<br \/>\u307e\u305f\u3001\u5c64\u3054\u3068\u306b\u8cac\u52d9\u304c\u660e\u78ba\u306b\u5206\u304b\u308c\u308b\u305f\u3081\u3001UI\u30fb\u30c7\u30fc\u30bf\u30fb\u30ed\u30b8\u30c3\u30af\u306e\u5206\u696d\u304c\u3057\u3084\u3059\u304f\u3001<br \/>\u30c1\u30fc\u30e0\u958b\u767a\u3084\u9577\u671f\u904b\u7528\u306b\u3082\u9069\u3057\u305f\u8a2d\u8a08\u3068\u3044\u3048\u307e\u3059\u3002<\/p>\n<p data-line=\"175\" class=\"code-line\">\u3088\u308a\u8a73\u3057\u3044\u89e3\u8aac\u306b\u3064\u3044\u3066\u306f\u3001\u4ee5\u4e0b\u306e\u8a18\u4e8b\u304c\u53c2\u8003\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p data-line=\"179\" class=\"code-line\">\u79c1\u81ea\u8eab\u3082\u3053\u306e\u6982\u5ff5\u3092\u5b8c\u5168\u306b\u7406\u89e3\u3067\u304d\u305f\u3068\u306f\u8a00\u3048\u305a\u3001\u3053\u306e\u8a18\u4e8b\u3092\u66f8\u304f\u306b\u3042\u305f\u3063\u3066\u6539\u3081\u3066\u95a2\u9023\u66f8\u7c4d\u30922\u518a\u8cfc\u5165\u3057\u3001\u7406\u89e3\u3092\u6df1\u3081\u3066\u3044\u308b\u6700\u4e2d\u3067\u3059\u3001\u3001\u3001<\/p>\n<h3 id=\"%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E6%88%90\" data-line=\"182\" class=\"code-line\">\n \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u69cb\u6210<\/h3>\n<div class=\"code-block-container\">\n<pre class=\"language-plaintext\"><code class=\"language-plaintext code-line\" data-line=\"183\">lib\/\n\u251c\u2500\u2500 main.dart\n\u2502\n\u251c\u2500\u2500 core\/                        # \u5171\u901a\u57fa\u76e4\uff08\u4f8b\u5916\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3001\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u3001\u30e6\u30fc\u30c6\u30a3\u30ea\u30c6\u30a3\u306a\u3069\uff09\n\u2502\n\u251c\u2500\u2500 presentation\/                # UI\u5c64\uff08\u753b\u9762\u30fb\u30a6\u30a3\u30b8\u30a7\u30c3\u30c8\u30fb\u72b6\u614b\u7ba1\u7406\uff09\n\u2502   \u251c\u2500\u2500 pages\/                   # \u5404\u6a5f\u80fd\u306e\u753b\u9762\n\u2502   \u2502   \u251c\u2500\u2500 home\/\n\u2502   \u2502   \u251c\u2500\u2500 user\/\n\u2502   \u2502   \u2514\u2500\u2500 settings\/\n\u2502   \u2502\n\u2502   \u251c\u2500\u2500 controllers\/             # \u72b6\u614b\u7ba1\u7406\uff08Riverpod Notifier \/ Provider\uff09\n\u2502   \u2502   \u251c\u2500\u2500 domain\/              # \u30c9\u30e1\u30a4\u30f3\u5358\u4f4d\u306e\u72b6\u614b\uff08\u4f8b: User, Content, Config\uff09\n\u2502   \u2502   \u2502   \u251c\u2500\u2500 user_controller.dart\n\u2502   \u2502   \u2502   \u251c\u2500\u2500 content_controller.dart\n\u2502   \u2502   \u2502   \u2514\u2500\u2500 config_controller.dart\n\u2502   \u2502   \u2502\n\u2502   \u2502   \u2514\u2500\u2500 feature\/             # \u6a5f\u80fd\u5358\u4f4d\u306e\u72b6\u614b\uff08\u753b\u9762\u30fb\u6a5f\u80fd\u30ed\u30b8\u30c3\u30af\u306b\u5bfe\u5fdc\uff09\n\u2502   \u2502       \u251c\u2500\u2500 home_controller.dart\n\u2502   \u2502       \u251c\u2500\u2500 user_detail_controller.dart\n\u2502   \u2502       \u2514\u2500\u2500 settings_controller.dart\n\u2502   \u2502\n\u2502   \u2514\u2500\u2500 shared\/                  # \u5171\u901aUI\uff08\u5171\u901aWidget\u30fb\u30da\u30fc\u30b8\u306a\u3069\uff09\n\u2502       \u251c\u2500\u2500 widgets\/\n\u2502       \u2514\u2500\u2500 pages\/\n\u2502\n\u251c\u2500\u2500 application\/                 # \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5c64\uff08\u30e6\u30fc\u30b9\u30b1\u30fc\u30b9\u30fb\u30b5\u30fc\u30d3\u30b9\uff09\n\u2502   \u251c\u2500\u2500 user\/\n\u2502   \u251c\u2500\u2500 content\/\n\u2502   \u2514\u2500\u2500 settings\/\n\u2502\n\u251c\u2500\u2500 domain\/                      # \u30c9\u30e1\u30a4\u30f3\u5c64\uff08\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u30fb\u30e2\u30c7\u30eb\uff09\n\u2502   \u251c\u2500\u2500 entities\/\n\u2502   \u251c\u2500\u2500 value_objects\/\n\u2502   \u251c\u2500\u2500 repositories\/\n\u2502   \u2514\u2500\u2500 services\/\n\u2502\n\u2514\u2500\u2500 data\/                        # \u30c7\u30fc\u30bf\u5c64\uff08API\u30fbDB\u30fb\u6c38\u7d9a\u5316\uff09\n    \u251c\u2500\u2500 datasources\/\n    \u251c\u2500\u2500 repositories\/\n    \u251c\u2500\u2500 mappers\/\n    \u2514\u2500\u2500 remote\/\n<\/code><\/pre>\n<\/div>\n<h3 id=\"%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E3%81%AE%E9%96%A2%E4%BF%82%E5%9B%B3\" data-line=\"227\" class=\"code-line\">\n \u30ec\u30a4\u30e4\u30fc\u306e\u95a2\u4fc2\u56f3<\/h3>\n<p><span class=\"embed-block zenn-embedded zenn-embedded-mermaid\"><iframe id=\"zenn-embedded__08e98892180a3\" src=\"https:\/\/embed.zenn.studio\/mermaid#zenn-embedded__08e98892180a3\" data-content=\"flowchart%20TD%0A%20%20%25%25%20%3D%3D%3D%3D%3D%20%E3%83%8E%E3%83%BC%E3%83%89%E5%AE%9A%E7%BE%A9%20%3D%3D%3D%3D%3D%0A%20%20W%5B%22Widget%20(UI)%22%5D%0A%20%20C%5B%22Controller%20(Notifier)%22%5D%0A%20%20A%5B%22Application%20(UseCase%20%2F%20Service)%22%5D%0A%20%20D%5B%22Domain%20(Entity%20%2F%20Repository%20Interface)%22%5D%0A%20%20X%5B%22Data%20(Repository%20Impl%20%2F%20DataSource)%22%5D%0A%0A%20%20%25%25%20%3D%3D%3D%3D%3D%20%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%E3%83%95%E3%83%AD%E3%83%BC%EF%BC%88%E9%A0%86%E6%96%B9%E5%90%91%EF%BC%89%20%3D%3D%3D%3D%3D%0A%20%20W%20--%3E%7C%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E6%93%8D%E4%BD%9C%7C%20C%0A%20%20C%20--%3E%7CUseCase%E5%AE%9F%E8%A1%8C%7C%20A%0A%20%20A%20--%3E%7C%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%7C%20D%0A%20%20D%20--%3E%7C%E3%83%87%E3%83%BC%E3%82%BF%E5%8F%96%E5%BE%97%2F%E4%BF%9D%E5%AD%98%E8%A6%81%E6%B1%82%7C%20X%0A%0A%20%20%25%25%20%3D%3D%3D%3D%3D%20%E7%B5%90%E6%9E%9C%E8%BF%94%E5%8D%B4%E3%83%95%E3%83%AD%E3%83%BC%EF%BC%88%E9%80%86%E6%96%B9%E5%90%91%EF%BC%89%20%3D%3D%3D%3D%3D%0A%20%20X%20--%3E%7C%E5%8F%96%E5%BE%97%E7%B5%90%E6%9E%9C%E3%82%92%E8%BF%94%E3%81%99%7C%20D%0A%20%20D%20--%3E%7C%E5%87%A6%E7%90%86%E7%B5%90%E6%9E%9C%E3%82%92%E8%BF%94%E3%81%99%7C%20A%0A%20%20A%20--%3E%7CDomain%20Model%E3%82%92%E8%BF%94%E3%81%99%7C%20C%0A%20%20C%20--%3E%7C%E7%8A%B6%E6%85%8B%E3%82%92%E6%9B%B4%E6%96%B0%EF%BC%88AsyncValue%E3%81%AA%E3%81%A9%EF%BC%89%7C%20W%0A%0A%20%20%25%25%20%3D%3D%3D%3D%3D%20%E7%8A%B6%E6%85%8B%E6%9B%B4%E6%96%B0%EF%BC%88UI%20%3D%20f(state))%20%3D%3D%3D%3D%3D%0A%20%20W%20--%3E%7C%E7%8A%B6%E6%85%8B%E5%A4%89%E5%8C%96%E3%82%92%E7%9B%A3%E8%A6%96%7C%20C%0A%0A%20%20%25%25%20%3D%3D%3D%3D%3D%20%E8%A3%9C%E8%B6%B3%20%3D%3D%3D%3D%3D%0A%20%20%25%25%20Controller%E3%81%AF%E5%8F%8C%E6%96%B9%E5%90%91%E3%81%A7UI%E3%81%A8%E3%82%84%E3%82%8A%E5%8F%96%E3%82%8A%E3%81%99%E3%82%8B%0A%20%20%25%25%20Application%E4%BB%A5%E4%B8%8B%E3%81%AF%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E2%86%92%E3%83%87%E3%83%BC%E3%82%BF%E9%96%93%E3%81%A7%E9%9D%9E%E5%90%8C%E6%9C%9F%E7%9A%84%E3%81%AB%E7%B5%90%E6%9E%9C%E3%82%92%E8%BF%94%E3%81%99\" frameborder=\"0\" scrolling=\"no\" loading=\"lazy\"><\/iframe><\/span><\/p>\n<h3 id=\"%E7%8A%B6%E6%85%8B%E9%A7%86%E5%8B%95%E6%A7%8B%E9%80%A0%E3%81%AE%E6%B5%81%E3%82%8C\" data-line=\"262\" class=\"code-line\">\n \u72b6\u614b\u99c6\u52d5\u69cb\u9020\u306e\u6d41\u308c<\/h3>\n<p><span class=\"embed-block zenn-embedded zenn-embedded-mermaid\"><iframe id=\"zenn-embedded__46d8f86f3fa9d\" src=\"https:\/\/embed.zenn.studio\/mermaid#zenn-embedded__46d8f86f3fa9d\" data-content=\"sequenceDiagram%0A%20%20participant%20U%20as%20User%0A%20%20participant%20W%20as%20Widget(UI)%0A%20%20participant%20S%20as%20Controller%0A%20%20participant%20A%20as%20Application(UseCase)%0A%20%20participant%20D%20as%20Domain(Entity%2FService)%0A%20%20participant%20R%20as%20Repository%0A%0A%20%20U-%3E%3EW%3A%20%E3%82%BF%E3%83%83%E3%83%97%2F%E5%85%A5%E5%8A%9B%0A%20%20W-%3E%3ES%3A%20%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E7%99%BA%E7%81%AB%EF%BC%88read%2Fwatch%EF%BC%89%0A%20%20S-%3E%3EA%3A%20UseCase%E5%AE%9F%E8%A1%8C%EF%BC%88%E5%89%AF%E4%BD%9C%E7%94%A8%2F%E3%83%95%E3%83%AD%E3%83%BC%EF%BC%89%0A%20%20S-%3E%3ED%3A%20Domain%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF%EF%BC%88%E5%90%8C%E6%9C%9F%E8%A8%88%E7%AE%97%EF%BC%89%0A%20%20A-%3E%3ER%3A%20Repository%20%E7%B5%8C%E7%94%B1%E3%81%A7I%2FO%0A%20%20R--%3E%3EA%3A%20%E7%B5%90%E6%9E%9C%0A%20%20A--%3E%3ES%3A%20Domain%20Model%0A%20%20D--%3E%3ES%3A%20%E8%A8%88%E7%AE%97%E7%B5%90%E6%9E%9C%0A%20%20S--%3E%3EW%3A%20%E7%8A%B6%E6%85%8B%E6%9B%B4%E6%96%B0%EF%BC%88AsyncValue%2FUIState%EF%BC%89%0A%20%20W-%3E%3EW%3A%20%E5%86%8D%E6%8F%8F%E7%94%BB%20(UI%20%3D%20f(state))\" frameborder=\"0\" scrolling=\"no\" loading=\"lazy\"><\/iframe><\/span><\/p>\n<h3 id=\"%E3%81%93%E3%81%AE%E6%A7%8B%E6%88%90%E3%81%AE%E7%8B%99%E3%81%84\" data-line=\"285\" class=\"code-line\">\n \u3053\u306e\u69cb\u6210\u306e\u72d9\u3044<\/h3>\n<p data-line=\"286\" class=\"code-line\">\u3053\u306e\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u69cb\u6210\u306e\u76ee\u7684\u306f\u3001Flutter\u306e\u300c\u5ba3\u8a00\u7684UI\u300d\u3068\u300cClean Architecture\u306e\u539f\u5247\u300d\u3092\u4e21\u7acb\u3055\u305b\u308b\u3053\u3068\u3067\u3059\u3002<\/p>\n<p data-line=\"288\" class=\"code-line\">\u7279\u306b\u3001\u6b21\u306e4\u70b9\u3092\u610f\u8b58\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<ol data-line=\"290\" class=\"code-line\">\n<li data-line=\"290\" class=\"code-line\">\u8cac\u52d9\u306e\u5206\u96e2\u304c\u3067\u304d\u308b\u3053\u3068\n<ul data-line=\"291\" class=\"code-line\">\n<li data-line=\"291\" class=\"code-line\">UI\uff08\u898b\u305f\u76ee\uff09\u30fb\u72b6\u614b\uff08Controller\uff09\u30fb\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\uff08UseCase\uff09\u30fb\u30c9\u30e1\u30a4\u30f3\u30eb\u30fc\u30eb\uff08Entity\uff09\u30fb\u5916\u90e8I\/O\uff08Repository\uff09\u3092\u660e\u78ba\u306b\u5207\u308a\u5206\u3051\u3001\u4f9d\u5b58\u65b9\u5411\u3092\u4e00\u5b9a\u306b\u4fdd\u3064<\/li>\n<li data-line=\"292\" class=\"code-line\">\u3069\u306e\u51e6\u7406\u3092\u3069\u306e\u5c64\u306b\u7f6e\u304f\u304b\u304c\u4e00\u8cab\u3057\u3066\u5224\u65ad\u3067\u304d\u308b<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"293\" class=\"code-line\">SSOT\uff08Single Source of Truth\uff09\u304c\u62c5\u4fdd\u3067\u304d\u308b\u3053\u3068\n<ul data-line=\"294\" class=\"code-line\">\n<li data-line=\"294\" class=\"code-line\">\u3059\u3079\u3066\u306e\u72b6\u614b\u306fRiverpod\u306eProvider\u3092\u4e2d\u5fc3\u306b\u4e00\u5143\u7ba1\u7406\u3055\u308c\u308b<\/li>\n<li data-line=\"295\" class=\"code-line\">UI\u306f\u72b6\u614b\u3092\u76f4\u63a5\u64cd\u4f5c\u305b\u305a\u3001\u300c\u72b6\u614b\u3092\u5909\u3048\u308b\u30c8\u30ea\u30ac\u30fc\u300d\u3060\u3051\u3092\u767a\u706b\u3059\u308b<\/li>\n<li data-line=\"296\" class=\"code-line\">Flutter\u306e\u300cUI = f(state)\u300d\u3068\u3044\u3046\u8a2d\u8a08\u601d\u60f3\u3092\u81ea\u7136\u306a\u5f62\u3067\u5b9f\u73fe\u3057\u3066\u3044\u308b<\/li>\n<li data-line=\"297\" class=\"code-line\">\u3053\u308c\u306b\u3088\u308a\u30c7\u30fc\u30bf\u306e\u6574\u5408\u6027\u3068\u518d\u73fe\u6027\u304c\u4fdd\u8a3c\u3055\u308c\u308b\u3002<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"298\" class=\"code-line\">\u5358\u65b9\u5411\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\u306b\u6700\u9069\u5316\u3055\u308c\u3066\u3044\u308b\u3053\u3068\n<ul data-line=\"299\" class=\"code-line\">\n<li data-line=\"299\" class=\"code-line\">State \u2192 UI \u2192 Event \u2192 State \u306e\u30b5\u30a4\u30af\u30eb\u304c\u660e\u78ba\u3067\u3001\u3069\u3053\u304b\u3089\u3067\u3082\u8ffd\u8de1\u53ef\u80fd<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<aside class=\"msg message\"><span class=\"msg-symbol\">!<\/span><\/p>\n<div class=\"msg-content\">\n<p data-line=\"302\" class=\"code-line\">\ud83d\udca1 \u4e00\u8a00\u3067\u307e\u3068\u3081\u308b\u3068\uff1a<\/p>\n<p data-line=\"304\" class=\"code-line\">\u300c\u72b6\u614b\u3092\u4e2d\u5fc3\u306b\u8cac\u52d9\u3092\u5206\u96e2\u3057\u3001\u5358\u65b9\u5411\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\u3092\u4fdd\u3061\u306a\u304c\u3089\u3001Clean Architecture\u306e\u4f9d\u5b58\u65b9\u5411\u3092\u5d29\u3055\u306a\u3044\u8a2d\u8a08\u3002\u300d<\/p>\n<\/div>\n<\/aside>\n<h2 id=\"mvvm%E3%81%A8feature-first%E6%A7%8B%E6%88%90%E3%81%AE%E8%AA%B2%E9%A1%8C%E3%82%92%E3%81%A9%E3%81%86%E8%A7%A3%E6%B1%BA%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B\" data-line=\"307\" class=\"code-line\">\n MVVM\u3068feature-first\u69cb\u6210\u306e\u8ab2\u984c\u3092\u3069\u3046\u89e3\u6c7a\u3057\u3066\u3044\u308b\u304b<\/h2>\n<h3 id=\"1.-mvvm%E3%81%A8riverpod%E3%81%AE%E8%B2%AC%E5%8B%99%E9%87%8D%E8%A4%87%E3%82%92%E8%A7%A3%E6%B6%88\" data-line=\"309\" class=\"code-line\">\n 1. MVVM\u3068Riverpod\u306e\u8cac\u52d9\u91cd\u8907\u3092\u89e3\u6d88<\/h3>\n<p data-line=\"310\" class=\"code-line\">\u3053\u306e\u69cb\u6210\u3067\u306f\u3001Riverpod\u306eNotifier\u3092Controller\u3068\u3057\u3066\u6271\u3044\u3001Presentation\u5c64\u306b\u304a\u3051\u308b\u72b6\u614b\u7ba1\u7406\u3068\u30d7\u30ec\u30bc\u30f3\u30c6\u30fc\u30b7\u30e7\u30f3\u30ed\u30b8\u30c3\u30af\u306e\u8cac\u52d9\u3092\u7d71\u5408\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p data-line=\"312\" class=\"code-line\">Clean Architecture\u306b\u304a\u3051\u308bController\uff08\u307e\u305f\u306fPresenter\uff09\u306f\u3001UI\u5c64\u3068\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5c64\uff08UseCase\u306a\u3069\uff09\u306e\u9593\u306b\u7acb\u3061\u3001\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u306e\u7d50\u679c\u3092UI\u304c\u6271\u3048\u308b\u5f62\u5f0f\u306b\u5909\u63db\u30fb\u4f1d\u9054\u3059\u308b\u5f79\u5272\u3092\u6301\u3064\u3068\u7406\u89e3\u3057\u3066\u3044\u307e\u3059\u3002<br \/>Flutter + Riverpod\u69cb\u6210\u3067\u306f\u3001\u3053\u306e\u6982\u5ff5\u7684\u306aController\u306e\u8cac\u52d9\u3092Notifier\u304c\u305d\u306e\u307e\u307e\u5b9f\u73fe\u3067\u304d\u308b\u305f\u3081\u3001UI\u304b\u3089\u306e\u30a4\u30d9\u30f3\u30c8\u3092\u53d7\u3051\u53d6\u308a\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5c64\u306e\u51e6\u7406\u7d50\u679c\u3092\u72b6\u614b\u3068\u3057\u3066\u4fdd\u6301\u3057\u3001UI\u306f\u305d\u306e\u72b6\u614b\u3092\u76e3\u8996\u3057\u3066\u81ea\u52d5\u7684\u306b\u518d\u63cf\u753b\u3055\u308c\u307e\u3059\u3002<\/p>\n<p data-line=\"315\" class=\"code-line\">\u3053\u306e\u3088\u3046\u306b\u3001Riverpod\u3092Presentation\u5c64\u306e\u4e2d\u5fc3\u306b\u636e\u3048\u308b\u3053\u3068\u3067\u3001MVVM\u3067\u66d6\u6627\u306b\u306a\u308a\u304c\u3061\u3060\u3063\u305f\u300c\u72b6\u614b\u3092\u3069\u3061\u3089\u304c\u6301\u3064\u306e\u304b\u300d\u3068\u3044\u3046\u554f\u984c\u3092\u89e3\u6d88\u3057\u3001\u72b6\u614b\u306e\u552f\u4e00\u306e\u66f4\u65b0\u6e90\uff08Single Source of Truth\uff09\u3092\u660e\u78ba\u306b\u4fdd\u3064\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n<h3 id=\"2.-feature-first%E6%A7%8B%E6%88%90%E3%81%AE%E7%8A%B6%E6%85%8B%E5%88%86%E6%95%A3%E3%82%92%E8%A7%A3%E6%B6%88\" data-line=\"317\" class=\"code-line\">\n 2. feature-first\u69cb\u6210\u306e\u72b6\u614b\u5206\u6563\u3092\u89e3\u6d88<\/h3>\n<p data-line=\"319\" class=\"code-line\">\u3082\u3046\u4e00\u3064\u306e\u8ab2\u984c\u306f\u3001feature-first\u69cb\u6210\u306b\u3088\u3063\u3066\u72b6\u614b\u304c\u8907\u6570\u306e\u6a5f\u80fd\u9593\u306b\u5206\u6563\u3057\u3001UI\u304c\u7570\u306a\u308bViewModel\u3092\u6a2a\u65ad\u7684\u306b\u53c2\u7167\u3059\u308b\u3053\u3068\u3067\u4f9d\u5b58\u95a2\u4fc2\u304c\u8907\u96d1\u5316\u3059\u308b\u70b9\u3067\u3057\u305f\u3002<\/p>\n<p data-line=\"321\" class=\"code-line\">\u672c\u69cb\u6210\u3067\u306f\u300cstate-first\uff08\u72b6\u614b\u4e2d\u5fc3\uff09\u300d\u3068\u3044\u3046\u8003\u3048\u65b9\u3092\u63a1\u7528\u3057\u3001\u72b6\u614b\u306e\u6d41\u308c\u3092Controller\u5358\u4f4d\u3067\u6574\u7406\u3057\u3066\u3044\u307e\u3059\u3002<br \/>UI\u306f\u4e3b\u3068\u306a\u308bController\u3092\u8ef8\u306b\u63cf\u753b\u3055\u308c\u3064\u3064\u3001\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u4ed6\u306eController\u306e\u72b6\u614b\u3082\u53c2\u7167\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u304c\u3001\u305d\u308c\u305e\u308c\u306eController\u304c\u72ec\u7acb\u3057\u305f\u8cac\u52d9\u3092\u6301\u3064\u305f\u3081\u3001\u6a5f\u80fd\u9593\u3067\u72b6\u614b\u3092\u76f4\u63a5\u5171\u6709\u30fb\u66f4\u65b0\u3059\u308b\u3088\u3046\u306a\u69cb\u9020\u306b\u306f\u306a\u308a\u307e\u305b\u3093\u3002<\/p>\n<p data-line=\"324\" class=\"code-line\">\u3053\u308c\u306b\u3088\u308a\u3001\u72b6\u614b\u306e\u6d41\u308c\u304c\u6574\u7406\u3055\u308c\u3001\u4f9d\u5b58\u95a2\u4fc2\u306e\u8ffd\u8de1\u3084\u4fee\u6b63\u304c\u5bb9\u6613\u306b\u306a\u308a\u307e\u3059\u3002<br \/>\u7d50\u679c\u3068\u3057\u3066\u3001Flutter\u304c\u6301\u3064\u5ba3\u8a00\u7684UI\u306e\u601d\u60f3\u3068\u3001Clean Architecture\u304c\u76ee\u6307\u3059\u8cac\u52d9\u5206\u96e2\u3092\u81ea\u7136\u306b\u4e21\u7acb\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002<\/p>\n<h2 id=\"%E7%8A%B6%E6%85%8B%E9%A7%86%E5%8B%95%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%81%AE%E8%A9%B3%E7%B4%B0\" data-line=\"327\" class=\"code-line\">\n \u72b6\u614b\u99c6\u52d5\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306e\u8a73\u7d30<\/h2>\n<h3 id=\"%E6%A6%82%E8%A6%81\" data-line=\"328\" class=\"code-line\">\n \u6982\u8981<\/h3>\n<p data-line=\"329\" class=\"code-line\">\u72b6\u614b\u99c6\u52d5\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\uff08State-Driven Clean Architecture\uff09\u306f\u3001\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306e\u4f9d\u5b58\u65b9\u5411\u539f\u5247\u3092\u5b88\u308a\u306a\u304c\u3089\u3001Flutter\u306e\u300c\u5ba3\u8a00\u7684UI\u300d\u3068\u300c\u72b6\u614b\u4e2d\u5fc3\u306e\u69cb\u9020\uff08UI = f(state)\uff09\u300d\u3001\u305d\u3057\u3066\u30b3\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\uff08\u95a2\u9023\u3059\u308bUI\u3068\u30ed\u30b8\u30c3\u30af\u3092\u8fd1\u63a5\u914d\u7f6e\u3059\u308b\u69cb\u9020\uff09\u306b\u6700\u9069\u5316\u3057\u305f\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u3067\u3059\u3002<\/p>\n<p data-line=\"331\" class=\"code-line\">\u3053\u306e\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306f\u3001\u6b21\u306e3\u3064\u306e\u8003\u3048\u65b9\u3092\u7d44\u307f\u5408\u308f\u305b\u3066\u518d\u69cb\u6210\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<div class=\"s_table\"><table data-line=\"333\" class=\"code-line\">\n<thead data-line=\"333\" class=\"code-line\">\n<tr data-line=\"333\" class=\"code-line\">\n<th>\u69cb\u6210\u8981\u7d20<\/th>\n<th>\u5f79\u5272<\/th>\n<th>Flutter\u3067\u306e\u5bfe\u5fdc<\/th>\n<\/tr>\n<\/thead>\n<tbody data-line=\"335\" class=\"code-line\">\n<tr data-line=\"335\" class=\"code-line\">\n<td>DDD\uff08Domain-Driven Design\uff09<\/td>\n<td>\u30d3\u30b8\u30cd\u30b9\u30eb\u30fc\u30eb\u3084\u30c9\u30e1\u30a4\u30f3\u30e2\u30c7\u30eb\u3092\u4e2d\u5fc3\u306b\u8a2d\u8a08\u3059\u308b<\/td>\n<td>domain\/ \u5c64\uff08Entity\u30fbValueObject\u30fbRepository Interface\uff09<\/td>\n<\/tr>\n<tr data-line=\"336\" class=\"code-line\">\n<td>MVU\uff08Model-View-Update\uff09<\/td>\n<td>\u5358\u65b9\u5411\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\u3067UI\u3092\u72b6\u614b\u306b\u540c\u671f\u3055\u305b\u308b<\/td>\n<td>presentation\/ \u5c64\uff08Notifier\u30fbWidget\uff09<\/td>\n<\/tr>\n<tr data-line=\"337\" class=\"code-line\">\n<td>Riverpod<\/td>\n<td>\u72b6\u614b\u306e\u5358\u4e00\u7ba1\u7406\u3068\u4f9d\u5b58\u95a2\u4fc2\u306e\u660e\u793a<\/td>\n<td>\u72b6\u614b\u99c6\u52d5\u69cb\u9020\u306e\u57fa\u76e4\uff08Controller = Notifier\uff09<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/div>\n<h3 id=\"%E5%90%84%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E3%81%AE%E5%BD%B9%E5%89%B2\" data-line=\"339\" class=\"code-line\">\n \u5404\u30ec\u30a4\u30e4\u30fc\u306e\u5f79\u5272<\/h3>\n<p data-line=\"340\" class=\"code-line\">\u72b6\u614b\u99c6\u52d5\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u3067\u306f\u3001\u305d\u308c\u305e\u308c\u306e\u30ec\u30a4\u30e4\u30fc\u304c\u300c\u8cac\u52d9\u306e\u5206\u96e2\u300d\u3068\u300c\u5358\u65b9\u5411\u4f9d\u5b58\u300d\u3092\u5b88\u308b\u3088\u3046\u306b\u8a2d\u8a08\u3055\u308c\u3066\u3044\u307e\u3059\u3002<br \/>\u4ee5\u4e0b\u3067\u306f\u5404\u30ec\u30a4\u30e4\u30fc\u306e\u5f79\u5272\u30fb\u69cb\u6210\u30fb\u7981\u6b62\u4e8b\u9805\u3092\u6574\u7406\u3057\u307e\u3059\u3002<\/p>\n<div class=\"s_table\"><table data-line=\"343\" class=\"code-line\">\n<thead data-line=\"343\" class=\"code-line\">\n<tr data-line=\"343\" class=\"code-line\">\n<th>\u30ec\u30a4\u30e4\u30fc<\/th>\n<th>\u4e3b\u306a\u8cac\u52d9<\/th>\n<th>\u4ee3\u8868\u7684\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u69cb\u6210<\/th>\n<\/tr>\n<\/thead>\n<tbody data-line=\"345\" class=\"code-line\">\n<tr data-line=\"345\" class=\"code-line\">\n<td><strong>core<\/strong><\/td>\n<td>\u30a2\u30d7\u30ea\u5168\u4f53\u306e\u57fa\u76e4\u6a5f\u80fd\uff08\u4f8b\u5916\u30fb\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30fbFirebase\u30fb\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u8a2d\u5b9a\u306a\u3069\uff09\u3002\u4ed6\u5c64\u306b\u5171\u901a\u30b5\u30fc\u30d3\u30b9\u3092\u63d0\u4f9b\u3059\u308b\u3002<\/td>\n<td><code>core\/{network, exceptions, firebase, router, utils}<\/code><\/td>\n<\/tr>\n<tr data-line=\"346\" class=\"code-line\">\n<td><strong>presentation<\/strong><\/td>\n<td>\u30e6\u30fc\u30b6\u30fc\u64cd\u4f5c\u3092\u53d7\u3051\u53d6\u308a\u3001Controller\uff08Notifier\uff09\u3092\u4ecb\u3057\u3066\u72b6\u614b\u3092\u7ba1\u7406\u30fb\u76e3\u8996\u3057\u3001UI\u3092\u518d\u63cf\u753b\u3059\u308b\u3002<\/td>\n<td><code>presentation\/{pages, controllers, shared}<\/code><\/td>\n<\/tr>\n<tr data-line=\"347\" class=\"code-line\">\n<td><strong>application<\/strong><\/td>\n<td>\u6a5f\u80fd\uff08Feature\uff09\u5358\u4f4d\u306bUseCase\u3092\u5b9a\u7fa9\u3057\u3001\u30d3\u30b8\u30cd\u30b9\u51e6\u7406\u3084\u30d5\u30ed\u30fc\u5236\u5fa1\u3001\u6a29\u9650\u30fb\u691c\u8a3c\u306a\u3069\u3092\u884c\u3046\u3002<\/td>\n<td><code>application\/<feature>\/{usecases, services}<\/feature><\/code><\/td>\n<\/tr>\n<tr data-line=\"348\" class=\"code-line\">\n<td><strong>domain<\/strong><\/td>\n<td>\u30d3\u30b8\u30cd\u30b9\u30eb\u30fc\u30eb\u30fb\u4e0d\u5909\u6761\u4ef6\u30fb\u30c9\u30e1\u30a4\u30f3\u30e2\u30c7\u30eb\uff08Entity \/ ValueObject\uff09\u3092\u5b9a\u7fa9\u3057\u3001\u5916\u90e8\u4f9d\u5b58\u306e\u306a\u3044\u7d14\u7c8b\u306a\u30ed\u30b8\u30c3\u30af\u5c64\u3002<\/td>\n<td><code>domain\/{entities, value_objects, repositories, services}<\/code><\/td>\n<\/tr>\n<tr data-line=\"349\" class=\"code-line\">\n<td><strong>data<\/strong><\/td>\n<td>\u5916\u90e8I\/O\uff08API \/ DB \/ Cache\uff09\u3092\u6271\u3044\u3001DTO\u3068Domain\u9593\u306e\u5909\u63db\u30fb\u6c38\u7d9a\u5316\u51e6\u7406\u3092\u62c5\u3046\u3002<\/td>\n<td><code>data\/{datasources, repositories, remote}<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/div>\n<h4 id=\"presentation%EF%BC%88ui-%2F-controller%EF%BC%89\" data-line=\"352\" class=\"code-line\">\n presentation\uff08UI \/ Controller\uff09<\/h4>\n<ul data-line=\"353\" class=\"code-line\">\n<li data-line=\"353\" class=\"code-line\">\u8cac\u52d9\n<ul data-line=\"354\" class=\"code-line\">\n<li data-line=\"354\" class=\"code-line\">\u30e6\u30fc\u30b6\u30fc\u64cd\u4f5c\u3092\u53d7\u3051\u53d6\u308a\u3001\u72b6\u614b\uff08Riverpod\uff09 \u3092\u66f4\u65b0\u3057\u3001UI\u3092\u518d\u63cf\u753b\u3059\u308b\uff08UI = f(state)\uff09<\/li>\n<li data-line=\"355\" class=\"code-line\">UI\u30a4\u30d9\u30f3\u30c8\u3092 Application \u306e UseCase \u306b\u6a4b\u6e21\u3057\u3059\u308b\uff08\u5883\u754c\u30a2\u30c0\u30d7\u30bf\uff09<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"356\" class=\"code-line\">\u69cb\u6210\n<ul data-line=\"357\" class=\"code-line\">\n<li data-line=\"357\" class=\"code-line\">presentation\/pages\/\u2026\uff1a\u30bf\u30d6\u5358\u4f4d\u306e\u753b\u9762\uff08home\/, scout\/ \u306a\u3069\uff09\u3068\u305d\u306e widgets\/<\/li>\n<li data-line=\"358\" class=\"code-line\">presentation\/controllers\/domain\/\uff1a\u6a5f\u80fd\u306b\u4f9d\u5b58\u3057\u306a\u3044\u30c9\u30e1\u30a4\u30f3\u60c5\u5831\u306e\u72b6\u614b\uff08\u4f8b\uff1auser_controller.dart\uff09<\/li>\n<li data-line=\"359\" class=\"code-line\">presentation\/controllers\/feature\/\uff1a\u753b\u9762\/\u30d5\u30ed\u30fc\u56fa\u6709\u306e\u4e00\u6642\u72b6\u614b\uff08\u4f8b\uff1aentry_controller.dart\uff09<\/li>\n<li data-line=\"360\" class=\"code-line\">presentation\/shared\/\uff1a\u5171\u901aUI\uff08\u30dc\u30bf\u30f3\u3001\u30c0\u30a4\u30a2\u30ed\u30b0\u3001\u5171\u901a\u30da\u30fc\u30b8\uff09<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"361\" class=\"code-line\">Controller \u306e\u8cac\u52d9\n<ul data-line=\"362\" class=\"code-line\">\n<li data-line=\"362\" class=\"code-line\">UseCase \u306e\u8d77\u52d5\u30fbAsyncValue \u306e\u9077\u79fb\u7ba1\u7406\uff08loading\/success\/error\uff09<\/li>\n<li data-line=\"363\" class=\"code-line\">\u753b\u9762\u30b9\u30b3\u30fc\u30d7\u306e\u72b6\u614b\u4fdd\u6301\uff08\u30d5\u30a3\u30eb\u30bf\u3001\u5165\u529b\u5024\u3001\u9078\u629e\u72b6\u614b\uff09<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"364\" class=\"code-line\">I\/O\n<ul data-line=\"365\" class=\"code-line\">\n<li data-line=\"365\" class=\"code-line\">In\uff1a\u30e6\u30fc\u30b6\u30fc\u30a4\u30d9\u30f3\u30c8\uff08\u30bf\u30c3\u30d7\/\u5165\u529b\uff09\u30fb\u65e2\u5b58\u306e Domain \u72b6\u614b<\/li>\n<li data-line=\"366\" class=\"code-line\">Out\uff1aUseCase \u3078\u306e\u30b3\u30de\u30f3\u30c9\u30fbUI \u306e\u72b6\u614b\u66f4\u65b0<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"367\" class=\"code-line\">Don\u2019t\n<ul data-line=\"368\" class=\"code-line\">\n<li data-line=\"368\" class=\"code-line\">\u30d3\u30b8\u30cd\u30b9\u30eb\u30fc\u30eb\u5b9f\u88c5\u3001\u5916\u90e8I\/O\u3001DTO\u64cd\u4f5c\u3001\u8907\u6570\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u3001\u6a29\u9650\u5224\u5b9a\u306e\u5185\u5305<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4 id=\"application%EF%BC%88usecase-%2F-service%EF%BC%89\" data-line=\"370\" class=\"code-line\">\n application\uff08UseCase \/ Service\uff09<\/h4>\n<ul data-line=\"371\" class=\"code-line\">\n<li data-line=\"371\" class=\"code-line\">\u8cac\u52d9\n<ul data-line=\"372\" class=\"code-line\">\n<li data-line=\"372\" class=\"code-line\">\u6a5f\u80fd\uff08feature\uff09\u5358\u4f4d\u306e\u30d3\u30b8\u30cd\u30b9\u64cd\u4f5c\u3092\u5b9a\u7fa9\u3057\u3001\u51e6\u7406\u306e\u6d41\u308c\u3092\u7de8\u6210\u3059\u308b\uff08\u30aa\u30fc\u30b1\u30b9\u30c8\u30ec\u30fc\u30b7\u30e7\u30f3\uff09<\/li>\n<li data-line=\"373\" class=\"code-line\">\u5165\u529b\u691c\u8a3c\u30fb\u6a29\u9650\u30c1\u30a7\u30c3\u30af\u30fb\u4f8b\u5916\/\u5931\u6557\u6642\u306e\u518d\u8a66\u884c\u30fb\u8907\u6570\u30ea\u30dd\u30b8\u30c8\u30ea\u9023\u643a\u306a\u3069\u3001\u526f\u4f5c\u7528\u3092\u4f34\u3046\u30d5\u30ed\u30fc\u3092\u5b89\u5168\u306b\u5b9f\u884c\u3059\u308b<\/li>\n<li data-line=\"374\" class=\"code-line\">Flutter\/Riverpod \u304b\u3089\u72ec\u7acb\u3057\u305f \u7d14\u30ed\u30b8\u30c3\u30af\u5c64 \u3068\u3057\u3066\u3001Presentation \u306b\u300c\u7d50\u679c\u300d\u3092\u8fd4\u3059<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"375\" class=\"code-line\">\u69cb\u6210\n<ul data-line=\"376\" class=\"code-line\">\n<li data-line=\"376\" class=\"code-line\">application\/<feature>\/usecases\/\u2026\uff1a\u5358\u4e00\u76ee\u7684\u306e\u64cd\u4f5c\uff08\u4f8b\uff1asubmit_entry_usecase.dart, reply_scout_usecase.dart\uff09<\/feature><\/li>\n<li data-line=\"377\" class=\"code-line\">application\/<feature>\/services\/\u2026\uff1a\u8907\u6570 UseCase \u3092\u675f\u306d\u308b\u30d5\u30ed\u30fc\u8abf\u6574\uff08\u4f8b\uff1aentry_flow_service.dart, scout_flow_service.dart\uff09<\/feature><\/li>\n<\/ul>\n<\/li>\n<li data-line=\"378\" class=\"code-line\">I\/O\n<ul data-line=\"379\" class=\"code-line\">\n<li data-line=\"379\" class=\"code-line\">In\uff1aPresentation\uff08Controller\uff09\u304b\u3089\u6e21\u3055\u308c\u308b\u5165\u529b\uff08Command\/\u30d1\u30e9\u30e1\u30fc\u30bf\uff09<\/li>\n<li data-line=\"380\" class=\"code-line\">Out\uff1aDomain \u30e2\u30c7\u30eb\uff0f\u7d50\u679c\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\uff08UI\u3067\u6d88\u8cbb\u3057\u3084\u3059\u3044\u5f62\u307e\u3067\u6574\u5f62\u53ef\u3002\u305f\u3060\u3057UI\u4f9d\u5b58\u306f\u6301\u305f\u306a\u3044\uff09<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"381\" class=\"code-line\">Don\u2019t\n<ul data-line=\"382\" class=\"code-line\">\n<li data-line=\"382\" class=\"code-line\">HTTP\/DB\u76f4\u63a5\u547c\u3073\u30fb\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u4f9d\u5b58\uff08BuildContext\u7b49\uff09\u30fbUI\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u76f4\u66f8\u304d<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4 id=\"domain\" data-line=\"384\" class=\"code-line\">\n domain<\/h4>\n<ul data-line=\"385\" class=\"code-line\">\n<li data-line=\"385\" class=\"code-line\">\u8cac\u52d9\n<ul data-line=\"386\" class=\"code-line\">\n<li data-line=\"386\" class=\"code-line\">\u30a2\u30d7\u30ea\u306e\u610f\u5473\u30e2\u30c7\u30eb\uff08\u30d3\u30b8\u30cd\u30b9\u4e0a\u306e\u6982\u5ff5\uff09\u3068\u4e0d\u5909\u6761\u4ef6\u3092\u30b3\u30fc\u30c9\u3067\u8868\u73fe\u3059\u308b\u4e2d\u6838\u5c64<\/li>\n<li data-line=\"387\" class=\"code-line\">\u30eb\u30fc\u30eb\u3092 Entity \/ ValueObject \/ Domain Service \u306b\u5206\u6563\u3055\u305b\u3001\u5916\u90e8\u4f9d\u5b58\u3092\u4e00\u5207\u6301\u305f\u306a\u3044<\/li>\n<li data-line=\"388\" class=\"code-line\">\u30c7\u30fc\u30bf\u53d6\u5f97\u30fb\u4fdd\u5b58\u306f Repository \u306e\u62bd\u8c61\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9 \u3067\u5ba3\u8a00\u3057\u3001\u5b9f\u88c5\u306f data \u5c64\u306b\u59d4\u8b72\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"389\" class=\"code-line\">\u69cb\u6210\n<ul data-line=\"390\" class=\"code-line\">\n<li data-line=\"390\" class=\"code-line\">domain\/entities\/\uff1a\u72b6\u614b\uff0b\u632f\u308b\u821e\u3044\u3092\u6301\u3064\u30e2\u30c7\u30eb\uff08\u4f8b\uff1aUser, Job, Scout, Entry\uff09<\/li>\n<li data-line=\"391\" class=\"code-line\">domain\/value_objects\/\uff1a\u5024\u306e\u6b63\u5f53\u6027\u3092\u4fdd\u8a3c\u3059\u308b\u5c0f\u3055\u306a\u578b\uff08\u4f8b\uff1aUserId, Email, SalaryRange\uff09<\/li>\n<li data-line=\"392\" class=\"code-line\">domain\/repositories\/\uff1a\u5916\u90e8I\/O\u306e\u62bd\u8c61\uff08\u4f8b\uff1aUserRepository, JobRepository\uff09<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"393\" class=\"code-line\">I\/O\n<ul data-line=\"394\" class=\"code-line\">\n<li data-line=\"394\" class=\"code-line\">In \/ Out \u3068\u3082\u306b Domain \u578b\u3060\u3051\uff08Entity \/ ValueObject \/ enum \/ sealed class \u306a\u3069\uff09<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"395\" class=\"code-line\">Don\u2019t\n<ul data-line=\"396\" class=\"code-line\">\n<li data-line=\"396\" class=\"code-line\">HTTP\/Dio\/DB\/SharedPreferences \u7b49\u306e\u5916\u90e8\u4f9d\u5b58\u3001UI\u77e5\u8b58\uff08\u6587\u8a00\/\u8272\/\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\uff09<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4 id=\"data\" data-line=\"398\" class=\"code-line\">\n data<\/h4>\n<ul data-line=\"399\" class=\"code-line\">\n<li data-line=\"399\" class=\"code-line\">\u8cac\u52d9\n<ul data-line=\"400\" class=\"code-line\">\n<li data-line=\"400\" class=\"code-line\">HTTP \/ DB \/ Cache \u306a\u3069\u5916\u90e8I\/O\u3092\u4e00\u624b\u306b\u62c5\u5f53\u3057\u3001DTO \u2194 Domain \u5909\u63db\u3092data\u5c64\u5185\u3067\u5b8c\u7d50\u3055\u305b\u308b<\/li>\n<li data-line=\"401\" class=\"code-line\">Domain\u5c64\u306e Repository \u62bd\u8c61\u3092\u5b9f\u88c5\u3057\u3001Domain\u30e2\u30c7\u30eb\u3092\u8fd4\u3059\uff08DTO\u306f\u5916\u306b\u51fa\u3055\u306a\u3044\uff09<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"402\" class=\"code-line\">\u69cb\u6210\n<ul data-line=\"403\" class=\"code-line\">\n<li data-line=\"403\" class=\"code-line\">data\/datasources\/\uff1a\u5916\u90e8\u30ea\u30bd\u30fc\u30b9\u3078\u306e\u30a2\u30af\u30bb\u30b9\u5b9f\u88c5\uff08\u30ed\u30fc\u30ab\u30ebDB\u64cd\u4f5c\u306a\u3069\uff09<\/li>\n<li data-line=\"404\" class=\"code-line\">data\/repositories\/\uff1aDomain \u306e Repository \u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9\u5b9f\u88c5\uff08UserRepositoryImpl\u306a\u3069\uff09<\/li>\n<li data-line=\"405\" class=\"code-line\">data\/mappers\/\uff1aDTO \u2194 Domain \u30e2\u30c7\u30eb\u306e\u5909\u63db\u30ed\u30b8\u30c3\u30af\u3092\u96c6\u7d04<\/li>\n<li data-line=\"406\" class=\"code-line\">data\/remote\/\uff1aOpenAPI Generator \u306b\u3088\u308a\u751f\u6210\u3055\u308c\u305f\u30af\u30e9\u30a4\u30a2\u30f3\u30c8<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"407\" class=\"code-line\">I\/O\n<ul data-line=\"408\" class=\"code-line\">\n<li data-line=\"408\" class=\"code-line\">In\uff1aDomain\u306eRepository\u62bd\u8c61\u304b\u3089\u306e\u8981\u6c42<\/li>\n<li data-line=\"409\" class=\"code-line\">Out\uff1arepositories \u2194 datasources \u2194 remote \u306e\u9023\u643a\u3001mappers\u3067\u5909\u63db<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"410\" class=\"code-line\">Don\u2019t\n<ul data-line=\"411\" class=\"code-line\">\n<li data-line=\"411\" class=\"code-line\">UI\/Riverpod\u3078\u306e\u4f9d\u5b58\u3001\u30d3\u30b8\u30cd\u30b9\u30eb\u30fc\u30eb\u5b9f\u88c5\uff08Domain\u306e\u8cac\u52d9\uff09\u3001UseCase\u306e\u624b\u7d9a\u304d\u30fb\u30aa\u30fc\u30b1\u30b9\u30c8\u30ec\u30fc\u30b7\u30e7\u30f3\uff08Application\u306e\u8cac\u52d9\uff09<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4 id=\"core\" data-line=\"413\" class=\"code-line\">\n core<\/h4>\n<ul data-line=\"414\" class=\"code-line\">\n<li data-line=\"414\" class=\"code-line\">\u8cac\u52d9\n<ul data-line=\"415\" class=\"code-line\">\n<li data-line=\"415\" class=\"code-line\">\u30a2\u30d7\u30ea\u6a2a\u65ad\u306e\u57fa\u76e4\u6a5f\u80fd\u306e\u63d0\u4f9b\u3068\u521d\u671f\u5316\uff08\u4f8b\u5916\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3001\u30ed\u30b0\u3001Firebase\u3001\u30e6\u30fc\u30c6\u30a3\u30ea\u30c6\u30a3\u3001\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\uff09<\/li>\n<li data-line=\"416\" class=\"code-line\">\u5171\u901a\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3084\u30b5\u30fc\u30d3\u30b9\u3092 Provider \u3068\u3057\u3066\u4f9b\u7d66 \u3057\u3001\u4e0a\u4f4d\u5c64\u304b\u3089\u518d\u5229\u7528\u53ef\u80fd\u306b\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"417\" class=\"code-line\">\u69cb\u6210\n<ul data-line=\"418\" class=\"code-line\">\n<li data-line=\"418\" class=\"code-line\">core\/exceptions\/\uff1a\u30a2\u30d7\u30ea\u5171\u901a\u306e\u4f8b\u5916\u578b\uff08AppException\u306a\u3069\uff09<\/li>\n<li data-line=\"419\" class=\"code-line\">core\/network\/\uff1aHTTP \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\uff08Dio\uff09\u8a2d\u5b9a\u30fb\u30a4\u30f3\u30bf\u30fc\u30bb\u30d7\u30bf\u30fb\u8a8d\u8a3c\u30d8\u30c3\u30c0\u30fc\u7ba1\u7406<\/li>\n<li data-line=\"420\" class=\"code-line\">core\/firebase\/\uff1aCrashlytics \/ Analytics \u306a\u3069\u306eSDK\u521d\u671f\u5316\u30fb\u5171\u901a\u30e1\u30bd\u30c3\u30c9<\/li>\n<li data-line=\"421\" class=\"code-line\">core\/utils\/\uff1a\u65e5\u4ed8\u3001UUID\u3001\u30d5\u30a9\u30fc\u30de\u30c3\u30bf\u306a\u3069\u306e\u6c4e\u7528\u95a2\u6570<\/li>\n<li data-line=\"422\" class=\"code-line\">core\/router\/\uff1a\u30a2\u30d7\u30ea\u306e\u30eb\u30fc\u30c8\u5b9a\u7fa9\uff08app_router.dart\u3001route_paths.dart\uff09<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"423\" class=\"code-line\">I\/O\n<ul data-line=\"424\" class=\"code-line\">\n<li data-line=\"424\" class=\"code-line\">In\uff1a\u5404\u5c64\u304b\u3089\u306e\u5229\u7528\u8981\u6c42\uff08\u4f8b\u5916\u9001\u51fa\u30fb\u30ed\u30b0\u30fbHTTP\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u6ce8\u5165\uff09<\/li>\n<li data-line=\"425\" class=\"code-line\">Out\uff1aDio \/ Logger \/ Crashlytics \/ Clock \u306a\u3069\u306e \u5171\u901a\u30b5\u30fc\u30d3\u30b9\u3092Provider\u3067\u63d0\u4f9b<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"426\" class=\"code-line\">Don\u2019t\n<ul data-line=\"427\" class=\"code-line\">\n<li data-line=\"427\" class=\"code-line\">\u6a5f\u80fd\u56fa\u6709\u30ed\u30b8\u30c3\u30af\u3001UI\u6587\u8a00\u3001DTO\u2194Domain\u5909\u63db\uff08data\u306e\u8cac\u52d9\uff09\u3001UseCase \/ Repository \u306e\u5b9f\u88c5\uff08application\/data\u306e\u8cac\u52d9\uff09<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3 id=\"%E6%A7%8B%E6%88%90%E3%81%AE%E7%90%86%E7%94%B1%EF%BC%9Aflutter%E3%81%A8%E3%81%AE%E6%95%B4%E5%90%88%E6%80%A7%EF%BC%88%E5%AE%A3%E8%A8%80%E7%9A%84ui-%C3%97-%E5%8D%98%E6%96%B9%E5%90%91%E3%83%87%E3%83%BC%E3%82%BF%E3%83%95%E3%83%AD%E3%83%BC-%C3%97-%E8%B2%AC%E5%8B%99%E3%81%AE%E5%88%86%E9%9B%A2%EF%BC%89\" data-line=\"429\" class=\"code-line\">\n \u69cb\u6210\u306e\u7406\u7531\uff1aFlutter\u3068\u306e\u6574\u5408\u6027\uff08\u5ba3\u8a00\u7684UI \u00d7 \u5358\u65b9\u5411\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc \u00d7 \u8cac\u52d9\u306e\u5206\u96e2\uff09<\/h3>\n<h4 id=\"%E7%8A%B6%E6%85%8B%E4%B8%AD%E5%BF%83%E3%81%AE%E8%A8%AD%E8%A8%88%E6%80%9D%E6%83%B3\" data-line=\"430\" class=\"code-line\">\n \u72b6\u614b\u4e2d\u5fc3\u306e\u8a2d\u8a08\u601d\u60f3<\/h4>\n<p data-line=\"431\" class=\"code-line\">Flutter \u306f\u300cUI = f(state)\u300d\u3068\u3044\u3046\u5ba3\u8a00\u7684 UI \u306e\u601d\u60f3\u3092\u524d\u63d0\u3068\u3057\u3066\u304a\u308a\u3001UI \u306f\u5e38\u306b\u300c\u72b6\u614b\u306e\u7d50\u679c\u300d\u3068\u3057\u3066\u63cf\u753b\u3055\u308c\u307e\u3059\u3002<br \/>\u3057\u305f\u304c\u3063\u3066\u3001\u8a2d\u8a08\u306e\u51fa\u767a\u70b9\u306f\u300c\u3069\u306e UI \u3092\u8868\u793a\u3059\u308b\u304b\u300d\u3067\u306f\u306a\u304f\u3001\u300c\u3069\u306e\u72b6\u614b\u3092\u3069\u306e\u3088\u3046\u306b\u4fdd\u6301\u3057\u3001\u3069\u306e\u3088\u3046\u306b\u66f4\u65b0\u3059\u308b\u304b\u300d\u306b\u3042\u308a\u307e\u3059\u3002<br \/>\u305d\u306e\u305f\u3081\u3001\u72b6\u614b\u3092\u9069\u5207\u306b\u5b9a\u7fa9\u3057\u3001\u7ba1\u7406\u5358\u4f4d\u3092\u660e\u78ba\u306b\u5206\u96e2\u3059\u308b\u3053\u3068\u304c\u6700\u3082\u91cd\u8981\u3067\u3059\u3002<br \/>Flutter \u3067\u306f\u72b6\u614b\u3092\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5168\u4f53\u306e\u552f\u4e00\u306e\u771f\u5b9f\u306e\u60c5\u5831\u6e90\uff08SSOT: Single Source of Truth\uff09\u3068\u3057\u3066\u6271\u3046\u306e\u304c\u539f\u5247\u3067\u3042\u308a\u3001UI\u306b\u9589\u3058\u305a\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5168\u4f53\u3067\u5171\u6709\u30fb\u518d\u5229\u7528\u3055\u308c\u308b\u3079\u304d\u3082\u306e\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<br \/>\u4e00\u65b9\u3067\u3001\u30d5\u30a9\u30fc\u30e0\u5165\u529b\u3084\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u306e\u9078\u629e\u72b6\u614b\u3068\u3044\u3063\u305f\u4e00\u6642\u7684\u306a\u5024\u306f\u3001useState \u3084 StatefulWidget \u306e\u3088\u3046\u306b\u30a6\u30a3\u30b8\u30a7\u30c3\u30c8\u5185\u90e8\u3067\u5b8c\u7d50\u3055\u305b\u308b\u65b9\u304c\u81ea\u7136\u3067\u3059\u3002<\/p>\n<h4 id=\"controller-%E3%81%AE%E9%85%8D%E7%BD%AE%E6%96%B9%E9%87%9D\" data-line=\"437\" class=\"code-line\">\n Controller \u306e\u914d\u7f6e\u65b9\u91dd<\/h4>\n<p data-line=\"438\" class=\"code-line\">\u3053\u306e\u72b6\u614b\u4e2d\u5fc3\u306e\u601d\u60f3\u306b\u57fa\u3065\u304d\u3001Controller\u3092\u7279\u5b9a\u306efeature\u914d\u4e0b\u306b\u7f6e\u304f\u69cb\u6210\u306f\u63a1\u7528\u3057\u3066\u3044\u307e\u305b\u3093\u3002<br \/>Controller\u3092\u6a5f\u80fd\u5358\u4f4d\u3067\u5206\u5272\u3057\u3066\u3057\u307e\u3046\u3068\u3001\u72b6\u614b\u304c\u6a5f\u80fd\u3054\u3068\u306b\u5206\u65ad\u3055\u308c\u3001\u540c\u3058\u30c9\u30e1\u30a4\u30f3\u60c5\u5831\u304c\u8907\u6570\u7b87\u6240\u3067\u7ba1\u7406\u3055\u308c\u308b\u7d50\u679c\u3068\u306a\u308a\u3001Flutter\u306e\u72b6\u614b\u4e2d\u5fc3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u3068\u77db\u76fe\u3057\u3066\u3057\u307e\u3044\u307e\u3059\u3002<br \/>\u305d\u306e\u305f\u3081\u3001\u672c\u69cb\u6210\u3067\u306f Controller\u3092\u5e38\u306b\u6c4e\u7528\u7684\u304b\u3064\u6a2a\u65ad\u7684\u306a\u5358\u4f4d\u3068\u3057\u3066\u8a2d\u8a08\u3057\u3001\u30a2\u30d7\u30ea\u5168\u4f53\u3067\u4e00\u8cab\u3057\u305f\u72b6\u614b\u7ba1\u7406\u3092\u884c\u3046\u524d\u63d0\u306b\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<h4 id=\"ui-%E6%A7%8B%E6%88%90%E3%81%AE%E8%80%83%E3%81%88%E6%96%B9%EF%BC%88%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E5%8D%98%E4%BD%8D%E3%81%A7%E6%95%B4%E7%90%86%EF%BC%89\" data-line=\"442\" class=\"code-line\">\n UI \u69cb\u6210\u306e\u8003\u3048\u65b9\uff08\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u5358\u4f4d\u3067\u6574\u7406\uff09<\/h4>\n<p data-line=\"443\" class=\"code-line\">\u4e00\u65b9\u3067\u3001UI \u306f\u72b6\u614b\u305d\u306e\u3082\u306e\u3067\u306f\u306a\u304f\u3001\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u69cb\u9020\u306b\u5f93\u3063\u3066\u6574\u7406\u3059\u308b\u306e\u304c\u5408\u7406\u7684\u3067\u3059\u3002Flutter\u306ego_router\u306f\u30db\u30fc\u30e0\u30bf\u30d6\u3084\u8a2d\u5b9a\u30bf\u30d6\u306e\u3088\u3046\u306b\u30b9\u30bf\u30c3\u30af\u69cb\u9020\u3067\u753b\u9762\u3092\u7ba1\u7406\u3059\u308b\u4ed5\u7d44\u307f\u3092\u6301\u3064\u305f\u3081\u3001presentation\/pages\/<tab>\/ \u306e\u3088\u3046\u306b\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u3084\u30b9\u30bf\u30c3\u30af\u5358\u4f4d\u3067\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u5206\u3051\u308b\u69cb\u6210\u304c\u6700\u3082\u76f4\u611f\u7684\u3067\u3059\u3002<br \/>\u3053\u308c\u306b\u3088\u308a\u3001\u753b\u9762\u9077\u79fb\u3084\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u306e\u69cb\u9020\u3068\u30d5\u30a1\u30a4\u30eb\u69cb\u6210\u304c\u4e00\u81f4\u3057\u3001UI \u30ec\u30a4\u30e4\u30fc\u306e\u8cac\u52d9\u3092\u300c\u72b6\u614b\u306e\u53cd\u6620\u300d\u3068\u300c\u30a4\u30d9\u30f3\u30c8\u767a\u706b\u300d\u306b\u660e\u78ba\u306b\u9650\u5b9a\u3067\u304d\u307e\u3059\u3002<\/tab><\/p>\n<h4 id=\"%E5%8D%98%E6%96%B9%E5%90%91%E3%83%87%E3%83%BC%E3%82%BF%E3%83%95%E3%83%AD%E3%83%BC%E3%81%A8%E4%BE%9D%E5%AD%98%E6%96%B9%E5%90%91%E3%81%AE%E6%95%B4%E5%90%88%E6%80%A7\" data-line=\"446\" class=\"code-line\">\n \u5358\u65b9\u5411\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\u3068\u4f9d\u5b58\u65b9\u5411\u306e\u6574\u5408\u6027<\/h4>\n<p data-line=\"447\" class=\"code-line\">\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306f\u4f9d\u5b58\u65b9\u5411\u3092\u5185\u5411\u304d\u306b\u5236\u5fa1\u3059\u308b\u8a2d\u8a08\u601d\u60f3\u3092\u6301\u3061\u3001\u7d50\u679c\u3068\u3057\u3066\u30c7\u30fc\u30bf\u3068\u5236\u5fa1\u306e\u6d41\u308c\u304c\u4e00\u65b9\u5411\u306b\u6574\u7406\u3055\u308c\u308b\u69cb\u9020\u3092\u4f5c\u308a\u307e\u3059\u3002<br \/>\u3053\u306e\u601d\u60f3\u306f Flutter \u306e\u300c\u5358\u65b9\u5411\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\uff08UI = f(state)\uff09\u300d\u3068\u975e\u5e38\u306b\u76f8\u6027\u304c\u826f\u304f\u3001\u72b6\u614b\u306e\u6d41\u308c\u3068\u8cac\u52d9\u306e\u5206\u96e2\u3092\u660e\u78ba\u306b\u4fdd\u3064\u4e0a\u3067\u4e21\u8005\u304c\u81ea\u7136\u306b\u565b\u307f\u5408\u3046\u8a2d\u8a08\u3068\u306a\u3063\u3066\u3044\u307e\u3059\u3002<\/p>\n<h4 id=\"shared-%E5%B1%A4%E3%81%AE%E6%89%B1%E3%81%84%EF%BC%88presentation-%E9%99%90%E5%AE%9A%EF%BC%89\" data-line=\"450\" class=\"code-line\">\n shared \u5c64\u306e\u6271\u3044\uff08Presentation \u9650\u5b9a\uff09<\/h4>\n<p data-line=\"451\" class=\"code-line\">\u672c\u69cb\u6210\u3067\u306f\u3001\u30a2\u30d7\u30ea\u5168\u4f53\u3092\u6a2a\u65ad\u3059\u308b shared \u5c64\u306f\u8a2d\u3051\u3066\u3044\u307e\u305b\u3093\u3002<br \/>\u518d\u5229\u7528\u53ef\u80fd\u306a\u8cac\u52d9\u306f\u5404\u5c64\u306b\u660e\u78ba\u306b\u5206\u62c5\u3055\u308c\u3066\u304a\u308a\u3001domain\u3084data\u306f\u3082\u3068\u3082\u3068\u6c4e\u7528\u7684\u3067\u5171\u901a\u6027\u304c\u9ad8\u304f\u3001application\u3082UseCase\u3084Service\u5358\u4f4d\u3067\u69cb\u6210\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u5168\u4f53\u5171\u6709\u306e shared \u5c64\u3092\u8ffd\u52a0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u305b\u3093\u3002<br \/>\u305d\u306e\u4e00\u65b9\u3067\u3001UI \u306b\u95a2\u3059\u308b\u5171\u901a\u8981\u7d20\u3060\u3051\u306f\u518d\u5229\u7528\u306e\u89b3\u70b9\u304b\u3089 presentation\/shared\/ \u306b\u914d\u7f6e\u3057\u3066\u3044\u307e\u3059\u3002<br \/>\u3053\u3053\u3067\u306f\u30dc\u30bf\u30f3\u3084\u30c0\u30a4\u30a2\u30ed\u30b0\u3001\u30b9\u30ca\u30c3\u30af\u30d0\u30fc\u3068\u3044\u3063\u305f\u898b\u305f\u76ee\u3084\u64cd\u4f5c\u306b\u95a2\u308f\u308b UI \u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u307f\u3092\u6271\u3044\u3001\u72b6\u614b\u5171\u6709\u306e\u3088\u3046\u306a\u30ed\u30b8\u30c3\u30af\u306f controller\/domain\/ \u306b\u96c6\u7d04\u3057\u3066\u3044\u307e\u3059\u3002<br \/>\u3053\u306e\u65b9\u91dd\u306b\u3088\u308a\u3001Clean Architecture \u306e\u8cac\u52d9\u5206\u96e2\u3092\u4fdd\u3061\u3064\u3064\u3001UI \u306e\u307f\u518d\u5229\u7528\u6027\u3092\u9ad8\u3081\u308b\u69cb\u9020\u3092\u5b9f\u73fe\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p data-line=\"457\" class=\"code-line\">\u3053\u306e\u5206\u5272\u306f\u3001Flutter \u306e\u300c\u72b6\u614b\u99c6\u52d5\u300d\u300c\u5ba3\u8a00\u7684UI\u300d\u601d\u60f3\u306b\u5fe0\u5b9f\u3067\u3042\u308a\u3001\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306e\u4f9d\u5b58\u65b9\u5411\u3092\u5d29\u3055\u305a\u3001go_router \/ Riverpod \/ AsyncNotifier \u306b\u6574\u5408\u3059\u308b\u69cb\u9020\u3067\u3042\u308a\u3001\u30b3\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u3088\u308b\u73fe\u5b9f\u7684\u306a\u958b\u767a\u52b9\u7387\u3092\u4e21\u7acb\u3057\u3066\u3044\u308b\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<p data-line=\"459\" class=\"code-line\">\u7d50\u8ad6\u3068\u3057\u3066\u3001Flutter\u306b\u304a\u3051\u308b\u6700\u9069\u306a\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306f\u300c\u72b6\u614b\u300d\u3092\u4e2d\u5fc3\u306b\u69cb\u7bc9\u3055\u308c\u305fClean Architecture\u3060\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<br \/>UI\u30fb\u72b6\u614b\u30fb\u30e6\u30fc\u30b9\u30b1\u30fc\u30b9\u30fb\u30c9\u30e1\u30a4\u30f3\u3092\u660e\u78ba\u306b\u5207\u308a\u5206\u3051\u3001Riverpod\u3092\u7528\u3044\u3066\u5358\u65b9\u5411\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\u3092\u5fb9\u5e95\u3059\u308b\u3053\u3068\u3067\u3001\u30a2\u30d7\u30ea\u306e\u4e00\u8cab\u6027\u3001\u62e1\u5f35\u6027\u3001\u305d\u3057\u3066\u30c6\u30b9\u30bf\u30d3\u30ea\u30c6\u30a3\u3092\u9ad8\u3044\u6c34\u6e96\u3067\u7dad\u6301\u3067\u304d\u308b\u69cb\u6210\u306b\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p data-line=\"462\" class=\"code-line\">\u4ee5\u4e0a\u304c\u79c1\u304c\u8003\u3048\u308bFlutter\u306b\u6700\u9069\u5316\u3055\u308c\u305f\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u30d1\u30bf\u30fc\u30f3\u3068\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u69cb\u6210\u3067\u3059\u3002<\/p>\n<h2 id=\"%E3%81%BE%E3%81%A8%E3%82%81\" data-line=\"464\" class=\"code-line\">\n \u307e\u3068\u3081<\/h2>\n<p data-line=\"465\" class=\"code-line\">\u4eca\u56de\u7d39\u4ecb\u3057\u305f\u300c\u72b6\u614b\u99c6\u52d5\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\uff08State-Driven Clean Architecture\uff09\u300d\u306f\u3001\u5f93\u6765\u306eClean Architecture\u306e\u539f\u5247\u3092\u7dad\u6301\u3057\u306a\u304c\u3089\u3001Flutter\u306e\u5ba3\u8a00\u7684UI\u3068\u72b6\u614b\u4e2d\u5fc3\u306e\u69cb\u9020\uff08UI = f(state)\uff09\u306b\u9069\u5408\u3055\u305b\u305f\u8a2d\u8a08\u3067\u3059\u3002<\/p>\n<p data-line=\"467\" class=\"code-line\">Flutter\u3067\u306f\u300cUI\u304c\u72b6\u614b\u306b\u5f93\u5c5e\u3059\u308b\u300d\u305f\u3081\u3001\u3069\u306e\u5c64\u3088\u308a\u3082\u72b6\u614b\uff08State\uff09\u306e\u8a2d\u8a08\u3068\u8cac\u52d9\u5206\u96e2\u304c\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u5168\u4f53\u306e\u54c1\u8cea\u3092\u5de6\u53f3\u3059\u308b\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002<\/p>\n<p data-line=\"469\" class=\"code-line\">\u3053\u306e\u69cb\u6210\u3067\u306f\u3001\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u610f\u56f3\u3092\u6301\u3063\u3066\u30ec\u30a4\u30e4\u30fc\u3092\u6574\u7406\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<ol data-line=\"470\" class=\"code-line\">\n<li data-line=\"470\" class=\"code-line\">\u72b6\u614b\u4e2d\u5fc3\u306e\u601d\u60f3\u306b\u6cbf\u3046\n<ul data-line=\"471\" class=\"code-line\">\n<li data-line=\"471\" class=\"code-line\">\u72b6\u614b\u3092\u4e2d\u5fc3\u306b\u30a2\u30d7\u30ea\u3092\u8a2d\u8a08\u3059\u308b\u3053\u3068\u3067\u3001UI\u306e\u518d\u63cf\u753b\u30fb\u30a4\u30d9\u30f3\u30c8\u4f1d\u64ad\u30fb\u30ed\u30b8\u30c3\u30af\u306e\u5883\u754c\u304c\u660e\u78ba\u306b\u306a\u308b<\/li>\n<li data-line=\"472\" class=\"code-line\">Flutter\u304c\u524d\u63d0\u3068\u3059\u308b\u5358\u65b9\u5411\u30c7\u30fc\u30bf\u30d5\u30ed\u30fc\u3068\u5b8c\u5168\u306b\u4e00\u81f4\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"473\" class=\"code-line\">\u8cac\u52d9\u3092\u660e\u78ba\u306b\u5206\u96e2\u3059\u308b\n<ul data-line=\"474\" class=\"code-line\">\n<li data-line=\"474\" class=\"code-line\">Controller\uff08Notifier\uff09\u306f\u72b6\u614b\u3092\u6271\u3046\u552f\u4e00\u306e\u5834\u6240\uff08SSOT\uff09<\/li>\n<li data-line=\"475\" class=\"code-line\">Application\u5c64\u306f\u300c\u4f55\u3092\u3059\u308b\u304b\u300d\u3092\u6c7a\u5b9a\u3059\u308b\u30e6\u30fc\u30b9\u30b1\u30fc\u30b9\u5358\u4f4d\u306e\u30ed\u30b8\u30c3\u30af<\/li>\n<li data-line=\"476\" class=\"code-line\">Domain\u5c64\u306f\u30d3\u30b8\u30cd\u30b9\u30eb\u30fc\u30eb\u3092\u3001Data\u5c64\u306f\u5916\u90e8I\/O\u3092\u62c5\u5f53\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"477\" class=\"code-line\">\u6a5f\u80fd\u5358\u4f4d\u3067\u306f\u306a\u304f\u69cb\u9020\u5358\u4f4d\u3067\u30b3\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\n<ul data-line=\"478\" class=\"code-line\">\n<li data-line=\"478\" class=\"code-line\">\u6a5f\u80fd\uff08feature\uff09\u3067\u306f\u306a\u304f\u3001**\u8cac\u52d9\uff08responsibility\uff09**\u3092\u57fa\u6e96\u306b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u5206\u5272\u3002<\/li>\n<li data-line=\"479\" class=\"code-line\">\u5404\u5c64\u304c\u660e\u78ba\u306b\u72ec\u7acb\u3057\u3001\u4fdd\u5b88\u6027\u30fb\u518d\u5229\u7528\u6027\u3092\u4e21\u7acb\u3059\u308b<\/li>\n<\/ul>\n<\/li>\n<li data-line=\"480\" class=\"code-line\">MVVM\u3092\u8d85\u3048\u308b\u69cb\u9020\u7684\u5358\u7d14\u3055\n<ul data-line=\"481\" class=\"code-line\">\n<li data-line=\"481\" class=\"code-line\">Flutter\u3067\u306fViewModel\u306e\u5b58\u5728\u7406\u7531\u304cRiverpod\u306b\u3088\u3063\u3066\u6d88\u5931\u3057\u3066\u3044\u308b<\/li>\n<li data-line=\"482\" class=\"code-line\">\u300cUI\uff1d\u72b6\u614b\u306e\u53cd\u6620\u300d\u3068\u3044\u3046\u601d\u60f3\u3092\u8ef8\u306b\u3001ViewModel\u3092\u4e0d\u8981\u3068\u3059\u308b\u8a2d\u8a08\u304c\u81ea\u7136<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p data-line=\"484\" class=\"code-line\">Flutter\u306e\u4e16\u754c\u3067\u306f\u3001\u30ed\u30b8\u30c3\u30af\u304cUI\u3092\u52d5\u304b\u3059\u306e\u3067\u306f\u306a\u304f\u3001\u72b6\u614b\u304cUI\u3092\u5c0e\u304f\u3002\u305d\u308c\u304c\u300c\u72b6\u614b\u99c6\u52d5\u30af\u30ea\u30fc\u30f3\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u300d\u306e\u6838\u5fc3\u3067\u3059\u3002<\/p>\n<p data-line=\"486\" class=\"code-line\">\u3053\u306e\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u304c\u3001\u3053\u308c\u304b\u3089Flutter\u3067\u30a2\u30d7\u30ea\u3092\u8a2d\u8a08\u30fb\u69cb\u7bc9\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u308b\u65b9\u3005\u306b\u3068\u3063\u3066<br \/>\u5c11\u3057\u3067\u3082\u6307\u91dd\u3084\u52a9\u3051\u306b\u306a\u308c\u3070\u5e78\u3044\u3067\u3059\u3002<\/p>\n<\/div>\n\n<br \/><a href=\"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed\">\u5143\u306e\u8a18\u4e8b\u3092\u78ba\u8a8d\u3059\u308b <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\u306f\u3058\u3081\u306b Flutter\u958b\u767a\u6b742\u5e74\u3067\u521d\u3081\u30660\u304b\u3089Flutter\u306e\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea\u3092\u4f5c\u3063\u3066\u307f\u3088\u3046\u3068\u601d\u3063\u305f\u6642\u306b\u3001\u3069\u3046\u3044\u3046\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u3092\u9078\u3076\u306e\u304c\u6700\u9069\u306a\u306e\u304b\u60a9\u307f\u307e\u3057\u305f\u3002 \u4eca\u307e\u3067\u643a\u308f\u3063\u3066\u3044\u305fFlutter\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u69cb\u6210\u306ff [&hellip;]","protected":false},"author":1,"featured_media":25068,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-25067","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-company-tec"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08 - \u30dd\u30b1\u30b3\u30f3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed\" \/>\n<meta property=\"og:locale\" content=\"ja_JP\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08 - \u30dd\u30b1\u30b3\u30f3\" \/>\n<meta property=\"og:description\" content=\"\u306f\u3058\u3081\u306b Flutter\u958b\u767a\u6b742\u5e74\u3067\u521d\u3081\u30660\u304b\u3089Flutter\u306e\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea\u3092\u4f5c\u3063\u3066\u307f\u3088\u3046\u3068\u601d\u3063\u305f\u6642\u306b\u3001\u3069\u3046\u3044\u3046\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u3092\u9078\u3076\u306e\u304c\u6700\u9069\u306a\u306e\u304b\u60a9\u307f\u307e\u3057\u305f\u3002 \u4eca\u307e\u3067\u643a\u308f\u3063\u3066\u3044\u305fFlutter\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u69cb\u6210\u306ff [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed\" \/>\n<meta property=\"og:site_name\" content=\"\u30dd\u30b1\u30b3\u30f3\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-24T22:41:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/11\/1764024103_og-base-w1200-v2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"info@pokecon.jp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u57f7\u7b46\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"info@pokecon.jp\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593\" \/>\n\t<meta name=\"twitter:data2\" content=\"4\u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/25067\\\/\"},\"author\":{\"name\":\"info@pokecon.jp\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\"},\"headline\":\"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08\",\"datePublished\":\"2025-11-24T22:41:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/25067\\\/\"},\"wordCount\":603,\"image\":{\"@id\":\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/11\\\/1764024103_og-base-w1200-v2.png\",\"articleSection\":[\"\u4f01\u696d\u30c6\u30c3\u30af\"],\"inLanguage\":\"ja\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/25067\\\/\",\"url\":\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed\",\"name\":\"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08 - \u30dd\u30b1\u30b3\u30f3\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/11\\\/1764024103_og-base-w1200-v2.png\",\"datePublished\":\"2025-11-24T22:41:44+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed#breadcrumb\"},\"inLanguage\":\"ja\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed#primaryimage\",\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/11\\\/1764024103_og-base-w1200-v2.png\",\"contentUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/11\\\/1764024103_og-base-w1200-v2.png\",\"width\":1200,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zenn.dev\\\/assign\\\/articles\\\/9180f90e65b8ed#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u30db\u30fc\u30e0\",\"item\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#website\",\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/\",\"name\":\"\u30dd\u30b1\u30b3\u30f3\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ja\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\",\"name\":\"info@pokecon.jp\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"caption\":\"info@pokecon.jp\"},\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/author\\\/infopokecon-jp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08 - \u30dd\u30b1\u30b3\u30f3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed","og_locale":"ja_JP","og_type":"article","og_title":"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08 - \u30dd\u30b1\u30b3\u30f3","og_description":"\u306f\u3058\u3081\u306b Flutter\u958b\u767a\u6b742\u5e74\u3067\u521d\u3081\u30660\u304b\u3089Flutter\u306e\u30e2\u30d0\u30a4\u30eb\u30a2\u30d7\u30ea\u3092\u4f5c\u3063\u3066\u307f\u3088\u3046\u3068\u601d\u3063\u305f\u6642\u306b\u3001\u3069\u3046\u3044\u3046\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u3092\u9078\u3076\u306e\u304c\u6700\u9069\u306a\u306e\u304b\u60a9\u307f\u307e\u3057\u305f\u3002 \u4eca\u307e\u3067\u643a\u308f\u3063\u3066\u3044\u305fFlutter\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u69cb\u6210\u306ff [&hellip;]","og_url":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed","og_site_name":"\u30dd\u30b1\u30b3\u30f3","article_published_time":"2025-11-24T22:41:44+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/11\/1764024103_og-base-w1200-v2.png","type":"image\/png"}],"author":"info@pokecon.jp","twitter_card":"summary_large_image","twitter_misc":{"\u57f7\u7b46\u8005":"info@pokecon.jp","\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593":"4\u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed#article","isPartOf":{"@id":"https:\/\/pokecon.jp\/job\/25067\/"},"author":{"name":"info@pokecon.jp","@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997"},"headline":"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08","datePublished":"2025-11-24T22:41:44+00:00","mainEntityOfPage":{"@id":"https:\/\/pokecon.jp\/job\/25067\/"},"wordCount":603,"image":{"@id":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed#primaryimage"},"thumbnailUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/11\/1764024103_og-base-w1200-v2.png","articleSection":["\u4f01\u696d\u30c6\u30c3\u30af"],"inLanguage":"ja"},{"@type":"WebPage","@id":"https:\/\/pokecon.jp\/job\/25067\/","url":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed","name":"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08 - \u30dd\u30b1\u30b3\u30f3","isPartOf":{"@id":"https:\/\/pokecon.jp\/job\/#website"},"primaryImageOfPage":{"@id":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed#primaryimage"},"image":{"@id":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed#primaryimage"},"thumbnailUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/11\/1764024103_og-base-w1200-v2.png","datePublished":"2025-11-24T22:41:44+00:00","author":{"@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997"},"breadcrumb":{"@id":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed#breadcrumb"},"inLanguage":"ja","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed"]}]},{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed#primaryimage","url":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/11\/1764024103_og-base-w1200-v2.png","contentUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/11\/1764024103_og-base-w1200-v2.png","width":1200,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/zenn.dev\/assign\/articles\/9180f90e65b8ed#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u30db\u30fc\u30e0","item":"https:\/\/pokecon.jp\/job\/"},{"@type":"ListItem","position":2,"name":"State-Driven Clean Architecture \u2014 Flutter + Riverpod\u3067\u8003\u3048\u308b\u72b6\u614b\u4e2d\u5fc3\u8a2d\u8a08"}]},{"@type":"WebSite","@id":"https:\/\/pokecon.jp\/job\/#website","url":"https:\/\/pokecon.jp\/job\/","name":"\u30dd\u30b1\u30b3\u30f3","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/pokecon.jp\/job\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ja"},{"@type":"Person","@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997","name":"info@pokecon.jp","image":{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","caption":"info@pokecon.jp"},"url":"https:\/\/pokecon.jp\/job\/author\/infopokecon-jp\/"}]}},"_links":{"self":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/25067","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/comments?post=25067"}],"version-history":[{"count":1,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/25067\/revisions"}],"predecessor-version":[{"id":25069,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/25067\/revisions\/25069"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/media\/25068"}],"wp:attachment":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/media?parent=25067"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/categories?post=25067"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/tags?post=25067"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}