- •1. Понятие информационной системы (ис). Корпоративные ис. Структура ис.
- •2. Понятие информационной системы (ис). Корпоративные ис. Классификация ис.
- •3. История развития ис.
- •4. .Net Framework. Общеязыковая среда исполнения (clr). Управляемые модули и сборки.
- •5. .Net Framework. Общая система типов (cts) и Общеязыковая спецификация (cls).
- •6. .Net Framework. Механизм сборки мусора.
- •7. C#. Объявление класса.
- •8. Java. Объявление класса.
- •9. C#. Делегаты.
- •10. C#. События.
- •11. C#. Наследование: правила, синтаксис. Сокрытие имен.
- •12. Java. Наследование: правила, синтаксис. Сокрытие имен.
- •13. Правила наследования типов. Принцип «Open-Closed Principle».
- •14. Правила наследования типов. Принцип «Liskov Substitution Principle».
- •15. C#. Приведение типов. Операторы as и is.
- •16. C#. Виртуальные и невиртуальные методы. Статические методы.
- •17. C#. Абстрактные и конечные методы.
- •310 Часть I. Язык с#
- •18. Java. Абстрактные, виртуальные, конечные и статические методы.
- •19. C# и Java. Интерфейсы.
- •20.C#. Структуры.
- •21. C#. Перечисления.
- •22.C#. Упаковка и распаковка объектов значимых типов.
- •23.C# и Java. Исключения. Механизм исключений.
- •24.C# и Java. Исключения. Классы исключений.
- •25.C# и Java. Исключения. Основные принципы использования механизма
- •26.C#. Обобщения: понятие и синтаксис. Ограничения обобщений.
- •27. Java. Обобщения: понятие и синтаксис.
- •28.C#. Коллекции.
- •29.Java. Коллекции.
- •30.C#. Dispose Pattern.
- •31. .Net Framework 3.0, 3.5, 3.5 sp1: общая характеристика.
- •32. C# 3.0, linq: обзор.
- •Источники данных
- •SqlMetal
- •33. Понятие жизненного цикла ис (жц ис). Каскадная модель жц ис.
- •34. Понятие жизненного цикла ис (жц ис). Спиральная модель жц ис.
- •35. Анализ требований. Функциональные и нефункциональные требования.
- •36 Требования и прецеденты. Формат описания прецедента. Структура прецедента.
- •37 Требования и прецеденты. Взаимосвязь прецедентов.
- •38 Модель предметной области. Концептуальные классы. Ассоциации и атрибуты.
- •39 Язык uml. Способы использования. Model Driven Architecture. Executable uml. ДиаграммыUml.
- •40 Диаграмма прецедентов.
- •41. Диаграмма классов. Обозначение классов. Отношение ассоциации.
- •42.Диаграмма классов. Обозначение интерфейсов. Отношение обобщения и зависимости.
- •43.Диаграмма объектов.
- •44.Диаграмма пакетов.
- •45.Диаграмма состояний.
- •46.Диаграмма развертывания.
- •49.Диаграмма коммуникации.
- •50.Паттерн: понятие, структура, классификация.
- •1) Понятие паттерна
- •2) Структура и Классификация паттернов
- •51. Проектирование на основе обязанностей. Принципы grasp.
- •52.Grasp: принцип Low Coupling.
- •53.Grasp: принцип High Cohesion.
- •54.Grasp: принцип Information Expert.
- •55. Grasp: принцип Creator.
- •56.Grasp: принцип Pure Fabrication.
- •57. Grasp: принцип Indirection.
- •59.Grasp: принцип Protected Variations.
- •60.Grasp: принцип Controller.
53.Grasp: принцип High Cohesion.
Проблема. Как обеспечить возможность управления сложностью?
Решение. Распределение обязанностей, поддерживающее высокую степень зацепления.
Зацепление (cohesion) (или более точно, функциональное зацепление) — это мера связанности и «сфокусированности» обязанностей класса.
Считается что элемент обладает высокой степенью зацепления, если его обязанности тесно связаны между собой и он не выполняет огромных объемов работы. В качестве элемента может выступать класс, подсистема и т. п.
Класс с низкой степенью зацепления выполняет много разнородных функций или несвязанных между собой обязанностей. Такие классы создавать нежелательно, поскольку они приводят к возникновению следующих проблем:
трудность понимания;
сложность при повторном использовании;
сложность поддержки;
надежность, постоянная подверженность изменениям.
Классы со слабым зацеплением, как правило, являются слишком «абстрактными» или выполняют обязанности, которые можно легко распределить между другими объектами.
Пример. Рассмотрим тот же пример, что и для Low Coupling.
Предположим, необходимо создать экземпляр объекта Payment и связать его с текущей продажей. Какой класс должен выполнять эту обязанность?
Для создания экземпляра объекта Payment можно использовать объект
Register. Тогда экземпляр объекта Register сможет отправить сообщение addPayment объекту Sale, передавая в качестве параметра новый экземпляр объекта Payment (рис. 1).
При таком распределении обязанностей платежи выполняет объект Register, т.е. объект Register частично несет ответственность за выполнение системной операции makePayment. В данном обособленном примере это приемлемо. Однако если и далее возлагать на класс Register обязанности по выполнению все новых и новых функций, связанных с другими системными операциями, то этот класс будет слишком перегружен и будет обладать низкой степенью зацепления.
Предположим, приложение должно выполнять пятьдесят системных операций и все они возложены на класс Register. Если этот объект будет выполнять все операции, то он станет чрезмерно «раздутым» и не будет обладать свойством зацепления. И дело не в том, что одна задача создания экземпляра объекта Payment сама по себе снизила степень зацепления объекта Register; она является частью общей картины распределения обязанностей.
На рис. 2 представлен другой вариант распределения обязанностей. Здесь функция создания экземпляра платежа делегирована объекту Sale. Благодаря этому поддерживается более высокая степень зацепления объекта Register. Поскольку такой вариант распределения обязанностей обеспечивает низкий уровень связывания и более высокую степень зацепления, он является более предпочтительным.
На практике уровень зацепления не рассматривают изолированно от других обязанностей и принципов, обеспечиваемых шаблонами Expert и Low Coupling.
Обсуждение. Как и о принципе слабого связывания, о высокой степени зацепления следует помнить в течение всего процесса проектирования. Этот шаблон необходимо применять при оценке эффективности каждого проектного решения.
Несколько сценариев, иллюстрирующих различную степень функционального зацепления.
Очень слабое зацепление. Только один класс отвечает за выполнение множества операций в самых различных функциональных областях. Допустим, существует класс RDB-RPC-Interface, полностью отвечающий за взаимодействие между реляционными БД и вызов удаленных процедур. Это две абсолютно разные функциональные области.
Слабое зацепление. Класс несет единоличную ответственность за выполнение сложной задачи из одной функциональной области. Допустим, некий класс RDBInterface полностью отвечает за взаимодействие с реляционными БД. Методы класса связаны между собой однако их слишком много, и их реализация требует огромных объемов кодов. Таких методов может быть несколько сотен или больше. Данный класс следует разделить на несколько более мелких классов.
Среднее зацепление. Класс имеет несложные обязанности в нескольких различных областях, логически связанных с концепцией этого класса, но не связанных между собой. Допустим существует класс Company, который несет полную ответственность за знание всех сотрудников компании и всю финансовую информацию. Эти две области не слишком связаны между собой, однако логически связаны понятием «компания». К тому же предполагается, что такой класс содержит небольшое количество открытых методов и требует незначительных объемов кода для их реализации.
Сильное зацепление. Класс имеет среднее количество обязанностей из одной функциональной области и для выполнения своих задач взаимодействует с другими классами. Допустим некоторый класс RDBInterface лишь частично отвечает за взаимодействие с реляционными БД. Для извлечения и хранения объектов в БД он взаимодействует с с десятком других классов.
Как правило, класс с высокой степенью зацепления содержит сравнительно небольшое количество методов, которые функционально тесно связаны между собой, и не выполняют слишком много функций. Они взаимодействуют с другими объектами для выполнения более сложных задач. Такие классы являются предпочтительными, поскольку просты в понимании, поддержке и повторном использовании.
Шаблон High Cohesion, как и другие понятия объектно-ориентированной технологии проектирования, имеет аналогию в реальном мире. Всем известно, что человек, выполняющий большое число разнородных обязанностей (особенно тех, которые можно легко распределить между другими людьми), работает не очень эффективно. Это касается менеджеров, которые не умеют распределять обязанности между своими подчиненными. Такие люди страдают от «низкой степени зацепления» и могут легко «расклеиться». Понятия Low Coupling и High Cohesion являются взаимозависимыми.
Некорректное связывание порождает неправильное зацепление, и наоборот. Предположим, например, что класс уровня пользовательского интерфейса, представляющий окно, сохраняет данные в БД и вызывает удаленные службы. Такой класс не только обладает слабым зацеплением, но и оказывается сильно связанным со многими другими элементами.
Когда не следует применять шаблон
Существует несколько случаев, когда низкое зацепление оказывается оправданным.
Одна из таких ситуаций возникает в том случае, когда обязанности или код группируются в одном классе или компоненте для упрощения его поддержки одним человеком. Однако в данном случае необходимо помнить о том, что такая группировка может привести и к усложнению поддержки. Например, предположим, что в приложении содержатся внедренные операторы SQL, которые в соответствии с другими шаблонами проектирования нужно распределить по десяти классам работы с базой данных. В этом случае лишь один или два эксперта в области SQL знают, как лучше всего определять и поддерживать эти операторы SQL, даже несмотря на то, что в проекте участвуют десятки программистов с опытом работы в области объектно-ориентированного программирования. Некоторые из них могут иметь достаточно высокий уровень знания объектно-ориентированных технологий. Предположим также, что эксперт в области SQL не обладает навыками программиста по созданию объектно-ориентированных программ. Архитектор программной системы может решить сгруппировать операторы SQL в одном классе RDBOperations, чтобы эксперту было легче работать с этими операторами в одном месте.
Другой пример слабого зацепления имеет отношение к распределенным серверным объектам. Поскольку быстродействие системы определяется производительностью удаленных объектов и их взаимодействием, иногда желательно создать несколько более крупных серверных объектов со слабым зацеплением, предоставляющих интерфейс многим операциям. Эта ситуация связана также с шаблоном Coarse-Grained Remote Interface (Укрупненный удаленный интерфейс), в рамках которого создаются укрупненные удаленные операции, выполняющие больше функций. Такое проектное решение объясняется повышенным влиянием удаленных вызовов на производительность сети. В качестве альтернативы вместо удаленного объекта с тремя операциями setName, setSalary и setHireDate лучше реализовать одну укрупненную удаленную операцию setEmployeeData, работающую с целым ножеством данных. Это приведет к уменьшению числа удаленных вызовов и, как следствие, к повышению производительности.
