Untitled

Code Architecture

<aside> ๐Ÿ’ก Code Architecture will be referred to Clean Architecture by Uncle Bob.

</aside>

It consists of four main modules: App, Domain, Data, and Device.

Folder structure

Nothing in an inner circle can know anything at all about something in an outer circle.

Untitled

lib/
    app/                          <--- application layer
        pages/                        <-- pages or screens
          sign_up/
	          views/
		          widgets/ <-- the entire widgets
		          login_0000.dart
		          sign_up_0111.dart
		          sign_up_0112.dart
		        controllers/
		        presenters/                  <--- usecase์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฒฐ๊ณผ๋ฅผ 
		      sign_up_details/
        utils/                        <--- ๋‚ ์งœ, ๋ฐ์ดํ„ฐ ์—ฐ์‚ฐ ๋“ฑ์˜ ๊ฐ€๊ณต
	        navigator.dart
	      providers/                    <--- ์ƒํƒœ ๊ด€๋ฆฌ Provider ๊ด€๋ จ ๋กœ์ง
    data/ 
		    config/                       <--- ๋ฐ์ดํ„ฐ์™€ ๊ด€๋ จ๋œ ๋ชจ๋“  ์„ค์ • ๊ฐ’
			    dio.dart 
			    path.dart                         
        repositories/                 <--- ๋ชจ๋“  API ํ˜ธ์ถœ
          data_auth_repo.dart           <-- example repo: handles all authentication
		    dto/                      <--- ๋ฐ์ดํ„ฐ ํ˜•์‹ ์ •์˜
    domain/                       <--- domain layer (business and enterprise) PURE DART
        entities/                 <--- ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ํ•ต์‹ฌ ๊ทœ์น™, usecases์—์„œ ์‚ฌ์šฉ
          user.dart                   <-- example entity
          manager.dart                <-- example entity
        usecases/                   <--- ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ตฌํ˜„
          user_usecase.dart          <-- example usecase extends `UseCase` or `CompletableUseCase`
    main.dart                     <--- entry point

Entity - UseCases - Presenter

์•„๋ž˜๋Š” ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์œ ์ฆˆ์ผ€์ด์Šค๋ฅผ ๊ฑฐ์ณ Presenter์™€ ์†Œํ†ตํ•˜๋Š” Flutter ์ฝ”๋“œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

  1. ์—”ํ‹ฐํ‹ฐ (Entity):
class UserEntity {
  final String name;
  final String email;

  UserEntity({required this.name, required this.email});
}

  1. ์œ ์ฆˆ์ผ€์ด์Šค (Use Case):
import 'package:my_app/entities/user_entity.dart';

class GetUserUseCase {
  UserEntity getUserById(String userId) {
    // ์—ฌ๊ธฐ์„œ๋Š” ๋‹จ์ˆœํžˆ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    return UserEntity(name: 'John Doe', email: '[email protected]');
  }
}

  1. ํ”„๋ ˆ์  ํ„ฐ (Presenter):
import 'package:my_app/entities/user_entity.dart';
import 'package:my_app/use_cases/get_user_use_case.dart';

class UserPresenter {
  final GetUserUseCase getUserUseCase;

  UserPresenter({required this.getUserUseCase});

  void getUserInfo(String userId) {
    // ์œ ์ฆˆ์ผ€์ด์Šค๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
    UserEntity user = getUserUseCase.getUserById(userId);

    // ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ UI์— ํ‘œ์‹œํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
    displayUserInfo(user);
  }

  void displayUserInfo(UserEntity user) {
    // UI์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    print('User Name: ${user.name}, Email: ${user.email}');
  }
}

์œ„ ์ฝ”๋“œ์—์„œ๋Š” ์—”ํ‹ฐํ‹ฐ(UserEntity)๊ฐ€ ์œ ์ฆˆ์ผ€์ด์Šค(GetUserUseCase)๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํ”„๋ ˆ์  ํ„ฐ(UserPresenter)์—๊ฒŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ ˆ์  ํ„ฐ๋Š” ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ UI์— ํ‘œ์‹œํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

Controller - View - Presenter

์•„๋ž˜๋Š” Presenter์™€ Controller, ๊ทธ๋ฆฌ๊ณ  View๊ฐ€ ์–ด๋–ป๊ฒŒ ์†Œํ†ตํ•˜๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” Dart ์ฝ”๋“œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.