решения в стиле ООП GRASP – набор правил для выделения обязанностей классов Не дают четкого ответа или алгоритма решения, задают «направление» решения (что лучше, а что – хуже) 15/79
одной причины для изменения класса OCP (Open/Closed Principle) Программные элементы (модули, пакеты, классы, методы) должны быть закрыты для изменения и открыты для расширения LSP (Liskov’s Substitution Principle) Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом ISP (Interface Segregation Principle) Несколько специфичных интерфейсов лучше, чем один универсальный DIP (Dependency Inversion Principle) Абстракции не зависят от деталей, детали зависят от абстракций Подробности – в семинаре Ивана Мальцева (2013 год) 16/79
слабое сопряжение между модулями (пакетами, классами) High Cohesion – высокая функциональная связность между методами внутри класса, классами внутри пакета или пакетами внутри подсистем Information Expert – обязанность назначается классу, владеющему наибольшей информацией для выполнения данной обязанности И другие (всего 9 штук) 18/79
Теряется ценность декомпозиции Теряется контроль из «единой точки» управления Сложнее понимать, сопровождать и изменять 24/79 Держать логически связные элементы «ближе» друг к другу – хорошая идея
Application DataAccess Часть бизнес- правила «П» Часть бизнес- правила «П» Часть бизнес- правила «П» При изменении правила менять код необходимо в нескольких местах, поэтому про это можно просто забыть
OrdersManager ordersManager; private Stock stock; private EmailService emailService; ... protected void onCreateOrderBtnClick(ActionEvent e) { Order order = createOrderFromFormFields(); Stock.ReservationResult reservationResult = stock.reserve(order.getItems()); if (reservationResult.isSuccessful()) { ordersManager.processNewOrder(order); emailService.sendEmail( createConfirmationMailMessage(order)); } ... } 28/79 Этот код должен находиться в слое Application
OrdersManager ordersManager; private Stock stock; private EmailService emailService; ... protected void onCreateOrderBtnClick(ActionEvent e) { Order order = createOrderFromFormFields(); Stock.ReservationResult reservationResult = stock.reserve(order.getItems()); if (reservationResult.isSuccessful()) { ordersManager.processNewOrder(order); emailService.sendEmail( createConfirmationMailMessage(order)); } ... } 28/79 Этот код должен находиться в слое Application
решения Пояснение «контракта» метода или класса, если «контракт» не очевиден из его сигнатуры Пояснение нетривиального алгоритма Пример использования метода или класса 38/79
решения Пояснение «контракта» метода или класса, если «контракт» не очевиден из его сигнатуры Пояснение нетривиального алгоритма Пример использования метода или класса 38/79 Вместо написания комментариев попробуйте сначала написать понятный код
или метода Пример «неинформативного» интерфейса package com.mycompany.eshop.adminconsole.dataaccess; interface Actions { long importCatalog(); long export(Date date); void cleanup(int mode); } 39/79
или метода Пример «неинформативного» интерфейса package com.mycompany.eshop.adminconsole.dataaccess; interface Actions { long importCatalog(); long export(Date date); void cleanup(int mode); } 39/79
или метода Пример «неинформативного» интерфейса package com.mycompany.eshop.adminconsole.dataaccess; interface Actions { long importCatalog(); long export(Date date); void cleanup(int mode); } 39/79
выполняет действия с БД * системы для интеграции с каталогом товаров на Ebay. * Действия запускаются администратором системы. */ interface Actions { /** импорт каталога с Ebay */ long importCatalog(); /** Экспорт каталога на Ebay на заданную дату */ long export(Date date); /** Удаление временных данных импорта и экспорта */ void cleanup(int mode); } 41/79
выполняет действия с БД * системы для интеграции с каталогом товаров на Ebay. * Действия запускаются администратором системы. */ interface Actions { /** импорт каталога с Ebay */ long importCatalog(); /** Экспорт каталога на Ebay на заданную дату */ long export(Date date); /** Удаление временных данных импорта и экспорта */ void cleanup(int mode); } 41/79
логику приложения естественным языком с помощью языка программирования Сначала решите, что хотите выразить. Затем воплотите это на языке программирования 43/79
класса class ReportingController { def tasksManager; def reportsService; def scheduleReportBuilding(def parameters) { return tasksManager.submit (task: { reportsService.buildReport(parameters); }, timeout: 60); } } 46/79 Часто макеты кода пишутся еще до завершения декомпозиции, это часть процесса проектирования
ее терминах! Пример сценария реализации Пользователь выбирает коня из списка на форме «Сферические кони» Затем нажимает кнопку «Коня в вакуум!» на той же форме Сферический конь помещается в вакуум 48/79
{ sphericalHorsesScenarios.moveToVacuum( getSelectedHorse()); } package com.mycompany.sphericalhorses.application; … public class SphericalHorsesScenarios { public void moveToVacuum(Horse horse) { Vacuum vacuum = VacuumFactory.create(defaultConfig()); horse.moveTo(vacuum); } 50/79 А это что? Этого нет в сценарии!
команда, но много концептуально похожих и связных приложений Решение Унификация реализации приложений (архитектура, фреймворки, инфраструктура, …) 61/79
команда, но много концептуально похожих и связных приложений Решение Унификация реализации приложений (архитектура, фреймворки, инфраструктура, …) Преимущество Привычная среда для разработчиков 61/79
проверка этапа компиляции Валидатор кода IDE вечно «ругался» Не было возможности использовать отладчик Не было IntelliSense Тяжело разрабатывать и исправлять ошибки 63/79 «Движок» Хранилище плагинов JS JS JS JS JavaScript-файлы. Каждый плагин – «фабрика», создающая сложный объект определенного типа Движок визуализирует сложные объекты, созданные плагинами
проверка этапа компиляции Валидатор кода IDE вечно «ругался» Не было возможности использовать отладчик Не было IntelliSense Тяжело разрабатывать и исправлять ошибки 63/79 «Движок» Хранилище плагинов JS JS JS JS JavaScript-файлы. Каждый плагин – «фабрика», создающая сложный объект определенного типа Движок визуализирует сложные объекты, созданные плагинами
проверка уровня компиляции Валидатор кода IDE стал «доволен» Отладка Groovy-кода в IDE хорошо работала Ура, есть IntelliSense! В разы повысилась производительность разработки 64/79 «Движок» Хранилище плагинов JS JS JS G S JavaScript заменили на Groovy-классы
проверка уровня компиляции Валидатор кода IDE стал «доволен» Отладка Groovy-кода в IDE хорошо работала Ура, есть IntelliSense! В разы повысилась производительность разработки 64/79 «Движок» Хранилище плагинов JS JS JS G S JavaScript заменили на Groovy-классы
часто файловый журнал (LOG) – единственный способ узнать, что происходит на Production Проектируйте вывод диагностической информации в журнал Используйте журнал и для сбора статистики Периодически анализируйте журналы 65/79
часто файловый журнал (LOG) – единственный способ узнать, что происходит на Production Проектируйте вывод диагностической информации в журнал Используйте журнал и для сбора статистики Периодически анализируйте журналы 65/79 Есть связанная тема «Обработка ошибок», но она заслуживает отдельного обсуждения
Учет объема файлов журналов Вдумчивое использование уровней критичности (DEBUG, INFO, WARN, ERROR) Запись нескольких файлов журналов Отдельная конфигурация для отладки, тестирования и «боевых условий» Возможность перенастройки в «боевых условиях» 66/79 Трезво оцените полезность каждой записи в журнале
ошибке? Версию приложения Версию ОС и (или) виртуальной машины Версию веб-браузера Версию драйвера БД Детальную информацию об ошибке Все это справедливо как для серверных, так и для клиентских приложений 67/79
ошибке? Версию приложения Версию ОС и (или) виртуальной машины Версию веб-браузера Версию драйвера БД Детальную информацию об ошибке Все это справедливо как для серверных, так и для клиентских приложений 67/79 Можно также вложить информацию об активности пользователя
тесты Следите за качеством исходного кода самого теста Документируйте тесты 68/79 Не забываем про недостатки документирования и комментариев в исходном коде
код, написанный «на всякий случай», а также конфигурации, документация и др. Отвлекает внимание Мешает увидеть истинное положение дел Вводит в заблуждение Делает работу разработчиков менее удобной 69/79
имен переменных, методов и их параметров, классов, … Уничтожение «бестолковых» комментариев или их улучшение 70/79 Вспоминайте народную мудрость: «Чисто не там, где убирают. Чисто там, где не сорят»
Наличие простых способов проверить, не сломалось ли что-то Например, автоматические тесты Организационные правила в проекте Например, любые улучшения и рефакторинги – это отдельные задачи 71/79