Насколько я могу судить, несмотря на бесчисленные миллионы или миллиарды, потраченные на обучение, языки и инструменты ООП, ООП не повысила производительность труда разработчиков или надежность программного обеспечения, а также не снизила затраты на разработку. Мало кто использует ООП в каком-либо строгом смысле (мало кто придерживается или понимает такие принципы, как LSP); похоже, что подходы, применяемые к моделированию проблемных областей, мало единообразны или непротиворечивы. Слишком часто класс используется просто для его синтаксического сахара; он помещает функции для типа записи в их собственное маленькое пространство имен.
Я написал большое количество кода для самых разных приложений. Хотя были места, где истинно замещаемый подтип играл важную роль в приложении, они были довольно исключительными. В общем, хотя много говорят на словах о «повторном использовании», реальность такова, что если кусок кода не выполняет именно то , что вы хотите, то очень мало рентабельного «повторного использования». Очень трудно спроектировать классы, чтобы их можно было правильно расширять , поэтому стоимость расширения обычно настолько велика, что «повторное использование» просто не стоит.
Во многих отношениях это меня не удивляет. Реальный мир - это не «ОО», и идея ОО, подразумеваемая в ОО - что мы можем моделировать вещи с помощью некоторой классовой таксономии - кажется мне очень фундаментальной ошибкой (я могу сидеть на столе, пне, капоте автомобиля кто-то на коленях - но не один из тех - стул). Даже если мы перейдем к более абстрактным областям, ОО-моделирование часто бывает сложным, нелогичным и, в конечном счете, бесполезным (рассмотрим классические примеры кругов / эллипсов или квадратов / прямоугольников).
Так чего мне здесь не хватает? Где ценность ООП, и почему все время и деньги не смогли сделать программное обеспечение лучше?
Нет эмпирических данных, свидетельствующих о том, что объектная ориентация является более естественным способом для людей думать о мире. Есть некоторые работы в области психологии программирования, которые показывают, что ОО не является более подходящим, чем другие подходы.
Объектно-ориентированные представления не кажутся универсально более удобными или менее пригодными для использования.
Недостаточно просто принять методы ОО и требовать от разработчиков использования таких методов, потому что это может оказать негативное влияние на производительность разработчика, а также на качество разрабатываемых систем.
Который из "О юзабилити OO представлений" из Communications of ACM Oct. 2000. В статьях в основном сравнивается OO с процессно-ориентированным подходом. Существует множество исследований того, как «думают» люди, работающие с методом ОО (Int. J. of Human-Computer Studies 2001, выпуск 54, или Human-Computer Interaction 1995, том 10, имеет целую тему об исследованиях ОО), и из того, что я прочитал, ничто не указывает на некоторую естественность ОО-подхода, который делает его более подходящим, чем более традиционный процедурный подход.
На грани религиозного, но я бы сказал, что вы рисуете слишком мрачную картину состояния современного ООП. Я бы сказал, что на самом деле это снизило затраты, сделало крупные программные проекты управляемыми и так далее. Это не означает, что это решило фундаментальную проблему программного беспорядка, и это не означает, что средний разработчик - эксперт ООП. Но модульность функций в объектные компоненты, безусловно, уменьшила количество спагетти-кода в мире.
Я могу вспомнить десятки библиотек, которые прекрасно подходят для повторного использования и которые сэкономили время и деньги, которые никогда не могут быть рассчитаны.
Но в той степени, в которой ООП было пустой тратой времени, я бы сказал, что это связано с отсутствием подготовки программистов, что усугубляется крутой кривой обучения изучению отображения ООП для конкретного языка. Некоторые люди "получают" ООП, а другие никогда не будут.
Реальный мир - это не «ОО», и идея ОО, заключающаяся в том, что мы можем моделировать вещи с помощью некоторой классовой таксономии, кажется мне очень фундаментальной ошибкой.
В то время как это верно и было замечено другими людьми (возьмите Степанова, изобретателя STL), остальное - ерунда. ООП может быть ошибочным, и это, конечно, не серебряная пуля, но это делает крупномасштабные приложения намного проще, потому что это отличный способ уменьшить зависимости. Конечно, это верно только для «хорошего» дизайна ООП. Небрежный дизайн не даст никакого преимущества. Но хороший, развязанный дизайн может быть очень хорошо смоделирован с использованием ООП и не очень хорошо с использованием других методов.
Существуют гораздо лучшие, более универсальные модели ( на ум приходит модель типа Haskell ), но они также часто являются более сложными и / или трудными для эффективного внедрения. ООП - хороший компромисс между крайностями.
Я писал код ОО последние 9 лет или около того. Кроме использования сообщений, мне трудно представить другой подход. Основное преимущество, которое я вижу, полностью соответствует тому, что сказал CodingTheWheel: модульность. Естественно, OO побуждает меня создавать свои приложения из модульных компонентов, которые имеют чистые интерфейсы и четкие обязанности (то есть слабосвязанный, очень сплоченный код с четким разделением задач).
Я думаю, что OO ломается, когда люди создают глубоко вложенные классовые иерархии. Это может привести к сложности. Однако выделение общей финктальности в базовый класс, а затем повторное использование этого в других классах-потомках - очень элегантная вещь, ИМХО!
@CodingTheWheel
Но в той степени, в которой ООП было пустой тратой времени, я бы сказал, что это связано с отсутствием подготовки программистов, что усугубляется крутой кривой обучения изучению отображения ООП для конкретного языка. Некоторые люди "получают" ООП, а другие никогда не будут.
Я не знаю, если это действительно удивительно, хотя. Я думаю, что технически обоснованные подходы (LSP - очевидная вещь) затрудняют использование , но если мы не используем такие подходы, это делает код хрупким и нерасширяемым в любом случае (потому что мы больше не можем рассуждать об этом). И я думаю, что противоречивые результаты, к которым нас приводит ООП, делают неудивительным, что люди не поднимают это.
Что еще более важно, поскольку нормальным людям программное обеспечение уже в принципе слишком сложно для надежного и точного написания, должны ли мы действительно превозносить технику, которая последовательно преподается плохо и кажется трудной для изучения? Если выгоды были четкими, то это может быть стоит настойчивая, несмотря на трудности, но это, кажется, не так.
@Sean
Однако выделение общей финктальности в базовый класс, а затем повторное использование этого в других классах-потомках - очень элегантная вещь, ИМХО!
Но «процедурные» разработчики делали это десятилетиями. Синтаксис и терминология могут отличаться, но эффект идентичен. ООП - это больше, чем «повторное использование общей функциональности в базовом классе», и я мог бы даже пойти так далеко, чтобы сказать, что это вообще трудно описать как ООП; вызов одной и той же функции из разных битов кода - такая же старая техника, как и сама подпроцедура.
@Konrad
ООП может быть ошибочным, и это, конечно, не серебряная пуля, но это делает крупномасштабные приложения намного проще, потому что это отличный способ уменьшить зависимости
Это догма. Я не вижу, что делает ООП значительно лучше в этом отношении, чем процедурное программирование старого. Всякий раз, когда я делаю вызов процедуры, я изолирую себя от особенностей реализации.
«Даже если нет фактической [информационной архитектуры], это не значит, что мы не испытываем и не воспринимаем ее как таковую. Дзен-буддисты говорят, что нет фактического« я », но они по-прежнему называют своих детей», - Эндрю Хинтон.
Это парадигма программирования. Созданная для того, чтобы нам, простым смертным, было проще разбить проблему на более мелкие, работоспособные части ...
Если вы не находите это полезным. Не используйте его, не платите за обучение и будьте счастливы.
Я, с другой стороны, считаю это полезным, поэтому я буду :)
Относительно прямого процедурного программирования, первый фундаментальный принцип ООП - это понятие сокрытия и инкапсуляции информации. Эта идея приводит к понятию класса, который отделяет интерфейс от реализации. Это чрезвычайно важные концепции и основа для создания основы, позволяющей думать о разработке программ по-другому и лучше (я думаю). Вы не можете спорить против этих свойств - здесь нет компромисса, и это всегда более чистый способ модулировать вещи.
Другие аспекты ООП, включая наследование и полиморфизм, также важны, но, как уже упоминали другие, они обычно используются чрезмерно. То есть: иногда люди используют наследование и / или полиморфизм, потому что они могут, а не потому, что они должны иметь. Они представляют собой мощные концепции и очень полезны, но их необходимо использовать с умом, а не автоматические выигрышные преимущества ООП.
Относительно повторного использования. Я согласен, что повторное использование перепродано для ООП. Это возможный побочный эффект хорошо определенных объектов, обычно более примитивных / универсальных классов, и является прямым результатом концепции инкапсуляции и сокрытия информации. Потенциально легче использовать повторно, потому что интерфейсы четко определенных классов просто более понятны и несколько самодокументированы.
@Джефф
Относительно прямого процедурного программирования, первый фундаментальный принцип ООП - это понятие сокрытия и инкапсуляции информации. Эта идея приводит к понятию класса, который отделяет интерфейс от реализации.
Который имеет более скрытую реализацию: iostreams C ++ или FILE * s C?
Я думаю, что использование непрозрачных объектов контекста (HANDLE в Win32, FILE * в C, чтобы назвать два хорошо известных примера - черт, HANDLE живут по другую сторону барьера режима ядра, и это действительно не получает гораздо более инкапсулированный, чем это) также встречается в процедурном коде; Я изо всех сил пытаюсь понять, как это что-то особенное для ООП.
Я полагаю, что это может быть отчасти из-за того, что я изо всех сил пытаюсь увидеть преимущества: части, которые явно хороши, не являются специфическими для ООП, тогда как части, которые являются специфическими для ООП, явно не хороши! (это не означает, что они обязательно плохие, скорее, я не видел доказательств того, что они широко применимы и неизменно полезны).
ООП имеет снижение затрат и повышение эффективности.
Когда я сделал переход с классического ASP / VBScript на C #, я заметил ОГРОМНОЕ увеличение производительности благодаря ООП.
Я думаю, что использование непрозрачных объектов контекста (HANDLE в Win32, FILE * в C, чтобы назвать два хорошо известных примера - черт, HANDLE живут по другую сторону барьера режима ядра, и это действительно не получает гораздо более инкапсулированный, чем это) также встречается в процедурном коде; Я изо всех сил пытаюсь понять, как это что-то особенное для ООП.
HANDLE
s (и остальная часть WinAPI) - ООП! C не очень хорошо поддерживает ООП, поэтому специального синтаксиса нет, но это не значит, что он не использует те же понятия. WinAPI во всех смыслах этого слова - объектно-ориентированная структура.
Видите, в этом и заключается проблема с каждым отдельным обсуждением, связанным с ООП или альтернативными методами: никто не знает точно об определении, все говорят о чем-то другом, и, следовательно, консенсус не может быть достигнут. Похоже, трата времени для меня.
РУЧКИ (и остальная часть WinAPI) - ООП!
Они все же? Они не наследуются, они, конечно, не заменяемы, им не хватает четко определенных классов ... Я думаю, что они далеки от "ООП".
РУЧКИ (и остальная часть WinAPI) - ООП!
Они все же? Они не наследуются, они, конечно, не заменяемы, им не хватает четко определенных классов ... Я думаю, что они далеки от "ООП".
Вы когда-нибудь создавали окно, используя WinAPI? Затем вы должны знать, что вы определяете class ( RegisterClass
), создаете экземпляр it ( CreateWindow
), вызываете виртуальные методы ( WndProc
) и методы базового класса ( DefWindowProc
) и так далее. WinAPI даже берет номенклатуру из ООП SmallTalk, вызывая методы «сообщения» (Window Messages).
Дескрипторы не могут быть наследуемыми, но есть final
в Java. Им не хватает класса, они являются заполнителем для класса: вот что означает слово «ручка». Глядя на такие архитектуры, как MFC или .NET WinForms, сразу видно, что, кроме синтаксиса, ничто не сильно отличается от WinAPI.
Слишком часто класс используется просто для его синтаксического сахара; он помещает функции для типа записи в их собственное маленькое пространство имен.
Да, я нахожу это слишком распространенным. Это не объектно-ориентированное программирование. Это объектно-ориентированное программирование и ориентированное на данные программирование. За 10 лет работы с OO Languages я вижу людей, которые в основном занимаются объектно-ориентированным программированием. OBP ломается очень быстро IMHO, так как вы получаете худшее из двух слов: 1) процедурное программирование без соблюдения проверенной методологии структурированного программирования и 2) ООП без соблюдения проверенной методологии ООП.
ООП сделано правильно, это прекрасная вещь. Это делает очень сложные проблемы легкими для решения, и для непосвященных (не пытающихся казаться напыщенными там), это может почти казаться волшебством. При этом ООП является лишь одним из инструментов в наборе методологий программирования. Это не конец всей методологии. Это просто хорошо подходит для больших бизнес-приложений.
Большинство разработчиков, которые работают на языках ООП, используют примеры ООП, сделанные прямо в рамках и типах, которые они используют изо дня в день, но они просто не знают об этом. Вот несколько очень простых примеров: ADO.NET, Hibernate / NHibernate, Logging Frameworks, различные типы языковых коллекций, стек ASP.NET, стек JSP и т. Д. ... Все это в значительной степени зависит от ООП в их кодовых базах.
Вы когда-нибудь создавали окно, используя WinAPI?
Больше раз, чем я хочу вспомнить.
Затем вы должны знать, что вы определяете класс (RegisterClass), создаете его экземпляр (CreateWindow), вызываете виртуальные методы (WndProc) и методы базового класса (DefWindowProc) и так далее. WinAPI даже берет номенклатуру из ООП SmallTalk, вызывая методы «сообщения» (Window Messages).
Тогда вы также узнаете, что он не отправляет сообщения самостоятельно, что является большой зияющей пустотой. У этого также есть дерьмовый подкласс.
Дескрипторы не могут быть наследуемыми, но в Java есть финал. Им не хватает класса, они являются заполнителем для класса: вот что означает слово «ручка». Глядя на такие архитектуры, как MFC или .NET WinForms, сразу видно, что, кроме синтаксиса, ничто не сильно отличается от WinAPI.
Они не наследуются ни по интерфейсу, ни по реализации, минимально заменяемы, и они существенно не отличаются от того, что процедурные кодеры делали с незапамятных времен.
Это действительно так? Лучшие биты ООП - это просто ... традиционный процедурный код? Это большое дело?
ООП - это не создание повторно используемых классов, а создание классов Usable.
В моем опыте анализа кода и разработки проектов, через который я прошел, ценность ООП не полностью осознана, потому что многие разработчики должным образом не концептуализировали объектно-ориентированную модель в своих умах. Таким образом, они не программируют с ОО-дизайном, очень часто продолжают писать процедурный код сверху вниз, что делает классы довольно плоским . (если вы можете даже назвать это "дизайн" в первую очередь)
Довольно страшно наблюдать, как маленькие коллеги знают о том, что такое абстрактный класс или интерфейс, не говоря уже о том, чтобы правильно спроектировать иерархию наследования в соответствии с потребностями бизнеса.
Однако, когда присутствует хороший дизайн ОО, просто радостно читать код и видеть, что код естественным образом превращается в интуитивные компоненты / классы. Я всегда воспринимал системную архитектуру и дизайн как проектирование различных отделов и рабочих мест в компании - все это для того, чтобы выполнить определенную часть работы в общей схеме вещей, испуская синергию, необходимую для продвижения организации / системы вперед.
Это, к сожалению , довольно редко . Как и соотношение красиво сконструированных и ужасно сконструированных физических объектов в мире, то же самое можно сказать о разработке программного обеспечения и проектировании. Наличие хороших инструментов в своем распоряжении не обязательно дает хорошие практики и результаты.
Может быть, капот, колени или дерево не стул, но все они ISittable.
Может быть, капот, колени или дерево не стул, но все они ISittable.
Да, но только ex post facto. Они ISittable, потому что кто-то сел на них.
Я знаю, что ООП полезен почти исключительно на синтаксической основе (инкапсуляция, перегрузка операторов, проверка типов). Что касается преимуществ ООП ... я не знаю. Я не думаю, что это хуже, чем процедурные вещи.
С другой стороны, мой лектор ООП сказал, что ООП важен, потому что в противном случае «код имел бы слишком много циклов». Да уж. Иногда удручает, что я плачу 500 долларов за бумагу. :(
Я полностью согласен с ответом Джеффа из InSciTek , просто добавлю следующие уточнения:
- Сокрытие информации и инкапсуляция: критически важны для любого поддерживаемого кода. Это можно сделать, проявляя осторожность на любом языке программирования, не требуя OO-функций, но это сделает ваш код слегка OO-подобным.
- Наследование: Существует одна важная прикладная область, для которой все эти ОО -типа являются своего рода и содержат- идеально подходят: графические пользовательские интерфейсы. Если вы попытаетесь создать графический интерфейс без поддержки языка OO, вы все равно будете создавать функции, подобные OO, и это будет сложнее и более подвержено ошибкам без поддержки языка. Поляна (недавно) и X11 Xt (исторически) например.
Использование OO-функций (особенно глубоко вложенных абстрактных иерархий), когда нет смысла, бессмысленно. Но для некоторых областей применения это действительно важно.
Повторное использование не должно быть целью ООП - или любой другой парадигмы в этом отношении.
Повторное использование является побочным эффектом хорошего дизайна и надлежащего уровня абстракции. Код достигает повторного использования, делая что-то полезное, но не настолько, чтобы сделать его негибким. Неважно, является ли код ОО или нет - мы повторно используем то, что работает, и нетривиально делать это самим. Это прагматизм.
Мысль об ОО как о новом способе повторного использования посредством наследования в корне ошибочна. Как вы заметили, нарушений LSP предостаточно. Вместо этого ОО должным образом рассматривается как метод управления сложностью проблемной области. Целью является ремонтопригодность системы с течением времени. Основным инструментом для достижения этого является отделение открытого интерфейса от частного внедрения. Это позволяет нам иметь правила типа «Это должно быть изменено только с помощью ...», применяемые компилятором, а не проверку кода.
Использование этого, я уверен, вы согласитесь, позволяет нам создавать и поддерживать чрезвычайно сложные системы. В этом есть большая ценность, и это не так просто сделать в других парадигмах.
Я считаю, что наиболее выгодным качеством ООП является скрытие / управление данными. Однако есть много примеров, когда ООП используется не по назначению, и я думаю, что именно здесь возникает путаница.
То, что вы можете превратить что-то в объект, не означает, что вы должны это делать. Однако, если это сделает ваш код более организованным / более простым для чтения, тогда вам определенно следует это сделать.
Отличный практический пример, где ООП очень полезен, - это класс «product» и объекты, которые я использую на нашем веб-сайте. Поскольку каждая страница является продуктом, а каждый продукт имеет ссылки на другие продукты, может возникнуть путаница в отношении того, к какому продукту относятся ваши данные. Является ли эта переменная "strURL" ссылкой на текущую страницу, домашнюю страницу или страницу статистики? Конечно, вы можете создать различные переменные, которые ссылаются на одну и ту же информацию, но proCurrentPage-> strURL гораздо проще понять (для разработчика).
Кроме того, прикрепление функций к этим страницам намного чище. Я могу сделать proCurrentPage-> CleanCache (); Вслед за proDisplayItem-> RenderPromo (); Если бы я просто вызвал эти функции и предположил, что текущие данные были доступны, кто знает, какое зло произойдет. Кроме того, если бы мне пришлось передать правильные переменные в эти функции, я бы вернулся к проблеме наличия всех видов переменных для различных продуктов, лежащих вокруг.
Вместо этого, используя объекты, все данные и функции моего продукта приятны, понятны и просты для понимания.
Однако. Большая проблема с ООП - это когда кто-то считает, что ВСЕ должно быть ООП. Это создает много проблем. У меня есть 88 таблиц в моей базе данных. У меня всего около 6 классов, и, может быть, мне нужно около 10. Мне определенно не нужно 88 классов. Большую часть времени прямой доступ к этим таблицам совершенно понятен в тех обстоятельствах, которые я им использую, и ООП фактически затруднит / утомителен, чтобы добраться до основной функциональности происходящего.
Я полагаю, что гибридная модель объектов полезна, а процедурная - практична и является наиболее эффективным методом кодирования. Обидно, что у нас есть все эти религиозные войны, когда люди выступают за использование одного метода за счет других. Они оба хороши, и у них обоих есть свое место. В большинстве случаев в обоих крупных проектах используются оба метода (в некоторых небольших проектах вам может понадобиться только один объект или несколько процедур).
Да, ООП не решил всех наших проблем, извините за это. Однако мы работаем над SOA, которая решит все эти проблемы.
«Реальный мир - это не« ОО »»
В самом деле? Мой мир полон объектов. Я использую один сейчас. Я думаю, что наличие программных «объектов» моделирует реальные объекты не так уж плохо.
ОО-проекты для концептуальных вещей (таких как Windows, не окна реального мира, а панели дисплея на мониторе моего компьютера) часто оставляют желать лучшего. Но для реальных вещей, таких как счета-фактуры, заказы на доставку, страховые претензии и тому подобное, я думаю, что эти вещи в реальном мире являются объектами. У меня на столе стопка, поэтому они должны быть настоящими.
Я думаю, что эти вещи реального мира являются объектами
Ты сделаешь?
Какие методы есть в счете? Ой, подожди. Он не может заплатить сам, он не может отправить себя, он не может сравнивать себя с товарами, которые поставщик фактически поставил. У него нет никаких методов вообще; это абсолютно инертно и не функционально. Это тип записи (структура, если хотите), а не объект.
Также и другие вещи, которые вы упоминаете.
То, что что-то реально, не делает его объектом в ОО-смысле этого слова. ОО-объекты - это своеобразная связь состояния и поведения, которая может действовать самостоятельно. Это не то, что в изобилии в реальном мире.
Для меня ценность ООП состоит в том, чтобы уменьшить область и отделить состояние от поведения. С меньшей областью код легче понять.
Это может быть сделано в большинстве языков, все, что необходимо для достижения этой цели, - это способ для государства делегировать вызов метода поведению и способ для поведения, чтобы далее делегировать вызов родительскому поведению.
Поскольку набор классов эффективно моделирует домен, магического метода не существует. Как пианино, мы должны практиковаться. ООП - это абстрактный инструмент, он может помочь вам создавать код более простым способом, но он не может думать и анализировать область вашего приложения для вас.
Что мне подходит, так это как можно дольше оставаться рядом с доменом, при этом избегая дублирования кода.
ООП хорошо подходит для программирования внутренних компьютерных структур, таких как «виджеты» GUI, где, например, SelectList и TextBox могут быть подтипами Item, которые имеют общие методы, такие как «перемещение» и «изменение размера».
Проблема в том, что 90% из нас работают в мире бизнеса, где мы работаем с такими бизнес-концепциями, как Счет, Сотрудник, Работа, Заказ. Они не очень хорошо подходят для ООП, потому что «объекты» более туманные, подверженные изменениям в соответствии с реинжинирингом бизнеса и так далее.
В худшем случае ОО с энтузиазмом применяется к базам данных, включая вопиющие «усовершенствования» ОО к базам данных SQL, которые по праву игнорируются, за исключением тех, кто использует базы данных, которые считают, что они должны быть правильным способом, потому что они новее.