Я недавно прочитал сообщение в блоге « Три больших лжи», и мне трудно оправдать вторую ложь, которая цитируется здесь:
(ЛОЖЬ № 2) КОД ДОЛЖЕН БЫТЬ ПРОИЗВЕДЕН Вокруг модели мира
В коде нет никакого смысла в том, чтобы быть какой-то моделью или картой воображаемого мира. Я не знаю, почему это так привлекательно для некоторых программистов, но оно чрезвычайно популярно. Если в игре есть ракета, будьте уверены, что существует класс «Rocket» (при условии, что код - C ++), который содержит данные только для одной ракеты и выполняет непростые задачи. Не обращая внимания ни на то, что на самом деле делается преобразование данных, ни на расположение данных. Или, если на то пошло, без базового понимания, что там, где есть одна вещь, вероятно, больше, чем одна.
Несмотря на то, что для такого дизайна существует множество проблем с производительностью, наиболее важным является то, что он не масштабируется. Вообще. Сто ракет стоит в сто раз больше одной ракеты. И очень вероятно, что это стоит даже больше, чем это! Даже для непрограммиста это не должно иметь никакого смысла. Экономия от масштаба. Если у вас есть что-то еще, это должно стать дешевле, а не дороже. И способ сделать это - правильно спроектировать данные и сгруппировать вещи с помощью аналогичных преобразований.
Вот мои проблемы с этой ложью в частности.
В коде есть ценность быть моделью / картой воображаемого мира, так как моделирование воображаемого мира помогает (по крайней мере мне лично) визуализировать и организовать код.
Для меня класс "Ракета" является для меня совершенно правильным выбором. Возможно, «Ракеты» можно разбить на типы Ракет, такие как AGM-114 Hellfire и т. Д., Которые будут содержать силу полезной нагрузки, максимальную скорость, максимальный радиус разворота, тип цели и т. Д., Но все же каждая ракета должна иметь позицию и скорость.
Конечно, наличие 100 Ракет стоит более 1 Ракеты. Если на экране 100 ракет, для обновления их позиции необходимо выполнить 100 различных вычислений. Второй абзац звучит так, как будто он утверждает, что если существует 100 Ракет, то для обновления состояния потребуется менее 100 вычислений?
Моя проблема здесь в том, что автор представляет «ошибочную» модель программирования, но не представляет способ ее «исправить». Возможно, я прибегаю к аналогии с классом Rocket, но мне бы очень хотелось понять причины этой лжи. Какая альтернатива?
источник
Ответы:
Во-первых, давайте посмотрим на некоторый контекст: это гейм-дизайнер, пишущий в блоге, тема которого заключается в том, чтобы получить последнее падение производительности процессора Cell BE. Другими словами: речь идет о программировании консольных игр, точнее, программировании консольных игр для PlayStation 3.
Теперь программисты игр - любопытная куча, программисты консольных игр - тем более, и Cell BE - довольно странный процессор. (Есть причина, по которой Sony выбрала более привычный дизайн для PlayStation 4!)
Итак, мы должны посмотреть на эти заявления в этом контексте.
В этом посте есть и некоторые упрощения. В частности, эта ложь № 2 представлена плохо.
Я бы сказал, что все, что абстрагируется от реального мира, в некотором смысле является моделью. А поскольку программное обеспечение не является реальным, а виртуальным, оно всегда является абстракцией и, следовательно, всегда моделью. Но! Модель не должна иметь четкое отображение 1: 1 в реальном мире. Это, в конце концов, то, что делает его моделью в первую очередь.
Так что, в некотором смысле, автор явно неправ: программное обеспечение - это модель. Период. В каком-то другом смысле он прав: эта модель вообще не должна напоминать реальный мир.
Я приведу пример, который я уже приводил в некоторых других ответах за эти годы, - (в) знаменитый пример «Введение в OO 101». Вот как выглядит банковский счет практически во всех классах OO:
Итак:
balance
это данные , аtransfer
это операция .Но! Вот как выглядит банковский счет практически во всех банковских программах:
Таким образом, теперь
transfer
это данные , иbalance
является операция (левый сгиб журнала транзакций). (Вы также заметите, чтоTransactionSlip
он неизменный,balance
является чистой функцией,TransactionLog
может быть «почти» неизменяемой структурой данных только для добавления… Я уверен, что многие из вас заметили явные ошибки параллелизма в первой реализации, которые теперь волшебным образом исчезают » .)Обратите внимание, что оба они являются моделями. Оба из них одинаково действительны. Оба они верны. Обе эти модели одно и то же. И все же они точно двойственны друг другу: все, что является данными в одной модели, является операцией в другой модели, а все, что является операцией в одной модели, является данными в другой модели.
Итак, вопрос не в том , моделируете ли вы «реальный мир» в своем коде, а в том , как вы его моделируете.
Как выясняется, вторая модель на самом деле также показывает, как банкинг работает в реальном мире. Как я уже упоминал выше, эта вторая модель в основном неизменна и чиста и неуязвима к ошибкам параллелизма, что на самом деле очень важно, если учесть, что не так давно было время, когда
TransactionSlip
были настоящие листки бумаги, которые были разосланы через лошадь и карету.Тем не менее, тот факт, что эта вторая модель фактически совпадает как с тем, как работает реальная банковская система, так и с тем, как работает реальная банковская программа, автоматически не делает ее более «правильной». Потому что, на самом деле, первая («неправильная») модель довольно близко приближает взгляды банковского клиента на свой банк. Для них ,
transfer
это операция (они должны заполнить форму), иbalance
представляет собой часть данных в нижней части их выписки со счета.Таким образом, вполне может быть и так, что в коде ядра игрового движка высокопроизводительного шутера PS3 не будет
Rocket
типа, но все же будет происходить некоторое моделирование мира, даже если модель выглядит странно кому-то, кто не является экспертом в области программирования движка физики консольных игр.источник
balance
как данные и транзакции как больше данных, так и передавать как операции, потому что это то, что видит пользователь, даже несмотря на то, что серверная часть может относиться к нему по-другому.Я не согласен с каждой «ложью», которую он предлагает.
TL; DR Автор этой статьи пытался спорить, чтобы сделать их статью более интересной, но так называемые «ложь» принимаются разработчиками программного обеспечения по уважительным причинам.
Ложь № 1 - Большой О имеет значение для масштабирования. Никого не волнует, если крошечному приложению требуется больше времени, что является единственной постоянной величиной времени, они заботятся о том, чтобы при удвоении входного размера оно не умножало время выполнения в 10 раз.
Ложь № 2 - Моделирование программ после реального мира позволяет программисту, смотрящему на ваш код 3 года спустя, легко понять, что он делает. Код должен быть поддерживаемым, иначе вам придется потратить часы, пытаясь понять, что пытается сделать программа. Другой ответ предполагает, что вы можете иметь более общие классы, такие как
LaunchPad
иMassiveDeviceMover
. Это не обязательно плохой класс, чтобы иметь, но вам все равно нуженRocket
класс. Как кто-то должен знать, чтоMassiveDeviceMover
делает или что он движется? Это движущиеся горы, космические корабли или планеты? Это в основном означает, что добавление в такие классыMassiveDeviceMover
делает вашу программу менее эффективной (но, возможно, более читаемой и понятной).Кроме того, стоимость времени на разработку стала превышать стоимость оборудования давно. Это ужасная идея, начинать с попыток проектирования с оптимизацией перед вашими мыслями. Вы программируете это простым и понятным способом, а затем настраиваете свою программу, узнавая, какие части ваших программ занимают много времени для запуска. Не забывайте: 80% времени выполнения используется 20% программы.
Ложь № 3 - Кодекс чрезвычайно важен. Хорошо написанный (и модульный) код допускает повторное использование (экономя бесчисленное количество человеко-часов). Это также позволяет вам просматривать и распознавать неверные данные, чтобы их можно было обработать. Данные прекрасны, но без кода было бы невозможно анализировать и получать из них полезную информацию.
источник
В системе электронной коммерции вы не имеете дело с «ракетами» на уровне класса, вы имеете дело с «продуктами». Так что это зависит от того, чего вы пытаетесь достичь, и вашего желаемого уровня абстракции.
В игре можно утверждать, что ракеты являются просто одним из многих типов «движущихся объектов». К ним применима та же физика, что и ко всем другим движущимся объектам. Так что, по крайней мере, «ракета» будет наследовать от более общего базового класса «движущийся объект».
В любом случае, автор цитируемого вами отрывка, кажется, немного преувеличил свой случай. Ракеты все еще могут иметь уникальные характеристики, такие как «количество оставшегося топлива» и «тяга», и вам не нужно сто классов, чтобы представить это для сотни ракет, вам нужна только одна. Создание объектов довольно дешево стоит в большинстве приличных языков программирования, поэтому, если вам нужно отслеживать ракетоподобные вещи, идея о том, что вы не должны создавать объекты Rocket, потому что это может быть слишком дорого, не имеет особого смысла.
источник
Проблема с реальным миром - это вся эта проклятая физика. Мы разделяем вещи на физические объекты в реальном мире, потому что их легче перемещать, чем отдельные атомы, или гигантский расплавленный шлак чего-то, что потенциально может быть ракетой.
Аналогичным образом, реальный мир предоставляет ряд полезных функций, на которые мы полагаемся. Сделать пингвинские исключения очень легко - «все птицы летают, кроме ...». И действительно легко маркировать вещи как ракеты, я имею в виду, если я назову этого пингвина ракетой и подожгу его ... это просто не работает.
То, как мы концептуально разделяем вещи в реальном мире, работает с учетом этих ограничений. Когда мы делаем что-то в коде, мы должны разделить вещи, чтобы они работали хорошо в соответствии с теми ограничениями, которые явно отличаются.
Подумайте о сетях. Мы не моделируем порты, провода и маршрутизаторы в коде. Вместо этого мы абстрагируем сетевое взаимодействие в соединения и протоколы. Мы делаем это, потому что это полезная абстракция независимо от реализации в реальном мире. И это накладывает полезные ограничения (например: вы не можете общаться, пока соединение не открыто), которые имеют значение только в коде .
Так что да, иногда моделирование кода после реального мира работает, но это совпадение . Когда люди говорят об ООП, объекты не являются объектами реального мира. То, что школы и учебники говорят иначе - трагедия десятилетий.
источник
Rocket
в коде этого парня нет типа, я готов поспорить, что, тем не менее, есть какая-то модель…Альтернатива - моделировать вещи, которые заботятся о ваших программах. Даже если ваша программа имеет дело с ракетами, вам может не понадобиться объект, называемый a
Rocket
. Например, у вас может бытьLaunchPad
сущность,LaunchSchedule
сущность иMassiveDeviceMover
сущность. Тот факт, что все это помогает запуску ракет, не означает, что вы сами управляете ракетами.источник
Это реальная проблема, но я дам вам свое мнение как разработчика, может быть, это поможет.
Во-первых, я бы не назвал эту ложь обычными заблуждениями. Назвать это ложью - это просто обман.
Один Он прав, в чем-то. Не собираюсь тратить на это много времени, потому что это не часть вопроса. Но по сути он прав. Я мог бы перефразировать это как «То, что работает в лаборатории, может не работать в реальной жизни». Слишком часто разработчики придерживаются дизайна, который работает в «лаборатории», но терпит неудачу в реальных приложениях.
«Три звука» для меня немного мыльны, но по сути он снова прав. Но это можно переписать так, чтобы «писать код в соответствии с вашими потребностями, не пытайтесь соответствовать потребностям вашего кода».
Еще раз два , вот он и прав. Я видел, как разработчики потратили недели или больше времени на разработку класса «ракета», когда работал бы простой класс «транспортное средство», или еще более простой «подвижный» класс. Если все, что нужно вашей ракете, это двигаться с левой стороны экрана вправо и издавать звук, тогда вы можете использовать тот же класс, который вы использовали для автомобилей, поездов, лодок и мух. 100 должно стоить меньше, чем аргумент 1 * 100, кажется, затрачено на разработку, и не так много в вычислительных затратах. Хотя придерживаться меньшего числа общих классов, которые можно использовать повторно, «дешевле», чем многие конкретные классы, которые нельзя использовать повторно. Вероятно, это можно переписать так: «общие классы лучше, чем конкретные классы,
По сути, вся статья может быть переписана с меньшим количеством модных слов, и в лучшем случае это будет только длинный абзац. Тем не менее, это пост в блоге, сфокусированный на узкой области программирования. Я выполнил некоторое встроенное программирование и могу согласиться с общей идеей, стоящей за этими утверждениями, хотя вокруг них есть немало «ошибок», чтобы сделать их подходящими для презентации на GDC.
Последнее замечание, статья была написана в 2008 году (насколько я мог судить). Вещи меняются быстро. Утверждения верны сегодня, но встроенные системы сегодня гораздо более распространены, чем тогда, и модели развития меняются. Возможно, даже в ответ на эту статью / разговор.
источник
Мне кажется интересным, что эта ложь сосредоточена вокруг академических проблем: платформы, эффективности использования памяти и данных. Но это полностью игнорирует человеческий фактор.
Программное обеспечение предназначено для удовлетворения потребностей людей. Как правило, это количественно с точки зрения бизнеса - есть клиенты, которые хотят чего-то, и сторонники, которые готовы заплатить, чтобы это произошло. Если программное обеспечение написано так, чтобы удовлетворить потребности обеих сторон уравнения, то это хорошее программное обеспечение, если нет, то это плохое программное обеспечение.
Если платформа не важна для клиента, то платформа не важна. Если эффективность памяти не важна для клиента, то это не важно. Если данные не важны для клиента, то данные не важны. Если код работает, но не может быть прочитан или поддержан, и клиент хочет быстрых и надежных изменений по приемлемой цене, то плохо написанный код - это плохо. Если код работает, но не может быть прочитан или поддержан, а клиенту все равно или он готов платить за дорогие рефакторинги, то плохо написанный код - это хорошо.
Большая ложь в том, что все, кроме человеческого элемента, имеет значение. Почему важны данные? Потому что есть какой-то клиент или заинтересованная сторона, которая нуждается в этом. Это «большая правда».
источник
ИМХО Если код «разработан вокруг модели мира», его будет легче понять, как для дизайнеров и разработчиков, так и для сопровождающих. Но я думаю, что это не только я, и не только программное обеспечение. Из Википедии: Научное моделирование - это научная деятельность, цель которой состоит в том, чтобы облегчить понимание, определение, количественное определение, визуализацию или моделирование определенной части или элемента мира путем ссылки на него с существующими и обычно общепринятыми знаниями.
источник