Как вы думаете, объектно-ориентированное программирование является решением для сложности. Почему? Эта тема может быть немного спорным, но мои намерения знать ответ, почему у специалистов здесь!
Как вы думаете, объектно-ориентированное программирование является решением для сложности. Почему? Эта тема может быть немного спорным, но мои намерения знать ответ, почему у специалистов здесь!
Ответы:
Нет решения для сложности.
В «Мифическом человеко-месяце» Фред Брукс обсуждает разницу между случайной и существенной сложностью в программировании. Случайная сложность вызвана нашими инструментами и методами, такими как необходимость писать и тестировать дополнительный код на языке, потому что мы не можем выразить наши идеи напрямую и тому подобное. Новые методы и методы могут уменьшить случайную сложность. Я могу писать программы быстрее и лучше, чем двадцать пять лет назад, потому что у меня есть лучшие языки и инструменты.
Существенная сложность возникает из-за того, что то, что мы пытаемся делать с программированием, по своей сути сложно, и что существует неснижаемая сложность. «Существенный» в данном контексте означает «относящийся к сути вещи», а не «очень необходимый».
Поэтому он утверждал, что не будет никакой серебряной пули, что написание программного обеспечения будет по-прежнему затруднительным.
Я настоятельно рекомендую вам прочесть его книгу: в частности, я рекомендую издание Silver Anniversary с дополнительным эссе "No Silver Bullet". При этом он рассматривает предложенные решения по сложности и учитывает их влияние. (То, что он считает наиболее эффективным, - это программа для упаковки в термоусадочную пленку - однажды напишите что-нибудь сложное и продайте тысячи или миллионы копий.)
Теперь объектно-ориентированное программирование помогает, если все сделано правильно, создавая абстракции и скрывая сложность. У объекта класса есть определенное определенное поведение, которое мы можем рассуждать, не заботясь о сложности реализации. Правильно написанные классы слабо связаны друг с другом, и «разделяй и властвуй» является отличным способом справиться со сложностью, если вам это удастся. Они также обладают высокой связностью, поскольку представляют собой набор функций и данных, которые очень тесно связаны друг с другом.
Я ожидаю, что вы получите лучшие ответы в ближайшее время, но вот простой:
ООП помогает * со сложностью, моделируя программное обеспечение ближе к тому, как мы моделируем все остальное в мире. Как правило, проще представить объект шара, взаимодействующий со стенным объектом, чем представить последовательность процедур и структур данных, выполняющих одно и то же, поскольку это ближе к тому, как мы взаимодействуем с реальным миром.
* Потому что ничто не может «решить» сложность
Я думаю, что текущее основное определение ООП не является хорошим решением для управления сложностью.
Если вы вернетесь к его корням, я полагаю, что Алан Кей сильно повлиял на «шутку».
Поскольку Lisp не был испорчен массовым внедрением, ему, вероятно, удалось сохранить свои основные ценности. Поэтому я думаю, что рассмотрение того, как lisp решает эту проблему сложности, может дать нам некоторое представление, и мы можем использовать его в качестве основы для своего рода оценки того, насколько полезен ООП при работе со сложностью.
Если вы посмотрите на конец «Лекции 3a: Пример Хендерсона Эшера» SICP , Хэл Абельсон предлагает, чтобы сложность управлялась не разбиванием задачи на более мелкие подзадачи, а созданием слоев абстракции. На высшем уровне вы выражаете решение сложной проблемы в терминах решения нижнего уровня абстракции.
Я думаю, что ООП изначально задумывался как механизм для создания этих слоев абстракций.
К сожалению, в настоящее время ООП (ab) используется для написания спагетти-кода / структур.
Я приведу пример: многопользовательская игра FPS.
На высшем уровне игра работает, когда кучка игроков бегает по карте и стреляет друг в друга из оружия.
На следующем более низком уровне мы должны поговорить о картах, оружии и игроках. Возможно, мы можем говорить о них как о физических объектах, которые взаимодействуют в мире игры.
На следующем более низком уровне мы можем говорить о том, как объекты физически взаимодействуют (движение, столкновения и т. Д.).
И так далее.
Это означает (и я как бы цитирую SICP ..), что на каждом уровне мы решаем не только конкретную конкретную проблему, но и класс проблем, которые как бы попадают в окрестности проблемы, которую мы » пытаемся решить. Поэтому, если в описании проблемы есть небольшие изменения, это, скорее всего, потребует лишь небольших изменений в решении.
Таким образом, разумный способ использования ООП состоит в том, чтобы создавать слои абстракций, на каждом уровне абстракции вы решаете проблему, используя «объекты» с уровня, который находится непосредственно ниже.
Вот цитата, которую я цитировал из лекции: http://www.youtube.com/watch?v=CYtrfncMqHQ
Как обычно, я не согласен со всеми. ООП не только предоставляет вам инструменты для управления сложностью, но и создает огромную сложность, потому что это неадекватная и математически поддельная парадигма. Это не смущает программистов, пытающихся моделировать вещи с ООП, которые нельзя смоделировать с помощью ООП.
На мой взгляд, основная работа здесь - это конструирование объектно-ориентированного программного обеспечения Мейера. В нем подробно описан ряд требований, в том числе одно, которое я считаю крайне важным: принцип Open-Closed. Это говорит о том, что вещь должна быть открыта для расширения, но закрыта для использования одновременно.
Мейер начинает выводить объектную ориентацию из этих требований, воплощенных в Eiffel. Инкапсуляция обеспечивает закрытие, открытость наследования, и упомянутая «вещь» - это класс.
Я считаю эту работу хорошей наукой, потому что Мейер явно ошибался, и из-за качества его работы можно точно определить ошибку и исправить ее.
Ошибка делает класс или тип модульной единицей. Это неправильно и доказуемо так. Даже Мейер осознал проблему (называемую проблемой ковариации), что ООП не может обрабатывать отношения арности выше единицы (то есть ООП отлично работает для свойств, но не работает на бинарных отношениях). В Eiffel эта проблема привела к несостоятельности системы типов!
Решение вполне понятно. Единица модульности должна быть больше, чем один тип. Он должен состоять из нескольких типов и методов, связанных с ними.
Неудивительно, что эта модель абстракции опирается на математическую теорию абстракции, а именно на теорию категорий: типы - это объекты категории, а методы (функции) - стрелки.
С помощью этой модели представления нескольких типов известны набору функций. Представление скрыто от общественности, так что это инкапсуляция, но мы используем модули, а не классы.
Стандартный мета-язык (SML) и Ocaml основаны непосредственно на этой модели. Ocaml также имеет классы и ООП: это не бесполезно, потому что ООП дает вам диспетчеризацию свойств, то есть динамическое связывание. Однако большинство проблем реального мира связаны с отношениями, и неудивительно, что в Окамле классы не так часто используются.
Неудивительно, что наследование практически не используется в стандартной библиотеке шаблонов C ++.
Простой факт в том, что ООП не дает вам правильных инструментов для управления сложностью, он даже не дает вам инструментов для решения действительно простых задач, вместо этого он ввел в заблуждение и запутал два поколения программистов. ООП - это не самая злая и плохая вещь, которая случилась с программированием с тех пор, как С, Фортран и Кобол начали уставать.
У объектно-ориентированного программирования есть корни, которые можно проследить до 1960-х годов. Поскольку аппаратное и программное обеспечение становится все более сложным, управляемость часто становится проблемой. Исследователи изучили способы поддержания качества программного обеспечения и разработали объектно-ориентированное программирование, частично для решения общих проблем, уделяя особое внимание дискретным, многократно используемым элементам логики программирования.
Таким образом, объектно-ориентированная программа может рассматриваться как совокупность взаимодействующих объектов, в отличие от обычной модели, в которой программа рассматривается как список задач (подпрограмм), которые необходимо выполнить. В ООП каждый объект способен принимать сообщения, обрабатывать данные и отправлять сообщения другим объектам. Каждый объект можно рассматривать как независимую «машину» с определенной ролью или ответственностью. Действия (или «методы») над этими объектами тесно связаны с самим объектом.
http://en.wikipedia.org/wiki/Object-oriented_programming
Такое разделение интересов, наряду с другими особенностями объектной ориентации, такими как полиморфизм, наследование, передача сообщений, развязка и инкапсуляция, обеспечивают логическую и концептуальную основу, с помощью которой можно эффективно управлять сложностью больших программ.
Существует много видов сложности при разработке программного обеспечения. На уровне программирования ООП стремится решать сложность, используя объекты и классы для моделирования проблемной области. Хорошо известный гуру сказал, что решение проблемы - это просто представление проблемы, так что решением является само представление. Следовательно, с помощью абстракции с использованием классов, инкапсуляции с использованием модификаторов и методов доступа, наследования для определения отношений и повторного использования, композиции для установления отношений и сотрудничества между классами, полиморфизма как средства, упрощающего определение различных поведений в похожих объектах, можно управлять сложностью.
Есть и другие способы управления сложностью программного обеспечения, например, логическое (Prolog) и функциональное (Haskell) программирование.
На уровне выше, чем программирование, нам нужны шаблоны проектирования и принципы для управления ООП. Следовательно, ООП управляет сложностью на низком (кодирующем) уровне, в то время как эти методологии, такие как Шаблоны проектирования и Принципы, направляют разработку решения на более высокий (системный и прикладной) уровень и делают сложность разработки и обработки программного обеспечения более управляемой.
Чтобы ответить на ваш вопрос, да, ООП - это всего лишь решение для обработки сложности среди многих других решений. Это решение на низком уровне. Нам нужны шаблоны и принципы проектирования, чтобы направлять ООП на более высокий уровень.
Объектно-ориентированное программирование управляет существенной и необязательной сложностью, но также не уменьшает ее.
Я предпочитаю определение, данное Эриком Стивеном Рэймондом в «Искусстве программирования на Unix» , потому что оно разграничивает существенную, необязательную и случайную сложность. http://www.faqs.org/docs/artu/ch13s01.html#id2964646
ООП ничего не делает для существенной или дополнительной сложности, они являются функцией требований программы. Это может повлиять на случайную сложность, так как иногда вы можете создать более элегантный дизайн с помощью ООП. Однако иногда дизайн хуже при использовании ООП.
Сложные проблемы не могут быть оказаны проще с помощью технологии, они могут быть только удалось с помощью технологии.
ООП - это технология, концепция и способ решения проблемы.
ООП дает вам инструменты для реализации проекта, которые могут упростить управление сложностью, но вы также можете легко иметь плохой дизайн, который увеличивает вашу сложность. Другими словами, если не использовать должным образом, вы можете столкнуться с технологической сложностью в своих задачах.
Имейте в виду, что есть много других аспектов, которые будут определять, насколько успешным будет ваш проект (например, стиль управления проектом, определение проблемы, управление изменениями и т. Д.). Используемая вами технология имеет отношение только к тому, насколько она поможет вам справиться с проблемой.
В конце концов, объектно-ориентированное программирование не может быть решением проблемы сложности; это просто инструмент для управления им. (при правильном использовании)
Ориентация на объект (как обычно используется) является полезным инструментом во многих случаях, но не является достаточным решением для сложности.
В частности, это часто добавляет много «дополнительной сложности ». Примерами являются сложность, связанная с наследованием реализации, необходимость предоставления большого количества «стандартных функциональных возможностей» suach as equals (), hashCode () и т. Д. Хорошая презентация Стюарта Хэллоуэя на эту тему: « Простота не легкая »
Объекты в большинстве языков также имеют тенденцию инкапсулировать множество изменяемых состояний, что в параллельном мире все больше начинает казаться плохим дизайнерским решением. Снова интересное видео от Rich Hickey рассказывает о различии между идентичностью объекта и состоянием, а также о том, как может быть ошибкой объединять их.
Объектно-ориентированное программирование - это способ представления проблемы, ни больше, ни меньше. Он сам по себе не менее сложен, чем любая другая парадигма программирования. Хорошо спроектированная система ООП управляет и уменьшает сложность, но также очень легко спроектировать систему, которая намного сложнее, чем необходимо, и мешает всему.
Как часто говорят в C ++, ООП дает вам достаточно веревки, чтобы повеситься.
Я думаю, ДА , просто потому, что он позволяет вам разделить сложность на маленькие самодостаточные «строительные блоки», которые скрывают детали, а затем использовать их для создания необходимой вам функциональности, шаг за шагом, слой за слоем.
Разделяй и властвуй.
ООП - это попытка найти решение.
Лучший способ управлять сложностью - создавать абстракции. Если я смогу превратить свои данные в полезные коллекции с узнаваемыми функциями, которые работают с этими коллекциями, я могу начать думать о коллекциях как о «отдельных вещах». Это основа для классов и методов. В этом отношении, правильно спроектированный ООП может помочь управлять сложностью.
Где-то по пути кто-то решил, что мы могли бы использовать ООП, чтобы помочь решить проблему повторного использования кода. Я имею в виду, зачем изобретать велосипед? Если кто-то еще проделал большую часть работы по решению этой проблемы, используйте то, что он сделал, добавьте настройки, которые требуются вашему конкретному проекту, и вуаля! Вы создали мощное, сложное приложение с относительно небольшой работой с вашей стороны. ОО программисты могут быть очень продуктивными программистами.
Конечным результатом является то, что современные программисты OO в конечном итоге становятся «учениками колдуна», где они связывают кучу больших, громоздких библиотек с помощью нескольких строк «клея» и получают что-то, что работает. Сорта. Своего рода. Большую часть времени. Есть ли потенциальные побочные эффекты от использования этой библиотеки с этой? Может быть. Но у кого есть время, чтобы действительно покопаться в коде, содержащемся в этих библиотеках? Особенно, когда библиотеки развиваются. В результате мы получаем раздутые приложения, где программисту нужно было несколько классов и методов из этой библиотеки, но приложение должно нести вес всех ДРУГИХ вещей, которые им не нужны.
Конечным результатом является то, что вы получаете гораздо больше сложности, чем вам нужно.
Еще один механизм борьбы со сложностью, который вы хотите разделить функциональность. Вы хотите, чтобы все ваши функции доступа к данным в одном месте. Вы хотите, чтобы все функции вашего пользовательского интерфейса были в одном месте. Вы хотите, чтобы все ваши контроллеры в одном месте. Таким образом, вы создаете разные классы, которые управляют различными частями функциональности. Все идет нормально. И это масштабируется до некоторой степени; ваши разработчики, обладающие навыками доступа к данным, могут писать эти классы, ваши пользователи с пользовательским интерфейсом могут писать классы с пользовательским интерфейсом и т. д. Все хорошо.
Пока вы не должны поддерживать что-то написанное кем-то другим.
Да, приятно знать, что все функции доступа к данным находятся здесь. Но как их называть?
Этот метод вызывает этот метод в этом классе. Но когда я смотрю на определение класса, нет метода с таким именем. О, это наследуется от чего-то еще на один или два уровня в цепочке наследования. Подожди минуту; этот класс реализовал интерфейс? Сколько разных классов реализуют этот интерфейс? И мы используем какую-то сложную систему времени выполнения (я смотрю на тебя, Spring), чтобы «соединить» экземпляры классов во время выполнения? Где можно использовать ЛЮБОЙ класс, реализующий этот интерфейс?
В результате вы получаете множество маленьких, дискретных методов, которые делают точные вещи. Но этот называет его одним в другом классе. Который называет это один в другом классе. Который называет это один в другом классе. Который называет это, в дополнительном классе. Который возвращает результат определенного типа. На котором вы должны вызвать метод, чтобы сделать определенную вещь. Который возвращает результат другого типа. И т.п.
Для этого есть термин: код спагетти.
В итоге получается очень сложная система, необходимая только для написания кода. Следовательно IDE, такие как Visual Studio, Eclipse и NetBeans. Все из которых имеют значительную кривую обучения. Действительно, многие из них могут инкапсулировать / объединять несколько инструментов, разработанных разными группами, каждая из которых имеет свои собственные кривые обучения.
Это управляет сложностью?
Отладка кода в два раза сложнее, чем его написание. Удачи в отладке некоторых из этих вещей. Особенно, если он использует несколько библиотек, «соединенных вместе» во время выполнения с использованием какой-либо системы внедрения зависимостей.
В итоге: ООП предоставляет то, что выглядит как многообещающий инструмент, помогающий управлять сложностью. Реальность такова, что полученный код имеет тенденцию быть ужасно раздутым (потому что вы не можете извлечь только те части, которые вам нужны, из всех этих связанных библиотек), и вам нужны сложные инструменты для навигации по коду. Это быстро становится кошмаром обслуживания.
ИМХО, это чистый убыток; это добавляет больше сложности, чем устраняет. Это позволяет вам делать вещи, которые были бы чрезвычайно сложными, возможно, даже невозможными, без него. Но любой крупный проект быстро превращается в неразрешимый беспорядок.
Если вы уже знаете, как это работает, и помните об этом, у вас может быть шанс сохранить его.
Не забывайте применять закон Иглсона: любой ваш собственный кодекс, который вы не просматривали в течение шести месяцев, с таким же успехом может быть написан кем-то другим.
До некоторой степени...
Почему? Потому что это облегчает очень логичную модульность. По крайней мере, по сравнению с процедурным программированием, где слишком заманчиво просто написать огромную кучу кода для спагетти.
Причина, по которой объектно-ориентированное программирование помогает нам справляться со сложностью, заключается в том, что оно заставляет нас писать код определенным образом, а не множеством способов. Программирование, ориентированное на задачи, гораздо более интуитивно понятно, поэтому программирование начиналось именно так. Объектная ориентация требует обучения и практики, чтобы понять и эффективно использовать, но, ограничивая программирование определенным путем, она позволяет обученным эффективно поддерживать написанный код.
Это не более логичный или реальный мир, чем любой другой метод, это просто способ сосредоточить наше решение проблем с помощью аналогичных линз. Многие технические специальности используют парадигму неинтуитивной жесткой методологии для решения сложных задач.
Третий метод управления сложностью - это функциональное программирование, и, возможно, в будущем появятся и другие новые методы.
я думаю, что это скорее решение для удобства обслуживания, потому что, как программист, вы должны размещать методы там, где у вас есть данные, создавая, таким образом, объектную модель вашего приложения.
да, это также решение для сложности, предоставляя модель для вас, чтобы «увидеть» ваш код естественным образом, как объекты, которые имеют свойства и возможные действия