Принцип єдиної відповідальності - це те, що ваш код виконує лише одну річ, і ви можете розділити всю функціональність на кілька класів, які призначені для виконання однієї конкретної речі. Прикладом є конкретний клас для перевірки, виконання певної ділової логіки, збагачення моделі, отримання даних, оновлення даних, навігація тощо.
Розділення проблем стосується того, що ваш код не буде щільно пов'язаний з деякими іншими класами / системами. Використання інтерфейсів у вашому коді дуже допомагає, таким чином ви можете безперешкодно з'єднати класи / системи, які вам кодують. Плюсом цього є те, що простіше також перевірити свій код. Існує багато рамок (IoC), які можуть допомогти вам досягти цього, але ви можете, звичайно, також реалізувати таку річ.
Приклад чогось SoC, але не має SRP
public class Foo
{
private readonly IValidator _validator;
private readonly IDataRetriever _dataRetriever;
public Foo(IValidator validator, IDataRetriever dataRetriever)
{
_validator = validator;
_dataRetriever = dataRetriever;
}
public NavigationObject GetDataAndNavigateSomewhereIfValid()
{
var data = _dataRetriever.GetAllData();
if(_validator.IsAllDataValid(data))
{
object b = null;
foreach (var item in data.Items)
{
b = DoSomeFancyCalculations(item);
}
if(_validator.IsBusinessDataValid(b))
{
return ValidBusinessLogic();
}
}
return InvalidItems();
}
private object DoSomeFancyCalculations(object item)
{
return new object();
}
private NavigationObject ValidBusinessLogic()
{
return new NavigationObject();
}
private NavigationObject InvalidItems()
{
return new NavigationObject();
}
}
Як бачимо, цей код недостатньо поєднаний з класами або іншими системами, оскільки він використовує лише деякі інтерфейси, щоб робити речі. Це добре з точки зору SoC.
Як ви бачите, цей клас також містить 3 приватні методи, які роблять деякі химерні речі. З точки зору SRP, ці методи, ймовірно, повинні бути розміщені в деяких власних класах. 2 з них роблять щось із навігацією, що б відповідало якомусь класу INavigation. Інший робить деякі химерні розрахунки для елемента, це, ймовірно, може бути розміщено в класі IBusinessLogic.
Маючи щось подібне, у вас обох є SoC та SRP:
public class Foo
{
private readonly IValidator _validator;
private readonly IDataRetriever _dataRetriever;
private readonly IBusinessLogic _businessLogic;
private readonly INavigation _navigation;
public Foo(IValidator validator, IDataRetriever dataRetriever, IBusinessLogic businessLogic, INavigation navigation)
{
_validator = validator;
_dataRetriever = dataRetriever;
_businessLogic = businessLogic;
_navigation = navigation;
}
public NavigationObject GetDataAndNavigateSomewhereIfValid()
{
var data = _dataRetriever.GetAllData();
if(_validator.IsAllDataValid(data))
{
object b = null;
foreach (var item in data.Items)
{
b = _businessLogic.DoSomeFancyCalculations(item);
}
if(_validator.IsBusinessDataValid(b))
{
return _navigation.ValidBusinessLogic();
}
}
return _navigation.InvalidItems();
}
}
Звичайно, ви можете обговорити, чи варто всю цю логіку розмістити в GetDataAndNavigateSomewhereIfValid
методі. Це те, що ви повинні вирішити для себе. Мені здається, що цей метод робить занадто багато матеріалів.