1993
(Это эссе взято из введения к книге "On Lisp").
Это давний принцип стиля программирования, что функциональные элементы программы не должны быть слишком большими. Если какой-то компонент программы вырастает за пределы стадии, на которой он легко понятен, он превращается в массу сложности, которая скрывает ошибки так же легко, как большой город скрывает беглецов. Такое программное обеспечение будет трудно читать, трудно тестировать и трудно отлаживать.
В соответствии с этим принципом, большая программа должна быть разделена на части, и чем больше программа, тем больше она должна быть разделена. Как разделить программу? Традиционный подход называется проектированием сверху вниз: вы говорите: "Цель программы - сделать эти семь вещей, поэтому я делю ее на семь основных подпрограмм. Первая подпрограмма должна делать эти четыре вещи, поэтому она, в свою очередь, будет иметь четыре собственные подпрограммы" и так далее. Этот процесс продолжается до тех пор, пока вся программа не приобретет нужный уровень детализации - каждая часть достаточно велика, чтобы делать что-то существенное, но достаточно мала, чтобы быть понятой как единое целое.
Опытные программисты на Lisp делят свои программы по-другому. Помимо нисходящего проектирования, они следуют принципу, который можно назвать восходящим проектированием - изменение языка в соответствии с проблемой. В Lisp вы не просто пишете свою программу вниз к языку, вы также строите язык вверх к вашей программе. В процессе написания программы вы можете подумать: "Вот бы в Lisp был такой-то и такой-то оператор". И вы идете и пишете его. После этого вы понимаете, что использование нового оператора упростит разработку другой части программы, и так далее. Язык и программа развиваются вместе. Подобно границе между двумя враждующими государствами, граница между языком и программой проводится и перерисовывается, пока в конце концов не упирается в горы и реки - естественные границы вашей проблемы. В итоге ваша программа будет выглядеть так, как будто язык был создан специально для нее. А когда язык и программа хорошо подходят друг другу, в итоге вы получаете понятный, небольшой и эффективный код.
Стоит подчеркнуть, что проектирование снизу вверх не означает просто написание той же программы в другом порядке. Когда вы работаете снизу вверх, в итоге обычно получается совсем другая программа. Вместо единой, монолитной программы вы получите более крупный язык с более абстрактными операторами и написанную на нем программу меньшего размера. Вместо перемычки вы получите арку.
В обычном коде, как только вы абстрагируетесь от частей, которые являются просто бухгалтерскими, то, что остается, становится намного короче; чем выше вы поднимаете язык, тем меньшее расстояние вам придется преодолеть сверху вниз. Это дает несколько преимуществ:
Проектирование снизу вверх в определенной степени возможно и в других языках, кроме Lisp. Всякий раз, когда вы видите библиотечные функции, проектирование снизу вверх имеет место. Однако Lisp дает вам гораздо более широкие возможности в этой области, и дополнения к языку играют пропорционально большую роль в стиле Lisp - настолько большую, что Lisp - это не просто другой язык, а совершенно другой способ программирования.
Это правда, что такой стиль разработки больше подходит для программ, которые могут быть написаны небольшими группами. Однако в то же время он расширяет границы того, что может быть сделано небольшой группой. В книге "Мифический человеко-месяц" Фредерик Брукс предположил, что производительность группы программистов не растет линейно с увеличением ее размера. По мере увеличения размера группы производительность отдельных программистов падает. Опыт программирования на Lisp подсказывает более веселый способ сформулировать этот закон: по мере уменьшения размера группы производительность отдельных программистов растет. Маленькая группа выигрывает, относительно говоря, просто потому, что она меньше. Когда небольшая группа также использует преимущества техник, которые делает возможным Lisp, она может выиграть полностью.
Новинка: Скачать On Lisp бесплатно.
Примечания
[1] "Но никто не сможет прочитать программу, не понимая всех ваших новых утилит". Чтобы понять, почему такие утверждения обычно ошибочны, см. раздел 4.8.