Имеет ли процедурное программирование какие-либо преимущества перед ООП?

[Edit:] ранее я задал этот вопрос как, возможно, плохо сформулированный вопрос о том, когда использовать ООП, а когда использовать процедурное программирование-некоторые ответы подразумевали, что я просил помочь понять ООП. Напротив, Я много использовал ООП, но хочу знать, когда использовать процедурный подход. Судя по ответам, я считаю, что существует довольно сильный консенсус в отношении того, что ООП обычно является лучшим всесторонним подходом, но что процедурный язык должен использоваться, если архитектура ООП будет не предоставлять никаких преимуществ повторного использования в долгосрочной перспективе.

однако мой опыт в качестве программиста Java был иным. Я видел массивную Java-программу, которую я спроектировал, переписал гуру Perl в 1/10 кода, который я написал, и, казалось бы, так же надежен, как моя модель совершенства ООП. Моя архитектура увидела значительное количество повторного использования, и все же более сжатый процедурный подход дал превосходное решение.

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

может ли кто-нибудь предложить примеры того, как будут выглядеть эти сценарии?

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

22 ответов


Я бы предложил использовать самый краткий, основанный на стандартах подход, который вы можете найти для любой данной проблемы. Ваш коллега, который использовал Perl, продемонстрировал, что хороший разработчик, хорошо знающий конкретный инструмент, может достичь больших результатов независимо от методологии. Вместо того, чтобы сравнивать ваши проекты Java-versus-Perl в качестве хорошего примера процедурных дебатов против ООП, я хотел бы увидеть противостояние между Perl и аналогичным кратким языком, таким как Ruby, который также имеет преимущества объектной ориентации. Вот это я и хотел бы увидеть. Я предполагаю, что Ruby выйдет на первое место, но я не заинтересован в провоцировании языковой войны-я имею в виду только то, что вы выбираете подходящий инструмент для работы - любой подход может выполнить задачу наиболее эффективным и надежным способом. Java может быть надежным из-за его объектной ориентации, но как вы и ваш коллега и многие другие, которые преобразуются в динамические языки, такие как Ruby и Python в наши дни есть гораздо более эффективные решения, будь то процедурные или ООП.


Мне нравится стекло' правила 3, Когда дело доходит до повторного использования (что, похоже, вас интересует).

1) в 3 раза сложнее создание повторно используемых компонентов как один использовать компоненты
2) многоразовый компонент должен быть опробован в трех различные приложения, прежде чем это будет быть достаточно общим, чтобы принять библиотека повторного использования

из этого я думаю, что вы можете экстраполировать эти следствия

a) если у вас нет бюджета в 3 раза больше времени, чем тебе потребуется. чтобы создать один компонент use, возможно вы должны воздержаться от повторного использования. (Предполагая Сложность = Время)
Б) если у вас нет 3 мест, где вы бы использование компонента вы строите, может, тебе стоит воздержаться от строительства? повторно используемые компоненты.

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


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


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

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


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

(ссылка:http://en.wikipedia.org/wiki/Object-oriented_programming):

ряд известных исследователей и программистов критиковали ООП. Вот неполный список:

  • лука Карделли написал статью под названием "Плохие инженерные свойства объектно-ориентированных языков".

  • Ричард Столлман написал в 1995 году", добавив ООП для Emacs это явно не улучшение; я использовал ООП при работе с оконными системами Lisp Machine, и я не согласен с обычным мнением, что это превосходный способ программирования."

  • исследование Potok et al. не выявил существенных различий в производительности между ООП и процедурными подходами.

  • Кристофер дата Джей заявил, что критическое сравнение с другими технологиями ООП, реляционных, в частности, затруднено из-за отсутствия согласованное и строгое определение ООП. Предложена теоретическая основа ООП, которая использует ООП как своего рода настраиваемую систему типов для поддержки РСУБД.

  • Александр Степанов предположил, что ООП предоставляет математически ограниченную точку зрения и назвал ее "почти такой же мистификацией, как искусственный интеллект" (возможно, ссылаясь на проекты искусственного интеллекта и маркетинг 1980-х годов, которые иногда рассматриваются как чрезмерно усердные в ретроспектива.)

  • Пол Грэм предположил, что цель ООП-действовать как "механизм выпаса", который удерживает посредственных программистов в посредственных Организациях от "нанесения слишком большого ущерба". Это за счет замедления продуктивных программистов, которые знают, как использовать более мощные и более компактные методы.

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

  • Ричард Мэнсфилд, автор и бывший редактор COMPUTE! журнал утверждает ,что"как и бесчисленные другие интеллектуальные причуды на протяжении многих лет ("актуальность", коммунизм," модернизм " и т. д.-История завалена ими), ОП будет с нами, пока в конечном итоге реальность не утвердится. Но учитывая, как ООП в настоящее время пронизывает как университеты, так и рабочие места, ООП вполне может оказаться длительным заблуждением. Целые поколения программистов-идеологов продолжают покидать академию, посвятив себя ООП и ничему, кроме ООП, до конца своих дней."а также цитируется как говорящий:" ООП-это написание программы, то, что происходит через безопасность аэропорта, - это полет".


Я думаю, что сухой принцип (не повторяйтесь) в сочетании с немного гибким-хороший подход. Создайте свою программу постепенно, начиная с простейшей вещи, которая работает, затем добавьте функции один за другим и перефакторируйте свой код по мере необходимости.

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

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

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

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

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


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


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

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

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

Если вы используете указатели, вы постоянно прыгаете в памяти, и ваш процессор должен перезагружать кэш каждый раз. Код ООП полон указателей: каждый объект хранится по его адресу памяти. Вы звоните new везде, которые распространяют ваши объекты по всей памяти, что делает оптимизацию кэша почти невозможной (если у вас нет распределителя или сборщика мусора, который держит вещи близко друг к другу). Вы вызываете обратные вызовы и виртуальные функции. Компилятор обычно не удается встроить виртуальные функции, а вызов виртуальной функции относительно медленный (перейти к VMT, получить адрес виртуальной функции, вызвать ее [это включает в себя нажатие параметров и локальных переменных в стеке, выполнение функции, а затем все]). Это имеет большое значение, когда у вас есть цикл от 0 до 1000000 25 раз в секунду. Используя процедурный стиль, нет виртуальной функции, и optimizar может встроить все в эти горячие циклы.


эти два понятия не являются взаимоисключающими, очень вероятно, что вы будете использовать PP в сочетании с ООП, я не вижу, как их разделить.


Я думаю, что пригодность ООП зависит больше от предметной области, в которой вы работаете, чем от размера проекта. Существуют некоторые предметные области (САПР, имитационное моделирование и др.), где ООП карты, естественно, к концепции. Однако есть много других областей, где сопоставление заканчивается неуклюжим и несообразным. Многие люди, использующие ООП для всего, похоже, тратят много времени, пытаясь вбить квадратные колышки в круглые отверстия.

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


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

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

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

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

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

помните, что, как и многие другие объекты идей программирования, являются инструментом. Вам придется использовать ваше лучшее суждение о том, насколько хорошо они работают для вашего проекта. Для моего программного обеспечения CAD/CAM для металлорежущих станков есть важные математические функции, которые не помещаются в объекты, потому что нет причин для них быть в объектах. Вместо этого они предоставляются из библиотеки и используются объектом, который в них нуждается. Тогда есть некоторые математические функции, которые были сделаны объектно-ориентированными, поскольку их структура естественно приводит к этой настройке. (Взяв список пунктов и преобразовав его в несколько разных виды режущих дорожек). Снова используйте свое лучшее суждение.


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

одна из моих эвристик основана на том, как "состояние" ситуации. Если процедура загрязняет пространство имен или может повлиять на глобальное состояние (плохо или непредсказуемо), то инкапсуляция этой функции в объект или класс, вероятно, разумна.


процедурные программы могут быть проще для определенного типа программы. Как правило, это короткие скриптоподобные программы.


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

Если все работает и не будет изменено, кого волнует, ОО это или нет? Это работает. Дело сделано. Если вы можете добраться до этого момента быстрее писать процедурно, то, возможно, это путь ходить.

но вы уверены, что это не будет изменено? Предположим, вы, скорее всего, добавите новые типы структур данных. Каждый раз, когда вы добавляете новый тип структуры данных, с которым вы хотите, чтобы эти функции работали, вы должны убедиться, что нашли и изменили каждую из этих функций, чтобы добавить новый случай "еще Если", чтобы проверить и добавить поведение, которое вы хотите повлиять на новый тип структуры данных. Боль от этого увеличивается по мере того, как программа становится все больше и сложнее. Чем больше вероятно, это, тем лучше для вас будет идти с подходом OO.

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


Я считаю, что Грейди Буч сказал однажды, что вы действительно начинаете получать большую пользу от ООП в 10000+ строк кода.

тем не менее, я всегда буду идти OO-way. Даже на 200 строк. Это превосходный подход в долгосрочной перспективе, и накладные расходы-это просто переоцененное оправдание. Все большое начинается с малого.


Я всегда начинаю проектирование сверху вниз, и в верхних частях гораздо проще думать в терминах ООП. Но когда приходит время кодировать некоторые небольшие конкретные части, вы гораздо более продуктивны с помощью программирования только процедур. ООП хорош в проектировании и формировании проекта, так что парадигма divide-et-impera может быть применена. Но вы не можете применять его во всех аспектах своего кода, как это было в религии:)


Если вы" думаете ОО", когда программируете, то я не уверен, что имеет смысл спрашивать: "когда я должен вернуться к процедурному программированию?"Это эквивалентно тому, чтобы спросить Java-программистов, что они не могут сделать, потому что java требует классов. (Языки Ditto .NET).

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


хочешь в джунгли?


большинство исследований обнаружили, что код OO является более кратким, чем процессуальный код. Если вы посмотрите на проекты, которые переписали существующий код C на C++ (не то, что я обязательно советую , кстати), вы обычно видите сокращение размера кода между 50 и 75 процентами.

Итак, ответ - всегда используйте OO!


ИМХО, долгосрочные преимущества ООП перевешивают время, сэкономленное в краткосрочной перспективе.

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


вы можете написать плохое программное обеспечение в обеих концепциях. Тем не менее, сложное программное обеспечение намного проще писать, понимать и поддерживать на языках OO, чем в процедурных. Я написал очень сложные ERP-приложения на процедурном языке (Oracle PL / SQL), а затем переключился на ООП (C#). Это был и есть глоток свежего воздуха.


мои два цента...

преимущества процедурного программирования

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

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