Что является преимуществом объектно ориентированного подхода перед структурированным
Технология разработки ПО
Объектный подход к разработке программного обеспечения
Сущность объектно-ориентированного подхода
Нами были выделены два наиболее популярных подхода (парадигмы) к анализу и проектированию информационных систем: структурный и объектно-ориентированный.
Первое отличие этих подходов друг от друга заключается в принципах декомпозиции и структурной организации элементов (компонентов, модулей) системы. Согласно этим принципам система представляет собой структуру, состоящую из четко выраженных модулей, связанных между собой определенными отношениями.
При использовании структурного подхода (первый вид декомпозиции) выполняется функциональная (процедурная, алгоритмическая) декомпозиция системы, т. е. она представляется в виде иерархии (дерева) взаимосвязанных функций. На высшем уровне система представляется единым целым с наивысшей степенью абстракции и по мере детализации (добавления уровней) разбивается на функциональные компоненты с более конкретным содержанием.
Второй вид декомпозиции – объектно-ориентированный. В рамках этого подхода система разбивается на набор объектов, соответствующих объектам реального мира, взаимодействующих между собой путем посылки сообщений.
Вторым отличием является объединение в объекте как атрибутивных данных (характеристики, свойства), так и поведения (функции, методы). В функционально-ориентированных системах функции и данные хранятся (существуют) отдельно.
Третье отличие двух подходов заключается в структурной организации внутри модулей системы. В структурном подходе модуль состоит из функций, иерархически связанных между собой отношением композиции (англ. part-of – часть-целое), т. е. функция состоит из подфункций, подфункция из подподфункций и т.д. В объектно-ориентированном подходе иерархия выстраивается с использованием двух отношений: композиции и наследования (англ. is-a – это есть). При этом в объектно-ориентированном подходе «объект-часть» может включаться сразу в несколько «объектов-целое». Таким образом, модуль в структурном подходе представляется в виде дерева, а в объектно-ориентированном подходе – в виде ориентированного графа, т. е. с помощью более общей структуры.
Наиболее популярными методологиями, поддерживающими данный подход, в настоящий момент являются:
Базовым средством фиксации (документирования) результатов проектирования систем посредством этих методологий является Унифицированный язык моделирования (Unified Modeling Language, UML).
Плюсы, минусы и перспективы ООП в современной разработке
Авторизуйтесь
Плюсы, минусы и перспективы ООП в современной разработке
Директор Exiting Vim, амбассадор всероссийского конкурса для IT-специалистов «Цифровой прорыв» — флагманского проекта президентской платформы «Россия — страна возможностей».
Давайте применим концепцию MVP к рассмотрению объектно-ориентированного программирования, а чтобы не быть субъективными, также взглянем на функциональное и прототипное программирование. Прежде всего, интересно, что разработано на них. А также какие перспективы ждут разработчиков — то есть количество открытых вакансий на рынке труда.
Прототипные языки программирования
Императивная парадигма, где реализация программного продукта осуществляется за счет оперирования иерархиями объектов. Это полезно для компактных программ с небольшим объёмом кода.
Самая известная реализация прототипной спецификации ECMAScript — язык JavaScript. Традиционная его ниша — фронтенд. Но с недавних пор ведётся также активная разработка на этом языке и бэкенд-решений.
Вот как выглядит поиск по вакансиям программистов на прототипных языках:
Функциональные языки программирования
Декларативная парадигма программирования, которая строится на функциях, что удобно для параллельной и распределенной разработки. Программам, написанным с использованием данной парадигмы, свойственны такие свойства, как высокая степень параллелизации вычислений, повышенные требования к производительности и надежности.
Haskell применяется в финансовом программировании, при анализе рисков, в системах поддержки принятия решений. Erlang применяется в телекоммуникациях.
Смотрим вакансии (кстати, уровень зарплаты по ним выше среднего):
Объектно-ориентированное программирование
Императивная парадигма, где реализация программного продукта осуществляется за счёт оперирования иерархиями классов и объектов. Базируется на таких подходах, как полиморфизм, инкапсуляция, абстракция и наследование.
Всё построено на повторном использовании кода, что ускоряет разработку. Кроме того, найти программистов на ООП несложно, потому что это очень развитый рынок — и в продуктовом, и в HR-смыслах. Это хорошо видно по количеству вакансий:
ООП используется при написании операционных систем, СУБД, компиляторов, драйверов, множества прикладных программ. Например, достаточно сказать, что почти все известные браузеры, Microsoft Office, Adobe Photoshop и Illustrator — продукты объектно-ориентированного программирования.
Похоже, его рано списывать со счетов. Однако многие критикуют ООП. Какие претензии предъявляют очевидному лидеру, чем он не угодил?
Критика объектно-ориентированного программирования
ООП не раз подвергалось критике. Одно из самых ярких обвинений прозвучало от британского программиста — Джо Армстронга.
Проблема с объектно-ориентированными языками заключается в том, что у них есть вся эта неявная среда, которую они носят с собой. Вы хотели банан, но получили гориллу, держащую банан и все джунгли.
Это во многом справедливо. Помимо недостаточно качественной поддержки параллельных и распределенных систем, ООП отличается относительно низким качеством конечного продукта.
В процессе трансляции объектно-ориентированных программ в исполняемый код центрального процессора возникает ряд неоптимальностей по использованию памяти и вычислительного времени процессорных ядер.
ООП предоставляет вам множество способов замедлить работу ваших программ.
А небезызвестный Линус Торвальдс часто критиковал ООП и С++ в частности, упоминая в том числе отсутствие ограничений. Речь о том, что большое количество инструментов и методов позволяет добиваться функционально одинаковых реализаций множеством различных способов. Это можно было бы считать преимуществом, но появляется риск ошибок, обнаружить которые очень сложно. Наследование объектов может привести к тому, что баг «вылезет» в неожиданном месте, далеко от исходной неточности в описании «родителя».
Как же получилось, что такой уязвимый, избыточный, громоздкий подход к программированию стал основным в глобальном масштабе и до сих пор сохранил свои позиции?
Преимущества объектно-ориентированного программирования
Первые программы на языках программирования высокого уровня, по сути, не были структурированы, и это не вызывало проблем, потому что объёмы кода были, по современным меркам, ничтожны. Кроме того, тогда ещё не существовало репозитариев, не было интернета, и тиражирование исходных кодов программных продуктов было крайне затруднительным.
По мере того, как наперегонки развивались Hardware и Software, объёмы исходных кодов в программах начали стремительно расти. Теперь для его поддержки уже требовалась определенная архитектура. Стали применяться различные подходы к оформлению исходных кодов, и в конечном счёте появились парадигмы программирования. ООП выделялось сразу несколькими критично важными отличиями:
Повторяемость кода ООП привела к созданию библиотек классов. Можно тратить всё меньше времени на получение уже полученных ранее результатов — причём даже не очень важно, кем именно и на каких проектах были сделаны прежние разработки. Так и начал формироваться парадокс банана: с одной стороны — упрощение разработки за счёт тиражирования уже реализованных классов. С другой — неоптимальное использование аппаратных ресурсов.
В ходе развития программного продукта могут потребоваться расширения и дополнения, уже реализованные в подключенных библиотеках, и тогда остаётся только их задействовать. Нечто похожее сейчас используется во многих коммерческих продуктах, причём не только софтверных.
Сама идея «разработки про запас» довольно удобна с точки зрения продаж. Как и выбор высокого темпа вместо перфекционизма в качестве кода. Лучше продать сегодня и сдать проект завтра, чем растянуть всё на годы и вылететь с рынка.
При всех своих недостатках объектно-ориентированное программирование позволяет быстрее, экономичнее и гораздо удобнее в плане управления процессом распределённой разработки получать работающий код. Да, возможно, в нём есть значительные неоптимальности, возможно их даже много. Но зато проект уже работает, по крайней мере, в виде прототипа. Этого достаточно для презентаций, получения первых клиентов и внедрений.
Всё равно первоначальные маркетинговые, интерфейсные и многие другие идеи придётся ещё неоднократно дорабатывать, а возможно, и менять. С точки зрения компании и особенно стартапа, выгоднее двигаться быстрее.
Резюме
В нулевых годах начали массово распространяться многоядерные и многопроцессорные системы. Возникла потребность в распределенных вычислениях, а чуть позже в вычислениях на графических процессорах. Оказалось, что ООП справляется с такими задачами значительно хуже, чем функциональные программы. Даже исходя из одного этого фактора, можно усомниться в бесконечном доминировании ООП.
Конечно, пропорции в разработке будут меняться. Это уже происходит. Кроме того, рано или поздно появятся принципиально другие, новые подходы — и они могут оказаться недостижимо более производительными, особенно на модернизированном железе.
Тем не менее, пока что ООП остается надёжным, удобным инструментом. Похоже, в ближайшие годы ничего не предвещает серьезных подвижек, так что можно смело использовать объектно-ориентированное программирование и в качестве личного карьерного плана, и для запуска проектов.
Структурное против ООП программирование
Доброго времени суток. В этой статье я хочу показать не то, чем лучше структурное программирование или объектное, а то как нужно писать и там и там. И возможно это послужит выбором для тех, кто только хочет начать программировать и не знает какой язык выбрать и что может быть удобней. Я взял за пример языка C и JAVA.
Начну с первого, что приходит на ум. Это вроде не паттерн, но в ООП это приходится иногда использовать. Пишу сначала пример на java. Допустим нам нужно создать класс для двух видов реализации. К примеру нам нужно создать класс, чтобы подключаться к сайту по http и https. Это маленький пример, например этот же способ можно использовать, когда ты хочешь для android рисовать и в Opengl 2.0 es и Opengl 3.0 es. В этом случае будет больше кода и если сделать это таким способом, который приведу я, то вид кода будет нормальный. Но этот способ конечно же придумал не я, я его сам вычитал из книги когда-то. И так https и http. Чтобы это сделать, нужно создать интерфейс. И к этому интерфейсу присваивать нужный класс, в зависимости от типа протокола. Я точно не помню, но вроде я где-то читал, что ООП вправляет мозги. Что это позволяет писать грамотный красивый код. Возможно так. Но я почти в ООП не программирую и поэтому может это я так много кода пишу, а настоящий программист сделает более лаконичный код. Но вот хочу показать пример. Вот это интерфейс java.
Здесь мы объявляет две функции, одна для соединения, другая для получения URLConnection. Теперь два класса, чтобы это сработало.
Сколько кода нужно писать в connect и getConnection не важно. Для примера я выбрал мало кода, но его может быть много, если например Opengl es программировать. Но это удобно. Итак, осталась функция main.
На C можно воспользоваться curl и не писать много кода, но как бы этот пример можно было решить средствами C? В C есть указатели — это его сила. А вот пример на C — функция main.
Структура conn объявлена в другом файле.
Для init_http выделен целый файл с областью видимости, которые нужны для http.
Для init_https дополнительно нужен ssl. Поэтому в этом файле будут все те данные, которые нужны для этого подключения.
Если статья понравиться, то я буду писать продолжение в будущем. Пока я ещё наверное плохо знаю ООП, чтобы написать больше примеров, но думаю, что если не заброшу ООП, то начинающим читателям будет интересно посмотреть отличия при написании в структурном и ООП-программировании.
Что является преимуществом объектно ориентированного подхода перед структурированным
Объектно-ориентированное программирование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования.
Программа считается объектно-ориентированной, только если выполнены все три указанных требования. В частности, программирование, не использующее наследование, называется не объектно-ориентированным, а программированием с помощью абстрактных типов данных.
Основные принцыпы ООП.
Это единственно верный порядок парадигм ООП, так как каждая последующая использует предыдущие.
Что такое «инкапсуляция»?
Инкапсуляция – это свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе и скрыть детали реализации от пользователя, открыв только то, что необходимо при последующем использовании.
Цель инкапсуляции — уйти от зависимости внешнего интерфейса класса (то, что могут использовать другие классы) от реализации. Чтобы малейшее изменение в классе не влекло за собой изменение внешнего поведения класса.
Что такое «наследование»?
Наследование – это свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью.
Класс, от которого производится наследование, называется предком, базовым или родительским. Новый класс – потомком, наследником или производным классом.
Полиморфизм – это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.
Полиморфная переменная, это переменная, которая может принимать значения разных типов, а полиморфная функция, это функция у которой хотя бы один аргумент является полиморфной переменной. Выделяют два вида полиморфных функций:
Абстрагирование – это способ выделить набор общих характеристик объекта, исключая из рассмотрения частные и незначимые. Соответственно, абстракция – это набор всех таких характеристик.
Что представляет собой «обмен сообщениями»?
Объекты взаимодействуют, посылая и получая сообщения. Сообщение — это запрос на выполнение действия, дополненный набором аргументов, которые могут понадобиться при выполнении действия. В ООП посылка сообщения (вызов метода) — это единственный путь передать управление объекту. Если объект должен «отвечать» на это сообщение, то у него должна иметься соответствующий данному сообщению метод. Так же объекты, используя свои методы, могут и сами посылать сообщения другим объектам. Обмен сообщениями реализуется с помощью динамических вызовов, что приводит к чрезвычайно позднему связыванию (extreme late binding).
Расскажите про основные понятия ООП: «класс», «объект», «интерфейс».
Класс – это способ описания сущности, определяющий состояние и поведение, зависящее от этого состояния, а также правила для взаимодействия с данной сущностью (контракт).
С точки зрения программирования класс можно рассматривать как набор данных (полей, атрибутов, членов класса) и функций для работы с ними (методов).
С точки зрения структуры программы, класс является сложным типом данных.
Объект (экземпляр) – это отдельный представитель класса, имеющий конкретное состояние и поведение, полностью определяемое классом. Каждый объект имеет конкретные значения атрибутов и методы, работающие с этими значениями на основе правил, заданных в классе.
Интерфейс – это набор методов класса, доступных для использования. Интерфейсом класса будет являться набор всех его публичных методов в совокупности с набором публичных атрибутов. По сути, интерфейс специфицирует класс, чётко определяя все возможные действия над ним.
В чем заключаются преимущества и недостатки объектно-ориентированного подхода в программировании?
Что подразумевают в плане принципов ООП выражения «является» и «имеет»?
«является» подразумевает наследование. «имеет» подразумевает ассоциацию (агрегацию или композицию).
В чем разница между композицией и агрегацией?
Ассоциация обозначает связь между объектами. Композиция и агрегация — частные случаи ассоциации «часть-целое».
Агрегация предполагает, что объекты связаны взаимоотношением «part-of» (часть). Композиция более строгий вариант агрегации. Дополнительно к требованию «part-of» накладывается условие, что экземпляр «части» может входить только в одно целое (или никуда не входить), в то время как в случае агрегации экземпляр «части» может входить в несколько целых.
Что такое статическое и динамическое связывание?
Присоединение вызова метода к телу метода называется связыванием. Если связывание проводится компилятором (компоновщиком) перед запуском программы, то оно называется статическим или ранним связыванием (early binding).
В свою очередь, позднее связывание (late binding) это связывание, проводимое непосредственно во время выполнения программы, в зависимости от типа объекта. Позднее связывание также называют динамическим (dynamic) или связыванием на стадии выполнения (runtime binding). В языках, реализующих позднее связывание, должен существовать механизм определения фактического типа объекта во время работы программы, для вызова подходящего метода. Иначе говоря, компилятор не знает тип объекта, но механизм вызова методов определяет его и вызывает соответствующее тело метода. Механизм позднего связывания зависит от конкретного языка, но нетрудно предположить, что для его реализации в объекты должна включаться какая-то дополнительная информация.
Для всех методов Java используется механизм позднего (динамического) связывания, если только метод не был объявлен как final (приватные методы являются final по умолчанию).
Что является преимуществом объектно ориентированного подхода перед структурированным
Объектно-ориентированный подход действительно лучше структурного
Перевод А. И. Легалова
Примечание: Предлагаемая Вашему вниманию статья уже успела обзавестись бородой. Однако, предпринятые в ней попытки обоснования достоинств объектного подхода представляют определенный интерес. Благодарю за ответ на призыв о потерянной ссылке. Теперь можно легко уличить меня в посредственном переводе и насладиться авторским текстом! А.Л.
Все говорят о нем, но никто его не определяет
Чем является программное обеспечение?
Что такое «качество программного обеспечения»?
Характеристики качества программного обеспечения
Корректность (правильность)
Обеспечивает правильную обработку на правильных данных
«Элегантно» завершает обработку ошибок
Может легко адаптироваться к изменяющимся требованиям
Многократность использования
Может использоваться и в других системах, а не только в той, для которой было создано.
Может легко использоваться с другим программным обеспечением
Эффективное использование времени, компьютерной памяти, дискового пространства и т.д.
Можно легко перенести на другие аппаратные и программные средства
Простота проверки, легкость разработки тестов при обнаружении ошибок, легкость обнаружения мест, где программа потерпела неудачу, и т.д.
Поддержка целостности
Защищает себя от неправильного обращения и неправильного употребления
Легкость использования
Для пользователя и для будущих программистов
Корректность и устойчивость
Легко спутать термины «Корректная программа» и «Устойчивая программа». Корректная программа работает, когда поданы на вход правильные данные. Она отвечает всем требованиям к спецификации данных и не терпит неудачу внутри заданного диапазона. Устойчивость подразумевает не только правильность. Устойчивая программа способна обработать ситуации, не запланированные проектом. Эти ситуации включают некорректный ввод пользователя, аппаратный отказ и ошибки во время выполнения программы. Устойчивые системы терпят неудачу элегантно, без потери критических данных. Легко увидеть, что обе характеристики необходимы для любой системы, которая будет оценена как высококачественное программное обеспечение. Если система некорректна, то она бесполезна. Если система неустойчива, то она окажется неспособной справиться с задачей в реальной ситуации.
Расширяемость
Эти принципы позволяют нам понять проблему в частях без опасения затеряться в несметном количестве непостижимых подробностей.
Многократность (повторность) использования и совместимость
Многократное использование может просматриваться на различных уровнях: при анализе, проектировании, и реализации. Оно поддерживает качество следующими способами:
Совместимость и многократное использование идут «взявшись за руки», потому что повторно используемое программное обеспечение (например, plug&play компоненты) должно быть совместимо с его новым окружением. Совместимое программное обеспечение поддерживает качество посредством использования прошлых усилий и подпорок при формировании новых систем. Программное обеспечение с низким коэффициентом совместимости требует огромных усилий, чтобы настроить систему на необходимое использование. Это усилие могло быть потрачено на проектирование лучшей системы или на улучшение эффективности кода.
Другие характеристики
Эти первые пять атрибутов качественного программного обеспечения (корректность, устойчивость, расширяемость, возможность многократного использования и совместимость) больше всего извлекают пользу при переходе от структурного к объектно-ориентированному подходу. Мы будем концентрироваться на них в оставшейся части статьи. Это не означает, что эффективность, переносимость, верификация, целостность и легкость использования имеют меньшее значение. Все перечисленные атрибуты важны при создании программного обеспечения истинно высокого качества.
Где структурное проектирование дает сбои
Теперь, когда мы знаем то, что ищем, когда создаем программное обеспечение, можно оценить качество работы существующих методов.
Краткий обзор нисходящего структурного проектирования
Нисходящее проектирование (известно также как нисходящая декомпозиция или пошаговое усовершенствование) отталкивается от общего утверждения относительно процесса, определяемого решаемой проблемой, к постепенно детализируемым утверждениям относительно каждой специфической задачи в этом процессе. На рис. 1 приведена типовая нисходящая декомпозиция «Подпрограммы импорта данных». Обратите внимание, что разделение осуществляется по строго функциональным линиям; мы заботимся лишь о том, что делает каждый модуль.
Рис. 1. Пример нисходящей функциональной декомпозиции
Нисходящие проектирования работает хорошо, потому что оно позволяет нам одновременно сосредотачиваться на меньшем количестве деталей. Это логичная методика, которая поощряет организованную доводку системы и уменьшает уровень сложности (степени интеграции) на каждой из последующих стадий проекта. По очевидным причинам, нисходящие проектирования подходит лучше всего тогда, когда применяется к проблемам, которые имеют ясно выраженный иерархический характер. К сожалению, многие из реальных проблем не иерархические. Проект, основанный на построении сверху вниз, имеет также и другие ограничения, которые станут очевидными при разработке и сопровождении больших программных систем.
Проблемы метода
Функциональную точку зрения трудно развивать
Каждая реальная система изменяется и эволюционирует. Нисходящий подход создает хорошую программную модель для исходных требований к системе. Но система изменяется, что ведет к появлению новых требований. Поэтому функциональная архитектура постепенно становится неуправляемой. Поскольку программное обеспечение разработано вокруг относительно фиксированной древовидной структуры (рис. 1), изменения обычно требуют длительного сокращения и прививания. Чистый и хорошо разработанный проект быстро становится «ужастиком», повествующим о новых и повисших связях. Сопровождение становится все более трудным, поскольку первоначальная архитектура медленно умирает с каждой новацией или изменением требований.
Реальные системы трудно охарактеризовать функционально
Многие из больших систем не имеют верхнего уровня. Например, система управления базой данных включает инструментальные средства для запроса данных, изменение данных, хранение непротиворечивых данных, и т.д. Нет какой-либо функции, являющейся самым важным звеном в этой системе. Определение этой системы в терминах одной функции верхнего уровня искусственно и приводит к чрезмерно сложным и неадаптивным архитектурам.
«Одним из наиболее важных решений, принимаемым при разработке системы, является предположение о том, как сделать декомпозицию верхнего уровня. При нисходящем подходе это решение необходимо принять в начале процесса проектирования, то есть тогда, когда имеется минимум информации. Возможно, наиболее серьезная слабость в том, что нисходящее функциональное проектирование требует, чтобы система характеризовалась одной функцией наверху. Это сомнительное требование для многих современных систем, управляемых событиями».
Фокусирование на функциональности теряет из виду данные
Из примера, представленного выше (рис. 1), видно, что нисходящий проект не фиксирует информацию о данных, используемых в программе. Функции же всегда что-то делают с данными. Обычно, одни и те же данные разделены между функциями (например, модификации, удаления, вставки и запроса, работающих с таблицей базы данных). Так как декомпозиция только высвечивает функциональные аспекты проблемы, влияние структур данных на проблему оказывается потерянным.
Функциональная ориентация производит код, менее пригодный для многократного использования
При нисходящем проектировании осуществляется непрерывное дробление проблемы на все более простые части. Каждый кусок анализируется и специфицируется отдельно без сильной связи между ним и остальной частью системы. Это является одной из причин, по которой проектирование «сверху вниз» так эффективно на этапе анализа проблемы. Данный метод работает хорошо при начальном проектировании системы, и помогает получить спецификации для выявления и решения проблемы. Однако каждый элемент программы разработан только с ограниченными требованиями к памяти. Так как маловероятно, что точно такие же требования встретятся при решении следующей проблемы, проект программы и код не могут быть обобщены для многократного использования.
Нисходящее проектирование не препятствует созданию общих подпрограмм, которые разделяются между многими программами; но оно не поощряет этот процесс. На самом деле, идея объединения повторно используемых программ в систему проявляется в восходящем подходе, являющимся обратной альтернативой нисходящему стилю.
Но что сказать о библиотеках подпрограмм?
Конечно, есть области, где функциональный подход работает хорошо. Эта тенденция проявляется там, где:
Области, которые соответствуют этим критериям, включают библиотеки математических подпрограмм для решения проблем линейной алгебры и дифференциально-разностных уравнений.
Итог по структурному проектированию
Для подведения итогов я процитирую Мейера Бертрана (Bertrand Meyer), так как вряд ли скажу лучше его:
Нисходящее функциональное проектирование плохо адаптируется к разработке крупных (больших) программных систем. Нисходящее проектирование остается полезной парадигмой для малых программ и индивидуальных алгоритмов. но оно практически не масштабируется на большие системы. Смысл не в том, что Вы не можете разрабатывать систему сверху вниз: можете. Но, выторговывая для себя краткосрочное удобство за длительную негибкость, Вы некорректно нагромождаете одну функцию над другой и (достаточно часто) функциональный интерфейс над более важными параметрами системы. Вы теряете из виду аспект данных, и Вы жертвуете возможностью многократного использования.
Как и почему преуспевают объектно-ориентированные методы
Теперь, когда мы исследовали нисходящее подход, и нашли его желательным в некоторых областях, можно направить наше внимание к объектно-ориентированному проектированию и увидеть, действительно ли оно решает любую из проблем, которые мы обнаружили.
Обзор объектно-ориентированного анализа и проектирования
Затем объектно-ориентированное проектирование переходит от моделирования предметной области к моделированию области реализации. Структура нашего класса теперь начинает включать описания специфических компьютерных объектов. Например: классы интерфейса пользователя (окна, меню, и т.д.), классы управления задачами (процессы, семафоры, и т.д.), классы обработки данных (списки, стеки, очереди, и т.д.). Поскольку объектно-ориентированный анализ и проектирование используют тот же самый язык (и могут использовать те же самые системы обозначений), проще (и более выгодно) выполнять оба процесса параллельно и итерационно. Как указывает Гради Буч (Grady Booch):
«Границы между анализом и проектированием размыты, хотя фокус каждого полностью различен. При анализе, мы пытаемся моделировать мир, обнаруживая классы и предметы, которые формируют словарь предметной области, а при проектировании, мы изобретаем абстракции и механизмы, которые обеспечивают поведение, требуемой этой моделью.»
Чрезвычайно важно отметить, что цели процессов анализа и процесса проектирования не сосредоточены исключительно на разработке решения, необходимого для текущего понимания проблемы. Скорее, они направлены на проектирование и формирование обобщенных классов с законченными и полезными структурами. Модели класса изложены в деталях и завершены вне частных текущих потребностей. Используя жаргон Мейера, можно сказать, что мы хотим, чтобы наши классы имели завершенный товарный список атрибутов и поведения.
Преимуществом этого, более общего, подхода, является то, что наши классы будут иметь возможности многократного использования в новых ситуациях, более расширяемыми и более совместимыми друг с другом. Они будут многократно используемыми, потому что разработаны не для одиночной задачи, а для моделирования конкретных характеристик объектов реального (или компьютерного) мира. Так как вполне вероятно, что тот же самый «предмет» вновь появится в других задачах, наша законченная модель, будет использована там, даже если предмет реализуется совершенно другим способом. Они будут расширяемы, потому что они разработаны обобщенно, без привязки к особенностям одной задачи. Могут быть добавлены дополнительные функциональные возможности, изменена реализация без того, чтобы нанести вред фундаментальным абстракциям. Классы будут более совместимы, потому что они разработаны так, чтобы быть завершенными, иметь ясно определенные (и защищенные) интерфейсы. Это означает, что они будут способны существовать в новых ситуациях без изменения.
Мы получили то, что позволяет нашим моделям не быть разбитыми и потерпевшими неудачу при изменении текущих требований. Дополнительным эффектом является то, что они будут полезны для решений многих других задач. При продолжительном использовании объектно-ориентированных методов, мы обнаружим, что имеем сундук с сокровищами в виде многократно используемых классов, применимых к различным проблемам, которые нам надо решить.
Объектно-ориентированное проектирование. Резюме
Мейер дает следующее формальное определение объектно-ориентированное проектирования: «конструирование программных систем в виде структурированных коллекций, реализующих абстрактные типы данных». Неформально он определяет это как «метод, который ведет к архитектурам программ, основанным на объектах, используемых системой или подсистемой (предпочтительнее чем «функция», которую система, как предполагается, выполняет)». Объект может быть рассмотрен как реализация некоторых знаний и некоторые операций, концептуально связанных друг с другом, так, чтобы имело смысл связывать их вместе.
Почему объектная ориентация работает
Объектно-ориентированный анализ, проектирование и программирование при совместной работе усиливают эффект, обеспечивая компьютерные решения, которые лучше моделируют предметную область, чем подобные системы, создаваемые на основе структурного подхода. Системы проще адаптировать к изменяющимся условиям, легче изменять, они устойчивее и позволяют создавать более крупные проекты, поддерживают многократное использование. Причины этих улучшений заключаются в следующем:
Объектная ориентация работает на более высоком уровне абстракции
Поскольку мы, люди, чрезвычайно ограничены, мы изобрели методы, чтобы стать более эффективными. Одним из наших, наиболее мощных методов, является форма избирательной амнезии по имени «Абстракция». Абстракция позволяет нам игнорировать детали задачи и концентрироваться на общем представлении (целом изображении). Нисходящее проектирование поддерживает абстракцию на функциональном уровне. Объектно-ориентированное проектирование поддерживает ее на уровне объекта. Так как объекты инкапсулируют как данные (атрибуты), так и функции (поведение), они работают с более высоким уровнем абстракции. Проектирование может переходить внутрь объекта, игнорируя остальную часть системы так долго, пока это необходимо.
Жизненный цикл объектно-ориентированный программы не требует никаких «прыжков»
Рис. 2. Каскадный («прыжковый») подход к разработке программного обеспечения.
Данные стабильнее функций
Конечно, данные и классы системы со временем изменяются. К счастью, объектно-ориентированные методы делают изменение данных более простым, менее болезненным и более устойчивым, чем подобные изменения в функциональной модели. В хорошо разработанной системе, данные приложения тщательно скрыты за интерфейсом класса. Изменения в данных влияют только на один класс (или связанную подсистему классов) и могут эффективно управляться и проверяться. Кроме того, мощь механизма наследования позволяет добавлять новые элементы, в подклассы существующих классов. Это означает, что мы не должны заново изобретать колесо для каждого нового изменения, и что появление нового кода с меньшей вероятностью приведет к ломке уже существующего кода.
Усиление роли хороших методов программирования
Несколько последних поколений проектировщиков и программистов были вскормлены на материнском молоке сокрытия информации, корректной области действия переменных и модульности. Мы обучились создавать программы с сильным взаимодействием, слабыми связями и ясным замыслом. Все это остается совершенно справедливым в объектно-ориентированном мире. Фактически, объектно-ориентированное проектирование и программирование добавляют фундамент к этим целям на уровне языка, делает более простым их достижение. Класс при объектно-ориентированном проектировании тщательно отделяет его интерфейс (спецификации того, что он может делать) от реализация этого интерфейса (как это делать, что он делает). Подпрограммы и атрибуты внутри класса тесно связны с объектом моделирования. В правильно разработанной модели, классы будут аккуратно сгруппированы в подсистемы, которые являются слабосвязанными, а связи между классами в различных подсистемах будут минимизированы.