Поэтому, когда вы пытаетесь обучить себя принципу единой ответственности, вы, скорее всего, встретите такие определения, как «Один метод должен делать только одно». и «Один класс должен быть только одной причиной для изменения». И потом всегда есть куча игрушечных примеров вроде
class Dog {
String bark() {
return "Woof";
}
}
Но мне очень сложно применить этот принцип в разработке корпоративных приложений.
У нас есть приложение, в котором есть «Элементы проекта», «Действия» и «Сотрудники». У сотрудника будет много действий, а у действия может быть один элемент проекта.
Некоторые сотрудники назначаются для всех элементов проекта, некоторые - только для группы. Элемент проекта может быть удален из сотрудника и назначен новый. Сотрудник может добавлять новые действия только с назначенными ему элементами проекта. Если элементы проекта не назначены, это означает, что доступны все.
У одного из наших клиентов было требование, они хотели видеть список любимых элементов проекта при добавлении новых действий. Неважно, как сотрудник выбирает элемент проекта, это другой взгляд.
Элементы любимого проекта должны быть упорядочены по некоторым интересным правилам. Это зависит от общей рассчитанной работы по Действиям, в которых существует Любимый элемент проекта, учитываются только последние 60 дней. По крайней мере, это конкретное требование ..
Так что моей обязанностью было реализовать это, и вот реализация, которая у меня есть:
public List<ProjectElement> getFavoriteProjectElementsSortedDescendingByTotalWorkHoursInLast60Days(Employee owner) {
// All Favorite Project Elements of Owner
final List<ProjectElement> favoriteProjectElementsOfOwner
= (List<ProjectElement>) (List<?>) favoriteBusinessObjectHelper.getAllFavoriteObjectsForBusinessObjectType(BusinessObjectType.PROJECT_ELEMENT.toInt());
// Activities by Favorite Project Elements
final List<Activity> favoriteProjectElementActivitiesForLast60Days
= activityFinder.findByInProjectElementsForLastGivenDates(owner, favoriteProjectElementsOfOwner, 60);
// Create a Map with Favorite Project Element - Calculated Work
final Map<ProjectElement, Long> projectElementTotalWorkMap = new HashMap<ProjectElement, Long>();
for (Activity activity : favoriteProjectElementActivitiesForLast60Days) {
final ProjectElement activityProjectElement = activity.getProjectElement();
if (!projectElementTotalWorkMap.containsKey(activityProjectElement)) {
projectElementTotalWorkMap.put(activityProjectElement, 0L);
}
final long calculatedWork = activity.getCalculatedWork();
final long totalCalculatedWork = projectElementTotalWorkMap.get(activityProjectElement) + calculatedWork;
projectElementTotalWorkMap.put(activityProjectElement, totalCalculatedWork);
}
// Sort the Map by value descending
final Map<ProjectElement, Long> sortedProjectElementTotalWorkMap
= InnboundSortTool.sortByValueDescending(projectElementTotalWorkMap);
// We do not want to show owners Favorite Project Element in the sidebar, if the Project Element is not available
// for Employee anymore.. See the comments at the end of the file.
final Set<ProjectElement> allowedProjectElementsForOwner = owner.getExplicitlyAssignedOnlyActiveProjectElements();
final ArrayList<ProjectElement> projectElementsSorted = new ArrayList<ProjectElement>();
for (ProjectElement projectElement : sortedProjectElementTotalWorkMap.keySet()) {
if (allowedProjectElementsForOwner.size() == 0) { // This means Employee does not have any restrictions, all Project Elements are available to him.
projectElementsSorted.add(projectElement);
} else { // If Employee has assigned Project Elements, we must check if the Favorite Project Element is assigned to him..
if (allowedProjectElementsForOwner.contains(projectElement)) {
projectElementsSorted.add(projectElement); // If yes, add it to list, if no simply continue the loop without adding.
}
}
if (projectElementsSorted.size() == 20) {
break; // 20 is an arbitrary value, we do not want to show too many Favorite Project Elements in the UI.. Limit by 20.
}
}
return projectElementsSorted;
}
Ого, это один большой метод, но он выполняет свою работу. Но он не делает ничего, не так ли? Но если каждый метод выполняет только одно действие, кто будет делать все это?
Могу ли я представить вспомогательный класс и делегировать все этому классу и начать звонить:
final Map<ProjectElement, Long> projectElementTotalWorkMap = helper.CreateprojectElementTotalWorkMap();
helper.removeUnassignedFavoriteProjectElementsFromEmployee();
и т.д? Но тогда я могу представить Помощника самому Помощнику? Где это вообще заканчивается? Когда я начинаю подобный рефакторинг, у меня появляются крайне бесполезные методы, которые просто вызывают другие методы, и этот класс будет выглядеть так:
List<ProjectElement> favoritesList;
favoritesList = helper.doThis();
favoritesList = helper.doThat();
favoritesList = helper.sort();
return favoritesList;
Я вообще не понимаю этого принципа? Думаю, нет, поэтому возникает вопрос, как мне исправить этот метод, чтобы он соответствовал «SRP»?