Чистая архитектура. Искусство разработки программного обеспечения - страница 20
Если система состоит из модулей, которые можно развертывать независимо, их можно разрабатывать независимо, разными командами. Это независимость разработки.
Заключение
Что такое ОО? Существует много взглядов и ответов на этот вопрос. Однако для программного архитектора ответ очевиден: ОО дает, посредством поддержки полиморфизма, абсолютный контроль над всеми зависимостями в исходном коде. Это позволяет архитектору создать архитектуру со сменными модулями (плагинами), в которой модули верхнего уровня не зависят от модулей нижнего уровня. Низкоуровневые детали не выходят за рамки модулей плагинов, которые можно развертывать и разрабатывать независимо от модулей верхнего уровня.
6. Функциональное программирование
Многие идеи функционального программирования появились задолго до появления самого программирования. Эта парадигма в значительной мере основана на λ-исчислении, изобретенном Алонзо Чёрчем в 1930-х годах.
Квадраты целых чисел
Суть функционального программирования проще объяснить на примерах. С этой целью исследуем решение простой задачи: вывод квадратов первых 25 целых чисел (то есть от 0 до 24).
В языках, подобных Java, эту задачу можно решить так:
>public class Squint {
> public static void main(String args[]) {
> for (int i=0; i<25; i++)
> System.out.println(i*i);
> }
>}
В Clojure, функциональном языке и производном от языка Lisp, аналогичную программу можно записать так:
>(println (take 25 (map (fn [x] (* x x)) (range))))
Этот код может показаться немного странным, если вы не знакомы с Lisp. Поэтому я, с вашего позволения, немного переоформлю его и добавлю несколько комментариев.
>(println;___________________ Вывести
> (take 25;_________________ первые 25
> (map (fn [x] (* x x));__ квадратов
> (range))));___________ целых чисел
Совершенно понятно, что >println
, >take
, >map
и >range
– это функции. В языке Lisp вызов функции производится помещением ее имени в круглые скобки. Например, >(range)
– это вызов функции range.
Выражение >(fn [x] (* x x))
– это анонимная функция, которая, в свою очередь, вызывает функцию умножения и передает ей две копии входного аргумента. Иными словами, она вычисляет квадрат заданного числа.
Взглянем на эту программу еще раз, начав с самого внутреннего вызова функции:
• функция >range
возвращает бесконечный список целых чисел, начиная с 0;
• этот список передается функции >map
, которая вызывает анонимную функцию для вычисления квадрата каждого элемента и производит бесконечный список квадратов;
• список квадратов передается функции >take
, которая возвращает новый список, содержащий только первые 25 элементов;
• функция >println
выводит этот самый список квадратов первых 25 целых чисел.
Если вас напугало упоминание бесконечных списков, не волнуйтесь. В действительности программа создаст только первые 25 элементов этих бесконечных списков. Дело в том, что новые элементы бесконечных списков не создаются, пока программа не обратится к ним.
Если все вышесказанное показалось вам запутанным и непонятным, тогда можете отложить эту книгу и прекрасно провести время, изучая функциональное программирование и язык Clojure. В этой книге я не буду рассматривать эти темы, так как не это является моей целью.
Моя цель – показать важнейшее отличие между программами на Clojure и Java. В программе на Java используется изменяемая переменная – переменная, состояние которой изменяется в ходе выполнения программы. Это переменная i – переменная цикла. В программе на Clojure, напротив, нет изменяемых переменных. В ней присутствуют инициализируемые переменные, такие как