Сегодня я начинаю серию постов о принципах SOLID — фундаментальных правилах разработки программного обеспечения, которые помогают создавать чистый, масштабируемый и поддерживаемый код.
SOLID — это аббревиатура из пяти принципов объектно-ориентированного программирования. Разберем каждую букву отдельно, начиная с S (Single Responsibility Principle)
Что такое Single Responsibility Principle
Принцип единственной ответственности гласит: каждый класс должен иметь только одну причину для изменения. Проще говоря — один класс решает одну задачу.
Применение к классам
❌Нарушение SRP
class UserManager {
// Работа с БД
User getUser(String id) => User(id: id, name: 'John');
void saveUser(User user) { /* сохранение */ }
// Валидация
bool validateEmail(String email) => email.contains('@');
// Уведомления
void sendWelcomeEmail(User user) { /* отправка */ }
// Отчеты
String generateReport(User user) => 'Отчет: ${user.name}';
}Класс выполняет четыре разные задачи: работа с БД, валидация, уведомления и отчеты. У него слишком много причин для изменения.
✅Правильное применение SRP
// Работа с базой данных
class UserRepository {
User getUser(String id) => User(id: id, name: 'John');
void saveUser(User user) { /* сохранение */ }
void deleteUser(String id) { /* удаление */ }
}
// Валидация данных
class UserValidator {
bool validateEmail(String email) {}
bool validatePassword(String password) {}
}
// Отправка уведомлений
class NotificationService {
void sendWelcomeEmail(User user) {}
}
// Генерация отчетов
class ReportGenerator {
String generateUserReport(User user) {}
}
Теперь каждый класс имеет только одну ответственность и одну причину для изменения.
Применение к методам
Принцип работает и на уровне методов — каждый метод должен
выполнять одну задачу.
❌Нарушение на уровне метода
void processOrder(Order order) {
// Валидация
if (order.items.isEmpty) throw Exception('Корзина пуста');
// Расчет
double total = 0;
for (var item in order.items) {
total += item.price * item.quantity;
}
// Сохранение
database.save(order);
// Уведомление
emailService.send(order.userEmail, 'Заказ оформлен');
}✅Правильное применение
class OrderService {
final OrderValidator validator;
final PriceCalculator calculator;
final OrderRepository repository;
final NotificationService notifications;
void processOrder(Order order) {
_validateOrder(order);
final total = _calculateTotal(order);
_saveOrder(order, total);
_notifyUser(order);
}
void _validateOrder(Order order) => validator.validate(order);
double _calculateTotal(Order order) => calculator.calculate(order);
void _saveOrder(Order order, double total) => repository.save(order);
void _notifyUser(Order order) => notifications.send(order);
}Каждый метод выполняет одну конкретную задачу.
Преимущества SRP
✔️Упрощение тестирования — каждый класс тестируется изолированно
✔️Легкость поддержки — изменения в одной части не влияют на другие
✔️Лучшая читаемость — код становится понятнее
✔️Переиспользование — специализированные классы легче использовать повторно
В следующих постах я расскажу о других принципах SOLID.
🔄Делитесь в комментариях своими примерами применения SOLID в ваших проектах! Интересно узнать, с какими сложностями вы сталкивались и как принципы SOLID помогли их решить