Книга: The Programmers

Литературная критика и паттерны проектирования

Литературная критика и паттерны проектирования

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

Чтобы окончательно прояснить эту позицию, рассмотрим язык ассемблера. Код операции (opcode) может выполнять большинство специфических установок выходов процессора по заданным входным значениям, но мы рассматриваем код операции посредством его мнемоники, например DAA (Десятичная Коррекция Аккумулятора — Decimal Adjust Accumulator). Даже когда есть взаимное соответствие между кодом операции и мнемоникой, более высокий уровень абстракции мнемоники может скрывать действие кода операции на аккумулятор, который просто преобразует биты в соответствии с алгоритмом. Если мы видим возможности обработки, предоставляемые кодом операции, можем ли мы «злоупотреблять» этим? Ответ зависит от обстоятельств.

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

Мы можем получить строгую и элегантную дисциплину из различия между намерением и действием. Рассмотрим следующий фрагмент:

//Search the list of available dealers and find those that
// handle the triggering stock. Send them notification of
// the event.
for(DealerIterator DI(DealersOnline); DI.more(); DI++)
  if(DI.CurrentDealer()->InPortfolio(TheEvent.GetStock()))
    DI.CurrentDealer()->HandleEvent(TheEvent);

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

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

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

Эта концепция развита далее в идее Дональда Кнута (Donald Knuth) о «грамотном программировании» (Literate Programming), которое, чтобы его сделать хорошо, требует средств системной поддержки, типа его Сетевой среды (Web environment) — прообраза WWW (World Wide Web). Но вам не нужно скупать все гири, чтобы получить удовольствие от спорта. Грамотное программирование — это скорее отношение (позиция), а не инструмент.

На этом уровне литературной критики мы можем получить серьезные выгоды от изучения паттернов проектирования (design patterns). Это компоненты архитектурной технологии, которая гораздо сложнее, чем обычный поток управления (flow control) с обработкой ошибок и другими типичными идиомами. Они чрезвычайно мощные и платформонезависимые. Почитайте прекрасную книгу Гаммы, Хелма, Джонсона и Влиссидеса (Gamma, Helm, Johnson, Vlissides), в которой они описывают паттерн как нечто, что

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

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

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

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

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

Например, вы оцениваете возможности мощной интегрированной среды. Вы используете Emacs на работе и доработали его, чтобы он управлял вашей кофеваркой. Я работаю на многих машинах, и, как это ни эксцентрично, я знаю, что на них всегда есть vi. Мы устанавливаем Emacs на новых машинах и обучаем vi новичков. Ваш LISP, конечно, sucks.

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

Оглавление книги


Генерация: 0.390. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз