Почему мне кажется, что студентов учат ООП неправильно

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

image

Вспомните, классические аналогии ООП, вот есть класс Домашние любимцы с методами «голос» и «есть», от него мы наследуем Кошку и Собаку и все хорошо.

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

Мы уже запутались, но Вовочка спрашивает: «а где в этом зоопарке статические методы, интерфейсы, абстрактные классы и чем отличается объект класса от самого класса?». Объяснить, несомненно, можно, но сложно. Понять, еще сложнее.

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

Теперь подумаем как объяснить ООП лучше?

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

image

Итак представим себе фирму, производящую самолеты и конструкторское бюро при этой фирме (ну, скажем, Боинг). Нам заказали несколько моделей: военный самолет, грузовой и пассажирский.

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

Код на Java
public abstract class ЧертежСамолета {  // чертеж нашей универсальной модели самолета;
        public abstract void взлет();
        public void полет() {
            // описание как наш самолет летит
        }
        public abstract void посадка();
 }


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

Код на Java
public interface ТребованияКСамолету { // то что должен уметь наш самолет
        long getМаксимальнуюСкорость();
        double getГрузоподьемность();
        long getПрактическийПотолок();
        void взлет();
        void полет();
        void посадка();
}

public abstract class ЧертежСамолета implements ТребованияКСамолету {
    ...


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

Код на Java
public abstract class ЧертежСамолета {  // чертеж нашей универсальной модели самолета;
        public abstract void взлет(); // виртуальные метод
        public void полет() {
            // описание как наш самолет летит
        }
        public abstract void посадка(); // виртуальные метод
 }


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

Код на Java
public class ЧертежПассажирскогоСамолета extends ЧертежСамолета {  
       public int getКолВоПассажиров() {
              return 120;
        }
        public void взлет() {
            поздороваться_с_пассажирами();
            провести_инструктаж();
            получить_разрешение_на_взлет();
            взлететь():
        }
        ...
}
public class ЧертежВоенногоСамолета  extends ЧертежСамолета {  
       public int getКолВоРакет() {
              return 5;
        }
        public void взлет() {
            получить_приказ();
            доложить_командиру();
            взлететь():
        }
        ...
}


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

Код на Java
ЧертежСамолета тотСамыйПотрепанныйБоингНаКоторомМыЛетелиВТурцию = new ЧертежПассажирскогоСамолета();

тотСамыйПотрепанныйБоингНаКоторомМыЛетелиВТурцию.setПотрепаность(0.99);


image

У каждой модели самолета есть общие параметры, например, процент аварийности. Каждое происшествие с любым самолетом этой модели его может изменить. Это статические методы и переменные класса.

Код на Java
ЧертежПассажирскогоСамолета.setАварийностьМодели(0.0);


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

Код на Java
public class ЧертежПассажирскогоСамолета extends ЧертежСамолета {  
       ...
        public void посадка() {
            предупредить_пассажиров();
            проверить_все_пассажирские_места();
            получить_разрешение_на_посадку();
            сесть():
        }
        ...
}
public class ЧертежВоенногоСамолета  extends ЧертежСамолета {  
        public void посадка() {
            получить_приказ();
            доложить_командиру();
            сесть():
        }
        ...
}


Если мы делаем самолет, но двигатель разрабатывает другая команда, нам проще не указывать его на самом чертеже самолета (тем более что один двигатель может использовать на большом количестве самолетов), а только указать «смотри чертеж такого-то двигателя». Это композиция.

Код на Java
public class ЧертежПассажирскогоСамолета extends ЧертежСамолета {  
       private ЧертежДвигателя двигатель = new ДвигательМ45ФирмыАстинМартин()
        ...
}


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

Если мы создали модель пассажирского самолета на 120 мест, а потом чуть-чуть доработали увеличив количество мест до 130 (за счет сокращения бизнес класса), нам не потребуется создавать новый чертеж, достаточно лишь указать изменения. Тут же становится легко понятно, почему если поменяется что-то в чертеже модели самолета на 120 мест, так же измениться самолет на 130 мест, так мы не делаем копию чертежей, мы только описываем, что изменилось в проекте. Это наследование.

Код на Java
public class ЧертежПассажирскогоСамолетаНа130Мест extends ЧертежПассажирскогоСамолета {  
       @Override
        public int getКолВоПассажиров() {
              return 130;
        }
        ...
}


Вопрос зачем вообще нужно ООП?

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

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

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

Спасибо за внимание!

P.S. Другие мои статьи (например, шпаргалку по Java SE) можно найти в моем профиле

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

Такой метод объяснения ООП вам кажется нагляднее и проще чем раньше?
Поделиться публикацией
Комментарии 473
    +8

    Аналогия класс-чертеж, объект-изделие действительно намного лучше, чем попытки объяснить что "коты вообще это класс, а Матроскин — инстанс".


    Как то странно объяснять абстрактные классы до того, как объяснены методы и понятие инстанса класса.


    Далее возможные вопросы от слушателей:


    1. Зачем нужно ооп?
    2. Как вот это все переносится на код?
    3. А я еще слышал термины "инкапсуляция", "абстракция", "поле (field) класса". Что это?
      +8
      … а когда внимательные слушатели спросят:

      4. Почему это конструкторское бюро Боинга поставило заказчику чертежи CRJ-200 Bombardier?

      заодно объяснить, что копирование готового кода со stackoverflow является хоть и распространённой, но не всегда верной практикой.
        0

        Ну тут как раз легче чем с котиками. Скопировав чертеж один в один мы не сможем воспроизвести его или часть потом. Соответственно, такой инженер будет стоить дешевле чем инженер, который понимает и сможет сделать такой самолёт сам.

          0
          Пока вы смеетесь, уже придумали название (example-centric programming, иногда opportunistic programming), пишут научные статьи и разрабатывают инструменты, поддерживающие этот подход :)

          Using the web is integral to an opportunistic approach to programming when focusing on speed and ease of development over code robustness and maintainability.
          0
          По моему личному опыту объяснение вида «класс — шаблон для объекта» для новичков — плохое, лучше условно разделить все преимущества и сразу объяснять, зачем нужна та или иная вещь.
            0
            можно смело сказить что ООП это формальная модель.
            как в математике система доказательств и терминология.
            помогает более формально думать
            +3
            А что означает «ВВП полосу»? Может ВПП? Тогда слово «полосу» лишнее. В Целом, идея интересная. Но вот я, к примеру, плохо мыслю абстракциями. Скажите, а вы могли бы попробовать написать сюда пример кода (скажем, на той-же Java), который бы вписывался в вашу концепцию пояснений? Мне вот, как новичку, гораздо проще было бы читать пояснения и видеть код.
              0
              Полностью согласен. Я тоже новичок и скажу даже проще — я из объяснений статьи понял совсем мало. Т.е. то, что уже понял до этого — понимание не углубилось, не стало ярче и крепче (инстанс, интерфейс), а то, что не понимал, не понял и сейчас (композиция, ассоциация).

              Автору всё равно спасибо, мне кажется, если расширить пояснения с одного абзаца до одного раздела с несколькими абзацами, с небольшими примерами кода и теми же абстрактными примерами «из жизни КБ Боинг», эта заметка могла бы реально стать «путеводной звездой».
                0
                Композиция. У вас есть самолет, у него есть двигатель ДС-900, его разрабатывает первая команда, вторая команда разрабатывает двигатель ДС-1500. Вы в своем чертеже можете использовать как ДС-900 так и ДС-1500.

                public class ЧертежПассажирскогоСамолета extends ЧертежСамолета {  
                       private ЧертежДвигателя двигатель = new ДвигательДС900()
                       ||
                       private ЧертежДвигателя двигатель = new ДвигательДС1500()
                }
                

                PS возможно более понятный пример получится. Есть класс таблицы расчета зарплаты. У нее есть ViewEngine первый вариант реализации выведет таблицу как в excel, а второй вариант выведет в текстовом формате в консоль, при этом никаких дополнительных изменений кроме выбора вариации ViewEngine вам не нужно.

                Скрытый текст
                — |column |
                — | param 1 |
                — | param 2 |
                — | param 3 |
                  0
                  В данном случае необходимо вводить интерфейс СовместимыйДвигатель.

                  class PassengerAirCraft extends AirCraft {
                      /**
                       * При проектировании указывается совместимость с двигателями
                       */
                      private EngineInterface $engine;
                      /**
                       * Конструктор это и есть наш сборочный конвейер,
                       * который получает в требованиях модель двигателя
                       * @param $engineModel
                       */
                      public function __construct($engineModel) {
                          /**
                           * Фабрика поставляет нам необходимую модель двигателя
                           */
                          $this->engine = EngineFactory::provide($engineModel);
                      }
                  }
                  

              +4
              Одна проблема — объяснить что это. Другая — объяснить зачем всё это вообще нужно.
                +4
                Совершенно верно, люди не понимают что такое ООП, потому что они начинают с небольших проектов, в которых у них и так всё по полочкам, но им говорят, ваш проект вырастет, делайте сразу хорошо, они долго думают, как это должно быть, что бы было правильно в ООП, а как только проект начинает расти, внезапно вся «раскладка» на ООП, становится другой, а потом ещё раз… И тогда, начинается искреннее недопонимание, почему изначальный ООП код не развивается, а мешает развиваться, причём все говорят, что вы сделали неправильно «первую раскладку», вы не понимаете ООП. Вот, последнее непонимание и важно, а не как сделать в первый раз. И поверьте, ваши «чертежи» и самолёты в этом никак не помогут.
                  0

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

                +2

                Хм… а как насчет ООП в случаи, когда классов нет? То же прототипно-ориентированное (пример, javascript).
                Или вот есть пример Golang, есть ли там ООП или нет?

                  –4
                  ООП — одна из разновидностей композиции (проектирование) систем.

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

                  Развитие ООП в JS смысла не имеет вовсе. Ну, если только — да, у нас не ахти какое ООП но пусть будет хоть такое — может кому и такое может хватить по жизни его (в разработке его), — ну, а если не хватит, то уж тогда использовать стороннюю библиотеку js и там уж и оттянуться с ООП уж так как никому (другим языкам с ООП) и не снилось.
                    +5

                    Это я к тому, что ООП — это ООП, а классо-ориентированное программирование всего лишь подвид ООП.


                    В JS ооп есть, а классов нет (не было). Вот так вот это работает.

                      –6
                      ООП — это ООП, а в JS ОП.
                        0
                        JS как бы мультипарадигменный язык и там можно применять ООП, а можно и не применять. Как в Python или C++.
                          +1
                          Простите, а что такое ОП? Объектное программирование? Сами придумали?

                          Частным случаем ООП является «Прототипное программирование». Оно и есть в JS.
                            –2

                            Объектное программирование — подмножество объектно-ориентированного без наследования.


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

                              0
                              Прототипы — это разновидность наследования, а не альтернативный механизм.
                                0

                                Не все источники с этим согласны.

                        0
                        вы можете использовать… стороннюю библиотеку JS, которая позволяет вам организовать ООП и прочее гораздо круче и разнообразнее чем во всех языках где ООП объявлено на стадии описания самого языка

                        А что за библиотека?

                          +1

                          Я ещё не гуглил, но вангую class.js object.js или oop.js :) Если какая-то библиотека может быть написана на JS, она будет написана на JS :)

                            0
                            LionZXY
                            Я ещё не гуглил, но вангую class.js object.js или oop.js
                            Почти, но нет! ;-)

                            «Благодаря силе прототипов JavaScript получился на редкость гибким. На волне вдохновения разработчики создали огромное количество библиотек со своими собственными объектными моделями. Популярная библиотека Stampit выжимает из прототипной системы всё возможное для того, чтобы манипулировать объектами так, как это невозможно в традиционных языках, базирующихся на классах.»

                            Ну и сама Stampit и примеры.

                            И вот как быть дальше с ООП в JS, "втянуть в себя", в стандарт JS библиотеку Stampit? — Но как?
                            JS — не модульный — в том смысле что в нём нет «пакетов» как в Java (в которой, к примеру, при обновлении версии Java, «втянули» пакет стороннего разработчика для удобного использования программирования потоков, который(пакет) фактически ничего не изменил на нижнем уровне (Thread.suspend(), Thread.resume() и прочие), но оказался удобен).

                              0

                              Для JS есть стандартная библиотека, как минимум. Не считая API типа WebSockets

                                –2
                                Для JS есть стандартная библиотека, как минимум.
                                Не понял вас. В JS вообще нет такого понятия как «стандартная библиотека» — Понятие «стандартная библиотека» это из мира C, С++, Java и прочих.
                                  0

                                  Понятия «стандартная библиотека» нет, а Standard Build-in Objects есть.

                                    –2
                                    staticlab
                                    Понятия «стандартная библиотека» нет, а Standard Build-in Objects есть.

                                    Понимаете в «Standard Build-in Objects» нет ни намёка на слово «library» или «file».

                                    Ну нет такого понятия как «стандартная библиотека» в JS, хоть плач!
                                      +1

                                      Ну и что? Я знаю, что вы любитель придираться именно к словам, но какая разница?

                                        +1

                                        Кроме того, выделенное вами слово (у вас на выделениях какая-то нездоровая фиксация) следует писать с мягким знаком.

                                          –1
                                          staticlab
                                          Ну и что? Я знаю, что вы любитель придираться именно к словам, но какая разница?
                                          Так я же выше пояснил, так как в JS нет стандартных библиотек, так что запросто добавить в JS какую-нибудь стандартную библиотеку нельзя! Хоть плачь.


                                          Кроме того, выделенное вами слово (у вас на выделениях какая-то нездоровая фиксация)
                                          Не обращайте внимание, это я для того чтобы расставить ударение!

                                          следует писать с мягким знаком.
                                          Вот тут правы! И только тут. (Виноват, путаюсь, ибо "ч" в белорусском всегда твёрдая и после неё никаких мягких — никакого смягчения, никакой мягкости, только жёсткость одна, только.)

                                            0
                                            Так я же выше пояснил, так как в JS нет стандартных библиотек, так что запросто добавить в JS какую-нибудь стандартную библиотеку нельзя! Хоть плачь.

                                            JS — не модульный — в том смысле что в нём нет «пакетов» как в Java (в которой, к примеру, при обновлении версии Java, «втянули» пакет стороннего разработчика для удобного использования программирования потоков

                                            Пишите proposal к стандарту, продвигайте его в TC39, и будет вам счастье.


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

                                              0
                                              staticlab
                                              Пишите proposal к стандарту, продвигайте его в TC39, и будет вам счастье.
                                              Написано, не принято. И это хорошо! :-)

                                              ECMAScript 4
                                              В самый разгар разработки ECMAScript 4 включал такие опции как:

                                              Классы
                                              Интерфейсы
                                              Пространства имён
                                              Пакеты
                                              Опциональные аннотации типов
                                              Опциональная статическая проверка типов
                                              Структурные типы
                                              Объявления типов
                                              Мультиметоды
                                              Параметризованные типы
                                              Хвостовые рекурсии
                                              Итераторы
                                              Генераторы
                                              Интроспекция
                                              Разбор типа для обработчиков исключений
                                              Связывание констант
                                              Правильный обзор блоков
                                              Деструктуризация
                                              Сжатые функциональные выражения
                                              Поддержка массивов



                                              Однако, Stampit выглядит как надстройка над стандартным прототипным ООП, а потому в таких случаях правильнее будет перенести в стандарт непосредственно идеи этой библиотеки, а не тащить «как есть». То есть, возможно, это будут некоторые новые методы класса Object.
                                              Вряд ли нужно тащить даже идеи этой библиотеки — она же есть и развивается сама по себе независимо от новых фич JS.

                                              Аналогично и по идеям из иных библиотек, типа Underscore.js и прочих и прочих…

                                              Зачем всё это тащить в стандарты JS — цель? — единственная разумная цель — тащить то, что может эффективно реализовано в NATIVE функциях JS-движков, используемых в броузерах и средах типа Node.js

                                              Ну, а стандартных библиотек в JS нет. (С)
                                                +2

                                                Тем не менее, стандартная библиотека в JS есть — это стандартные классы и методы, описанные в стандарте:


                                                The ECMAScript library of built-ins was expanded to support additional data abstractions including maps, sets, and arrays of binary numeric values as well as additional support for Unicode supplemental characters in strings and regular expressions. The built-ins were also made extensible via subclassing. The sixth edition provides the foundation for regular, incremental language and library enhancements.

                                                Clauses 17-26 define the ECMAScript standard library. It includes the definitions of all of the standard objects that are available for use by ECMAScript programs as they execute.
                                                  –1
                                                  staticlab
                                                  The ECMAScript library of built-ins was expanded to support additional data abstractions including maps, sets, and arrays of binary numeric values…
                                                  Точно, определить что стандартная библиотека — это не файл или не набор битов, который централизованно поставляется создателем (или дистрибутером) библиотеки, а это описание стандарта! — Это круто!

                                                  Но что нам говорит Википедия?
                                                  Стандартная библиотека языка программирования — набор модулей, классов, объектов, констант, глобальных переменных, шаблонов, макросов, функций и процедур, доступных для вызова из любой программы, написанной на этом языке и присутствующих во всех реализациях языка.
                                                  Да и не важно что тут нет слова ОПИСАНИЕ, а его нет, так как из ОПИСАНИЯ стандарта нельзя ничего вызвать из «любой программы, написанной на этом языке и присутствующих во всех реализациях языка.»

                                                  Определение — сила. Определите что ваши пожелания есть библиотека — и вы… на коне! ;-)
                                                    +1

                                                    Что за наркомания? Какое ещё описание стандарта? Откуда вы его взяли?

                                                      –1
                                                      staticlab
                                                      Какое ещё описание стандарта?

                                                      Обычное, на их сайте размещённое: This Ecma Standard defines the ECMAScript 2015 Language. It is the sixth edition of the ECMAScript Language Specification.

                                                      А вы бред про «The ECMAScript library...» где изволили откопать то?

                                                        0
                                                        Обычное, на их сайте размещённое

                                                        Вы читать по английски не умеете или только слова из контекста выдёргивать научились?


                                                        «Данный стандарт Ecma описывает язык ECMAScript 2015. Это шестая редакция спецификации языка ECMAScript.»


                                                        А вы бред про «The ECMAScript library...» где изволили откопать то?

                                                        Я же дал ссылку.

                                                          –1
                                                          staticlab
                                                          «Данный стандарт Ecma описывает язык ECMAScript 2015. Это шестая редакция спецификации языка ECMAScript.»

                                                          Нет, не так:
                                                          «Данный стандарт Ecma описывает [спецификацию] язык[a] ECMAScript 2015. Это шестая редакция спецификации языка ECMAScript.»


                                                          staticlab
                                                          Я же дал ссылку.

                                                          Точно, ссылка ведёт на сайт www.ecma-international.org

                                                          4.4Organization of This Specification#

                                                          Clauses 17-26 define the ECMAScript standard library. It includes the definitions of all of the standard objects that are available for use by ECMAScript programs as they execute.

                                                          the definitions — определение, описание.

                                                          То есть если распечатать по функциям эту ECMAScript standard library — и каждую распечатку в коленкор и на полку то и будет вам ECMAScript standard library!

                                                          Ну, а стандартных библиотек, которые вы могли бы скачать откуда-нибудь и непосредственно использовать в своём коде в JS нет. (С)
                                                            +1
                                                            Ну, а стандартных библиотек, которые вы могли бы скачать откуда-нибудь

                                                            Зачем её качать отдельно, если она стандартная? И множество классов из неё по определению есть "во всех реализациях языка"? Например, в составе Java есть стандартная библиотека с множеством классов, таких как java.lang.Object, java.util.ArrayList, java.util.Date, java.util.concurrent.FutureTask и т.п. В .NET это System.Object, System.Collections.ArrayList, System.DateTime, System.Threading.Tasks.Task. В Ruby это Object, Array, Time. В C++ это std::vector, std::chrono::*, std::future. В JS — Object, Array, Date, Promise.


                                                            Согласен, для такого довольно низкоуровневого языка как C++ возможна независимая стандартная библиотека, но в большинстве случаев её реализация привязана к среде исполнения. А вот совместимость как раз декларируется стандартом. На то он и стандарт.

                                                              0
                                                              Кстати, если на то пошло, то некоторые части этой библиотеки вполне поддаются скачиванию… Например, в виде пакета core-js.
                                                                –1
                                                                staticlab
                                                                Зачем её качать отдельно, если она стандартная?
                                                                Чтобы использовать.

                                                                staticlab
                                                                И множество классов из неё по определению есть «во всех реализациях языка»?
                                                                Этого не требуется по определению.

                                                                @staticlab
                                                                Согласен, для такого довольно низкоуровневого языка как C++ возможна независимая стандартная библиотека, но в большинстве случаев её реализация привязана к среде исполнения.
                                                                Но вы можете все их скачать из одного источника. — В случае JS скачивать нечего и негде.

                                                                mayorovp
                                                                если на то пошло, то некоторые части этой библиотеки вполне поддаются скачиванию… Например, в виде пакета core-js.
                                                                Это не стандартая библиотека JS и не часть её — это набор полифилов — то есть "временных костылей" для некоторых функций (методов).

                                                                Стандартных библиотек в JS нет. (С)
                                                                  0
                                                                  Этого не требуется по определению.

                                                                  Перечитайте ещё раз определение стандартной библиотеки из Википедии, которое вы же сами и процитировали.


                                                                  Но вы можете все их скачать из одного источника.

                                                                  Это не так.


                                                                  В случае JS скачивать нечего и негде.

                                                                  Реализации стандартных библиотек для движков V8 и SpiderMonkey скачать можно, но они написаны на C++. Реализации полифиллов тоже скачать можно. Опять-таки, наличие независимых реализаций для стандартных библиотек не требуется.


                                                                  это набор полифилов — то есть "временных костылей" для некоторых функций (методов).

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

                                                                    –1
                                                                    staticlab
                                                                    Реализации стандартных библиотек для движков V8 и SpiderMonkey скачать можно, но они написаны на C++.
                                                                    Нет, неверно написано вами, более полно и правильно надо писать так:

                                                                    Библиотеки, реализующее некоторые элементы стандарта JS для движков V8 и SpiderMonkey, скачать можно.

                                                                    Стандартных библиотек в JS нет. (С)
                                                                      0

                                                                      То есть с остальным вы не спорите, но всё равно упираетесь?

                                                                        –2
                                                                        То есть с остальным вы не спорите, но всё равно упираетесь?

                                                                        Мы начали с Стандартных библиотек в JS нет. (С)
                                                                        И закончили Стандартных библиотек в JS нет. (С)

                                                                        Всяческие попытки это опротестовать оказались (имхо) никчемными или отвлекающими. Не более того.

                                                                          +2

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

                                                                            –2
                                                                            Вашим тролльным способом можно доказать всё, что угодно.
                                                                            Не будем развешивать ярлыки.
                                                                            Вот, к примеру урл на стандартные Java библиотеки. Качайте и работайте.

                                                                            Теперь — раз вы утверждаете что Стандартных библиотек есть в JS, то приведите мне урл где я их могу скачать.

                                                                            Если такого урла нет — вы троль. (С)

                                                                              +1
                                                                              Мимо проходил

                                                                              Теперь — раз вы утверждаете что Стандартных библиотек есть в JS, то приведите мне урл где я их могу скачать.

                                                                              нате
                                                                              Спойлер
                                                                              Да, это ссылка на скачивания гугла хром, но как виртуальная машина Java это намного больше, чем просто стандартная библиотека Java (какому-нибудь JPython'у может быть нафиг не нужна эта библиотека), так и хром поддерживает определенный стандарт JS. Не вижу никакой разницы в данном случае. И да, между прочим реализаций Java тоже несколько.

                                                                              В случае JS скачивать нечего и негде.

                                                                              Качайте:
                                                                              1. браузеры,
                                                                              2. nodeJs и т.п.

                                                                              И там и там есть своя реализация стандарта JS (разная реализация во многом, но Java реализации J# в Net, Java в андроиде, у Oracle и OpenJDK тоже совсем не одинаковые)
                                                                                –2
                                                                                vedenin1980
                                                                                Да, это ссылка на скачивания гугла хром, но как виртуальная машина Java это намного больше, чем просто стандартная библиотека Java (какому-нибудь JPython'у может быть нафиг не нужна эта библиотека), так и хром поддерживает определенный стандарт JS. Не вижу никакой разницы в данном случае.

                                                                                Вот и ссылка появилась на… браузер хрома. :-(

                                                                                Меня один уверял, что между Java и JavaScript разницы он не видит. По крайней мере четыре первые буквы совпадают и оператор «new» там и там есть! ;-)

                                                                                vedenin1980
                                                                                В случае JS скачивать нечего и негде.
                                                                                — А вот staticlab как-то сомневается в этом.

                                                                                vedenin1980
                                                                                Качайте:
                                                                                1. браузеры,
                                                                                2. nodeJs и т.п.

                                                                                И там и там есть своя реализация стандарта JS (разная реализация во многом, но Java реализации J# в Net, Java в андроиде, у Oracle и OpenJDK тоже совсем не одинаковые)

                                                                                Есть некая разница между «разными (и частичными) реализациями стандарта» и «отсутствием стандартной библиотеки вообще»! — Многие её не улавливают. А она… есть. :-)
                              0
                              Блин, придется удалять весь код теперь. Было так удобно писать поддерживаемый и читаемый код, но вы открыли мне глаза! Спасибо!
                                +1

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


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

                                +7
                                ООП — оно не в языке, а в голове разработчика.
                                  +2

                                  Добавлю: ООП широко применяется в ядре Linux и "оконной" части WinAPI несмотря на полное отсутствие языковой поддержки.

                                    0

                                    Не не полное — есть структуры и в них можно хранить указатели на функции :)

                                    • НЛО прилетело и опубликовало эту надпись здесь
                                        0
                                        Не совсем. Указатели — это виртуальные методы. Обычные — это просто функции с неявным this-аргументом, возможно, перегруженные. А ещё правила каста указателей при наследовании, и это важнее всего остального по сути.
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                            0
                                            Я немного не о том.
                                            Вызов метода предполагает передачу this. Указатель на функцию, которая не примет объекта в качестве параметра, нельзя считать вызовом метода, потому что она не имеет контекста (this).
                                              +1

                                              Что мешает в простом C передавать первым параметром указатель на структуру?

                                                0
                                                Ничего. Но тогда нет необходимости таскать за собой и указатель на функцию, если нет задачи сделать её виртуальной.
                                  0

                                  В Javascript классы есть, причем начиная с ES2015 даже на уровне синтаксиса. Чего там и правда нет — так это переопределения членов, когда в базовом классе this.foo это одно, а в наследнике this.foo это что-то другое и друг с другом они никак не связаны. Но на уровне "чертежей и самолетов" никаких отличий между Javascript-классами, С++-классами и Java-классами не наблюдается (за исключением того факта что в Javascript можно "унаследовать" не только чертеж, но готовое изделие — однако "можно" не означает что так нужно делать).

                                    0
                                    Не знаю, как сделаны классы в ES2015, но до него обычно это были костыли-обертки над прототипным наследованием.

                                    Ну и да, вы бы хотя бы привели в пример тот же Python, потому что различия между классами в JavaScript и C++ катастрофические. Например, нет ограничения доступа для переменных.
                                      +3

                                      Ограничения доступа — прежде всего в голове у программиста. Без них он напишет #define private public и будет радоваться как круто он все устроил. Или применит заклинание Звезды Пустоты. Или напишет Паблика Морозова...


                                      Что же до костылей — то костыль был только один:


                                          function temp() {}
                                          temp.prototype = Foo.prototype;
                                          Bar.prototype = new temp();

                                      Потом в ES5 его внесли в стандартную библиотеку, обозвав Object.create. Все остальное — просто реализация ООП.

                                        0
                                        По мне как раз возможность ограничения доступа на уровне языка важна, ведь по сути без ограничений доступа только по коду непонятно будет где интерфейс, а где реализация. Наличие и соблюдение контрактов важно тем что, имхо: 1) снижает сложность системы за счет вынесения в паблик только специально предназначенных для этого вещей; 2) без костылей в виде комментариев или памяти программиста с ходу позволяет использовать параметрический полиморфизм над объектами с одинаковым контрактом; 3) облегчает инструментальное взаимодействие с кодом и использование той же контекстной подсказки.
                                          0

                                          Важна она как средство принудительного дисциплинирования прежде всего.

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

                                              Вас расслабляет, что разработчики модуля соблюдали дисциплину :)

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

                                              Но отсутствие контрактов не означает отсутствия классов или отсутствия ООП.
                                                0
                                                Но отсутствие контрактов не означает отсутствия классов или отсутствия ООП.

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

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

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

                                            0

                                            В Python, кстати, тоже нет ограничения доступа для полей. И ничего, никто не умер.

                                              0
                                              В ассемблере еще меньше ограничений, и никто от этого не умирает :)
                                                0

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

                                                0
                                                На самом деле небольшие есть) Но это не важно, как бы, я больше возражал фразе «классы в javascript почти такие же, как в C++».
                                              0
                                              Вообще-то в js классов нет и не было. То что вы называете классами в ES2015 — это синтаксический сахар, под капотом в себе кроет старые добрые прототипы.
                                                +1
                                                С вашей точки зрения в компьютерном мире нет вообще ничего. Это всё синтаксический сахар над нулями и единицами.
                                                0
                                                Чего там и правда нет — так это переопределения членов, когда в базовом классе this.foo это одно, а в наследнике this.foo

                                                Как же нет? Есть даже ключевое слово super, чтобы из наследника вызывать метод родителя:


                                                class A {
                                                    foo() {
                                                        console.log('A.foo()');
                                                    }
                                                }
                                                
                                                class B extends A {
                                                    foo() {
                                                        console.log('B.foo()');
                                                        super.foo();
                                                    }
                                                }
                                                
                                                (new B).foo();
                                                
                                                  0

                                                  А теперь попробуйте отключить полиморфизм, чтобы получить доступ к foo() из класса A имея объект класса B :-)

                                                    0

                                                    Позднее связывание имеете в виду или что?

                                                      +1
                                                      class A {
                                                          name = "world";
                                                      
                                                          hello() {
                                                              return $"Hello, {this.name}!";
                                                          }
                                                      }
                                                      class B extends A {
                                                          name = "B";
                                                      
                                                          who() {
                                                              return $"I am {this.name}";
                                                          }
                                                      }
                                                      
                                                      var b = new B();
                                                      console.log(b.hello()); // Ну и куда тут надо было super засунуть? :-)
                                                      
                                                        0
                                                        class A {
                                                            name = "world";
                                                        
                                                            hello() {
                                                                return $"Hello, {this.name}!";
                                                            }
                                                        }
                                                        class B extends A {
                                                            constructor() {
                                                              	super(); // В конструктор? Хотя вызов работает и без него.
                                                            }
                                                          
                                                            name = "B";
                                                        
                                                            who() {
                                                                return $"I am {this.name}";
                                                            }
                                                        }
                                                        
                                                        var b = new B();
                                                        console.log(b.hello()); // Ну и куда тут надо было super засунуть? :-)
                                                        
                                                          0
                                                          Да где работает-то? Если исправить синтаксические ошибки, то в консоль код выведет «Hello, B!». А надо было — «Hello, world!».

                                                          Да, вот исправленный неработающий код:

                                                          class A {
                                                              constructor() {
                                                              	this.name = "world";
                                                              }
                                                          
                                                              hello() {
                                                                  return `Hello, ${this.name}!`;
                                                              }
                                                          }
                                                          class B extends A {
                                                              constructor() {
                                                                  super();
                                                                  this.name = "B";
                                                              }
                                                            
                                                              who() {
                                                                  return `I am ${this.name}`;
                                                              }
                                                          }
                                                          
                                                          var b = new B();
                                                          console.log(b.hello()); // Ну и куда тут надо было super засунуть? :-)
                                                          
                                                0
                                                В Golang есть все возможности ООП, хотя и под несколько непривычным соусом. Структуры + методы структур = класс, есть интерфейсы, есть инкапсуляция, нет наследования, но есть композиция, которая даёт практически те же возможности( в терминах статьи, например, ЧертёжПассажирскогоСамолёта включал бы в себя ЧертёжСамолёта в виде композиции, по сути наследуя с возможностью переопределения все его методы). Тут на хабре было несколько хороших статей на эту тему.
                                                  +1

                                                  Проблема в том что сами авторы Go как бы не уверены. Поэтому все про это и спорят.

                                                    0
                                                    Ну собственно, всё зависит от того, какое определение ООП брать. На мой взгляд, Go реализует нужные возможности, называя их по другому. Но поскольку мнений о том, что считать ООП — дюже много, некоторым из определений Go не соответствует.
                                                +11

                                                Читал и думал: как хорошо быть старпёром, который учился программировать, когда про ООП ещё толком не слышали, и все споры были "сверху вверх" vs "снизу вверх".
                                                В итоге, когда оно пришло в наш кишлак, все вопросы были — "а как оно устроено". Прочитав про VMT — успокоился и вопросов больше не имел, пока не столкнулся с множественным наследованием в C++ — ибо не понимал, как оно сделано (кстати, убедился, что мои вопросы были обоснованы, когда последующие языки забанили множественное наследование от классов, разрешив только от интерфейсов и от микс-инов, это насквозь понятно).


                                                Единственная проблема — при виде 15 слоёв абстракции начинаешь поминать "Яву головного мозга".

                                                  –7
                                                  Угу, как старпер, подтверждаю.

                                                  Мне все больше и больше нравится мнение моего бывшего коллеги "ООП – неизменно стабильный результат"

                                                  Цитата для затравки
                                                  Учебники по ООП полны примеров, как легко и красиво решается задачка отображения геометрических фигур на холсте с одним абстрактным предком и виртуальной функцией показа. Но стоит применить такой подход к объектам реального мира, как возникнет необходимость во множественном наследовании от сотни разношёрстных абстрактных заготовок. Объект «книга» в приложении для библиотеки должен обладать свойствами «абстрактного печатного издания», в магазине – «абстрактного товара», в музее – «абстрактного экспоната», в редакции, типографии, в службе доставки… Можете продолжить сами.
                                                    +9

                                                    Цитата — классическая подмена понятий: проблемы архитектуры, построенной на наследовании, выдаются за проблемы ООП. При этом, как я уже в соседнем комментарии написал, наследование в ООП вообще необязательно. Да и в контексте языков, поддерживающих наследование, общеизвестен принцип "Composition over inheritance", и чуть менее общеизвестен, но тоже неплох, принцип "Abstract or final".

                                                      –7
                                                      Давайте не будем спорить о терминах, а возьмем их из словаря. В общеупотребительном определении ООП наследование является обязательным признаком. Если у вас есть иное авторитетное определение — дайте на него ссылку.

                                                      А то, что вы описали в своем комментарии обычно называется модульным программированием.
                                                        +5

                                                        Мнение человека, который придумал термин "ООП", достаточно авторитетно для вас? :-)


                                                        http://www.purl.org/stefan_ram/pub/doc_kay_oop_en

                                                          –8
                                                          Ну примерно как мнение братьев Черепановых относительно современного локомотива. :-) Ещё больше беды в том, что мнение не является определением.

                                                          Но спорить о терминах не буду. Если вы найдете словарь или стандарт с устраивающим вас определением — пользуйтесь им.

                                                          Смешной факт
                                                          Тот, кто придумал слово ВУЗ, был твердо уверен, что ВУЗ — заведение, то есть женского рода. Но увы, русский язык решил иначе. Примерно так же и с ООП — большинство людей под ним имеют ввиду нечто с виртуальным наследованием.

                                                          Ещё можете посмотреть, что значили разные ругательства в тот момент, когда эти слова впервые появились в языке. Очень много интересного для себя откроете.
                                                            +5

                                                            Строгого определения ООП автор Smalltalk не давал (впрочем, то, что он пишет в конце своего письма, вполне можно считать определением). Как, впрочем, такого определения и не давали авторы языка Simula. Оба языка при этом примерно одновременно ввели термин "объект". Соответственно, можно говорить о двух "школах" — "Смоллтолковской" и "Симуловской".


                                                            Появившийся позднее язык С++ был явным последователем Simula-школы, и именно в те времена — благодаря тому, что С++ был долгое время самым популярным объектно-ориентированным языком — в массовом сознании закрепился сформулированной Страуструпом триплет "инкапсуляция-последование-полиморфизм" и стал считаться чем-то вроде определения. Примерно в то же время появился и другой основанный на C язык, известный в то время в основном только немногочисленным обладателям компьютеров NeXT, следовавший принципам Smalltalk… :-)


                                                            Что касается определения.


                                                            Во-первых, предлагаю смотреть не в википедию курильщика, а в википедию здорового человека — то есть, в английскую. Никакого упоминания необходимости и достаточности свойств из того самого "триплета Страуструпа" вы там не найдете: они, несомненно, перечислены, но только в общем ряду других свойств некоторых объектно-ориентированных языков.


                                                            Во-вторых, сравним высказывание Алана Кея и Страуструповский триплет. Вот что пишет Алан Кей:


                                                            OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.

                                                            Вызов метода можно считать частным случаем Messaging. "local retention and protection and hiding of state-process" — по сути, инкапсуляция. "extreme late-binding of all things" — по сути, полиморфизм.


                                                            Итого, общими являются инкапсуляция и полиморфизм. Наследования у Кея нет.


                                                            Более поздний принцип проектирования объектно-ориентированных программ, высказанный применительно к языкам Симула-школы, гласит: предпочитайте композицию наследованию. С этим принципом согласно подавляющее большинство специалистов по проектированию ПО: Мартин Фаулер, Джошуа Блох, Эрик Эванс… Все они рекомендуют по возможности избегать наследования в тех языках, которые наследование реализуют.


                                                            Логичный вывод: наследование не является обязательным признаком ООП-языка.

                                                              –3
                                                              Вам очень хочется спорить о смысле слов? Ну спорьте, если найдете себе оппонента. Вы не понимаете главного — у слов нету одного единственного верного определения. А как только вы это поймете — вы придете к выводу, что никакого смысла в этом споре нет.

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

                                                              И ваша попытка поспорить о смысле терминов столь же бессмысленна, как и спор о том, возникает ли несовершеннолетие в 14 лет или нет.

                                                              То есть в смысле каких-то определений — вы правы, а в смысле других — нет.

                                                              Во-первых, предлагаю смотреть не в википедию курильщика, а в википедию здорового человека — то есть, в английскую.

                                                              Просите, вы определение какого термина ищите? Object-oriented programming или ООП? Очень многие слова при переводе меняют свой смысл. Так что отсылка к английской вики просто некорректна.

                                                              P.S. Строго по определению УК — если лицо 16 лет преступления не совершало, оно несовершеннолетним не является. :-) Хоть стой, хоть падай — но определение ровно такое.
                                                                +3
                                                                Просите, вы определение какого термина ищите? Object-oriented programming или ООП? Очень многие слова при переводе меняют свой смысл. Так что отсылка к английской вики просто некорректна.

                                                                То есть, вы хотите сказать, что термин "Object-oriented programming" приобрел определение, соответствующее Страуструповскому триплету, только в русскоязычной традиции? Окей, я бы мог с этим поспорить, но не буду — пусть будет так, я ради смеха даже соглашусь, чтобы положить к себе в копилку еще один аргумент, почему во избежание недопонимания надо использовать только англоязычные термины :-)

                                                                  –4
                                                                  Угу, это часто бывает. Вас не удивляет, что Metropolitan означает совсем не то, что Метрополитен.Ещё смешнее со словом секс, которое на английском означает просто пол.

                                                                  во избежание недопонимания надо использовать только англоязычные термины :-)
                                                                  Ну попробуйте с английским смыслом слова «секс». Буду очень удивлен, если вас поймут. А пришло это слово в русский язык примерно тогда же, когда ООП.

                                                                  То есть, вы хотите сказать, что термин «Object-oriented programming» приобрел определение, соответствующее Страуструповскому триплету, только в русскоязычной традиции?
                                                                  Если не путаю, то термин ООП пришел в русский язык вместе с книгой Страустрапа. Не знаю, как сейчас, но лет 25 назад даже считалось, что без множественного наследования — это не ООП.
                                                                    +3

                                                                    Ох! Окей, продолжу, предполагая, что вы не троллите. Если что, покажите табличку "сарказм", пожалуйста. :-)


                                                                    Ваша аналогия некорректна. Иностранные слова в русский язык заимствуются, после чего, как правило, живут сами по себе. Научные термины же международны по своей природе — ученые и инженеры бОльшую часть информации получают на принятом в их профессиональной области международном языке, а в нашем веке эту роль совершенно однозначно выполняет английский язык. Английские термины и их определения — это, в терминах DDD, ubiquitous language программистов. В связи с общедоступностью информации на этом самом ubiquitous language никакого самостоятельного развития и ответвлений не возникает; русскоязычные термины (которые, за исключением давным-давно (до 90-х) сложившихся терминов, либо являются прямым переводом, либо вообще англицизмами) в русской речи программиста используются только по той простой причине, что иначе было бы проще вообще все говорить по-английски.


                                                                    А с тем, что считалось 20 лет назад — я не спорю: тогда на фоне С++ всех остальных объектно-ориентированных языков и видно не было. И считалось "так" не только "у нас", но и "у них". С популяризацией же таких языков, как Javascript и Ruby, вспомнили, что не все так просто.


                                                                    Предлагаю сойтись на том, что "И-Н-П" является определением ООП-языков семейства Simula. :-)

                                                                      –2
                                                                      Вообще-то смысл терминов дрейфует в любом языке, а не только в русском. Как пример — дрейф смысла слова hacker. При этом английский дрейфует побыстрее русского.

                                                                      Более того, единый английский или единый русский язык — это всего лишь абстракция. На самом деле есть смесь диалектов (советую почитать по ссылке, Яндекс очень интересно об этом рассказывает).

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

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

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

                                                                      Что касается вашей трактовки ООП… Мне она не нравится тем, что тогда получается, что ООП возможен на любом языке, где есть структуры. Берем структуру, пишем набор методов для неё — и получаем собственно все, что вы имеете ввиду под ООП. Роль класса у нас исполняет модуль, но все нужные свойства вашей трактовки ООП вполне есть. Ну а в моем понимании ООП возможно лишь там, где есть VMT или его аналог.

                                                                      А с тем, что считалось 20 лет назад — я не спорю: тогда на фоне С++ всех остальных объектно-ориентированных языков и видно не было. И считалось «так» не только «у нас», но и «у них».

                                                                      Ну вот вы и признали дрейф англоязычного термина.
                                                                        –2
                                                                        Ну вот вам кусочек кода на Си
                                                                        struct usart_port;
                                                                        bool usart_driver_initialize (const struct usart_port *port, int rx_buffer_size, int tx_buffer_size);
                                                                        void usart_driver_set_bps (const struct usart_port *port, int bps);
                                                                        void usart_driver_set_parity (const struct usart_port *port, enum USART_DRIVER_PARITY parity);
                                                                        int usart_driver_send_byte_with_timeout (const struct usart_port *port,  uint8_t bt, int timeout_ticks);
                                                                        uint8_t usart_driver_receive_byte_with_timeout (const struct usart_port *port, uint8_t *dst, int timeout_ticks);
                                                                        



                                                                        Вы готовы признать, что это ООП? С моей точки зрения это модульное программирование. Можно назвать его программированием, ориентированным на объекты, но это не ООП. Ну хотя бы потому, что такой стиль написания придуман задолго до ООП.
                                                                          +2
                                                                          Модульное программирование — это отдельная характеристика, которая не конфликтует с ООП. Программа может быть одновременно ОО и модульной, также как может не быть ни ОО ни модульной. Кстати, в приведенном вами куске кода разбиения на модули не видно, хотя и подразумевается :)

                                                                          То что вы привели — это в таком виде обычное процедурное программирование. Кстати, не могли бы вы пояснить каким образом из слов вашего оппонента следует что этот кусок кода надо классифицировать как ООП?
                                                                            0
                                                                            Ну вот вам чуть урезанная цитата из @ymbix:
                                                                            Класс — это деталь реализации конкретных языков, совершенно необязательная

                                                                            Понятие наследования вообще не является необходимым — любое наследование заменяется композицией.

                                                                            Понятие виртуальных методов тоже не нужно:

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

                                                                            Ну вот «объект, взаимодействующие с другими в соответствии с контрактом» я и представил. :-) Но я тоже согласен, что это не ООП. Хотя инкапсуляция и некий полиморфизм тут есть.
                                                                              0
                                                                              Инкапсуляции тут нет: методы и данные отделены друг от друга. Полиморфизма тут тоже нет.

                                                                              Вот если бы структура `usart_port` была объявлена как-то так:

                                                                              struct usart_port {
                                                                                  struct vmt_t { // Я не помню можно ли так делать в Сях, предположим что можно. Если нет - эту структуру без проблем можно вынести наружу.
                                                                                      bool (*usart_driver_initialize) (const struct usart_port *port, int rx_buffer_size, int tx_buffer_size);
                                                                                      void (*usart_driver_set_bps) (const struct usart_port *port, int bps);
                                                                                      void (*usart_driver_set_parity) (const struct usart_port *port, enum USART_DRIVER_PARITY parity);
                                                                                      int (*usart_driver_send_byte_with_timeout) (const struct usart_port *port,  uint8_t bt, int timeout_ticks);
                                                                                      uint8_t (*usart_driver_receive_byte_with_timeout) (const struct usart_port *port, uint8_t *dst, int timeout_ticks);
                                                                                  } *vmt;
                                                                              
                                                                                  // ...
                                                                              }
                                                                              


                                                                              То получилось бы уже то самое ООП в языке Си.
                                                                                0
                                                                                ООП тут нет, разумеется. А инкапсуляция (в модуле) есть. Мой оппонент верно заявил, что классы не обязательны для ООП, вместо них могут быть модули или пространства имен. Полиморфизм есть, но куцый — времени линковки. То есть строго по определению — один вызов функции обрабатывает данные разных типов, ибо внутренняя структура типа фиксируется лишь при линковке.
                                                                                Вот если бы структура `usart_port` была объявлена как-то так:

                                                                                Э… батенька… это уж совсем никуда не годится. Не может понимание того, является ли вызывающий код ООП или нет базироваться на вызываемом коде. Иначе получится, что слинковали один модуль — это ООП, слинковали другой с тем же интерфейсов — не ООП. А это уж совсем бредово.

                                                                                Но вам +1 в карму за верную догадку. Кое-что в этом духе в потрохах есть:
                                                                                  void (*init_pins_and_clocks) (void);
                                                                                  void (*set_rs485_tx_enable_pin) (int enable);
                                                                                
                                                                                Правда и это — ну совсем не ООП, ибо все структуры формируются статически.
                                                                                  0
                                                                                  А вызывающий код и вызываемый совершенно не обязаны быть написаны в одной парадигме!

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

                                                                                    Максимум это код, ориентированный на объекты (struct usart_driver — вполне себе объект). Но не ООП.
                                                                            0

                                                                            Модульность необходима, но не достаточна. Тут сделан один шаг в сторону ООП, но отсутствует возможность абстрагирования от конкретного типа объекта. Можно говорить об этом с точки зрения отсутствия разделения контракта и конкретной реализации, можно — с точки зрения отсутствия полиморфизма, можно — с точки зрения отсутствия late binding, это все разные стороны одной монеты.


                                                                            Чтобы появилось ООП, в этом коде надо добавить указатели на функции в структуру и договориться, что снаружи модуля мы "не видим" никаких членов структуры, кроме этих указателей на функции. Похожим образом устроены модули в nginx: там, конечно, много performance hacks, но в целом — вполне себе ООП.

                                                                              –1
                                                                              но отсутствует возможность абстрагирования от конкретного типа объекта.
                                                                              Почему же? Абстрагирование полное. Это может быть RS323, а может быть RS485, RS422 или радиомодем. Если две функции сделать пустыми — это может быть USB, SPI или UDP. Если добавить пару функций — то можно и TCP/IP.

                                                                              Уж не говорю о том, что конкретная реализация ком-порта тут не определена. А она бывает совсем разная на STM32, LPC, Atmel или 80x86.

                                                                              Чтобы появилось ООП, в этом коде надо добавить указатели на функции в структуру
                                                                              Вы имеете ввиду синтаксис или семантику? Если синтаксис, то отличие между port1.usart_driver_initialize(200, 300) и usart_driver_initialize(&port1, 200, 300) не существенно. Ну да, первый вариант красивее, но не более того. Если речь о семантике, то во многих (если не во всех) реализациях в VMT включаются только виртуальные функции. Таким образом, у класса без виртуальных функций нет ни VMT, ни указателей на функции.

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

                                                                              можно — с точки зрения отсутствия полиморфизма, можно — с точки зрения отсутствия late binding, это все разные стороны одной монеты.
                                                                              Вот-вот-вот… Вы уже очень близко. Остался маленький шаг — понять, что при отсутствии наследования полиморфизм вырождается. То есть чтобы вести речь о полиформизме — должен быть выбор хотя бы из двух реализаций. А это означает, что без наследования — нет ООП, а есть лишь «программирование, ориентированное на объекты».
                                                                                0
                                                                                Вы имеете ввиду синтаксис или семантику?

                                                                                Семантику, разумеется.


                                                                                Почему же? Абстрагирование полное.

                                                                                Ок, давайте, чтобы не углубляться в ненужные детали, считать, что у нас только initialize, send и receive. Как будет выглядеть код, который создаст массив из N портов разного типа, и шлет в цикле во все порты строку "Hello"?


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

                                                                                Почему же? Достаточно интерфейсов. Или вообще duck typing.

                                                                                  –1
                                                                                  Почему же? Достаточно интерфейсов. Или вообще duck typing.
                                                                                  Интерейсы изоморфны множественному наследованию от абстрактных базовых классов без статических членов и методов. Утиная типизация — это те же интерфейсы, просто имя интерфейса не пишется явно, а вычисляется компилятором или рантаймом.

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

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

                                                                                  Как будет выглядеть код, который создаст массив из N портов разного типа, и шлет в цикле во все порты строку «Hello»?
                                                                                  Не понимаю, в чем у вас проблемы? Хотите через массив — ну ловите через массив.

                                                                                  Абсолютно очевидный код
                                                                                  #define N_PORTS 10
                                                                                  struct usart_port *ports[N_PORTS];
                                                                                  for (int i=0; i <N_PORTS; i++)
                                                                                       ports[i] = usart_driver_get_driver_by_number(i);
                                                                                  for (int i=0; i <N_PORTS; i++) {
                                                                                      usart_driver_initialize(ports[i],64,64);
                                                                                      usart_driver_set_bps(ports[i],  115200);
                                                                                      const char *str = "Hello";
                                                                                      while (*str)
                                                                                          usart_driver_send_byte_with_timeout
                                                                                              (ports[i], *str++, 1); 
                                                                                  }


                                                                                  В свою очередь прошу объяснить, зачем вам массив? Экономия микросекунды на медленных операциях с портом? Не, конечно, как бы дитя не вешалось, лишь бы потешилось, но все-таки, зачем?
                                                                                    0

                                                                                    Массив был прямым намеком на late binding и LSP, на классический пример про геометрические фигуры. Полиморфизм времени линковки не считается, конечно же.


                                                                                    В общем, я понял, в чем у нас ключевое расхождение. Вы считаете систему контрактов вариацией механизма наследования. Но это вам так кажется под влиянием языка С++, в котором интерфейсы реализуются через pure abstract classes, а функцию "implements" выполняет множественное наследование. На самом деле это концептуально разные вещи: C extends A, B означает "C является A и является B", а C implements A, B означает "C поддерживает протоколы A и B". Да, наследование (множественное) позволяет реализовать интерфейсы. Но для реализации интерфейсов наследование не является необходимостью — существует масса иных способов, когда наследования нет, а интерфейсы есть (например, в Go). Да и на той же Джаве я могу написать объектно-ориентированную программу без единого extends, пользуясь только implements.

                                                                                      0
                                                                                      Чтоб вам было понятней, рассмотрим два примера.

                                                                                      1. Классический С++ или Delphi, объекты с развитым наследованием, но без виртуальных методов. Наследники вовсю пользуются методами базового класса, но никаких виртуальных методов нет. Назовете ли вы этот стиль ООП?
                                                                                      2. Классическая связь двух приложений через COM/DCOM. Клиент написан в процедурном стиле, сервер — тоже. Интерфейс — наш собственный. Назовете ли вы это ООП?
                                                                                        –1

                                                                                        1 — не знаю, что там в Delphi, но в С++ точно нет — без виртуальных методов не получится реализовать late binding (хаки с прямым доступом к памяти по оффсету не рассматриваю, конечно).


                                                                                        2 — зависит от архитектуры приложений, вполне может быть, что и ООП. По крайней мере, сам COM-вызов это ООПшная штука.

                                                                                          0
                                                                                          Ага, то есть late binding для вас обязательное условие. Хорошо, пусть в программе есть виртуальные методы и их перекрытие, но эти методы не вызываются. Будет ли такая программа ООП?

                                                                                          Ещё усложним. Пусть при одних настройках late binding происходит, а при других — нет. Означает ли это, что программа становится ООП при изменении настроек?
                                                                                            0
                                                                                            В Delphi (как и в boost/C++) возможен late binding без виртуальных методов. Делается это через события — это такие указатели, указывающие на метод конкретного объекта. То есть семантически «событие» — это два указателя, один на объект другой на метод, но синтаксически — это единое целое. Вроде бы в С++17 эта фича уже добавлена.

                                                                                            Так что late binding возможен и без ООП.

                                                                                            Я уж не говорю про самые обычные указатели на процедуры, которые были ещё в Си. Они по сути — тоже late binding.
                                                                                              0

                                                                                              Late binding в прямом смысле слова, конечно, необязателен. Разумеется, может быть любой другой механизм — такой, как вы описываете, или диспетчер сообщений в Objective-C. Реализация вообще не имеет значения. Важно, что там, где мне надо знать только контракты, мне действительно достаточно знать только контракты, конкретный тип (как и вообще наличие в языке конкретных типов) меня абсолютно не волнует.


                                                                                              Псевдокодом:


                                                                                              interface Fooable {
                                                                                                  void foo();
                                                                                              }
                                                                                              class FooHandler {
                                                                                                  void handleFoo(Fooable fooable) {
                                                                                                      fooable.foo();
                                                                                                  }
                                                                                              }
                                                                                              
                                                                                              Fooable fooable = getSomeFooableAnyhow();
                                                                                              FooHandler fooHandler;
                                                                                              fooHandler.handleFoo(fooable);

                                                                                              При этом абсолютно не имеет значения, какого конкретно типа тут foo. Что именно делает getSomeFooableAnyhow() — не имеет значения, за исключением того, что возвращает нечто, реализующее интерфейс Fooable. Конкретная реализация всегда может быть изменена на другую, код завязан на контракты а не не конкретную реализацию.

                                                                                                0
                                                                                                Разумеется, может быть любой другой механизм — такой, как вы описываете, или диспетчер сообщений в Objective-C.
                                                                                                Вы сейчас договоритесь до того, что любая GUI-программа для windows — это ООП. Там как раз есть диспетчеризация сообщений и late binding, сделанный на switch и if. Ну и объекты (окна) и их классы.
                                                                                                Что именно делает getSomeFooableAnyhow() — не имеет значения, за исключением того, что возвращает нечто, реализующее интерфейс Fooable
                                                                                                Так ровно это и делает usart_driver. Вы же не знаете, что именно возвращает фабрика, указатель на usart_driver или указатель на иную структуру (наследника), в начале которой сидит usart_driver.
                                                                                                Конкретная реализация всегда может быть изменена на другую, код завязан на контракты а не не конкретную реализацию.
                                                                                                Вот-вот-вот. Ровно это и есть в usart_driver. Может вы зря решили, что это не ООП? :-)
                                                                                    –1
                                                                                    Это может быть RS323, а может быть RS485, RS422 или радиомодем.

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

                                                                                      0
                                                                                      Да ну? У RS485 есть особенность: надо отдельно включать и выключать передатчик. Ибо если на линии два передатчика передают разные сигналы, то минимум один из них может сгореть. Так что код для RS485 чуть иной, чем для RS232.
                                                                                        0
                                                                                        Код для RS485 отличается от кода в RS232 в драйвере или в прикладной части программы?

                                                                                        Если второе — то тут вообще нет никакой ни абстракции, ни полиморфизма, одна лишь видимость.

                                                                                        Если первое — то об этом надо было говорить с самого начала.
                                                                                          0
                                                                                          Первое. И об этом говорилось. И ещё раз повторю, что код для драйвера выбирается в момент линковки. Ну, если точнее — у нас десяток разных кодов для фабрики, выдающей ссылку на драйвера (по одному на плату). Это и дает независимость прикладного кода от железа.

                                                                                          Но принципиально я могу написать код для USB с тем же интерфейсом и слинковаться с ним. Или на SPI. Или на UDP.

                                                                                          У меня в соседнем участке кода — 4 разных реализации на один H-файл. Это такой вот полиморфизм времени линковки.
                                                                                            0
                                                                                            Хм, а как вы с таким подходом будете делать плату с двумя передатчиками разного типа?
                                                                                              0
                                                                                              Это вы про что? Про 4 реализации? Ну если вы мне покажите SoC, в котором одни порты под linux, другие под FREERTOS на STM32F4/F7, третьи на LPC, а четвертые на К1879ВЯ1Я — то я подумаю. :-)

                                                                                              А если про usart_driver, то там все довольно просто. Он состоит из трёх частей: обработчик прерывания, процедура старта передачи при появлении символа в очереди и универсального чтения-записи в очередь. Как видите, обе не универсальные части — не имеют публичных имен.

                                                                                              Обработчики прерывания — вообще ставятся при инициализации. А процедура старта передачи… Ну тут лучше указатель на функцию. Хотя можно и без него — ветвление по значению поля, но это сильно хуже.
                                                                                                0
                                                                                                Нет, погодите. У вас если уже готовые модули usart_driver. И два порта, один RS232, а другой RS485. Что и с чем вы будете линковать чтобы все заработало?
                                                                                                  0
                                                                                                  Линкуется с двумя модулями. Один -универсальный с кодом драйвера, второй уникальный для платы usart_hw, содержащий фабрику. Там статически заданы структуры портов, а в них — прерывания, пины и так далее. Для RS485 там будет и код процедуры, управляющей пином TX_ENA.
                                                                                                    0
                                                                                                    То есть управление пином TX_ENA пишется заново (или копи-пастится) для каждой новой платы содержащей порт RS485?
                                                                                                      0
                                                                                                      Да, разумеется, это намного удобнее и компактнее, чем «универсальная» процедура, которой надо передавать адрес регистра на шине и бита в этом регистре. И которая к тому же не универсальна, ибо управление TX_ENA может идти не только одним битом GPIO.
                                                                                                        0
                                                                                                        Нет, в ООП универсальность достигается другими средствами: через указатель на функцию/интерфейс, которая уже управляет пином. Похоже на то как сделано у вас. Но я не могу понять что именно у вас сделано.

                                                                                                        Управление пином TX_ENA у вас пишется в каких процедурах? В процедуре «вызвать перед передачей» или в процедуре «установить пин TX_ENA»?
                                                                                                          0
                                                                                                          Фактически у нас компонентно-ориентированное программирование. Ну или что-то близкое к нему.

                                                                                                          Управление пином TX_ENA у вас пишется в каких процедурах?
                                                                                                          Уже писал:

                                                                                                           void (*set_rs485_tx_enable_pin) (int enable);


                                                                                                          Мелкое замечание. Точно так же как шитый код бывает прямым, косвенным, индексным и так далее, точно так же позднее связывание — это не только вызов процедуры по указателю. В конкретной реализации мы можем иметь и switch, выбирающий исполнение в зависимости от типа объекта, и указание в объекте индекса в таблице процедур и много много иных способов. Для кода, предполагающего расширение — это неудобно. Но если расширение не предполагается, то можно и так. А возможность расширения системы классов — не является определяющим свойством ООП.
                                                                      +3
                                                                      Заведение — средний род.
                                                                        0
                                                                        Угу, это я описался.
                                                                        0
                                                                         
                                                                      0
                                                                      > В общеупотребительном определении ООП наследование является обязательным признаком. Если у вас есть иное авторитетное определение — дайте на него ссылку.

                                                                      Достаточно по вашей же ссылке переключить на на более употребительный английский
                                                                      0

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

                                                                        0
                                                                        Собственно да. Композиция структур в Go вполне себе обеспечивает наследование поведения, хотя и не является наследованием классов(которых в Go, о ужас, тоже нет!) в классическом понимании)
                                                                          0

                                                                          Прототипное программирование в, например, JS является объектным, но не является объектно-ориентированным согласно некоторым определениям, для которых важным в ООП является наличие иерархии классов.

                                                                        0
                                                                        Объект «книга» в приложении для библиотеки должен обладать свойствами «абстрактного печатного издания», в магазине – «абстрактного товара»

                                                                        Стоп-стоп. С чего вдруг он должен? Товар это отдельное понятие, именно с книгой никак не связанное. В магазине ведется учет объектов класса "Товар", в нем есть ссылка на объект "книга", или "журнал", или "булка хлеба".

                                                                          0
                                                                          Рекомендую все-таки не ограничиваться одной цитатой, а почитать хотя бы главу по ссылке. А уж после этого можно будет и поспорить — эффективно ли предложенное вами решение и какие таблицы в СУБД оно порождает.

                                                                          Подсказка: цены где хранить будете? Хочу найти самый дешевый букварь, как поиск в СУБД пойдет? Хочу найти товары с наибольшей маржой, как поиск пойдет?
                                                                            0

                                                                            Там пишут вещи, противоположные тому, о чем я сказал.


                                                                            Теперь объект «книга» это контейнер для чего-то продающегося, выдаваемого, хранящегося и пылящегося. Необходимо быстро менять контекст: в магазине вкладывать в книгу товар.

                                                                            У меня в книгу ничего не вкладывается, это отдельная сущность. В этой терминологии надо "вкладывать" в товар книгу.


                                                                            Подсказка: цены где хранить будете?

                                                                            Как этот вопрос связан с логической ошибкой в вашей цитате? Вы считаете, что единственный способ назначить книге цену это сделать у нее свойство "цена"? У самой книги нет такого свойства. Автор есть, название есть, а цены нет.


                                                                            Есть такое понятие SKU — stock keeping unit. На него обычно и назначается цена.

                                                                              –1
                                                                              В этой терминологии надо «вкладывать» в товар книгу.

                                                                              Это не важно, все равно сущности плодятся.
                                                                              У самой книги нет такого свойства. Автор есть, название есть, а цены нет.

                                                                              Это неудобно. У вас получаются двунаправленные связи. С одной стороны, когда печатается чек, мы из SKU лезем в книгу за названием. С другой стороны, когда ищем самый дешевый букварь — у нас сортировка книг по цене. Слишком тесные связи между объектами — признак плохого дизайна.

                                                                              Ещё хуже, что мы получаем кучу JOIN на выборке из СУБД. И катастрофически теряем скорость.

                                                                              Правильный метод проектирования таких систем — идти от СУБД. То есть прикинуть самые частые запросы, разработать структуру таблиц. А уже по ней — делать программные сущности. И понимать, что они вторичны относительно таблиц СУБД. В смысле, что для одной и то же СУБД разные программные модули могут иметь разные структуры классов.
                                                                                0
                                                                                Это не важно, все равно сущности плодятся.

                                                                                Что значит "плодятся"? Оба понятия, и "книга" и "товар", есть в предметной области магазина. И это разные понятия.


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

                                                                                Когда печатается чек, у нас основаня сущность это SKU. Когда ищем самый дешевый товар определенного типа, у нас основная сущность тоже SKU.
                                                                                Это сводится к запросу вида WHERE product_type_id = 123 ORDER BY price LIMIT 1, и это не куча джойнов, а 1-2, в зависимости от реализации, которые к тому же неплохо заменяются на отдельные запросы с IN.


                                                                                Связи между сущностями есть, только они идут из предметной области и вы никуда от них не денетесь. А если попробуете, то да, у вас будут все эти "проблемы с ООП". Только это не из-за ООП, а из-за неправильной архитектуры.

                                                                                  0
                                                                                  Кстати, предлагаю вам задуматься, как в вашем подходе сделать, чтобы цена одной и той же книги в одном филиале была 100 р, а в другом 110.
                                                                                    0
                                                                                    В рамках ООП? Легко. Можно даже гибче.

                                                                                    Стандартный подход такой. Базовый класс — это таблица «книги». Наследником этого базового класса является view «книга-товар». В момент создания view клиент передает серверу СУБД всю информацию, нужную для формирования цены. При выполнении продажи в таблицу продаж добавляется проводка, в которой есть все данные, использованные для формирования view. Торговые остатки — это тоже view, но от таблицы проводок и таблицы поступлений.

                                                                                    Таким образом, мы имеем на одной базе разные ценовые планы не только по филиалам, но и по отдельным клиентам с их скидочной историей.

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

                                                                                    Из недостатков — та самая хрупкость базового класса, о которой писал Сергей Тарасов ( cross_join ). То есть на этапе проектирования таблицы «книги» хорошо бы представлять, какие у нас будут view, Ещё недостаток — чуть увеличивается время старта.

                                                                                    А что блокируется в вашей модели при продаже? И какэту задачу решили вы, если ставите вопрос о разности цен в филиалах, а не гибкой скидочной политики для клиентов? Филиалы редко добавляются, с ними особой возни нет. А вот условия для клиентов меняются быстро, согласно полету фантазий маркетологов.
                                                                                      0
                                                                                      является view «книга-товар». В момент создания view клиент передает серверу СУБД всю информацию, нужную для формирования цены

                                                                                      Ну о чем и речь. Цена это не свойство книги, она находится вне её. Непонятно, зачем вам надо ту часть view, которая не относится к таблице "книги", каким-то образом от нее наследовать, если вы все равно передаете информацию отдельно.


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

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


                                                                                      А что блокируется в вашей модели при продаже?

                                                                                      Технические проблемы решаются техническими средствами. Мы говорим о правильности моделирования.

                                                                                        0
                                                                                        Цена это не свойство книги, она находится вне её.
                                                                                        Свойство книги — это стоимость, то есть закупочная цена (для магазина) или себестоимость издания (для издательства). А все остальные цены — вычисляются исходя из себестоимости, и неких коэффициентов жадности и эластичности цены, которые тоже относятся к книге.

                                                                                        В филиалах хранятся SKU со своей ценой. Если есть скидки, они применяются на эту цену.
                                                                                        То есть в каждом филиале сидит тетенька-калькулятор и вручную считает для каждой книги её продажную цену? Зачем такая глупость, если все данные для расчета продажной цены и так есть в системе?

                                                                                        А если уж система считает цену, то зачем её хранить? Чтобы при падении было веселее восстанавливать?

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

                                                                                        Одна моя СУБД вполне выживала при миллионе записей в секунду. Реальный пик там был порядка 10 тысяч, но мы захотели запас по производительности в 10 раз, а заказчик — ещё в 10 раз. Это на Pentium-II 300Мгц. В итоге — работает 15 лет в режиме 365 на 24 без сбоев и техобслуживания. И это — далеко не HighLoad.

                                                                                        На самом деле, что блокируется и на сколько — одна из самых важных характеристик структуры базы. Потому что там, где блокировка не влияет — можно и вообще без СУБД.
                                                                                          –1
                                                                                          Свойство книги — это стоимость

                                                                                          То есть она все-таки хранится в таблице "книги"? Ну значит это и есть SKU, вы их объединили для технических целей, и у вас нет проблем потому что всего один тип товаров.
                                                                                          Только еще есть отдельный view и цена вычисляется на основе отдельной информации. Одного объекта не хватает. Явно есть большая внешняя связанность (high coupling). Если вас это устраивает в поддержке, то хорошо, только не надо говорить, что это правильная модель, и в любой системе надо делать такую же структуру классов.


                                                                                          То есть в каждом филиале сидит тетенька-калькулятор и вручную считает для каждой книги её продажную цену? Зачем такая глупость, если все данные для расчета продажной цены и так есть в системе?

                                                                                          Не вижу связи. Все что может быть автоматизировано, вычисляется автоматизировано.


                                                                                          А если уж система считает цену, то зачем её хранить?

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


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

                                                                                          Ага, только это характеристика реализации, а не модели.


                                                                                          Ага, ваш уровень понятен. А как только у вас будет хотя бы сотня продаж в секунду — вы почувствуете на себе, зачем нужна правильная архитектура.
                                                                                          Одна моя СУБД вполне выживала при миллионе записей в секунду.

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


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

                                                                                            0
                                                                                            А что вы будете делать, «как только у вас» будет больше чем один тип товаров?
                                                                                            Да не вижу проблем. Один вариант: для все товаров — однотипные view, другой — рассматривать остальные товары как недокниги. то есть не заполнять часть полей. Ну вот вам второй метод во всей красе — полюбуйтесь на поля «Издательство» и ISBN у дырокола. А это — один из лучших книжных магазинов в стране.

                                                                                            Еще раз, разговор о правильности модели.
                                                                                            Это только в школе есть «правильное» решение и все остальные. А в реальной жизни у каждой модели свои плюсы и минусы.

                                                                                            Ага, только это характеристика реализации, а не модели.
                                                                                            Читайте книжки по внутреннему устройству СУБД и по организации баз данных. Тогда начнете понимать, что блокировки сильно зависят именно от модели. Честное слово, нет никакого желания рассказывать вам азы.
                                                                                              –1
                                                                                              Ну вот вам второй метод во всей красе — полюбуйтесь на поля «Издательство» и ISBN у дырокола.

                                                                                              Во-во, начинаются костыли. Как и "Авторские, выставочные, технические экземпляры — это или продажа по нулевой цене или передача на «удаленный» склад."


                                                                                              Тогда начнете понимать, что блокировки сильно зависят именно от модели.

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


                                                                                              Это только в школе есть «правильное» решение и все остальные. А в реальной жизни у каждой модели свои плюсы и минусы.

                                                                                              Я не понимаю, что вы хотите доказать. Что если у вас сделано через наследование и оно как-то работает, то высказывание "Объект «книга» в приложении для библиотеки должен обладать свойствами «абстрактного печатного издания», в магазине – «абстрактного товара»" является верным? Это не так, я показал, как сделать по-другому. Или что из этого следует, что проблемы в этом варианте — это проблемы использования ООП, и вместо него надо всё делать на ассоциативных массивах? Это тоже не так, в другом варианте с ООП этих проблем нет.

                                                                                                –1
                                                                                                Я сказал, что производительность здесь не обсуждается,
                                                                                                Это одно из важных свойств, так что обсуждается. Собственно, если производительность совсем не важна — СУБД не нужна, можно и на штатом бухгалтеров на бумажках все операции делать.

                                                                                                Это не так, я показал, как сделать по-другому.
                                                                                                Угу, только ваш вариант — без ООП. А о том, что в таблицах СУБД бывает ООП, вы похоже даже не слышали.
                                                                                                  0

                                                                                                  СУБД для большинства приложений — это не способ увеличить производительность системы, а стандартизированное хранилище данных, знакомое (в идеале) каждому разработчику и позволяющее не изобретать велосипеды для каждого приложения, требующего постоянного хранения данных. В некоторых случаях использование популярных СУБД даже заметно уменьшает производительность системы, но значительно повышает скорость её разработки. Собственно, наверное, в большинстве случаев замедляет систему по сравнению с созданным специально для неё хранилищем.

                                                                                                    0
                                                                                                    Собственно, наверное, в большинстве случаев замедляет систему по сравнению с созданным специально для неё хранилищем.

                                                                                                    С этим соглашусь, сами специализированную СУБД делали.

                                                                                                    А в остальном — не очень согласен. Современная СУБД — не только слой хранения, это три слоя: хранения (table), абстракции (view), примитивов (SQL-процедуры). Просто если нам не нужна скорость — мы можем отказаться от нескольких слоев.
                                                                                                      0

                                                                                                      В большинстве приложений даже view не используется. Причём по умолчанию. Если нам нужна скорость, то начинаем использовать СУБД более полно, упираемся — пытаемся поменять на конкурирующую, упираемся — пишем свою. Как-то так. Это оптимизации. Да, бывает, что заранее понятно, что дорогие оптимизации нужно сразу делать, но именно бывает.

                                                                                                        –3
                                                                                                        View — не для скорости, а для ООПшности. Оно дает возможность из таблиц с разной структурой получить однотипные представления и обрабатывать их одной и той же SQL-процедурой. Для скорости — SQL-слой.

                                                                                                        А что уровень понимания СУБД крайне низок — это правда. Ещё цитата из cross_join:

                                                                                                        Можно ли, будучи в здравом уме, представить себе, чтобы обработка данных шла быстрее их передачи между слоями системы и отображения? Для этого надо серьёзно постараться в освоении «паттернов», нагромоздить кучу вроде бы правильного, но бессмысленного кода с высокой цикломатической сложностью, глубинами иерархий и связностью классов. Ситуацию не спасала автоматическая генерация кода большей части этого Ада Паттернов по сравнительно простой модели с несколькими десятками сущностей.

                                                                                                        Если пишешь нагруженную работу с СУБД — значит или привлекаешь DBA или сам им становишься. А иначе — хождение по граблям.
                                                                                                          0

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


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


                                                                                                          P.S. Не минусовал, если что.

                                                                                                            –1
                                                                                                            Грубо, разработчик должен не забыть обновить все объекты, использующую через view таблицу, в которую он только что внёс изменения через изменение и сохранения состояния объекта, представляющего запись этой таблицы

                                                                                                            УЖАС. Вы что, завязались, что у вас один клиент СУБД? А если у вас масштабирование и 100 серверов независимо друг от друга изменяют те же таблицы? Как вы тогда будете «обновлять объекты»?

                                                                                                            В нормальной модели считается, что достоверное состояние объектов только в базе. И только на время одной транзакции оно достоверно в сервере.

                                                                                                            Ну а слой view делается под слоем SQL-запросов именно для объектности. Он изолирует детали физических таблиц от таблиц логических.

                                                                                                            Как общеизвестный пример — вертикальное шардирование. Бухгалтерские проводки каждого года хранятся в отдельной таблице. Prov2015, Prov2016, Prov2017, Prov2018 и так далее. Переключать имена таблицы в десятке мест — неудобно. Поэтому все SQL-запросы работают с view CurYearProv, а переключается это view в выборе отчетного периода.

                                                                                                            Лично я переношу в крайних случаях, когда не вижу иной относительно простой возможности удовлетворить нефункциональным, прежде всего, требованиям.
                                                                                                            Ну а я, если уж использую SQL-СУБД, то пишу на SQL. И более-менее универсальный клиент к ней.
                                                                                                              +1

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


                                                                                                              SQL над view слоем универсальный и не зависящий от СУБД

                                                                                                              Как SQL над view слоем может не зависеть от СУБД, если даже СУБД может оказаться не SQL?

                                                                                                                –1
                                                                                                                Ну а как у нас одна и та же программа на С++ работает на windows и linux? C одной стороны ограничиваем язык до подмножества, исполняемого всюду, с другой — слой совместимости.

                                                                                                                Chrome и gcc не перестают быть кроссплатформенным от того, что их нельзя запустить на MS-DOS. Так что невозможность запуска на не SQL-базах — это детали.
                                                                                                              –1
                                                                                                              Чтобы вам было понятней, идеал выглядит так: SQL над view слоем универсальный и не зависящий от СУБД, а то, что под view-слоем — может зависеть и от СУБД и даже от тонкостей настройки на конкретной машине.
                                                                                      –1
                                                                                      Оба понятия, и «книга» и «товар», есть в предметной области магазина. И это разные понятия.

                                                                                      Забудьте о магазине. Магазин действительно может торговать не только книгами. Возьмите библиотеку или книжное издательство. В чем для них разница между книгой и товаром?

                                                                                      Это сводится к запросу вида WHERE product_type_id = 123 ORDER BY price LIMIT 1,

                                                                                      Мда… Вообще-то поиск — полнотекстовый. И никаких типов в нем нет. Есть жанры, но книга запросто может принадлежать разным жанрам. Ну скажем "Дети капитана Гранта" — классика, приключения, учебник географии.

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

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

                                                                                        Абсолютно в том же. Различие только в том, что товаров меньше (а именно один). А принципы те же.


                                                                                        Мда… Вообще-то поиск — полнотекстовый. И никаких типов в нем нет.

                                                                                        Вообще-то вы сказали про определенный тип книг, а не про поиск по названию. Допустим есть книга "Веселые буквы" — по какому тексту вы определите, букварь это или сказка?
                                                                                        Ок, допустим у нас есть жанр "букварь". Как я сказал, запрос по типу можно заменить на запрос с IN. Получаем ID всех книг в жанре "букварь", дальше вместо product_type_id = 123 будет product_id IN (...). Заодно и один джойн убрали. Еще можно использовать возможности движка полнотекстового поиска, это отдельный разговор.


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

                                                                                        Очень просто. У товара есть цена, у книги нет. Вот у меня книга есть "Гарри Поттер и философский камень", какие у нее год выхода, автор, и цена? Первые 2 вы можете в независимых источниках, но цена везде будет разная. А еще может быть, что в пределах одного издательства книга отдельно имеет одну цену, а в составе подарочного издания другую.


                                                                                        Если в предметной области один тип товаров, это не значит, что книга имеет все свойства товара. Вы можете их объединить, если вам это нужно для технический целей (оптимизация запросов например), но надо понимать, что вы нарушаете правильную модель и это может привести к проблемам. Что и описано в статье, которую вы постоянно приводите.
                                                                                        И уж тем более это не значит, что для других предметных областей надо "в магазине вкладывать в книгу товар, в библиотеке – печатное издание, в отделе «книга-почтой» – ещё какую-нибудь хреновину".

                                                                                          0
                                                                                          Различие только в том, что товаров меньше (а именно один).
                                                                                          То есть в таблице «Товар» одна запись? ОК, опишите структуру СУБД для издательства исходя из этой вашей идеи.

                                                                                          Допустим есть книга «Веселые буквы» — по какому тексту вы определите, букварь это или сказка?
                                                                                          ОЗОН, например, ищет в том числе и по аннотации, потому и находит вот такое. А вот Буквоед ищет только по названию.

                                                                                          Ок, допустим у нас есть жанр «букварь».
                                                                                          Лучше допустим, что библиографии вас не учили. :-) ББК и УДК на букварях не пишется, а ISBN не дает возможности понять, что это букварь.

                                                                                          У товара есть цена, у книги нет.
                                                                                          Ох как интересно. То есть авторские экземпляры — это один товар, крупнооптовая поставка — другой товар, мелкооптовая — третий товар? В итоге вы дойдете до того, что раз для каждой крупной торговой сети цена разная, то и товар для каждой сети разный.

                                                                                          А что с количеством (торговыми остатками)? Вы его небось привязываете к товару? А теперь представьте, что торговые остатки для продажи по более высокой цене сошли в 0. Зато есть та де книга по цене для крупного опта, то есть по низкой. Как вы будете организовывать её продажу?

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

                                                                                          надо понимать, что вы нарушаете правильную модель
                                                                                          Мда… Диагноз ясен. Ничего страшного, лет через 20 вы сами будете смеяться над теми, кто видит лишь одну, истинно верную модель.

                                                                                          И уж тем более это не значит, что для других предметных областей надо «в магазине вкладывать в книгу товар,
                                                                                          Гм, вы хоть раз с view работали? А вообще, ООП в структуре СУБД использовали? Я вам в другом ответе написал, как происходит это вкладывание и что оно дает.
                                                                                            0
                                                                                            ОК, опишите структуру СУБД для издательства исходя из этой вашей идеи.

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


                                                                                            ОЗОН, например, ищет в том числе и по аннотации
                                                                                            Лучше допустим, что библиографии вас не учили.

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


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

                                                                                            Разные единицы продажи (которые SKU). Они ссылаются на один и тот же объект "книга".


                                                                                            А что с количеством (торговыми остатками)? Вы его небось привязываете к товару?

                                                                                            И это тоже привязывается к SKU. Stock keeping unit — складская учётная единица.


                                                                                            Зато есть та же книга по цене для крупного опта, то есть по низкой. Как вы будете организовывать её продажу?

                                                                                            Это организационные вопросы, к структуре классов они не имеют никакого отношения.


                                                                                            кто видит лишь одну, истинно верную модель.

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

                                                                                              0

                                                                                              Реальность одна (ну, если придерживаемся объективизма :) ), а моделей её множество, в зависимости от задач и степени познания реальности. Причём даже в одной системе может быть несколько моделей одного физического объекта. Например, взять конкретного человека, который в системе выступает то пользователем системы, то сотрудником, то клиентом.

                                                                                                0
                                                                                                Ну можно и так сказать, хотя это все-таки разные проекции более общей модели.

                                                                                                Все равно высказывание «Объект «книга» в приложении для библиотеки должен обладать свойствами «абстрактного печатного издания», в магазине – «абстрактного товара»» не является верным.
                                                                                                  +1

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


                                                                                                  Когда вы хотите читать книгу (которая уже есть у вас), вы, в общем случае, не думаете о ней как о товаре. Когда покупаете в подарок — не думаете о том, где дома её хранить будет одариваемый. В приложениях то же самое.

                                                                                                    0
                                                                                                    И их может быть множество одновременно в одном сознании в зависимости от контекста, от решаемой задачи.

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

                                                                                                      0

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

                                                                                                0
                                                                                                Я не знаком с предметной областью и описывать не буду.
                                                                                                Угу. Как критиковать — так знакомы, как придумать — так не знакомы.

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

                                                                                                Это такой секрет полишинеля, известный каждому первокласснику: букварь называется «Букварь», азбука «Азбука», а учебник чтения «Чтение». В учебниках для взрослых это не всегда так и учебник физики для ВУЗов может называться "Фейнмановские лекции по физике", но для малышей — только так.

                                                                                                Что касается подмешивания в поиск всего, где упомянуто слово «Букварь» — это решение разработчиков конкретных сайтов. Озон ещё и отличия в падежах игнорирует.

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

                                                                                                И это тоже привязывается к SKU. Stock keeping unit — складская учётная единица.

                                                                                                Это организационные вопросы, к структуре классов они не имеют никакого отношения.

                                                                                                Модель одна, потому что реальность у нас одна.
                                                                                                Вот это и есть ваша модель — фиксированная цена у SKU и наличие нескольких SKU на один и тот же артикул товара.

                                                                                                А есть другая модель — одна книга — один артикул — одно SKU. Зато цен на одну книгу может быть много. В этой модели нет проблемы «Мы не можем продать по дорогой цене, хотя книга есть в запасе».

                                                                                                А есть второй срез. Мы можем изменять остатки при помощи UPDATE прямо в SKU, а можем — использовать двойную запись. И это тоже будут разные модели.

                                                                                                Модель одна, потому что реальность у нас одна
                                                                                                Оптику не помните? Корпускулярно волновой-дуализм? То, что у нас одна реальность, абсолютно не мешает использовать разные модели.
                                                                                                  0
                                                                                                  Угу. Как критиковать — так знакомы, как придумать — так не знакомы.

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


                                                                                                  Это такой секрет полишинеля, известный каждому первокласснику

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


                                                                                                  Вот это и есть ваша модель — фиксированная цена у SKU и наличие нескольких SKU на один и тот же артикул товара.
                                                                                                  А есть другая модель — одна книга — один артикул — одно SKU.

                                                                                                  "Одно" — это частный случай "несколько".


                                                                                                  Зато цен на одну книгу может быть много. В этой модели нет проблемы «Мы не можем продать по дорогой цене, хотя книга есть в запасе».

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


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

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

                                                                                                    +1
                                                                                                    «Одно» — это частный случай «несколько».
                                                                                                    Вы, конечно, можете строить базу исходя из того, что у клиента может быть несколько имен, отчеств и фамилий. Но вряд ли это хорошая идея. :-)

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

                                                                                                    И все равно здесь не нужно никакое наследование.
                                                                                                    Отлично, что вы наконец-то признали, что ООП — не панацея. И далеко не всегда нужно.

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

                                                                                                      Ага, только это ситуация маловерятная ввиду особенностей предметной области, а несколько товаров это нормальная ситуация. И ваш пример с дыроколом это подтверждает.


                                                                                                      Особенно это кайфно на HiighLoad.

                                                                                                      А как вы новые книги в этом хайлоаде добавляете? Там ведь тоже количество меняется. Значит это возможно.


                                                                                                      Потому что сама такая перекладка показывает, что дизайн базы крив.

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


                                                                                                      Отлично, что вы наконец-то признали, что ООП — не панацея. И далеко не всегда нужно.

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

                                                                                                        0
                                                                                                        А как вы новые книги в этом хайлоаде добавляете?
                                                                                                        Добавление записей — это не обновление. При добавлении не блокируется чтение и очень слабо блокируется добавление других записей. А при обновлении блокируется прежде всего чтение. То есть все SELECT ждут, пока у вас пройдет UPDATE.

                                                                                                        Такая перекладка показывает только, что вам удобнее чтобы SKU для одной книги у вас был один,
                                                                                                        Не только мне (разработчику) удобнее, а бизнесу (заказчику). В моем варианте как пришел товар — так его можно продавать. В вашем варианте надо ждать, пока менеджер вручную выберет, под каким SKU его зачислить. То есть скорость работы софта зависит от человеческого придатка.

                                                                                                        Для выделения нового SKU товар должен хоть чем-то отличаться — цветом, размером, упаковкой, закупочной ценой, наконец. Но не продажной политикой. Какие есть скидки-наценки — определяются вовсе не «единица учёта запасов», которым является SKU.

                                                                                                        Почему вы приравниваете наследование к ООП?
                                                                                                        Потому что все остальное — не ООП. Обязательный признак ООП — это позднее связывание. То есть можно ограничиться наследованием интерфейсов и не наследовать данные, но без позднего связывания — это не ООП.

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

                                                                                                        Но это все равно будут классы со специфическими методами и типизированные объекты, связанные композицией.
                                                                                                        Это не ООП. Например в Ада изначально были package, в турбо-паскале — модули со схожими свойствами, и никто не считал их за ООП.
                                                                                                        0
                                                                                                        Вы, конечно, можете строить базу исходя из того, что у клиента может быть несколько имен, отчеств и фамилий. Но вряд ли это хорошая идея. :-)

                                                                                                        Да нет, иногда это просто-таки необходимо. На Госуслугах, например, я больше чем уверен, у физ. лиц хранится не по одному имени/фамилии. Да и в налоговой. Да и в банках… Да много где. Не самый удачный пример, короче )
                                                                                                          0
                                                                                                          Везде хранят по одному. При смене — обычно заводится новая запись. Куча проблем при перемене фамилии связано именно с этим. Более того — и номер паспорта обычно хранится только один, редко кто позволяет авторизоваться по нескольким номерам паспорта, везде хотят один — тот, который база считает верным.

                                                                                                          P.S. Собственно с этим связана "проблема несчастной Королевы", которая в половине документов КоролЁва. Никто не умеет сливать две записи в одну. Риелторы — стонут.
                                                                                                            0
                                                                                                            P.P.S. Лично я год назад мучался с оформлением пенсий для одной ВалерЬевны, которая в половине документов ВалерИевна. Увы, всего одна запись, отсюда и мучения.
                                                                                                            0

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

                                                                                                              0
                                                                                                              Замена паспорта вызывает замену данных в базе. Меняли бы фамилию — увидели бы сами. :-)
                                                                                                                0

                                                                                                                От базы зависит. В некоторых, даже публично доступных государственных, отображается по идентификатору текущие ФИО, но поиск по ФИО учитывает изменение ФИО в прошлом.

                                                                                                                  0
                                                                                                                  Можно примеры баз, в которых решена проблема КоролЕвы — КоролЁвы?