Дж. Арлоу, А. Нейштадт - UML 2 и Унифицированный процесс - Практический объектно-ориентированный анализ и проектирование (1158625), страница 69
Текст из файла (страница 69)
Правильно сформированныепроектные классыПроектная модель будет передана программистам для фактическогосоздания исходного кода. Код также может генерироваться непосредственно из самой модели, если это поддерживается инструментом моделирования. Следовательно, проектные классы должны быть достаточно подробно описаны. В процессе описания определяется, являетсяли класс «правильно сформированным» или нет.Проектный класс всегда должен оцениваться с точки зрения его пользователей.При создании важно всегда рассматривать проектный класс с точкизрения его потенциальных клиентов.
Каким они увидят этот класс –не слишком ли он сложен? Может быть чтото упущено? Как тесно онвзаимосвязан с другими классами? Соответствует ли его имя выполняемым функциям? Все это важно и может быть сведено в следующиечетыре основные характеристики правильно сформированного проектного класса:• полный и достаточный;• простой;• обладает высокой внутренней связностью;• обладает низкой связанностью с другими классами.17.5.1.
Полнота и достаточностьОткрытые операции класса определяют контракт между классом и егоклиентами.Открытые операции класса определяют контракт между классом и егоклиентами. Как и для делового контракта, важно, чтобы этот контракт был четким, правильно определенным и приемлемым для всехпартнеров.376Глава 17. Проектные классыПолнота характеризует соответствие предоставляемых классом сервисов тому, что ожидают клиенты. Предположения о наборе доступныхопераций клиенты будут делать исходя из имени класса.
Обратимсяк примеру из реальной жизни: при покупке новой машины вполне разумно ожидать, что у нее будут колеса! То же самое с классами: делатьвывод о том, какие операции должны быть доступны, клиенты будутиз имени класса и описания его семантики. Например, от класса BankAccount (банковский счет), предоставляющего операцию withdraw(...),будут ожидать и наличия операции deposit(...). Опятьтаки, если проектируется такой класс, как ProductCatalog (каталог продуктов), любойклиент может небезосновательно ожидать, что сможет добавлять, удалять и вести поиск продуктов (Product) по каталогу. Такая семантикаясно следует из имени класса.
Полнота гарантирует, что классы удовлетворяют всем справедливым ожиданиям клиента.Полный и достаточный класс предлагает пользователям такой контракт,какой они ожидают – не больше и не меньше.Достаточность, с другой стороны, гарантирует, что все операции класса полностью сосредоточены на реализации его предназначения.
Классникогда не должен удивлять клиента. Он должен содержать толькоожидаемый набор операций, не более этого. Например, обычная ошибка новичков: взять простой достаточный класс, такой как BankAccount,и затем добавить в него операцию по обработке кредитных карт или поуправлению политиками страхования и т. д. Достаточность заключается в максимально возможном сохранении простоты и узкой специализированности проектного класса.Золотое правило обеспечения полноты и достаточности: класс долженделать то, что ожидают от него пользователи, не больше и не меньше.17.5.2.
ПростотаОперации должны проектироваться таким образом, чтобы предлагатьединственный, простой, элементарный сервис. Класс не должен предлагать множество способов выполнения одного и того же, посколькуэто запутывает клиентов и может привести к усложнению технического обслуживания и проблемам совместимости.Простота – сервисы должны быть простыми, элементарными и уникальными.Например, если в классе BankAccount есть простая операция созданияодного депозитного вклада, в нем не должно быть более сложных операций, создающих два или более депозитов. Такого же эффекта можнодобиться, повторяя простую операцию.
Класс всегда должен предлагать самый простой и самый малый набор возможных операций.17.5. Правильно сформированные проектные классы377Хотя придерживаться простоты – хорошее правило, тем не менее возможны обстоятельства, вынуждающие от него отойти. Самой распространенной причиной нарушения ограничения простоты является повышение производительности.
Например, если групповое создание депозитных вкладов по сравнению с одиночным существенно повышаетпроизводительность, можно ослабить требование к простоте и ввестив класс BankAccount более сложную операцию deposit(…), обрабатывающую сразу несколько транзакций. Однако отправной точкой в проектировании всегда должен быть самый простой из возможных наборопераций. Усложнение должно происходить, только если для этогоесть веские и обоснованные причины.Это важный момент. Многие из так называемых проектных «оптимизаций» в большей степени основываются на вере, а не на твердых фактах.
В результате их влияние на фактическую производительностьвремени выполнения приложения мало или вообще отсутствует. Например, если приложение будет проводить в данной операции всего 1%своего времени, оптимизация этой операции может ускорить приложение не более чем на 1%. Полезное практическое правило: большинствоприложений проводит около 90% времени выполнения в 10% своихопераций. Вот эти операции и надо находить и оптимизировать, чтобыполучить реальное повышение производительности. Такую настройкупроизводительности можно осуществить только с помощью инструмента профилирования кода, такого как jMechanic для Java (http://jmechanic.sourceforge.net), который проводит сбор параметров производительности исполняющегося кода.
Конечно, это задача реализации,которая может влиять на проектную модель.17.5.3. Высокая внутренняя связностьКаждый класс должен моделировать только одно абстрактное понятиеи иметь набор операций, обеспечивающих предназначение класса. Этои есть связность (cohesion).
Если необходимо, чтобы у класса быломножество разных обязанностей, для реализации некоторых из нихможно создать «вспомогательные классы». Тогда основной класс может делегировать обязанности своим «помощникам».Внутренняя связность – одна из самых желательных характеристиккласса.
Связные классы обычно проще понимать, повторно использовать и обслуживать. У связного класса небольшой набор тесно взаимосвязанных обязанностей. Каждая операция, атрибут и ассоциациякласса специально проектируются для реализации этого маленького,узкоспециализированного набора обязанностей.Каждый класс должен отражать единственную четко определенную абстракцию, используя минимальный набор возможностей.378Глава 17. Проектные классыHotelBeanHotelCarBeanЧто не так с этой моделью?CarBeanРис. 17.5. Неверная модель системыКакто нам попалась на глаза модель системы продаж, приведеннаяна рис. 17.5, которая несколько смутила нас. В ней есть класс HotelBean(компонент гостиница), класс CarBean (компонент машина) и класс HotelCarBean (компонент машинагостиница) (компонент (bean) – это корпоративный компонент Java (Enterprise JavaBeans, EJBs)).
HotelBeanотвечал за сдачу комнат в гостиницах, CarBean – за прокат автомобилей, а HotelCarBean – за продажу пакета этих услуг (прокат автомобиляпри остановке в гостинице). Очевидно, что эта модель неверна по нескольким причинам.•Имена классов подобраны неверно – HotelStay (остановка в гостинице) и CarHire (прокат автомобиля) подошли бы намного лучше.•Суффикс «Bean» не нужен, поскольку он просто указывает на определенную деталь реализации.•Класс HotelCarBean имеет очень слабую связность – его две основныеобязанности (сдача гостиничных номеров и прокат автомобилей)уже выполняются двумя другими классами.•Это и не аналитическая модель (в ней есть информация проектирования – суффиксы «Bean»), и не проектная модель (она недостаточнополная).С точки зрения внутренней связности классы HotelBean и CarBean болееили менее приемлемы (при условии, что будут переименованы), но HotelCarBean просто абсурден.17.5.4.
Низкая связанность с другими классамиКонкретный класс должен быть ассоциирован ровно с таким количеством классов, которого достаточно для того, чтобы он мог реализовывать свои обязанности. Взаимоотношения должны устанавливатьсятолько в том случае, если между классами существует реальная семантическая связь – это обеспечивает низкую связанность (coupling).Класс должен быть ассоциирован с минимальным количеством классов,позволяющим ему реализовывать свои обязанности.Одна из распространенных ошибок неопытных ОО проектировщиков –объединение в модели всего со всем практически случайным образом.По сути, связанность – самый злостный ваш враг в объектном моделировании, поэтому необходимо заранее принимать меры, чтобы ограни17.6.
Наследование379чить отношения между классами и максимально сократить связанность.Объектная модель с большим количеством взаимосвязей эквивалентна «спагеттикоду» в неОО мире. Она приведет к созданию малопонятной и неудобной в эксплуатации системы. Вы увидите, что ОО системы с большим количеством взаимосвязей часто возникают в проектах, в которых нет формального процесса моделирования, а системапросто эволюционирует во времени произвольным образом.Неопытные проектировщики должны быть внимательными и не устанавливать связи между классами просто потому, что в одном из нихесть код, который может использоваться другим.
Это самый плохойвариант повторного использования, когда ради небольшой экономиивремени разработки в жертву приносится архитектурная целостностьсистемы. Все ассоциации между классами должны тщательно продумываться. Многие ассоциации перейдут в проектную модель непосредственно из аналитической, но целый ряд ассоциаций вводится иззаограничений реализации или желания повторно использовать код. Этиассоциации необходимо проверять наиболее внимательно.Конечно, некоторая степень связанности хороша и необходима. Допускается высокая связанность в рамках подсистемы, поскольку этоуказывает на высокую связность компонента. Подрывают архитектуру только многочисленные связи между подсистемами.