پیدا کردن یه معماری خوب برای پیادهسازی اپلیکیشن کار راحتی نیست و نیاز به تجربه زیادی داره. اگه از همون اول توسعه اپلیکیشن راه منطقی و منظمی رو پیش نگیریم؛ در گذر زمان هم توسعه اپلیکیشن برای ما سخت میشه و هم ممکنه در حین توسعه باگهای زیادی رو به صورت ناخواسته به وجود بیاریم که فیکس کردن اونها شاید کار سادهای نباشه.
حتی ممکنه شما از یک معماری برای پیادهسازی یه اپلیکیشن استفاده کنید و باهاش راحت باشید و جواب هم بگیرید، ولی همون معماری توی یه اپلیکیشن دیگه زیاد جوابگو نباشه. پس معماری نرمافزار چیزی نیست که بتونیم یک نسخه بپیچیم برای تمامی نرمافزارها.
ولی طبیعتا سطح همه برنامهنویس ها در اون سطحی نیست که بتونن یک معماری رو از صفر ایدهپردازی و پیاده کنن و اپلیکیشن خودشون رو بر اون اساس توسعه بدن.
یه راه حل اینه که از معماریهای معروف دنیای برنامهنویسی که امتحان خودشون رو پس دادن استفاده کنیم! مثل معماری MVC یا MVVM یا MVP یا چیزهای دیگه.
معماریای که امروز من میخوام راجع به اون صحبت کنم معماری Clean هست که این روزها توی دنیای فلاتر خیلی داره مورد استفاده قرار میگیره.
یکی از مهمترین چیزهایی که باید توی پیاده سازی یک معماری رعایت بشه اصل SoC یا Seperation of Concern یا جداسازی توجه هستش. (امیدوارم ترجمه خیلی بدی نکرده باشم?) به این معنی که ما به عنوان مثال وسط کدهای UI خودمون نیایم و یهو دیتایی رو از اینترنت دریافت کنیم، اون رو مدیریت کنیم و حتی همونجا State Management رو هم انجام بدیم.
کم کم بریم راجع به منطق معماری Clean صحبت کنیم؛ این معماری به طور کلی از 3 لایه تشکیل شده:
لایه Data & Platform:
این لایه بیرونیترین لایه اپلیکیشن ما هست، منظورم از بیرونیترین لایه اینه که بیشترین ارتباط رو با دنیای بیرون اپلیکیشن داره. این لایه دو قسمت کلی داره
قسمت اول Data هست که وظیفه تامین داده رو از منابع بیرونی (سرور، دیتابیس لوکال و...) داره، یعنی کدهایی که برای ارتباط با سرور (API) و کدهایی که برای خوندن داده از Local Database و... استفاده میشن توی این قسمت قرار دارن.
قسمت دوم Platform هست که در واقع همون ویجتها و صفحاتی هست که UI ما رو تشکیل میدن و کاربر با اونها تعامل داره.
پس دوتا منبع بیرونی داریم که توی این لایه باهاشون کار میکنیم: منابع داده (سرور و دیتابیس) و خود کاربر (یه سری چیزا بهش نشون میدیم و یه سری ورودیها ازش میگیریم)
لایه Presentation:
این لایه شامل کدهایی هستش که وظیفه تامین داده رو برای Platform Layer یا همون UI اپلیکیشن ما بر عهده دارن. این لایه هم از 2 بخش تشکیل شده: Repository و Presenter
کار قسمت Repository به این صورت هست که داده رو از Data Layer درخواست میکنه و اون دادههای خامی که از لایه داده گرفته رو تبدیل میکنه به دادههای قابل استفاده توی اپلیکیشن
و اما قسمت Presenter: توی این لایه ما به داده دسترسی داریم و کار اصلی این لایه State Management (مدیریت وضعیت) هست. کتابخونههایی مثل BLoC، Provider، Riverpod و... کارشون رو توی این لایه انجام میدن.
لایه Domain:
این لایه درونیترین لایه توی معماری Clean هست. کدهایی که مربوط به Business Logic ما میشن، Modelها، Usecaseها، Repositoryها و... توی این لایه قرار میگیرن.
شاید یه سوال براتون پیش اومده باشه اون هم اینکه Repositoryها مگه توی Presentation Layer نبودن؟ پس اینجا چیکار میکنن؟!
ماجرا به این صورته که ما کلاس Repository خودمون رو به صورت Abstract توی Domain پیاده میکنیم، بعد این کلاس توسط Repositoryهایی که توی لایه Presentation هستن ارث بری میشن.
چون ممکنه برای تامین داده قرار باشه از چند منبع داده گرفته بشه (سرور، دیتابیس یا حتی کش) بهتره که Repository رو به صورت Abstract توی Domain Layer پیاده کنیم
نکته قابل توجه این هستش که تمام لایه های اپلیکیشن ما به هم دیگه وابسته ان و با همدیگه ارتباط تنگاتنگی دارن.
تنها لایهای که به بقیه لایهها وابسته نیست Domain Layer هستش که شامل Business Logic ما میشه. به همین خاطر اگه به عنوان مثال ما بخوایم State Management خودمون رو از BLoC به Riverpod تغییر بدیم به عنوان مثال، نیازی به تغییر در کدهای لاجیک اصلیمون نداریم. (مدلها و...)
ساختار زیر یک Folder Structure خوب برای پیادهسازی این معماری رو نشون میده:
lib ├── data │ ├── constants.dart │ ├── datasources │ │ └── remote_data_source.dart │ ├── exception.dart │ ├── failure.dart │ ├── models │ │ └── weather_model.dart │ └── repositories │ └── weather_repository_impl.dart ├── domain │ ├── entities │ │ └── weather.dart │ ├── repositories │ │ └── weather_repository.dart │ └── usecases │ └── get_current_weather.dart ├── injection.dart ├── main.dart └── presentation ├── bloc │ ├── weather_bloc.dart │ ├── weather_event.dart │ └── weather_state.dart └── pages └── weather_page.dart
فولدر Presentation هم شامل Presentor میشه هم UI. لایه Presentor داره به وسیله BLoC کار State Management رو انجام میده.
فولدر Data هم شامل خود Data Provider ها میشه هم شامل Repository ها که دادهها رو به صورت مدل برای قسمت Presentor فراهم میکنه.
امیدوارم تونسته باشم توی این مقاله دید خوبی از این معماری بهتون بدم.
Sources:
https://dev.to/george_andronchik/clean-architecture-of-flutter-application-part-1-theory-3b6p