Ложь 2: код должен быть разработан вокруг модели мира? [закрыто]

23

Я недавно прочитал сообщение в блоге « Три больших лжи», и мне трудно оправдать вторую ложь, которая цитируется здесь:

(ЛОЖЬ № 2) КОД ДОЛЖЕН БЫТЬ ПРОИЗВЕДЕН Вокруг модели мира

В коде нет никакого смысла в том, чтобы быть какой-то моделью или картой воображаемого мира. Я не знаю, почему это так привлекательно для некоторых программистов, но оно чрезвычайно популярно. Если в игре есть ракета, будьте уверены, что существует класс «Rocket» (при условии, что код - C ++), который содержит данные только для одной ракеты и выполняет непростые задачи. Не обращая внимания ни на то, что на самом деле делается преобразование данных, ни на расположение данных. Или, если на то пошло, без базового понимания, что там, где есть одна вещь, вероятно, больше, чем одна.

Несмотря на то, что для такого дизайна существует множество проблем с производительностью, наиболее важным является то, что он не масштабируется. Вообще. Сто ракет стоит в сто раз больше одной ракеты. И очень вероятно, что это стоит даже больше, чем это! Даже для непрограммиста это не должно иметь никакого смысла. Экономия от масштаба. Если у вас есть что-то еще, это должно стать дешевле, а не дороже. И способ сделать это - правильно спроектировать данные и сгруппировать вещи с помощью аналогичных преобразований.

Вот мои проблемы с этой ложью в частности.

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

  2. Для меня класс "Ракета" является для меня совершенно правильным выбором. Возможно, «Ракеты» можно разбить на типы Ракет, такие как AGM-114 Hellfire и т. Д., Которые будут содержать силу полезной нагрузки, максимальную скорость, максимальный радиус разворота, тип цели и т. Д., Но все же каждая ракета должна иметь позицию и скорость.

  3. Конечно, наличие 100 Ракет стоит более 1 Ракеты. Если на экране 100 ракет, для обновления их позиции необходимо выполнить 100 различных вычислений. Второй абзац звучит так, как будто он утверждает, что если существует 100 Ракет, то для обновления состояния потребуется менее 100 вычислений?

Моя проблема здесь в том, что автор представляет «ошибочную» модель программирования, но не представляет способ ее «исправить». Возможно, я прибегаю к аналогии с классом Rocket, но мне бы очень хотелось понять причины этой лжи. Какая альтернатива?

thndrwrks
источник
9
@gnat: Этот вопрос относится непосредственно к области разработки программного обеспечения, поэтому я склонен дать ему некоторую свободу действий.
Роберт Харви,
12
Это сообщение в блоге написано довольно плохо и не защищает и не поддерживает свои требования слишком хорошо. Я бы не стал много думать об этом.
WhatsName
21
Тот, кто написал эту цитату, - идиот, мало понимающий концепции ОО или то, как они реализованы в программном обеспечении. Во-первых, мы не отображаем воображаемый мир, мы сопоставляем его с реальным миром. И если у вас есть 100 ракет, только состояние дополнительных ракет использует дополнительные ресурсы, а не модель или поведение. Кажется, у него разные представления об этом, и он предлагает решить проблему, которая не существует. «Группировка похожих вещей» в качестве оптимизации может иметь смысл иногда, но она полностью независима от использования классов или нет. Если вы хотите учиться, держитесь подальше от этого шарлатана.
Мартин Маат
3
Учитывая, что автор не удосужился написать более 5 абзацев, объясняющих «3 большие лжи», вы, вероятно, потратили больше времени на обдумывание статьи, чем он. Если он не потрудится приложить усилия, вы тоже не должны.
Калеб
9
Я думаю, что он имеет в виду, вам действительно нужно 100 [возможно, динамически распределенных с помощью виртуальных методов] «ракетных объектов», в отличие от списка позиций, списка скоростей и т. Д. (Имеющих список всех позиций и список скоростей означает, что вы можете использовать векторные инструкции для добавления скорости к позиции при каждом обновлении тика, а не писать
простой

Ответы:

63

Во-первых, давайте посмотрим на некоторый контекст: это гейм-дизайнер, пишущий в блоге, тема которого заключается в том, чтобы получить последнее падение производительности процессора Cell BE. Другими словами: речь идет о программировании консольных игр, точнее, программировании консольных игр для PlayStation 3.

Теперь программисты игр - любопытная куча, программисты консольных игр - тем более, и Cell BE - довольно странный процессор. (Есть причина, по которой Sony выбрала более привычный дизайн для PlayStation 4!)

Итак, мы должны посмотреть на эти заявления в этом контексте.

В этом посте есть и некоторые упрощения. В частности, эта ложь № 2 представлена ​​плохо.

Я бы сказал, что все, что абстрагируется от реального мира, в некотором смысле является моделью. А поскольку программное обеспечение не является реальным, а виртуальным, оно всегда является абстракцией и, следовательно, всегда моделью. Но! Модель не должна иметь четкое отображение 1: 1 в реальном мире. Это, в конце концов, то, что делает его моделью в первую очередь.

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

Я приведу пример, который я уже приводил в некоторых других ответах за эти годы, - (в) знаменитый пример «Введение в OO 101». Вот как выглядит банковский счет практически во всех классах OO:

class Account {
  var balance: Decimal
  def transfer(amount: Decimal, target: Account) = {
    balance -= amount
    target.balance += amount
  }
}

Итак: balanceэто данные , а transferэто операция .

Но! Вот как выглядит банковский счет практически во всех банковских программах:

class TransactionSlip {
  val transfer(amount: Decimal, from: Account, to: Account)
}

class Account {
  def balance = 
    TransactionLog.filter(t => t.to == this).map(_.amount).sum - 
    TransactionLog.filter(t => t.from == this).map(_.amount).sum
}

Таким образом, теперь transferэто данные , и balanceявляется операция (левый сгиб журнала транзакций). (Вы также заметите, что TransactionSlipон неизменный, balanceявляется чистой функцией, TransactionLogможет быть «почти» неизменяемой структурой данных только для добавления… Я уверен, что многие из вас заметили явные ошибки параллелизма в первой реализации, которые теперь волшебным образом исчезают » .)

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

Итак, вопрос не в том , моделируете ли вы «реальный мир» в своем коде, а в том , как вы его моделируете.

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

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

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

Йорг Миттаг
источник
1
Не означает ли это, что хороший код моделирует реальный мир, и что на самом деле это только неправильное понимание реального мира, которое приводит к плохой модели и, следовательно, к плохому коду?
Ицих
14
Я бы предпочел сформулировать это как «иногда реальный мир - это не то, что вы думаете» или «то, что« реальный мир »зависит от контекста». (Опять же, для владельца банковского счета, данные в нижней части их заявления очень реальны, в то время как для банковского работника они эфемерны.) Я думаю, что утверждение в сообщении в блоге в основном вызвано тем, что автор не понимает, что «моделирование» реальный мир "не означает" фотографировать и делать все, что вы там видите, классом ".
Йорг Миттаг
Внешний интерфейс для вашего приложения для онлайн-банкинга, вероятно, будет обрабатывать balanceкак данные и транзакции как больше данных, так и передавать как операции, потому что это то, что видит пользователь, даже несмотря на то, что серверная часть может относиться к нему по-другому.
user253751
@yitzih: каждая модель - это абстракция и упрощение, поэтому вы можете обвинить каждую модель в том, что она неверна, но это не конструктивно. Каждая модель должна соответствовать цели и должна быть достаточно хороша для этого, не тратя ресурсы на ненужные вещи. Для правительственного программного обеспечения человек может быть человеком, который может участвовать в выборах, должен платить налоги или может состоять в браке с другим человеком, для нашего программного обеспечения CRM человек - это человек, который связан с заказами и имеет адрес доставки (и ни моделирует, как (а) он ест)…
Хольгер,
2
Если человек знает что-нибудь о банковском деле, ему будет легче найти второе, и, поскольку известные ему банковские методы были изобретены для обеспечения банковской работы, они могут сделать банковское программное обеспечение работающим. Не потому, что вторая модель «больше похожа на реальный мир», а потому, что она описывает лучший банк. Первая модель может быть одинаково точным представлением реального нефункционального банка! Угадайте, что: если вам нужно хорошее банковское программное обеспечение, то программистам нужно научиться хорошо делать банковские операции, хотя бы из документации по требованиям.
Стив Джессоп
19

Я не согласен с каждой «ложью», которую он предлагает.

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

Ложь № 1 - Большой О имеет значение для масштабирования. Никого не волнует, если крошечному приложению требуется больше времени, что является единственной постоянной величиной времени, они заботятся о том, чтобы при удвоении входного размера оно не умножало время выполнения в 10 раз.

Ложь № 2 - Моделирование программ после реального мира позволяет программисту, смотрящему на ваш код 3 года спустя, легко понять, что он делает. Код должен быть поддерживаемым, иначе вам придется потратить часы, пытаясь понять, что пытается сделать программа. Другой ответ предполагает, что вы можете иметь более общие классы, такие как LaunchPadи MassiveDeviceMover. Это не обязательно плохой класс, чтобы иметь, но вам все равно нужен Rocketкласс. Как кто-то должен знать, что MassiveDeviceMoverделает или что он движется? Это движущиеся горы, космические корабли или планеты? Это в основном означает, что добавление в такие классы MassiveDeviceMoverделает вашу программу менее эффективной (но, возможно, более читаемой и понятной).

Кроме того, стоимость времени на разработку стала превышать стоимость оборудования давно. Это ужасная идея, начинать с попыток проектирования с оптимизацией перед вашими мыслями. Вы программируете это простым и понятным способом, а затем настраиваете свою программу, узнавая, какие части ваших программ занимают много времени для запуска. Не забывайте: 80% времени выполнения используется 20% программы.

Ложь № 3 - Кодекс чрезвычайно важен. Хорошо написанный (и модульный) код допускает повторное использование (экономя бесчисленное количество человеко-часов). Это также позволяет вам просматривать и распознавать неверные данные, чтобы их можно было обработать. Данные прекрасны, но без кода было бы невозможно анализировать и получать из них полезную информацию.

yitzih
источник
5
Я думаю, что я больше сочувствую # 3. За 30 лет программирования подавляющее большинство ошибок, проблем с производительностью и других проблем, которые я видел, были решены путем исправления представления данных. Если данные верны, код практически пишет сам.
Ли Даниэль Крокер
6
Реальная проблема с # 3 заключается в том, что он сравнивает яблоки с апельсинами, а не то, что код важнее данных или наоборот.
Док Браун
3
Исходные данные не в ваших руках, но способ представления данных в вашем программном обеспечении полностью находится в их распоряжении. Возможно, вы называете эту часть «кодированием», но я думаю, что это не так: например, оно часто не зависит от языка и часто выполняется до начала любого кодирования. Я согласен, однако, что код, который очищает некрасивые входные данные, часто является хорошей вещью; но вы не можете сделать это, пока у вас нет определения «чистый».
Ли Дэниел Крокер
3
На самом деле я не думаю, что Ложь № 3 - это Ложь. Фред Брукс уже писал десятилетия назад: «Покажите мне свои блок-схемы и скройте ваши таблицы, и я буду продолжать озадачиваться. Покажите мне ваши таблицы, и мне обычно не понадобятся ваши блок-схемы; они будут очевидны». (В настоящее время мы, вероятно, будем говорить об «алгоритмах» и «типах данных» или «схемах».) Таким образом, важность данных давно известна.
Йорг Миттаг
1
@djechlin Моя точка зрения была не в том, что данные не важны или что код важнее. Просто эти данные не важнее, чем код. Они оба очень важны и сильно зависят друг от друга.
Ицих
6

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

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

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

Роберт Харви
источник
5

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

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

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

Какая альтернатива?

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

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

Telastyn
источник
1
+1: Протоколы являются очень «реальным миром» абстракцией. Например, даже в современном мире сотрудники протокола являются одними из самых важных сотрудников штата, например, для государственного визита. Кто идет первым по красной дорожке на встрече G8, Обама или Путин? Они обнимаются или пожимают друг другу руки? Как мне приветствовать араб против индейца? И так далее. У нас есть много «вещей» в «реальном мире», которые не являются «вещами» в «физическом мире». Моделирование реального мира не означает моделирование физического мира. Даже если Rocketв коде этого парня нет типа, я готов поспорить, что, тем не менее, есть какая-то модель…
Йорг Миттаг
... реальный мир, даже если он не соответствует чему-то «физическому» (в смысле «осязаемого»). Я не был бы слишком удивлен, обнаружив там реальные «физические» объекты (в смысле «вещей, которые физик мог бы распознать»), такие как кватернионы, тензоры, поля и т. Д., Которые, конечно, также « вещи реального мира "и" модели реального мира ".
Йорг Миттаг
Алан Кей представлял Dynabook как компьютер, который будет давать детям при рождении и который станет расширением их мозга. Целью паттерна MVC было бы то, чтобы View и Controller ликвидировали разрыв между мозгом и моделью для поддержки метафоры прямой манипуляции, т.е. иллюзии, что компьютер является лишь расширением мозга, и что можно напрямую манипулировать объектами модели своими мыслями. И это то, что мы имеем в виду, когда говорим, что модель предметной области моделирует «реальный мир». Следует реализовать абстракции в нашем мозгу.
Йорг Миттаг
И когда я думаю о физическом движке для консольных игр, то, вероятно, я действительно не думаю о ракетах, и поэтому в моем коде не должно быть модели ракеты. Но я , наверное , думает некоторые другие «реальный мир мысли», и там должны быть модели тех , в коде.
Йорг Миттаг
2

Альтернатива - моделировать вещи, которые заботятся о ваших программах. Даже если ваша программа имеет дело с ракетами, вам может не понадобиться объект, называемый a Rocket. Например, у вас может быть LaunchPadсущность, LaunchScheduleсущность и MassiveDeviceMoverсущность. Тот факт, что все это помогает запуску ракет, не означает, что вы сами управляете ракетами.

BobDalgleish
источник
0

Моя проблема здесь в том, что автор представляет «ошибочную» модель программирования, но не представляет способ ее «исправить». Возможно, я прибегаю к аналогии с классом Rocket, но мне бы очень хотелось понять причины этой лжи. Какая альтернатива?

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

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

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

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

Еще раз два , вот он и прав. Я видел, как разработчики потратили недели или больше времени на разработку класса «ракета», когда работал бы простой класс «транспортное средство», или еще более простой «подвижный» класс. Если все, что нужно вашей ракете, это двигаться с левой стороны экрана вправо и издавать звук, тогда вы можете использовать тот же класс, который вы использовали для автомобилей, поездов, лодок и мух. 100 должно стоить меньше, чем аргумент 1 * 100, кажется, затрачено на разработку, и не так много в вычислительных затратах. Хотя придерживаться меньшего числа общих классов, которые можно использовать повторно, «дешевле», чем многие конкретные классы, которые нельзя использовать повторно. Вероятно, это можно переписать так: «общие классы лучше, чем конкретные классы,

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

Последнее замечание, статья была написана в 2008 году (насколько я мог судить). Вещи меняются быстро. Утверждения верны сегодня, но встроенные системы сегодня гораздо более распространены, чем тогда, и модели развития меняются. Возможно, даже в ответ на эту статью / разговор.

coteyr
источник
-1

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

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

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

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

Прайс Джонс
источник
4
К сожалению, клиенты хотят быстрого и грязного кода, который легко читать и обслуживать, дешево, без усилий по тестированию и без ошибок.
Гонен, я
@ user889742 Ха! Правда. Вы точно заявили, что инженерные проблемы все время пытаются решить архитекторы, и что делает индустрию таким интересным пространством для работы.
Прайс Джонс
Он игнорирует человеческий фактор, потому что он разработчик игр, и эра обслуживания игры относительно недолговечна, хотя сегодня дольше, чем в 2008 году. Патчи первого дня, по-видимому, являются нормой в играх в наши дни. Еще в 2008 году патчи для игр были еще относительно редки.
RubberDuck
-1

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

Гонен я
источник