В чем сила объектно-ориентированного дизайна — семантика или инкапсуляция?

StackOverflow https://stackoverflow.com/questions/669042

Вопрос

Объектно-ориентированное проектирование (ООД) сочетает в себе данные и их методы.Насколько я понимаю, это позволяет достичь двух замечательных целей:он обеспечивает инкапсуляцию (поэтому меня не волнует, какие данные там есть, а только то, как я получаю нужные значения) и семантику (он связывает данные вместе с именами, и его методы последовательно используют данные так, как изначально предполагалось).

Так в чем же сила OOD?Напротив, функциональное программирование приписывает богатство глаголам, а не существительным, поэтому и инкапсуляция, и семантика обеспечиваются методами, а не структурами данных.

Я работаю с системой, которая находится на функциональном конце спектра, и постоянно стремлюсь к семантике и инкапсуляции ОО.Но я вижу, что объектно-ориентированная инкапсуляция может стать препятствием для гибкого расширения объекта.Так что на данный момент я рассматриваю семантику как большую силу.

Или инкапсуляция является ключом ко всему стоящему коду?

Редактировать:Я имею в виду конкретно тип инкапсуляции, который здесь обеспечивает ОО. changeColor(door,blue) становится door.changeColor(blue).

Это было полезно?

Решение

Похоже, вы используете довольно узкое определение «инкапсуляции». Правильно ли я предполагаю, что вы определяете инкапсуляцию как «объединение данных с методами»?

Если я ошибаюсь, то, пожалуйста, проигнорируйте остальную часть этого поста.

Инкапсуляция – это не расплывчатый термин;на самом деле, это определено Международной организацией по стандартизации.Эталонная модель открытой распределенной обработки ISO определяет следующие пять концепций:

Сущность:Любая конкретная или абстрактная вещь, представляющая интерес.

Объект:Модель сущности.Объект характеризуется своим поведением и, вдвойне, своим состоянием.

Поведение (объекта):Коллекция действий с набором ограничений на то, когда они могут выполняться.

Интерфейс:Абстракция поведения объекта, состоящая из подмножества взаимодействий этого объекта вместе с набором ограничений на то, когда они могут происходить.

Инкапсуляция:свойство, заключающееся в том, что информация, содержащаяся в объекте, доступна только посредством взаимодействия на интерфейсах, поддерживаемых объектом.

Далее мы можем сделать самоочевидное предложение:поскольку некоторая информация доступна через эти интерфейсы, некоторая информация должна быть скрыта и недоступна внутри объекта.Свойство, которое демонстрирует такая информация, называется сокрытием информации, которое Парнас определил, утверждая, что модули должны быть спроектированы так, чтобы скрывать как трудные решения, так и решения, которые могут измениться, см. одну из замечательных статей по вычислительной технике:

http://www.cs.umd.edu/class/spring2003/cmsc838p/Design/criteria.pdf

Важно отметить, что не только данные скрыты от информации:это некоторая подгруппа поведения, связанная с объектом, которую трудно или вероятно изменить.

В своем посте вы, кажется, говорите, что разница между инкапсуляцией в ОО и функциональном программировании проистекает из управления данными, но, по крайней мере, согласно ISO и Парнасу, управление данными не является ключом к инкапсуляции.Поэтому я не понимаю, почему инкапсуляция в функциональном программировании должна отличаться от инкапсуляции в объектно-ориентированном программировании.

Кроме того, в своем посте вы упоминаете, что функциональное программирование обеспечивает инкапсуляцию: «... методами, а не структурами данных». Это, я думаю, разница не абсолютная, а масштабная.Если я использую слово «Объект», а не «Структура данных» (опять же, пожалуйста, дайте мне знать, если я неправильно истолковываю), то вы, похоже, находите значение в объектно-ориентированной инкапсуляции по объекту и в функциональном программировании по методу.

Тем не менее, согласно приведенному выше определению ISO, объект — это все, что я хочу смоделировать.Таким образом, классы могут быть инкапсулированы внутри пакета, при условии, что некоторые из этих классов вносят вклад в интерфейс пакета (т. е. общедоступные классы пакета), а некоторые скрыты от информации (частные классы в пакете).

Точно так же методы инкапсулируются внутри класса: некоторые методы являются общедоступными, а некоторые — закрытыми.Можно даже пойти на ступеньку ниже и сказать, что последовательные последовательности кода Маккабиана инкапсулированы в методы.Каждый из них формирует граф узлов, инкапсулированных в инкапсулированные области;и все эти графы образуют стек графов.Таким образом, функциональное программирование может быть хорошо инкапсулировано на уровне функции/файла, но это ничем не отличается от графа метода/класса ОО и, по сути, не отличается от графа классов/пакетов ОО.

Также обратите внимание, что слово Парнас употребляется выше:изменять.Сокрытие информации касается потенциальных событий, таких как изменение сложных проектных решений в будущем.Вы спрашиваете, в чем сила ОО;Что ж, инкапсуляция, безусловно, является сильной стороной ОО, но тогда возникает вопрос: «В чем заключается сила инкапсуляции?», и ответ на него очень ясен:управление изменениями.В частности, инкапсуляция снижает максимальное потенциальное бремя изменений.

Здесь полезна концепция «потенциальной связи».

«Связь» сама по себе определяется как «мера силы связи, устанавливаемой соединением одного модуля с другим» в другой великой статье по вычислительной технике:

http://www.research.ibm.com/journal/sj/382/stevens.pdf

И как говорится в статье словами, которые с тех пор не были улучшены: «Минимизация связей между модулями также минимизирует пути, по которым изменения и ошибки распространяются в другие части системы, тем самым устраняя катастрофические «волновые» эффекты, когда изменения в одной части вызывают ошибки в другом, вызывающие необходимость дополнительных изменений в другом месте, порождающие новые ошибки и т. д.».

Однако, как определено здесь, существуют два ограничения, которые можно легко снять.Во-первых, связь не измеряет внутримодульные связи, и эти внутримодульные связи могут вызывать столько же «пульсирующих» эффектов, сколько и межмодульные связи (в статье действительно определяется «связность», чтобы связать внутримодульные связи). элементы, но это не определяется с точки зрения связей между элементами (т. е. ссылок на метки или адреса), с помощью которых была определена связь).Во-вторых, связь любой компьютерной программы является заданной, поскольку модули соединяются или;в определении сцепления мало возможностей для управления потенциальными изменениями, о которых говорит Парнас.

Обе эти проблемы в некоторой степени решаются с помощью концепции потенциальной связи:максимально возможное количество связей, образуемых между всеми элементами программы.В Java, например, класс, который является частным для пакета (аксессор по умолчанию) внутри пакета, не может иметь соединений, сформированных с ним (т. е. никакие внешние классы не могут зависеть от него, несмотря на отражение), но открытый класс внутри пакета может есть зависимости от него.Этот открытый класс будет способствовать потенциальному связыванию, даже если в данный момент от него не зависят никакие другие классы — классы могут зависеть от него в будущем, когда дизайн изменится.

Чтобы увидеть силу инкапсуляции, рассмотрим принцип бремени.Принцип бремени принимает две формы.

В сильной форме утверждается, что бремя преобразования набора сущностей зависит от количества преобразованных сущностей.Слабая форма утверждает, что максимальное потенциальное бремя преобразования набора сущностей является функцией максимального потенциального числа преобразованных сущностей.

Бремя создания или модификации любой программной системы зависит от количества созданных или измененных классов (здесь мы используем «классы», предполагая объектно-ориентированную систему и занимаясь инкапсуляцией на уровне класса/пакета;мы могли бы в равной степени заняться уровнем функций/файлов функционального программирования).(Заметьте, что «бремя» современной разработки программного обеспечения обычно требует затрат, или времени, или и того, и другого.) Классы, зависящие от конкретного, измененного класса, имеют более высокую вероятность быть затронутыми, чем классы, которые не зависят от измененного класса.

Максимальная потенциальная нагрузка, которую может наложить модифицированный класс, — это влияние на все классы, которые от него зависят.

Таким образом, уменьшение зависимостей от модифицированного класса снижает вероятность того, что его обновление повлияет на другие классы, и тем самым снижает максимальную потенциальную нагрузку, которую может наложить этот класс.(Это не более чем переформулировка статьи «Структурированный дизайн».)

Таким образом, уменьшение максимального потенциального количества зависимостей между всеми классами в системе снижает вероятность того, что воздействие на конкретный класс приведет к обновлениям других классов, и, таким образом, снижает максимальную потенциальную нагрузку всех обновлений.

Таким образом, инкапсуляция, уменьшая максимальное потенциальное количество зависимостей между всеми классами, смягчает слабую форму принципа бремени.Все это описано в «Теории инкапсуляции», которая пытается математически доказать такие утверждения, используя потенциальную связь в качестве логического средства структурирования программы.

Заметьте, однако, что когда вы спрашиваете: «Является ли инкапсуляция ключом ко всему стоящему коду?», ответ, несомненно, должен быть таким:нет.Не существует единого ключа ко всему стоящему коду.В определенных обстоятельствах инкапсуляция — это просто инструмент, помогающий улучшить качество кода, чтобы он стал «стоящим».

Вы также пишете, что "... Инкапсуляция может стать препятствием для гибкого расширения объекта». Да, безусловно, может:он действительно задуман как барьер против расширения проектных решений объекта, которые трудно или могут изменить.Однако это не считается чем-то плохим.Альтернативный подход заключается в том, чтобы сделать все классы общедоступными и заставить программу выражать максимальную потенциальную связь;но тогда слабая форма Принципа бремени утверждает, что обновления будут становиться все более дорогостоящими;это затраты, относительно которых следует измерять барьеры на пути расширения.

Наконец, вы провели интересное сравнение между инкапсуляцией и семантикой и отметили, что, по вашему мнению, семантика ОО является его большей силой.Я тоже не семантик (я даже не знал о существовании такого слова до того, как добрый мистер Рэмси упомянул его в своем комментарии), но я предполагаю, что вы имеете в виду «семантику» в смысле «значения или интерпретация значения слова», и, по сути, класс с методом woof() должен называться Dog.

В этой семантике действительно есть огромная сила.

Что мне любопытно, так это то, что вы противопоставляете семантику инкапсуляции и ищете победителя;Сомневаюсь, что ты найдешь его.

На мой взгляд, есть две силы, которые мотивируют инкапсуляцию:семантическое и логическое.

Семантическая инкапсуляция просто означает инкапсуляцию, основанную на значении инкапсулированных узлов (если использовать общий термин).Итак, если я скажу вам, что у меня есть два пакета, один из которых называется «животное», а другой — «минерал», а затем дам вам три класса Dog, Cat и Goat и спрошу, в какие пакеты должны быть инкапсулированы эти классы, тогда, учитывая никакой другой информации, вы были бы совершенно правы, утверждая, что семантика системы предполагает, что три класса должны быть инкапсулированы в пакет «животное», а не в пакет «минерал».

Однако другой мотивацией для инкапсуляции является логика и, в частности, исследование потенциальной связи, упомянутое выше.Теория инкапсуляции фактически предоставляет уравнения для количества пакетов, которые следует использовать для инкапсуляции ряда классов, чтобы минимизировать потенциальную связь.

Для меня инкапсуляция в целом — это компромисс между семантическим и логическим подходами:Я позволю потенциальному связыванию моих программ превысить минимальный уровень, если это облегчит семантическое понимание программы;но огромные и расточительные уровни потенциальной связи будут предупреждением о том, что мою программу необходимо реструктурировать, независимо от того, насколько семантически она очевидна.

(И если добрый мистер Рэмси все еще читает, не могли бы вы или ваши друзья-семантики дать мне лучшее слово для фазы «Семантика», которую я здесь использую?Было бы хорошо использовать более подходящий термин.)

Привет Эд.

Другие советы

Инкапсуляция и возникающая в результате абстракция, несомненно, являются основными сильными сторонами ОО.«Вещи» определяют, какие «действия» могут быть к ним применены, поэтому существительные приобретают более высокую семантическую значимость, чем глаголы.

В конечном счете, трудно представить себе разработку сложной системы в согласованной и удобной для сопровождения форме без определенного уровня инкапсуляции.

Как программист на Лиспе, чья объектная система, возможно, не обеспечивает ни того, ни другого, я говорю:ни один из вышеперечисленных.

блин:«объектная модель псевдоSmalltalk проигрывает, а общие функции (соответственно ограниченные правилом отсутствия внешних переопределений) выигрывают».

Я думаю, что желательные атрибуты, которые вы и другие перечисляют здесь (инкапсуляция, модульность и т. д.), не так присущи объектно-ориентированному подходу, как вы думаете.Они часто предоставляются вместе с ООП в стиле Java, но не просто являются его следствием.

Изолирующая сложность IMO является основной целью любого дизайна:инкапсуляция функциональности за интерфейсом, который проще в использовании чем сам функционал.

ОО предоставляет для этого различные механизмы - два упоминаются:

Инкапсуляция позволяет проектировать пользовательскую поверхность, независимую от фактической реализации.(перефразируя: «Проще — значит иначе»).

Семантика позволяет моделировать сущности, которые представляют элементы проблемной области, чтобы их было легче понять.


Любой проект, достигающий определенного размера, становится упражнением в управлении сложностью.Я готов поспорить, что с годами программирование приблизилось к пределам сложности, с которыми мы научились справляться.

Я не баловался функциональным программированием в течение многих лет, но, в моем понимании, это лучше всего можно описать математическим значением слов мощный, элегантный и красивый.«Красивый» и «элегантный» в этом контексте пытаются описать блестящее понимание истинной или значимой структуры сложной системы, глядя на нее с точки зрения, где она удивительно проста.он принимает сложность как данность и пытается с ней справиться.

Гибкость, о которой вы упоминаете, насколько я понимаю, заключается в возможности изменять POV в соответствии с вашими потребностями, но это противоречит инкапсуляции:то, что является бессмысленной деталью с одной позиции, может оказаться единственной значимой с другой.

OO, OTOH — это редукционистский подход:мы меняем точку зрения, переходя на более высокий уровень.В «старом ОО» существует единая иерархия точек зрения, интерфейсы в этой модели являются способом моделирования различных точек зрения.

Если можно так сказать, сила ОО больше подходит «нормальным людям».

Какая-то форма модульность является ключом к любому масштабируемому дизайну.Ограниченность человеческих существ не позволяет людям «усвоить» слишком много информации одновременно, поэтому нам приходится подразделять проблемы на управляемые, связные части, чтобы обеспечить основу для решения проблем. понимание большой проект, а также способ разделить рабочие задания большого проекта среди многих людей.

Как выбрать наиболее эффективное «разделение»/«разделение» большого проекта для достижения вышеперечисленных целей?Опыт показал, что объектно-ориентированный подход здесь является большим победителем, и я думаю, что многие люди согласятся, что два ключевых атрибута объектно-ориентированного подхода, которые делают его успешным в этом:

  • Инкапсулированный:каждый класс инкапсулирует «секрет» — набор специфичных для реализации предположений, которые, вероятно, придется со временем изменить в отношении его реализации — и предоставляет интерфейс, который не зависит от этих предположений;наслоение таких инкапсулированных абстракций позволяет создать надежную конструкцию, в которой компоненты/реализации можно легко заменять в случае ожидаемых изменений.
  • Ориентированный на существительное:в большинстве областей люди, кажется, лучше сначала разлагают модель предметной области, размышляя о существительных/данных предметной области, а затем определяют вспомогательные глаголы, которые связаны с каждым существительным.

Что касается функционального программирования (FP) и объектно-ориентированного программирования, у меня есть в блоге об этом, но вкратце я думаю, что FP больше касается методов реализации, тогда как OO больше касается структуры и дизайна программы, и, таким образом, они дополняют друг друга, при этом OO более доминирует на «большом» конце шкалы, а FP более доминирует. на «маленьком» конце.То есть в большом проекте высокоуровневая структура лучше всего описывается проектированием ОО-класса, но многие детали уровня модуля (реализации и детали форм интерфейсов модулей) лучше всего формируются с помощью ФП. влияния.

Сила объектно-ориентированного проектирования пропорциональна тому, насколько позднее связывание происходит в конструкции.Это понятие ОО Кея, а не понятия Найгаарда. Алан Кей написал:

ООП для меня означает только обмен сообщениями, локальный Удержание, защита и сокрытие государственного процесса, и крайние запоздалое связывание всех вещей.Это может быть на Smalltalk и на LISP.Там возможно другие системы, в которых это возможно, но я не в курсе им.

Большая часть литературы игнорирует позднее связывание в пользу идеи объектной ориентации C++.

Давайте сделаем шаг назад и посмотрим на это с более высокого уровня.Преимущества любой языковой функции заключаются в способности кратко выразить проблему/решение более естественным способом по отношению к проблемной области.

Механика ООП легко реализуется на простом языке C с помощью структур и указателей на функции.Поступая таким образом, вы даже можете почувствовать себя ООП.Однако в такой среде идиомы ООП не так распространены.Когда есть реальная языковая поддержка ООП, проявляется выразительность парадигмы, и то, как язык реализует идею, оказывает очень реальное влияние на то, что и как «говорится».Например, посмотрите различия в коде с использованием замыканий/лямбда-выражений в Lisp, Python, Ruby и т. д.

Итак, в конечном итоге речь идет не о компонентах и ​​базовых концепциях, а о том, как они собираются вместе и используются, что делает объектно-ориентированный подход в C++ тем, чем он является.

Инкапсуляция в сочетании с полиморфизмом.Способность классов большинства ООП-языков реализовывать один или несколько интерфейсов оказала наибольшее влияние на разработку моего программного обеспечения.Эта функция позволяет мне точно определить взаимодействие между двумя объектами.

Не только определять взаимодействия, но и документировать их, чтобы спустя годы я мог вернуться к этому участку кода и ясно увидеть, что происходит.

Эта особенность является основной причиной, по которой я предпочитаю использовать языки ООП функциональным языкам.Несмотря на то, что программное обеспечение, написанное на функциональных языках, очень мощное, его сложно поддерживать, поскольку цикл обслуживания измеряется десятилетиями.(Программное обеспечение AutoLisp находится в AutoCAD)

ИМХО, ОО просто означает объекты, взаимодействующие с другими объектами.Инкапсуляция просто означает абстрагирование концепции.Итак, вы создаете Socket и .Connect() для чего-то.Как это соединяется, вас не волнует (это, по сути, мое определение инкапсуляции).

И чисто функциональное программирование может использовать объект для связи.но эти объекты должны быть неизменяемыми.Итак, опять же, ИМХО, FP может легко использовать концепцию ОО;Императивный язык, такой как C, все еще может использовать концепцию ОО.например, файл для каждого «класса» с частным разделом, который не следует использовать.

Ваш вопрос звучит так: Вы хотите извлечь выгоду из дом, разобрав кирпич.

Возможность предоставления семантического контекста и инкапсуляции являются лишь базовыми возможностями класса в ОО.(Как кирпичная банка, выдерживают определенную силу и претендуют на определенное пространство.)

Продолжим аналогию:Чтобы получить максимум от кирпичиков, просто сложите их вместе.Тем То же самое относится и к классам и объектам.

Там много шаблонов проектирования который может быть использован для ОО программирование.Большинство из них полагаются на способности «инкапсуляции» и "семантический", о котором Вы упомянули.

Некоторые из этих закономерностей даже являются ответом на третий абзац Вашего вопроса:

  • Если вы хотите расширить поведение существующего класса, вы можете создать производный класс.
  • Если вы хотите расширить или изменить поведение существующего объекта, вы можете рассмотреть возможность шаблон декоратора.

Настоящая сила объектно-ориентированного подхода заключается в полиморфизме, а не в инкапсуляции.Инкапсуляция в определенной степени достижима и используется в функциональных языках, но полиморфизм был бы очень неудобен, если бы он был реализован на функциональном языке.

(Прочитайте «Шаблон проектирования» автора Банда из четырех чтобы понять силу ОО.)

@Phil, разница, которую вы упомянули, если я вас правильно понимаю, заключается в том, как программа вызывает данные/метод:в oo сначала существует объект/экземпляр, а затем через объект вызываются данные/метод объекта;в функциональном метод вызывается напрямую.

Однако, глядя на реализацию функциональной программы, мы видим, что данные и метод упакованы (в файл, а не в класс).Например, программа C имеет заголовочный файл, в котором объявляются функции, доступные из другого файла, а данные являются личными данными, если они доступны только через эти объявленные функции.Если программист достаточно осторожен, большая часть объектно-ориентированной инкапсуляции может быть реализована в функциональных программах.(Даже наследование доступно при использовании определенных приемов с указателями.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top