Намерен ли Дейкстра на модуляризацию кода, когда писал о разделении интересов?


9

Сначала я прочитал отрывок из статьи Эдсгера В. Дейкстры 1974 года «О роли научной мысли»:

Позвольте мне попытаться объяснить вам, что на мой вкус характерно для всего разумного мышления. Дело в том, что человек желает углубленно изучать аспект своего предмета изолированно ради своей собственной последовательности, все время зная, что он занимает себя только одним из аспектов. Мы знаем, что программа должна быть правильной, и мы можем изучать ее только с этой точки зрения; мы также знаем, что он должен быть эффективным, и мы можем, так сказать, изучить его эффективность в другой день. В другом настроении мы можем спросить себя, а если да, то почему программа желательна. Но ничего не получается - наоборот! - одновременно занимаясь этими различными аспектами. Это то, что я иногда называю «разделением интересов», что, даже если это не вполне возможно, пока что это единственная доступная техника для эффективного упорядочения своих мыслей, о которой я знаю. Это то, что я имею в виду под «сосредоточением своего внимания на каком-то одном аспекте»: это не означает игнорирование других аспектов, это просто признание того факта, что с точки зрения этого аспекта другой не имеет значения. Это одно- и многодорожечный одновременно.

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

То есть, скажем, перед вами код, который в одном файле содержит понятия представления, репозитория, контроллера, обработки событий, фабрики и т. Д. - все в одном файле.

Для краткого примера, вот код, который имеет доступ к данным и представление (вывод):

$sql = "SELECT * FROM product WHERE id = " . db_input($id);
$row = db_fetch_array(db_query($sql)); 
<option value="<?=$row['id']?>"<?= $row['ver'] == $row['ver'] ? '  selected="selected"' : '' ?>>Version <?=$row['ver']?></option>

Используя современную OO, я мог бы разместить доступ к данным в своем собственном файле, используя шаблон Repository, код View может перейти в собственный шаблон файла, и я могу связать их вместе для связи через контроллер (или Action или Request Handler), и я могу добавить фабрику для создания и подключения различных зависимостей. И у меня может быть файл конфигурации, который определяет эти фабрики. Конечно, это один шаг от одного файла-все.

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

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

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

Должно ли разделение интересов оставаться умственным упражнением, а не физическим?
Другими словами, должно ли существовать несоответствие между ментальными (фокус на) и физическими (код на бумаге) аспектами программирования?


5
Я почти уверен, что к 1974 году он просто рассматривал модульное программирование как очевидный факт, и именно поэтому он не обсуждал это явно в этой статье. Документ Парнаса о том, как модулировать, был в 1972 году, и к тому времени вопрос о том, стоит ли модульность, уже не был вопросом. На самом деле, то, что вы описываете, - это даже не модульное программирование, это структурированное программирование , за которое сам Дейкстра настойчиво высказывался в 1968 году в своей классической статье «Перейти к опасному».
Йорг Миттаг

Итак, возможно, я могу больше понимать «разделение интересов» как упражнение на умственную концентрацию, а модульность - как способ инкапсулировать аспект кода на бумаге. Однако теперь я вижу разделение интересов и модульность скорее как отдельные понятия.
Деннис

@ JörgWMittag, вы можете определить различие между структурным и модульным программированием? Некоторые ссылки в Google предполагают, что они одинаковы.
Деннис

Структурированные = IF, WHILE, FORа GOTO. Modular = модули с четко определенным публичным API, строго отделенным от скрытой внутренней реализации и представления. (Например, Модула, Меса, Модула-2, Модула-3, более поздние диалекты Паскаля ( UNIT).)
Йорг Миттаг

Ответы:


2

Дейкстра делает явное заявление о том, как думать. Модуляризация программы (и процесса) - и ее желательность - возможно, является результатом этого мышления, но ключевой момент, который он делает, заключается в том, как оценить проблему. Программа обычно является решением проблемы, и, выступая за «разделение интересов», он предлагает мудрый совет. Лучшим примером этого является, пожалуй, «оптимизация». Шутка была: «При планировании оптимизации программы, ваша первая стратегия должна быть: не надо». Другими словами, вы хотите сосредоточиться на том, чтобы сначала сделать программу правильной. Сделать его быстрым и модным - это проблема, которую следует отделить, но не полностью устранить.


14

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

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


9

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

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


5
Я думаю, что следует отметить, что большая часть современной мысли о разделении проблем пришла из ранних работ, которые в конечном итоге породили Аспектно-ориентированное программирование от IBM. Я думаю, что первоначальные статьи (конец 90-х - начало 2000-х годов) имеют наибольшее влияние. Прошло много времени, и все сайты изменились. Не уверен, смогу ли я найти их снова.
Берин Лорич

2
Сложнее всего пытаться определить, что означает «одна вещь». Без этого идея бесполезна с точки зрения практического написания кода, и неправильное ее использование немедленно отрицательно сказывается на сложности написания, чтения, понимания, обслуживания и тестирования кода.
jpmc26

1
Это действительно помогло бы нам понять вашу позицию, если бы вы (а) объяснили, что, по вашему мнению, Дейкстра имел в виду под «разделением интересов», и (б) объяснили ПОЧЕМУ, по вашему мнению, то, что он имел в виду, больше не имеет значения.
Джон Р. Стром

2

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

  1. Сначала я рассматриваю данные. Данные представляют логические предикаты проблемы. Классы конструируются для абстрагирования сущностей в реальном мире, а их атрибуты являются параметрами абстракции. Ассоциации между классами представляют функциональные отображения между экземплярами классов. На данный момент нет никакого кода, вовлеченного в мышление, и нет понятия какой-либо обработки. Просто статичный взгляд на логику, вовлеченную в предмет.
  2. Второе я считаю динамикой. Любой класс с нетривиальным жизненным циклом моделируется как конечный автомат. Это включает в себя соображения о выполнении последовательности и синхронизации. Опять же, никакой код просто не работает, как вещи взаимодействуют и упорядочиваются.
  3. В-третьих, я рассматриваю обработку. Здесь, фактическая алгоритмическая работа, которая должна быть сделана при переходах состояний или в других синхронных операциях.

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

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


1

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

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

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

Это не то, как растут грибы или водоросли ... Как это для смиренного факта?


-1

Я полагаю, что конкретный ответ на цитату Дейкстры был рассмотрен, поскольку вы заявляете «Используя современную ОО, я мог бы поместить доступ к данным в свой собственный файл» и спрашивали «Должно ли разделение интересов оставаться умственным упражнением, а не физическим?» позвольте мне обратить ваше внимание на то, куда нас направляют современные принципы ОО.

Следует следовать принципам SOLID при разработке с использованием ОО. Вот хорошая ссылка для них, но TLDR по «разделению интересов» в основном содержится в S в SOLID: Принцип единой ответственности или SRP.

Это, безусловно, физическое упражнение, а не умственное. В вашем конкретном примере MVC (или его родные MVVM и MVP) предписывает физически разделять концерты Model, View и Controller / Presenter / ViewModel в отдельные файлы. Я видел несколько реализаций MVVM, в которых они реализованы в виде отдельных сборок, чтобы еще больше ограничить тенденцию «смешивать концепции».

Но. Это выходит за рамки простого «это представление, а это модель», если вы следуете мнению дяди Боба об этом.

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

Я настоятельно рекомендую вам исследовать это дальше, используя предоставленные ссылки, или выполнить поиск в Интернете для «твердых принципов».


Нет. Принципы SOLID настолько далеки от реальности написания кода (= философского), что их можно понять любым отдаленно полезным способом, если вы уже знаете, как писать хороший код, и в этом случае они в лучшем случае избыточны. Использование их в качестве руководящих принципов без опыта и умений приводит к крайне плохому коду.
jpmc26
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.