Введение.
Увеличиваем читаемость данных.
Увеличиваем читаемость комбинаторов.
Увеличиваем читаемость анонимных классов.
Увеличиваем читаемость имен классов.
Увеличиваем читаемость generic-ов – typedef для бедных.
Увеличиваем читаемость generic-ов-2, используем вывод типов Java.
Увеличиваем отлаживаемость этого хозяйства.
Прочитайте J vocabulary.
Карринг по последнему аргументу.
Пары и бинарные отношения.
Крупные комбинаторы.
Заключение.
ВВЕДЕНИЕ.
Есть задачи, которые удобнее всего решать в функциональном стиле. Среди этих задач есть такие, которые можно лаконично и читаемо решить и на Java. В этой статье речь пойдет именно о них.
Речь также пойдет о рефакторинге кода, неосознанно написанного в функциональном стиле (такого, как new AndFilter(new FieldMatchesPatternFilter(new FieldReference("name"), ".*John.*"), new BlaBlaBlaFilter())), в читаемую и лаконичную форму.
DISCLAIMER.
Большая часть данной статьи не имеет отношения к собственно функциональному программированию (далее – ФП). В основном будут рассмотрены способы повышения читаемости некоторых часто встречающихся паттернов, особенно часто встречающихся при использовании функционального стиля, и без которых об ФП не может быть и речи. О приемах собственно ФП будет сказано совсем немного, ближе к концу статьи.
Вот некоторые из недостатков Java, с которыми мы будем бороться.
"kingdom of nouns" (традиция считать все на свете существительным и считать, что вычислить сумму двух чисел можно, только создав экземпляр ЧисленногоСумматора и любезно послав ему сообщение). Этот недостаток порождает громоздкий код, переполненный лишними factory- и builder-классами, скрывающий логику работы программы – кажется, что код, собственно говоря, ничего не делает – только создает бесконечные FooFactory, BarProcessor и GazonkProvider'ы.
Отсутствие встроенного синтаксиса для конструирования и деконструирования (разбора на составные части) данных – пар и кортежей, списков и т.п. Этот недостаток приводит к загромождению программы кодом, создающим данные – последовательностями List.add() или Map.put(), и – что менее заметно, но более вредно – закрывает дорогу к обильному использованию составных данных в коде и в API – например, разработчик библиотеки для работы с регулярными выражениями может воздержаться от добавления полезного оптимизированного метода «выполнить сразу несколько поисков-и-замен» с аргументом «список пар шаблон/замена», поскольку вызов этого метода потребует громоздкого кода для создания такого списка.
Плохой синтаксис generic-ов, отсутствие полноценных вывода типов и полиморфизма. Этот недостаток делает нечитаемыми сколько-нибудь сложные параметризованные типы и выражения с ними, а также часто заставляет писать дублирующийся код (сложность выражения «List Pair String,Integer list = new ArrayList Pair String,Integer » гораздо выше реальной сложности сущности «список пар из строки и числа»; отсутствие вывода типов для конструкторов – самое яркое проявление этого недостатка).
В качестве орудий пригодятся такие возможности Java 5, как import static, varargs – и немного пороха в пороховницах.
Приемы будут даны в виде серии сравнений «типичный код vs. хороший код» на коротких примерах из разных областей. Одна из целей статьи – показать, что эти приемы применимы в любой области.
Language: Russian
Commentary: 17111
Tags: Библиотека;Компьютерная литература;Java