Architecture Layers বিস্তারিত
Clean Architecture-এ Flutter applications তিনটি প্রধান layer-এ বিভক্ত। প্রতিটি layer-এর নিজস্ব দায়িত্ব এবং structure রয়েছে।
🎯 Domain Layer (Core Business Logic)
Domain Layer হল Clean Architecture-এর হৃদয়। এটি সবচেয়ে inner layer এবং কোনো external dependencies নেই।
📦 Components
🏷 Entities
Business objects যা application-এর core data represent করে।
class User {
final String id;
final String name;
final String email;
final DateTime createdAt;
const User({
required this.id,
required this.name,
required this.email,
required this.createdAt,
});
}
🎯 Use Cases
Specific business operations বা actions। একটি use case একটি নির্দিষ্ট কাজ করে।
class GetUserProfileUseCase {
final UserRepository _repository;
GetUserProfileUseCase(this._repository);
Future<User> call(String userId) async {
return await _repository.getUserById(userId);
}
}
📋 Repository Interfaces
Data layer-এর সাথে communication-এর জন্য abstract contracts।
abstract class UserRepository {
Future<User> getUserById(String id);
Future<List<User>> getAllUsers();
Future<User> createUser(User user);
Future<User> updateUser(User user);
Future<void> deleteUser(String id);
}
✅ Domain Layer-এর নিয়ম
- কোনো external dependencies নেই
- শুধুমাত্র Dart core libraries ব্যবহার করে
- Business logic এবং rules এখানে থাকে
- UI বা database সম্পর্কে কিছু জানে না
📊 Data Layer (External Data Management)
Data Layer external data sources (API, Database, Cache) থেকে data handle করে।
📦 Components
🏗 Models
API response এবং database entities represent করে। JSON serialization এখানে হয়।
class UserModel with _$UserModel {
const factory UserModel({
required String id,
required String name,
required String email,
required String createdAt,
}) = _UserModel;
factory UserModel.fromJson(Map<String, dynamic> json) =>
_$UserModelFromJson(json);
}
extension UserModelX on UserModel {
User toEntity() {
return User(
id: id,
name: name,
email: email,
createdAt: DateTime.parse(createdAt),
);
}
}
🌐 Data Sources
External APIs বা local databases-এর সাথে communication।
abstract class UserRemoteDataSource {
Future<UserModel> getUserById(String id);
Future<List<UserModel>> getAllUsers();
Future<UserModel> createUser(UserModel user);
}
class UserRemoteDataSourceImpl implements UserRemoteDataSource {
final Dio _dio;
UserRemoteDataSourceImpl(this._dio);
Future<UserModel> getUserById(String id) async {
final response = await _dio.get('/users/$id');
return UserModel.fromJson(response.data);
}
}
🔄 Repository Implementations
Domain layer-এর repository interfaces implement করে।
class UserRepositoryImpl implements UserRepository {
final UserRemoteDataSource _remoteDataSource;
final UserLocalDataSource _localDataSource;
UserRepositoryImpl(this._remoteDataSource, this._localDataSource);
Future<User> getUserById(String id) async {
try {
final userModel = await _remoteDataSource.getUserById(id);
await _localDataSource.cacheUser(userModel);
return userModel.toEntity();
} catch (e) {
final cachedUser = await _localDataSource.getCachedUser(id);
return cachedUser.toEntity();
}
}
}
✅ Data Layer-এর নিয়ম
- Domain layer-এর interfaces implement করে
- External dependencies (HTTP, Database) এখানে থাকে
- Data transformation (Model ↔ Entity) এখানে হয়
- Error handling এবং caching logic এখানে থাকে
🖥 Presentation Layer (UI & User Interaction)
Presentation Layer user interface এবং user interactions handle করে।
📦 Components
📱 Pages/Screens
UI components যা user দেখে এবং interact করে।
class UserProfilePage extends StatelessWidget {
const UserProfilePage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Profile')),
body: BlocBuilder<UserProfileBloc, UserProfileState>(
builder: (context, state) {
if (state is UserProfileLoading) {
return Center(child: CircularProgressIndicator());
}
if (state is UserProfileLoaded) {
return UserProfileView(user: state.user);
}
return Center(child: Text('Error loading user'));
},
),
);
}
}
🎮 Controllers/BLoC
State management এবং business logic calls।
GetX Controller:
class UserController extends GetxController {
final GetUserProfileUseCase _getUserProfileUseCase;
UserController(this._getUserProfileUseCase);
final _user = Rx<User?>(null);
final _isLoading = false.obs;
User? get user => _user.value;
bool get isLoading => _isLoading.value;
Future<void> loadUserProfile(String userId) async {
try {
_isLoading.value = true;
final user = await _getUserProfileUseCase(userId);
_user.value = user;
} catch (e) {
Get.snackbar('Error', 'Failed to load user profile');
} finally {
_isLoading.value = false;
}
}
}
BLoC:
class UserProfileBloc extends Bloc<UserProfileEvent, UserProfileState> {
final GetUserProfileUseCase _getUserProfileUseCase;
UserProfileBloc(this._getUserProfileUseCase) : super(UserProfileInitial()) {
on<LoadUserProfile>(_onLoadUserProfile);
}
Future<void> _onLoadUserProfile(
LoadUserProfile event,
Emitter<UserProfileState> emit,
) async {
emit(UserProfileLoading());
try {
final user = await _getUserProfileUseCase(event.userId);
emit(UserProfileLoaded(user));
} catch (e) {
emit(UserProfileError(e.toString()));
}
}
}
🔗 Bindings/Providers
Dependency injection setup।
GetX Binding:
class UserBinding extends Bindings {
void dependencies() {
Get.lazyPut<UserRemoteDataSource>(
() => UserRemoteDataSourceImpl(Get.find()),
);
Get.lazyPut<UserRepository>(
() => UserRepositoryImpl(Get.find(), Get.find()),
);
Get.lazyPut<GetUserProfileUseCase>(
() => GetUserProfileUseCase(Get.find()),
);
Get.lazyPut<UserController>(
() => UserController(Get.find()),
);
}
}
✅ Presentation Layer-এর নিয়ম
- শুধুমাত্র Domain layer-এর সাথে communicate করে
- UI state management এখানে হয়
- User input validation এখানে হয়
- Navigation logic এখানে থাকে
🔄 Layer Communication Flow
sequenceDiagram
participant UI as 🖥 UI (Page)
participant Controller as 🎮 Controller/BLoC
participant UseCase as 🎯 Use Case
participant Repo as 📋 Repository Interface
participant RepoImpl as 🔄 Repository Impl
participant DataSource as 🌐 Data Source
participant API as 🌍 External API
UI->>Controller: User Action
Controller->>UseCase: Execute Business Logic
UseCase->>Repo: Request Data
RepoImpl->>DataSource: Fetch Data
DataSource->>API: HTTP Request
API-->>DataSource: Response Data
DataSource-->>RepoImpl: Model Data
RepoImpl-->>UseCase: Entity Data
UseCase-->>Controller: Business Result
Controller-->>UI: Update UI State
📚 Next Steps
Layer structure বুঝার পর folder organization দেখুন:
- 📂 Folder Structure - Project-এ কিভাবে organize করবেন
- 🔄 Workflow - Development workflow এবং best practices
💡 Pro Tip: প্রতিটি layer-এর দায়িত্ব আলাদা রাখুন। Mixing layers হল সবচেয়ে common mistake!