Подтвердить что ты не робот

Недостаток ООП?

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

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

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

Я понимаю, что пример, который он дал, едва ли имел никакого смысла, но у меня было это сомнение -

Можем ли мы отключить иерархии классов динамично (я уверен в себе в Java это невозможно) в идеале объектно-ориентированный дизайн?

4b9b3361

Ответ 1

Я не совсем понимаю его пример.

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

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

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

Что касается вашего последнего вопроса "Можем ли мы отключить иерархии классов в идеальном объектно-ориентированном дизайне?", я не уверен, что вы имеете в виду здесь. Если вы спрашиваете об изменении иерархии во время выполнения и делаете это так, чтобы отношение подтипирования больше не существовало с какой-либо точки выполнения, тогда да. Это возможно на некоторых языках, таких как Smalltalk. Некоторые утверждают, что это "Больше ООП". В smalltalk "методы", поддерживаемые типом, определяются в точке вызова метода на основе текущей иерархии и текущего содержимого каждого класса. Хотя я люблю smalltalk, это одна из особенностей, с которой я не сумасшедший, поскольку предпочитаю проверять время компиляции с меньшими неожиданностями во время выполнения.

Ответ 2

Просто потому, что у вас есть молот, не означает, что все это гвоздь.

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

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

Но рассмотрим суть вопроса интервьюеров, хотя: когда ООП выбирает выбор парадигмы?.

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

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

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

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

Ответ 3

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

Тем не менее, люди критиковали ООП. Например, Steve Yegge Выполнение в Королевстве существительных.

Ответ 4

Его пример не имеет смысла. Ракета не наследуется от тела. У этого есть "тело". Это сдерживание. Поэтому в какой-то момент вы бы "удалили" часть, прикрепленную к ракете, когда ее выбросили.

Ответ 5

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

OO трудно проверить

  • Нет прямого доступа к переменным/атрибутам класса чтения/записи - возможно, потребуется ввести геттеры и сететеры, которые разрушают инкапсуляцию.

  • Наследование может изменить поведение метода в подклассе

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

  • Классы с loh cohesion могут быть трудными для тестирования, поскольку это может означать, что класс делает больше, чем указано.

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

Классика - это предпочтение композиции над наследованием. Наследование заключается в том, чтобы захватить абстракции вдоль шва, что ваша система меняется.

Если вы не совсем четко фиксируете эту абстракцию, тогда да, вы получите странные силы на свои проекты. Но это проблема программирования в мире, где абстракции не совсем правильны для того, чего вы пытаетесь достичь. Не то, чтобы они когда-либо были идеальными.

Ответ 10

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

Ответ 11

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

Например, мы имеем класс A, B, C и D. Класс A имеет классы методов B, C и D. Класс B имеет методы класса D. Таким образом, мы могли бы получить класс D из B и B из A. С другой стороны, мы выведем C из A, потому что C не нуждается в материале B. Поэтому мы в основном решили проблему с ненужным материалом, добавив один дополнительный класс в иерархию. Конечно, если что-то подобное не было поймано на этапе планирования, а класс B использовался в качестве базового класса, было бы сложнее разбить класс B на два класса, но с некоторыми дополнительными усилиями проблема с ненужным багажом будет решена.

Ответ 12

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

Я не знаю, как интервьюер представил вопрос или как вы отреагировали, но одно из самых коротких событий ООП - это не сам ООП. Это плохое использование ООП и плохие отношения "IS-A", которые люди пытаются создать. Если единственная причина, по которой вы можете создать иерархию наследования, - это повторное использование кода, это плохая причина. По утверждению АОП, это лучший подход. (перед тем, как вы начнете плакать или пропустить голос, обратите внимание, что я сказал "может быть" )

OOP - это интерфейс и тип, а не реализация. Знание того, что объект может вернуть список кандидатов на работу, - это все, что мне нужно знать. Независимо от того, что происходит из РСУБД, ориентированной на колонку db, веб-службы или даже таблицы, несущественно. Я знаю, что могу передать этот объект в качестве параметра другим методам, и они могут называть "FetchJobCandidates" и знать, что он получит кандидатов на работу. На пути есть подводные камни, но в основном, если вы думаете о занятиях, основанных на том, что они выставляют остальному миру, а не тому, что они делают внутри, вы находитесь на лучшей ИМО.

Ответ 13

Можно ли просто использовать это в ООП?

RocketShip.BodyPart1 = ничего или

RocketShip.BodyPart1.isDetached = false?

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

Ответ 14

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

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

Ответ 15

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

Ответ 16

Один из способов моделирования объекта, который изменяет его подкласс, заключается в использовании шаблона состояния . Используя ваш вопрос интервью и некоторую помощь Wikipedia, здесь приведен код Java, который показывает, как вы могли бы моделировать переходы состояния по мере прохождения ракеты его различные этапы. Я не показывал этапы командного модуля, но они следуют аналогичной схеме через лунный спуск, лунное восхождение, раннее схождение на лунной орбите и возвращение на Землю. Вероятно, вы могли бы найти гораздо более интересное поведение для добавления в интерфейс ISpaceShipState.

public class SpaceShip {
    private ISpaceShipState m_state = new SaturnFiveState();

    public void setState(ISpaceShipState state) {
        m_state = state;
    }

    public void jettison() {
        m_state = m_state.transition();
    }

    public int getStageNumber() {
        return m_stage.getStageNumber();
    }

    public int getNumberOfRocketMotors() {
        return m_stage.getNumberOfRocketMotors();
    }

    public String getRocketMotorTypeName() {
        return m_stage.getRocketMotorTypeName();
    }
}

interface ISpaceShipState {
    public ISpaceShipState transition();
    public int             getStageNumber();
    public int             getNumberOfRocketMotors();
    public String          getRocketMotorTypeName();
}

public class SaturnFiveState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveSecondStageState();
    }

    public int getStageNumber() {
        return 1;
    }

    public int getNumberOfRocketMotors() {
        return 5;
    }

    public String getRocketMotorTypeName() {
        return "F-1";
    }
}

public class SaturnFiveSecondStageState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveThirdStageState();
    }

    public int getStageNumber() {
        return 2;
    }

    public int getNumberOfRocketMotors() {
        return 5;
    }

    public String getRocketMotorTypeName() {
        return "J-2";
    }
}

public class SaturnFiveThirdStageState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveCommandModuleState();
    }

    public int getStageNumber() {
        return 3;
    }

    public int getNumberOfRocketMotors() {
        return 1;
    }

    public String getRocketMotorTypeName() {
        return "J-2";
    }
}

Можно ли отключить иерархии классов динамически (я уверен, что в Java это невозможно) в идеальном объектно-ориентированном дизайне?

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

Ответ 17

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

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

Если вы думаете об основных понятиях объектно-ориентированного программирования; инкапсуляция, полиморфизм, классы, наследование.. есть проблемы со всеми этими основными концепциями ООП.

Ответ 18

может быть что-то вроде проблемы с круглым эллипсом