Сообщений 33    Оценка 75 [+0/-1]         Оценить  
Система Orphus

От редакции

Автор: Чистяков Влад (VladD2)
The RSDN Group

Источник: RSDN Magazine #6-2004
Опубликовано: 19.03.2005
Исправлено: 09.06.2005

В этот раз хочется сказать несколько слов о паттернах. Но не в том смысле, как их понимают очень многие – то есть паттернах программирования, описанных GoF, а скорее, о паттернах мышления как идиоме.

На нашем сайте особой популярностью пользуются длинные и, как правило, безрезультатные дискуссии типа "Что-то vs. что-то", например, "Функциональные языки vs. что-то еще". Все такие споры можно свести к следующему: апологеты языка/подхода А явно или неявно утверждают, что A лучше, чем В. При этом утверждается, что в А есть возможность Х, отсутствующая в В. После нескольких итераций спора оказывается, что Х реализуема и в В, но для этого необходимо некоторое усилие, возможно, однократное – например, создание некоторого шаблона (template) (это естественно, так как практически на любом современном языке можно реализовать машину Тьюринга, способную решить любые вычислительные задачи). Иногда этот шаблон может полностью реализовать Х, а иногда требует некоторых дополнительных действий при каждом применении. Последнее дает козыри апологетам А, и в дальнейшем спор крутится вокруг этого. Таким образом, спор зачастую вырождается в обсуждение возможности реализации Х средствами В и удобства этой реализации.

Главное, что упускают апологеты А – это то, что они неправильно строят свои рассуждения. Отсутствие Х в В – это не техническая проблема, а концептуальная. Х для В по сути является паттерном. Для не знающего о возможности Х этой возможности в В просто не существует. С другой стороны, незнание паттерна Х не мешает применять этот паттерн в А, куда он изначально встроен. Это происходит потому, что в А человек оперирует Х на уровне базового понятия. Важно понять, что Х в данном случае – высокоуровневая сущность, реализация которой не имеет значения для пользователя.

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

SomeIterator iterator = someCollection.GetIterator();
while (!iterator.HasNext())
{
  SomeType value = iterator.Next();
  ...
}

или так:

std::for_each(someCollection.begin(), someCollection.end(), someFunctor);
...
void someFunctor(SomeType value) { ... }

А при наличии встроенной в язык поддержки так:

foreach (SomeType value in someCollection)
  …

или так:

for (value in someCollection)
  ...

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

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

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


Эта статья опубликована в журнале RSDN Magazine #6-2004. Информацию о журнале можно найти здесь
    Сообщений 33    Оценка 75 [+0/-1]         Оценить