4. Заключение
§ 48. Элементы объектно-ориентированного программирования. В первой главе мы сформулировали, что в самом общем смысле объектно-ориентированное программирование совмещает две идеи: абстрактные типы данных и иерархические типы данных. Во второй и третьей главах мы подробно рассмотрели, посредством каких именно возможностей объектно-ориентированные языки позволяют программисту создавать и использовать абстрактные и иерархические типы. То есть позволяют, согласно классическому определению ООП, представлять программу как совокупность взаимодействующих объектов (абстрактные типы данных), каждый из которых является экземпляром класса, которые образуют иерархию наследования (иерархические типы данных). Ключевые и наиболее общие из соответствующих возможностей языков программирования обычно называют элементами объектно-ориентированного программирования. Чаще всего выделяют следующие необходимые и достаточные элементы ООП:
1) инкапсуляция;
2) наследование;
3) полиморфизм.
В разных источниках перечень элементов может быть разным, но, по сути, речь идет об одном и том же. Так, в книге [Буч, 3] автор выделяет четыре основных элемента объектной модели: абстрагирование, инкапсуляция, модульность, иерархия. Однако вполне можно сказать, что инкапсуляция – механизм реализации абстрагирования, полиморфизм и наследование – разные аспекты иерархии, а модульность – в контексте ООП – та же инкапсуляция, при этом в более широком контексте она не является характеристикой только ООП. То есть эти два списка основных элементов, по сути, равнозначны. Мы уже рассмотрели их в предыдущих главах. Перечень основных элементов представляет собой технологическое определение ООП.
Читатель может найти немало материалов на тему концептуальных проблем ООП, вынуждающих разработчиков применять специальные подходы, которые в принципе не нужны в рамках других парадигм. Однако представляется, что так же, как процедурное (структурное) программирование в некоторым смысле является концептуальной базой для ООП, ООП так или иначе останется концептуальной базой для других парадигм. Здесь мы можем порекомендовать читателю часть 2 книги [Мартин 11], посвященную парадигмам программирования. Разработчики объектно-ориентированных языков настроены вполне оптимистично. Процитируем Дж. Гослинга [17]: «В данное время объектно-ориентированная парадигма действует очень хорошо. Всякого рода дебаты касаются второстепенных вопросов – различные теоретико-языковые споры ведутся, по существую, по незначительным модификациям, но основная идея объектно-ориентированного программирования оказалось удивительно удачной и не обнаружила каких-либо серьезных изъянов». В обозримом будущем знание ООП останется в числе базовых навыков любого программиста.
В заключение, в следующих параграфах мы коротко обозначим современные объектно-ориентированные языки и, далее, приведем заключительные рекомендации по дальнейшему изучению ООП и нерассмотренным темам.
§ 49. Языки программирования. Объектно-ориентированные языки активно развиваются, в том числе, стремясь преодолеть отдельные ограничения объектной модели. Например, объектно-ориентированные языки активно вбирают в себя элементы функционального программирования и различные специальные механизмы организации работы в многопоточной среде. При этом многие не ОО-языки или на уровне языка, или на уровне библиотек реализуют или эмулируют элементы ООП. Например, это относится к самому распространенному языку программирования – JavaScript.
Согласно исследованию HackerRank 2018 Developer Skill Report (http://research.hackerrank.com/developer-skills/2018/) наиболее распространенные языки с точки зрения количества работодателей следующие: JavaScript (47,8 %), Java (47,4 %), Python (33 %), C++ (21 %), C (18,9 %), C# (17,9 %), PHP (14,6 %), Ruby (8,1 %), Конкретные цифры достаточно условны и зависят от отрасли, так в некоторых отраслях в том же исследовании востребованность C# превышает 30 %. При этом Java, Python, C++, C#, Ruby – полноценные объектно-ориентированные языки. Остальные так или иначе поддерживают элементы ООП.
Перечисляя объектно-ориентированные языки, нельзя не назвать давно устаревший, но в свое время внесший значительный клад в развитие ООП язык Simula. Попытайтесь определить, что выполняет следующий код:
Class Rectangle (Width, Height); Real Width, Height;
Begin
Real Area, Perimeter;
Procedure Update;
Begin
Area := Width * Height;
Perimeter := 2*(Width + Height)
End of Update;
Boolean Procedure IsSquare;
IsSquare := Width=Height;
Update;
OutText("Прямоугольник создан: "); OutFix(Width,2,6);
OutFix(Height,2,6); OutImage
End of Rectangle;
Ref(Rectangle) R;
R :- New Rectangle(50, 40);
Этот язык был создан в 60-х годах и поддерживал объекты, классы, наследование, виртуальные процедуры, сборку мусора и некоторые другие возможности, которые ошибочно представляются прерогативой исключительно современных языков, созданных в 90-х и 00-х годах.
§ 50. Рекомендации по дальнейшему изучению. Изложенный в книге материал охватывает все ключевые темы ООП, однако мы не стремились дать исчерпывающий анализ, потому что при первом знакомстве большая детализация отвлекала бы от существа изучаемых вопросов. Не так много литературы развернуто обсуждает основы ООП, отметим классические книги [Мейер 13] и [Буч 3], на которые мы уже неоднократно ссылались в тексте. По языку программирования C# существует множество хороших вводных книг, статей и даже видеокурсов. Упомянем лишь книгу [Скит 20], рекомендуемую читателю, уже имеющему некоторый опыт разработки. При рассмотрении специфических тем, таких как как обобщенное программирование или объектно-реляционные базы данных, мы указывали рекомендуемые для более глубокого знакомства материалы непосредственно в тексте.
Объектно-ориентированное программирование – это инструмент. Соответственно, как любой инструмент, его можно применять с разной степенью эффективности, по назначению или не по назначению. Вопросы эффективного применения относятся к другой дисциплине – объектно-ориентированному проектированию и анализу. Мы уже упоминали об этом, рассматривая некоторые принципы проектирования. На эту тему доступно достаточно много книг, назовем некоторые из них: [Мартин 11], [Ousterhout 22], [Мейер 13], [5], [Буч 3], [Ларман 7].
Одна из особенностей объектно-ориентированного подхода (за которую, он нередко подвергается критике) – гибкость архитектуры, позволяющая программировать в широчайшем диапазоне решений одной и той же задачи. От одной крайности, когда программа состоит из небольшого числа классов с большими статическими методами («объектно-недоориентированное» программирование), до другой крайности, когда разработчик стремиться максимально задействовать весь «арсенал» технических возможностей, избыточно усложняя систему («объектно-переориентированное» программирование). Усугубляет эту проблему то, что в рамках учебных примеров, задач, даже в объеме курсовых и дипломным университетских работ проблематично выйти на тот масштаб кода, когда действительно в полной мере проявляются преимущества объектно-ориентированной парадигмы. «ООП проявляет себя во всем блеске, когда системы увеличиваются в размерах, когда над ними работают большие команды, когда системы развиваются во времени.» (Дж. Гослинг) [17] До некоторого времени разработчику приходится довольствоваться в большей мере теоретическим пониманием этих преимуществ. Найти верное оптимальное решение может помочь непрерывное обучение и опыт. В качестве ориентира процитируем Дж. Скита: «Я обычно предпочитаю понятный код умному» [20].
В заключение отметим, что часто обучение программированию начинается с книги по некоторому языку программирования, где главное – изложение синтаксиса языка. Это безусловно необходимо, но не должно быть первым шагом. Опыт показывает, что разработчики, руководствовавшиеся во время обучения (в том числе, самообразования) исключительно принципом практической применимости знаний «здесь и сейчас», тратят значительно больше усилий на решение сложных и нетипичных задач и на освоение новых технологий и языков программирования. Процитируем известного специалиста в сфере объектно-ориентированного проектирования Дж. Рамбо [17]: «…по моему впечатлению, во многих колледжах принят узкий взгляд на компьютерные науки с акцентом на конкретные языки программирования и системы, а не на понимание важных базовых компьютерных принципов… Думаю, главный талант в компьютерной области (а также в физике и других творческих сферах) – способность к абстрагированию. К сожалению, мой опыт показывает, что мене 50 % программистов в достаточной мере способы к абстракции. Один из моих коллег полагает, что в действительности их меньше 10 %. Возможно, он прав.»
Понимание концепций и базовых элементов ООП позволяет видеть в тех или иных особенностях языков программирования не заявляемые маркетологами «уникальные возможности», а разновидности реализации широко известных идей.
Вопросы и задания
Назовите и кратко охарактеризуйте основные элементы ООП.
Назовите элементы объектно-ориентированных языков, которые свойственны не только им, а заимствованы из процедурных языков.
Познакомьтесь с определением ООП с точки зрения теории языков программирования по книге [Мартин 11].
Назовите примеры современных объектно-ориентированных языков программирования.
Просмотрите содержание и предметный указатель настоящей книги; убедитесь, что вы имеете ясное представление о всех темах, заявленных в содержании, и вам понятны все термины, приведенные в предметном указателе.
** Потратьте несколько дней на изучение фрагментов кода крупных признанных проектов на C#, например, на github.com.
** Прочитайте книгу по C#.
** Прочитайте несколько книг из списка литературы.
Оставьте отзыв о книге на сайте автора newobj.ru/oop.