автордың кітабын онлайн тегін оқу Объектно-ориентированный подход. 5-е межд. изд
Переводчик И. Сигайлюк
Технический редактор М. Петруненко
Литературные редакторы М. Петруненко, А. Руденко
Художник В. Мостипан
Корректор Н. Викторова
Верстка Л. Егорова
Мэтт Вайсфельд
Объектно-ориентированный подход. 5-е межд. изд.. — СПб.: Питер, 2021.
ISBN 978-5-4461-1431-3
© ООО Издательство "Питер", 2021
Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.
Шэрон, Стейси, Стефани и Пауло
Благодарности
Как и в случае с первыми четырьмя изданиями, эта книга потребовала совместных усилий многих людей. Я хотел бы поблагодарить как можно больше этих людей, поскольку без их помощи книга никогда бы не увидела свет.
Прежде всего, хотелось бы выразить благодарность моей жене Шэрон за помощь. Она не только поддерживала и подбадривала меня во время длительного написания книги, но и выступила в роли первого редактора черновиков.
Я также хотел бы поблагодарить маму и других членов моей семьи за их постоянную поддержку.
Трудно поверить в то, что работа над первым изданием этой книги началась еще в 1998 году. На протяжении работы над всеми пятью изданиями мне было очень приятно сотрудничать с ребятами из компании Pearson. А работа с такими редакторами, как Марк Тэбер (Mark Taber) и Тоня Симпсон (Tonya Simpson), принесла мне массу удовольствия.
Выражаю особую благодарность Джону Апчерчу (Jon Upchurch) за проверку большей части приведенного в этой книге кода, а также за научное редактирование рукописи. Его обширные познания в технических областях оказали неоценимую помощь.
И наконец, спасибо моим дочерям Стейси и Стефани, а также коту Пауло за то, что постоянно держат меня в тонусе.
Об авторе
Мэтт Вайсфельд — профессор колледжа, разработчик программного обеспечения и автор. Проживает в Кливленде, штат Огайо. Прежде чем стать штатным преподавателем, Мэтт 20 лет проработал в индустрии информационных технологий разработчиком ПО, занимая должность адъюнкт-профессора, вел предпринимательскую деятельность. Имеет степень магистра MBA и computer science. Помимо первых четырех изданий книги «Объектно-ориентированный подход», написал еще две книги на тему разработки программного обеспечения, а также опубликовал множество статей в таких журналах, как developer.com, Dr. Dobb’s Journal, The C/C++ Users Journal, Software Development Magazine, Java Report и международном журнале Project Management.
Авторские права на иллюстрации
Рисунок 8.1, скриншот Microsoft Word, © Корпорация Microsoft, 2019.
Рисунок 8.2, скриншот документации API, © Корпорация Oracle, 1993, 2018.
От издательства
Ваши замечания, предложения и вопросы отправляйте по адресу электронной почты comp@piter.com (издательство «Питер», компьютерная редакция).
Мы будем рады узнать ваше мнение!
На сайте издательства http://www.piter.com вы найдете подробную информацию о наших книгах.
Введение
Как следует из названия, эта книга посвящена объектно-ориентированному подходу. Хотя выбор темы и названия книги является важным решением, оно оказывается совсем не простым, когда речь идет о концептуальной теме. Во многих книгах рассматривается тот или иной уровень программирования и объектной ориентации. В отдельных популярных книгах охватываются темы, в число которых входят объектно-ориентированный анализ, объектно-ориентированное проектирование, шаблоны проектирования, объектно-ориентированные данные (XML), унифицированный язык моделирования Unified Modeling Language (UML), объектно-ориентированная веб-разработка (в том числе мобильная), различные объектно-ориентированные языки программирования и многие другие темы, связанные с объектно-ориентированным программированием (ООП).
Однако при чтении таких книг многие люди забывают, что все эти темы базируются на одном фундаменте: важно, как вы мыслите объектно-ориентированным образом. Зачастую бывает так, что многие профессионалы в области создания программного обеспечения, а также студенты начинают читать эти книги, не потратив достаточно времени и усилий на то, чтобы действительно разобраться в концепциях проектирования, кроющихся за кодом.
Я считаю, что освоение объектно-ориентированных концепций не сводится к изучению конкретного метода разработки, языка программирования или набора инструментов проектирования. Работа в объектно-ориентированном стиле является образом мышления. Эта книга всецело посвящена объектно-ориентированному мышлению.
Отделение языков программирования, методик и инструментов разработки от объектно-ориентированного мышления — нелегкая задача. Зачастую люди знакомятся с объектно-ориентированными концепциями, «ныряя» с головой в тот или иной язык программирования. Например, какое-то время назад многие программисты на C впервые столкнулись с объектной ориентацией, перейдя прямо на C++ еще до того, как они хотя бы отдаленно познакомились с объектно-ориентированными концепциями.
Важно понимать значительную разницу между изучением объектно-ориентированных концепций и программированием на объектно-ориентированном языке. Я четко осознал это до того, как начал работать еще над первым изданием данной книги, когда прочитал статью, написанную Крейгом Ларманом (Craig Larman) What the UML Is — and Isn’t («Что такое UML и чем он не является»). В этой статье он пишет:
К сожалению, в контексте разработки программного обеспечения и языка UML, позволяющего создавать диаграммы, умение читать и писать UML-нотацию, похоже, иногда приравнивается к навыкам объектно-ориентированного анализа и проектирования. Конечно, на самом деле это не так, и последнее из упомянутого намного важнее, чем первое. Поэтому я рекомендую искать учебные курсы и материалы, в которых приобретению интеллектуальных навыков в объектно-ориентированном анализе и проектировании придается первостепенное значение по сравнению с написанием UML-нотации или использованием средств автоматизированной разработки программного обеспечения.
Таким образом, несмотря на то что изучение языка моделирования является важным шагом, намного важнее сначала приобрести объектно-ориентированные навыки. Изучение UML до того, как вы полностью разберетесь в объектно-ориентрованных концепциях, аналогично попытке научиться читать электрические схемы, изначально ничего не зная об электричестве.
Та же проблема возникает с языками программирования. Как отмечалось, многие программисты на С ушли в область объектной ориентации, перейдя на С ++, прежде чем соприкоснуться с объектно-ориентированными концепциями. Это всегда обнаруживается в процессе собеседования. Довольно часто разработчики, которые утверждают, что они программисты на C ++, являются просто программистами на C, использующими компиляторы C ++. Даже сейчас, с такими хорошо зарекомендовавшими себя языками, как C # .NET, VB .NET, Objective-C, Swift и Java, ключевые вопросы во время собеседования при приеме на работу могут быстро выявить сложности в понимании объектно-ориентированных концепций.
Ранние версии Visual Basic не являются объектно-ориентированными. Язык C тоже не объектно-ориентированный, а C++ разрабатывался как обратно совместимый с ним. По этой причине вполне возможно использовать компилятор C++ при написании синтаксиса на C, но отказавшись от всех объектно-ориентированных свойств C++. Язык Objective-C создавался как расширение стандартного языка ANSI C. Что еще хуже, программисты могут применять ровно столько объектно-ориентированных функций, сколько нужно для того, чтобы сделать приложения непонятными для остальных программистов, как использующих, так и не использующих объектно-ориентированные языки.
Таким образом, жизненно важно, чтобы вы, приступая к изучению того, как пользоваться средами объектно-ориентированной разработки, сначала освоили фундаментальные объектно-ориентированные концепции. Не поддавайтесь искушению сразу перейти непосредственно к языку программирования, сначала уделите время освоению объектно-ориентированного мышления.
Что нового в пятом издании
Как часто отмечалось во введении к предыдущим изданиям, мое видение первого издания заключалось в том, чтобы придерживаться концепций, а не сосредоточиваться на конкретной новейшей технологии. Несмотря на следование такому же подходу в пятом издании, я стараюсь привести больше «контраргументов», чем в предыдущих четырех изданиях. Этим я даю понять, что хотя объектно-ориентированная разработка, несомненно, имеет важнейшее значение, не стоит ограничивать лишь ею свое внимание.
Поскольку книга была впервые издана в 1999 году, за прошедшее время успели появиться многие технологии, а некоторые были вытеснены. В те времена язык Java только находился в начале своего становления и был главным языком в сфере объектно-ориентированного программирования. В скором времени веб-страницы уже являлись неотъемлемой частью личной и деловой жизни. И нам хорошо известно, насколько повсеместными стали мобильные устройства. За последние 20 лет разработчики программ столкнулись с XML, JSON, CSS, XSLT, SOAP и RESTful Web Services. В устройствах Android используется Java и, уже, Kotlin, а в iOS — Objective C и Swift.
Хочу обратить внимание на то, что за 20 лет (и четыре издания книги) мы охватили много различных технологий. В этом издании я ставлю себе основной задачей сконцентрировать весь предыдущий материал и вернуться к изначальному замыслу первого издания — концепциям объектно-ориентированного программирования. Мне приятно считать, что каким бы ни был успех первого издания книги, он связан с тем, что оно было сосредоточено на самих концепциях. Мы, в некотором роде, прошлись по кругу, потому что настоящее издание включает в себя все технологии, которые были упомянуты.
Наконец, концепции, которые объединяют все эти технологии в методику проектирования, описываются принципами SOLID. Ими пронизана каждая глава этого издания, а также две новые главы в конце.
Пять принципов SOLID:
• SRP — принцип единственной ответственности (Single Responsibility Principle).
• OCP — принцип открытости/закрытости (Open/Close Principle).
• LSP — принцип подстановки Барбары Лисков (Liskov Substitution Principle).
• ISP — принцип разделения интерфейса (Interface Segregation Principle).
• DIP — принцип инверсии зависимостей (Dependency Inversion Principle).
В первых девяти главах я расскажу о принципах объектно-ориентированного программирования, которые считаю классическими. Последние три главы посвящены паттернам проектирования, избеганию зависимостей и понятию SOLID, которое построено на классических принципах и предполагает четко определенную методику.
Целевая аудитория
Эта книга представляет собой общее введение в фундаментальные концепции объектно-ориентированного программирования. Понятие концепции важно, потому что хотя весь материал темы для наглядности сопровождается кодом, главная цель книги — познакомить читателя с азами объектно-ориентированного мышления. Немаловажно для программистов и понимание того, что объектно-ориентированное программирование не представляет собой какой-то отчетливой парадигмы (пускай многие в это и верят), но является лишь частью обширного инструментария для современных разработчиков программного обеспечения.
Когда в 1995-м был подготовлен начальный материал для первого издания, объектно-ориентированное программирование только появилось. Я могу так сказать потому, что, помимо немногих объектно-ориентированных языков вроде Smalltalk, настоящих языков объектно-ориентированного программирования в то время не существовало. C++, где применение объектно-ориентированных конструкций необязательно, был доминирующим языком программирования, основанным на C. Первый релиз Java 1.0 состоялся в 1996 году, а C# — в 2002-м. Собственно, когда вышло первое издание этой книги в 1999 году, никто не мог быть уверен, что объектно-ориентированное программирование действительно станет ведущей парадигмой среди разработчиков (Java 2 вышел только в декабре 1998-года). Несмотря на доминирование в настоящее время, объектно-ориентированное программирование не лишено некоторых любопытных изъянов, к которым мы еще вернемся.
Итак, аудитория этой книги сейчас отличается от аудитории первого издания.
С 1995 и вплоть до 2010 года я в основном обучал структурных программистов искусству объектно-ориентированного программирования. Подавляющее большинство моих учеников набирали опыт на COBOL, FORTRAN, C и VB как во время учебы, так и на работе. Сегодняшние ученики, которые выпускаются из заведений, пишут видеоигры, создают сайты или мобильные приложения, практически уже научились писать программы на объектно-ориентированных языках. Из этого следует, что подход пятого издания значительно отличается от того, что был в первом, втором и последующих. Вместо того чтобы обучать структурных программистов разработке на объектно-ориентированных языках, сейчас нам нужно обучать поколение программистов, выросших на таких языках.
Целевая аудитория этой книги включает проектировщиков, разработчиков, программистов и менеджеров проектов, дизайнеров, проще говоря, всех желающих получить общее представление о том, что такое объектно-ориентированное программирование. Я очень надеюсь на то, что прочтение этой книги создаст прочную основу для перехода к материалам, затрагивающим более продвинутые темы.
Подход, примененный в этой книге
К настоящему времени должна быть очевидна моя твердая убежденность в том, что сначала нужно хорошо освоить объектно-ориентированное мышление, а затем уже приступать к изучению языка программирования или моделирования. Эта книга наполнена примерами кода и UML-диаграмм, однако необязательно владеть определенным языком программирования или UML для того, чтобы переходить к ее чтению. Но после всего того, что я сказал об изучении в первую очередь объектно-ориентированных концепций, почему же в этой книге так много кода и диаграмм класса?
Во-первых, они отлично иллюстрируют объектно-ориентированные концепции. Во-вторых, они жизненно важны для освоения объектно-ориентированного мышления и должны рассматриваться на вводном уровне. Основной принцип заключается не в том, чтобы сосредотачиваться на Java, C# и т.д., а в использовании их в качестве средств, которые помогают понять основополагающие концепции.
Обратите внимание на то, что мне очень нравится применять UML-диаграммы классов как визуальные средства, помогающие понять классы, их атрибуты и методы. Фактически диаграммы классов — это единственный компонент UML, использованный в этой книге. Я считаю, что UML-диаграммы классов отлично подходят для представления концептуальной природы объектных моделей. Я продолжу использовать объектные модели в качестве образовательного инструмента для наглядной демонстрации конструкции классов и того, как классы соотносятся друг с другом.
Примеры кода в этой книге иллюстрируют концепции вроде циклов и функций. Однако понимание этого кода как такового не является необходимым условием для понимания самих концепций; возможно, целесообразно иметь под рукой книгу, в которой рассматривается синтаксис соответствующего языка, если вы захотите узнать дополнительные подробности.
Я не могу строго утверждать, что эта книга не учит языку Java, C# .NET, VB .NET, Objective-C, Swift или UML, каждому из которых можно было бы посвятить целые тома. Я надеюсь, что она пробудит в вас интерес к другим объектно-ориентированным темам вроде объектно-ориентированного анализа, объектно-ориентированного проектирования и объектно-ориентированного программирования.
Глава 1. Введение в объектно-ориентированные концепции
Хотя многие программисты не осознают этого, объектно-ориентированная разработка программного обеспечения существует с начала 1960-х годов. Только во второй половине 1990-х годов объектно-ориентированная парадигма начала набирать обороты, несмотря на тот факт, что популярные объектно-ориентированные языки программирования вроде Smalltalk и C++ уже широко использовались.
Расцвет объектно-ориентированных технологий совпал с началом использования сети интернет в качестве платформы для бизнеса и развлечений. А после того как стало очевидным, что Сеть активно проникает в жизнь людей, объектно-ориентированные технологии уже заняли удобную позицию для того, чтобы помочь в разработке новых веб-технологий.
Важно подчеркнуть, что название этой главы звучит как «Введение в объектно-ориентированные концепции». В качестве ключевого здесь использовано слово «концепции», а не «технологии». Технологии в индустрии программного обеспечения очень быстро изменяются, в то время как концепции эволюционируют. Я использовал термин «эволюционируют», потому что хотя концепции остаются относительно устойчивыми, они все же претерпевают изменения. Это очень интересная особенность, заметная при тщательном изучении концепций. Несмотря на их устойчивость, они постоянно подвергаются повторным интерпретациям, а это предполагает весьма любопытные дискуссии.
Эту эволюцию можно легко проследить за последние два десятка лет, если понаблюдать за прогрессом различных индустриальных технологий, начиная с первых примитивных браузеров второй половины 1990-х годов и заканчивая мобильными/телефонными/веб-приложениями, доминирующими сегодня. Как и всегда, новые разработки окажутся не за горами, когда мы будем исследовать гибридные приложения и пр. На всем протяжении путешествия объектно-ориентированные концепции присутствовали на каждом этапе. Вот почему вопросы, рассматриваемые в этой главе, так важны. Эти концепции сегодня так же актуальны, как и 25 лет назад.
Фундаментальные концепции
Основная задача этой книги — заставить вас задуматься о том, как концепции используются при проектировании объектно-ориентированных систем. Исторически сложилось так, что объектно-ориентированные языки определяются следующими концепциями: инкапсуляцией, наследованием и полиморфизмом (справедливо для того, что я называю классическим объектно-ориентированным программированием). Поэтому если тот или иной язык программирования не реализует все эти концепции, то он, как правило, не считается объектно-ориентированным. Наряду с этими тремя терминами я всегда включаю в общую массу композицию; таким образом, мой список объектно-ориентированных концепций выглядит так:
• инкапсуляция;
• наследование;
• полиморфизм;
• композиция.
Мы подробно рассмотрим все эти концепции в книге.
Одна из трудностей, с которыми мне пришлось столкнуться еще с самого первого издания книги, заключается в том, как эти концепции соотносятся непосредственно с текущими методиками проектирования, ведь они постоянно изменяются. Например, все время ведутся дебаты об использовании наследования при объектно-ориентированном проектировании. Нарушает ли наследование инкапсуляцию на самом деле? (Эта тема будет рассмотрена в следующих главах.) Даже сейчас многие разработчики стараются избегать наследования, насколько это представляется возможным. Вот и встает вопрос: «А стоит ли вообще применять наследование?».
Мой подход, как и всегда, состоит в том, чтобы придерживаться концепций. Независимо от того, будете вы использовать наследование или нет, вам как минимум потребуется понять, что такое наследование, благодаря чему вы сможете сделать обоснованный выбор методики проектирования. Важно помнить, что с наследованием придется иметь дело с огромной вероятностью при сопровождении кода, поэтому изучить его нужно в любом случае.
Как уже отмечалось во введении к этой книге, ее целевой аудиторией являются люди, которым требуется общее введение в фундаментальные объектно-ориентированные концепции. Исходя из этой формулировки, в текущей главе я представляю фундаментальные объектно-ориентированные концепции с надеждой обеспечить моим читателям твердую основу для принятия важных решений относительно проектирования. Рассматриваемые здесь концепции затрагивают большинство, если не все темы, охватываемые в последующих главах, в которых соответствующие вопросы исследуются намного подробнее.
Объекты и унаследованные системы
По мере того как объектно-ориентированное программирование получало широкое распространение, одной из проблем, с которыми сталкивались разработчики, становилась интеграция объектно-ориентированных технологий с существующими системами. В то время разграничивались объектно-ориентированное и структурное (или процедурное) программирование, которое было доминирующей парадигмой разработки на тот момент. Мне всегда это казалось странным, поскольку, на мой взгляд, объектно-ориентированное и структурное программирование не конкурируют друг с другом. Они являются взаимодополняющими, так как объекты хорошо интегрируются со структурированным кодом. Даже сейчас я часто слышу такой вопрос: «Вы занимаетесь структурным или объектно-ориентированным программированием?» Недолго думая, я бы ответил: «И тем и другим».
В том же духе объектно-ориентированный код не призван заменить структурированный код. Многие не являющиеся объектно-ориентированными унаследованные системы (то есть более старые по сравнению с уже используемыми) довольно хорошо справляются со своей задачей. Зачем же тогда идти на риск столкнуться с возможными проблемами, изменяя или заменяя эти унаследованные системы? В большинстве случаев не стоит этого делать лишь ради внесения изменений. В сущности, в системах, основанных не на объектно-ориентированном коде, нет ничего плохого. Однако совершенно новые разработки, несомненно, подталкивают задуматься об использовании объектно-ориентированных технологий (в некоторых случаях нет иного выхода, кроме как поступить именно так).
Хотя на протяжении последних 25 лет наблюдалось постоянное и значительное увеличение количества объектно-ориентированных разработок, зависимость мирового сообщества от сетей вроде интернета и мобильных инфраструктур способствовала еще более широкому их распространению. Буквально взрывной рост количества транзакций, осуществляемых в браузерах и мобильных приложениях, открыл совершенно новые рынки, где значительная часть разработок программного обеспечения была новой и главным образом не обремененной заботами, связанными с унаследованными системами. Но даже если вы все же столкнетесь с такими заботами, то на этот случай есть тенденция, согласно которой унаследованные системы можно заключать в объектные обертки.
Объектные обертки
Объектные обертки представляют собой объектно-ориентированный код, в который заключается другой код. Например, вы можете взять структурированный код (вроде циклов и условий) и заключить его в объект, чтобы этот код выглядел как объект. Вы также можете использовать объектные обертки для заключения в них функциональности, например параметров, касающихся безопасности, или непереносимого кода, связанного с аппаратным обеспечением, и т.д. Обертывание структурированного кода детально рассматривается в главе 6 «Проектирование с использованием объектов».
Одной из наиболее интересных областей разработки программного обеспечения является интеграция унаследованного кода с мобильными и веб-системами. Во многих случаях мобильное клиентское веб-приложение в конечном счете «подключается» к данным, располагающимся на мейнфрейме. Разработчики, одновременно обладающие навыками в веб-разработке как для мейнфреймов, так и для мобильных устройств, весьма востребованы.
Вы сталкиваетесь с объектами в своей повседневной жизни, вероятно, даже не осознавая этого. Вы можете столкнуться с ними, когда едете в своем автомобиле, разговариваете по сотовому телефону, используете свою домашнюю развлекательную систему, играете в компьютерные игры, а также во многих других ситуациях. Электронные соединения, по сути, превратились в соединения, основанные на объектах. Ориентируясь на мобильные веб-приложения, бизнес тяготеет к объектам, поскольку технологии, используемые для электронной торговли, по своей природе в основном являются объектно-ориентированными.
Мобильная веб-разработка
Несомненно, появление интернета значительно способствовало переходу на объектно-ориентированные технологии. Дело в том, что объекты хорошо подходят для использования в сетях. Хотя интернет был в авангарде этой смены парадигмы, мобильные сети теперь заняли не последнее место в общей массе. В этой книге термин «мобильная веб-разработка» будет использоваться в контексте концепций, которые относятся как к разработке мобильных веб-приложений, так и к веб-разработке. Термин «гибридные приложения» иногда будет применяться для обозначения приложений, которые работают в браузерах как на веб-устройствах, так и на мобильных аппаратах.
Процедурное программирование в сравнении с объектно-ориентированным
Прежде чем мы углубимся в преимущества объектно-ориентированной разработки, рассмотрим более существенный вопрос: что такое объект? Это одновременно и сложный, и простой вопрос. Сложный он потому, что изучение любого метода разработки программного обеспечения не является тривиальным. А простой он в силу того, что люди уже мыслят в категориях «объекты».
ПОДСКАЗКА
Посмотрите на YouTube видеолекцию гуру объектно-ориентированного программирования Роберта Мартина. На его взгляд, утверждение «люди мыслят объектно» впервые сделали маркетологи. Немного пищи для размышлений.
Например, когда вы смотрите на какого-то человека, вы видите его как объект. При этом объект определяется двумя компонентами: атрибутами и поведением. У человека имеются такие атрибуты, как цвет глаз, возраст, вес и т.д. Человек также обладает поведением, то есть он ходит, говорит, дышит и т.д. В соответствии со своим базовым определением, объект — это сущность, одновременно содержащая данные и поведение. Слово одновременно в данном случае определяет ключевую разницу между объектно-ориентированным программированием и другими методологиями программирования. Например, при процедурном программировании код размещается в полностью отдельных функциях или процедурах. В идеале, как показано на рис. 1.1, эти процедуры затем превращаются в «черные ящики», куда поступают входные данные и откуда потом выводятся выходные данные. Данные размещаются в отдельных структурах, а манипуляции с ними осуществляются с помощью этих функций или процедур.
Разница между объектно-ориентированным и структурным проектированием
При объектно-ориентированном проектировании атрибуты и поведения размещаются в рамках одного объекта, в то время как при процедурном или структурном проектировании атрибуты и поведение обычно разделяются.
Рис. 1.1. Черный ящик
При росте популярности объектно-ориентированного проектирования один из фактов, который изначально тормозил его принятие людьми, заключался в том, что использовалось много систем, которые не являлись объектно-ориентированными, но отлично работали. Таким образом, с точки зрения бизнеса не было никакого смысла изменять эти системы лишь ради внесения изменений. Каждому, кто знаком с любой компьютерной системой, известно, что то или иное изменение может привести к катастрофе, даже если предполагается, что это изменение будет незначительным.
В то же время люди не принимали объектно-ориентированные базы данных. В определенный момент при появлении объектно-ориентированной разработки в какой-то степени вероятным казалось то, что такие базы данных смогут заменить реляционные базы данных. Однако этого так никогда и не произошло. Бизнес вложил много денег в реляционные базы данных, а совершению перехода препятствовал главный фактор — они работали. Когда все издержки и риски преобразования систем из реляционных баз данных в объектно-ориентированные стали очевидными, неоспоримых доводов в пользу перехода не оказалось.
На самом деле бизнес сейчас нашел золотую середину. Для многих методик разработки программного обеспечения характерны свойства объектно-ориентированной и структурной методологий разработки.
Как показано на рис. 1.2, при структурном программировании данные зачастую отделяются от процедур и являются глобальными, благодаря чему их легко модифицировать вне области видимости вашего кода. Это означает, что доступ к данным неконтролируемый и непредсказуемый (то есть у множества функций может быть доступ к глобальным данным). Во-вторых, поскольку у вас нет контроля над тем, кто сможет получить доступ к данным, тестирование и отладка намного усложняются. При работе с объектами эта проблема решается путем объединения данных и поведения в рамках одного элегантного полного пакета.
Рис. 1.2. Использование глобальных данных
Правильное проектирование
Мы можем сказать, что при правильном проектировании в объектно-ориентированных моделях нет такого понятия, как глобальные данные. По этой причине в объектно-ориентированных системах обеспечивается высокая степень целостности данных.
Вместо того чтобы заменять другие парадигмы разработки программного обеспечения, объекты стали эволюционной реакцией. Структурированные программы содержат комплексные структуры данных вроде массивов и т.д. C++ включает структуры, которые обладают многими характеристиками объектов (классов).
Однако объекты представляют собой нечто намного большее, чем структуры данных и примитивные типы вроде целочисленных и строковых. Хотя объекты содержат такие сущности, как целые числа и строки, используемые для представления атрибутов, они также содержат методы, которые характеризуют поведение. В объектах методы применяются для выполнения операций с данными, а также для совершения других действий. Пожалуй, более важно то, что вы можете управлять доступом к членам объектов (как к атрибутам, так и к методам). Это означает, что отдельные из этих членов можно скрыть от других объектов. Например, объект с именем Math может содержать две целочисленные переменные с именами myInt1 и myInt2. Скорее всего, объект Math также содержит методы, необходимые для извлечения значений myInt1 и myInt2. Он также может включать метод с именем sum() для сложения двух целочисленных значений.
Сокрытие данных
В объектно-ориентированной терминологии данные называются атрибутами, а поведения — методами. Ограничение доступа к определенным атрибутам и/или методам называется сокрытием данных.
Объединив атрибуты и методы в одной сущности (это действие в объектно-ориентированной терминологии называется инкапсуляцией), мы можем управлять доступом к данным в объекте Math. Если определить целочисленные переменные myInt1 и myInt2 в качестве «запретной зоны», то другая логически несвязанная функция не будет иметь возможности осуществлять манипуляции с ними, и только объект Math сможет делать это.
Руководство по проектированию классов Sound
Имейте в виду, что можно создать неудачно спроектированные объектно-ориентированные классы, которые не ограничивают доступ к атрибутам классов. Суть заключается в том, что при объектно-ориентированном проектировании вы можете создать плохой код с той же легкостью, как и при использовании любой другой методологии программирования. Просто примите меры для того, чтобы придерживаться руководства по проектированию классов Sound (см. главу 5).
А что будет, если другому объекту, например myObject, потребуется получить доступ к сумме значений myInt1 и myInt2? Он обратится к объекту Math: myObject отправит сообщение объекту Math. На рис. 1.3 показано, как два объекта общаются друг с другом с помощью своих методов. Сообщение на самом деле представляет собой вызов метода sum объекта Math. Метод sum затем возвращает значение объекту myObject. Вся прелесть заключается в том, что myObject не нужно знать, как вычисляется сумма (хотя, я уверен, он может догадаться). Используя эту методологию проектирования, вы можете изменить то, как объект Math вычисляет сумму, не меняя объект myObject (при условии, что средства для извлечения значения суммы останутся прежними). Все, что вам нужно, — это сумма, и вам безразлично, как она вычисляется.
Рис. 1.3. Коммуникации между объектами
Простой пример с калькулятором позволяет проиллюстрировать эту концепцию. При определении суммы на калькуляторе вы используете только его интерфейс — кнопочную панель и экран на светодиодах. В калькулятор заложен метод для вычисления суммы, который вызывается, когда вы нажимаете соответствующую последовательность кнопок. После этого вы сможете получить правильный ответ, однако не будете знать, как именно этот результат был достигнут — в электронном или алгоритмическом порядке.
Вычисление суммы не является обязанностью объекта myObject — она возлагается на Math. Пока у myObject есть доступ к объекту Math, он сможет отправлять соответствующие сообщения и получать надлежащие результаты. Вообще говоря, объекты не должны манипулировать внутренними данными других объектов (то есть myObject не должен напрямую изменять значения myInt1 и myInt2). Кроме того, по некоторым причинам (их мы рассмотрим позднее) обычно лучше создавать небольшие объекты со специфическими задачами, нежели крупные, но выполняющие много задач.
Переход с процедурной разработки на объектно-ориентированную
Теперь, когда мы имеем общее понятие о некоторых различиях между процедурными и объектно-ориентированными технологиями, углубимся и в те и в другие.
Процедурное программирование
При процедурном программировании данные той или иной системы обычно отделяются от операций, используемых для манипулирования ими. Например, если вы решите передать информацию по сети, то будут отправлены только релевантные данные (рис. 1.4) с расчетом на то, что программа на другом конце сетевой магистрали будет знать, что с ними делать. Иными словами, между клиентом и сервером должно быть заключено что-то вроде джентльменского соглашения для передачи данных. При такой модели вполне возможно, что на самом деле по сети не будет передаваться никакого кода.
Рис. 1.4. Данные, передаваемые по сети
Объектно-ориентированное программирование
Основное преимущество объектно-ориентированного программирования заключается в том, что и данные, и операции (код), используемые для манипулирования ими, инкапсулируются в одном объекте. Например, при перемещении объекта по сети он передается целиком, включая данные и поведение.
Единое целое
Хотя мышление в контексте единого целого теоретически является прекрасным подходом, сами поведения не получится отправить из-за того, что с обеих сторон имеются копии соответствующего кода. Однако важно мыслить в контексте всего объекта, передаваемого по сети в виде единого целого.
На рис. 1.5 показана передача объекта Employee по сети.
Рис. 1.5. Объект, передаваемый по сети
Правильное проектирование
Хорошим примером этой концепции является объект, загружаемый браузером. Часто бывает так, что браузер заранее не знает, какие действия будет выполнять определенный объект, поскольку он еще «не видел» кода. Когда объект загрузится, браузер выполнит код, содержащийся в этом объекте, а также использует заключенные в нем данные.
Что такое объект?
Объекты — это строительные блоки объектно-ориентированных программ. Та или иная программа, которая задействует объектно-ориентированную технологию, по сути, является набором объектов. В качестве наглядного примера рассмотрим корпоративную систему, содержащую объекты, которые представляют собой работников соответствующей компании. Каждый из этих объектов состоит из данных и поведений, описанных в последующих разделах.
Данные объектов
Данные, содержащиеся в объекте, представляют его состояние. В терминологии объектно-ориентированного программирования эти данные называются атрибутами. В нашем примере, как показано на рис. 1.6, атрибутами работника
Рис. 1.6. Атрибуты объекта Emp
