규칙 7 : 모든 엔티티를 작게 유지 (Keep All Entities Small)
클래스나 패키지가 너무 크면 읽기 어렵고, 유지보수가 힘들어집니다. 따라서 아래와 같은 기준으로 관리하는 것이 중요합니다.
Java 기준: 클래스는 50줄 이하, 패키지는 10개 파일 이하로 유지.
Flutter 기준: 클래스는 300줄 이하로 유지 가능. 응집력과 책임 분리를 고려해서 관리.
클래스 크기
Java: 50줄 이하
Flutter: 300줄 이하 (기능 분리 중요)
패키지 크기
Java: 10개 파일 이하
Flutter: 하나의 목적을 가진 패키지로 관리
기능 분리
UI와 로직 분리:
UI와데이터 처리를 별도로 관리
Flutter 코드 예시 : To-Do 앱
Before: 긴 클래스
lib/
└── todo_manager.dart todo_manager.dart
class ToDoManager {
final List<ToDo> _todos = [];
void addToDo(String title) {
_todos.add(ToDo(
id: DateTime.now().toString(),
title: title,
isCompleted: false,
));
}
void toggleComplete(String id) {
final index = _todos.indexWhere((todo) => todo.id == id);
if (index != -1) {
_todos[index].isCompleted = !_todos[index].isCompleted;
}
}
void deleteToDo(String id) {
_todos.removeWhere((todo) => todo.id == id);
}
List<ToDo> get todos => List.unmodifiable(_todos);
}
class ToDo {
final String id;
final String title;
bool isCompleted;
ToDo({
required this.id,
required this.title,
this.isCompleted = false,
});
}문제점
응집도 낮음:
ToDo데이터 모델과 관리 로직(ToDoManager)이 하나의 파일에 있어 역할이 혼재되어 있음.
확장성 부족:
새로운 기능 추가 시 이 파일에 계속 코드를 추가해야 하므로 파일 크기가 커짐.
재사용성 저하:
ToDo모델과 관련 로직을 다른 곳에서 사용하려면, 해당 파일 전체를 가져가야 하는 문제가 있음.
After: 작은 엔티티로 리팩터링된 코드
구조를 다음과 같이 분리:
lib/
├── models/
│ └── todo.dart // 데이터 모델
├── services/
│ ├── todo_service.dart // 상태 관리
│ └── todo_repository.dart // 데이터 처리 분리models/todo.dart
class ToDo {
final String id;
final String title;
final bool isCompleted;
ToDo({
required this.id,
required this.title,
this.isCompleted = false,
});
ToDo copyWith({String? title, bool? isCompleted}) {
return ToDo(
id: id,
title: title ?? this.title,
isCompleted: isCompleted ?? this.isCompleted,
);
}
}services/todo_repository.dart
import '../models/todo.dart';
class ToDoRepository {
final List<ToDo> _todos = [];
List<ToDo> fetchTodos() {
return List.unmodifiable(_todos);
}
void saveToDo(ToDo todo) {
_todos.add(todo);
}
void deleteToDo(String id) {
_todos.removeWhere((todo) => todo.id == id);
}
}services/todo_service.dart
import '../models/todo.dart';
import 'todo_repository.dart';
class ToDoService {
final ToDoRepository _repository = ToDoRepository();
List<ToDo> get todos => _repository.fetchTodos();
void addToDo(String title) {
final newToDo = ToDo(id: DateTime.now().toString(), title: title);
_repository.saveToDo(newToDo);
}
void toggleComplete(String id) {
final todos = _repository.fetchTodos();
final index = todos.indexWhere((todo) => todo.id == id);
if (index != -1) {
final updatedToDo = todos[index].copyWith(
isCompleted: !todos[index].isCompleted,
);
_repository.saveToDo(updatedToDo);
}
}
void deleteToDo(String id) {
_repository.deleteToDo(id);
}
}결과
짧고 단순한 클래스:
각 파일이 300 줄 이하로 유지됨.
클래스별 역할이 분리되어 코드 가독성이 증가.
응집력 있는 패키지:
models,services로 분리하여 각 패키지가 명확한 목적을 가짐.
유지보수 용이성:
새로운 기능 추가 시 관련 클래스만 수정하면 됨.
독립적인 구조로 다른 프로젝트에서도 재사용 가능.
Last updated