Как в вашем проекте применяются принципы функционального программирования?

Ответ

В проекте мы используем гибридный подход, сочетая объектно-ориентированное проектирование домена с элементами функционального программирования (ФП) для обработки данных и написания выразительного, безопасного кода.

Основные применяемые концепции ФП:

  1. Иммутабельность (Immutability): Широкое использование record (Java 16+), final полей и создание новых объектов вместо изменения существующих. Это предотвращает случайные side-effects и упрощает работу в многопоточных сценариях.
  2. Чистые функции (Pure Functions): Функции, результат которых зависит только от входных аргументов и не имеет побочных эффектов (не изменяет глобальное состояние). Это упрощает тестирование и рассуждение о коде.
  3. Использование Stream API: Для декларативной обработки коллекций вместо императивных циклов.

Практический пример:

// Задача: получить список имен пользователей старше 18 лет.
// Императивный подход (менее предпочтительный):
List<String> names = new ArrayList<>();
for (User user : users) {
    if (user.getAge() > 18) {
        names.add(user.getName());
    }
}

// Функциональный подход с Stream API (предпочтительный):
List<String> filteredNames = users.stream()
        .filter(user -> user.getAge() > 18) // Predicate (фильтрация)
        .map(User::getName)                 // Function (преобразование)
        .toList();                          // Сбор в неизменяемый список

Преимущества такого подхода:

  • Читаемость: Код описывает что нужно сделать, а не как.
  • Упрощение тестирования: Легко тестировать отдельные лямбда-выражения.
  • Потенциал для параллелизма: Замена .stream() на .parallelStream() для простого распараллеливания.

Ограничения: Мы не используем ФП «фанатично». Сложная бизнес-логика с состоянием по-прежнему инкапсулируется в классах (ООП), а ФП служит инструментом для операций над данными.

Ответ 18+ 🔞

Ну ты смотри, какие мы тут модные, блядь! Взяли и смешали в одну кучу, как салат оливье: ООП, ФП, всё намешали, чтобы код был не просто рабочий, а чтобы на него смотреть было приятно, как на картину, блядь.

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

На чём мы, собственно, едем:

  1. Иммутабельность, ёпта. Это наше всё. Никаких тебе неожиданных изменений объекта, пока ты в соседнем потоке с ним работаешь. record'ы, final поля — красота, блядь. Сделал объект — и спи спокойно, он как скала. Хочешь что-то поменять? Создавай новый, нахуй! Зато никаких сюрпризов.
  2. Чистые функции, блядь. Это как в аптеке: положил на весы аргументы — получил результат. Никаких тайных операций с глобальными переменными где-то в подполье. Всё прозрачно, всё предсказуемо. Тестировать — одно удовольствие, а не ебаться с моками всего мира.
  3. Stream API — наше оружие массового поражения циклов. Забыли, что такое for с кучей вложенных if? И правильно, блядь.

Смотри, как было и как стало:

// Старый, императивный способ. Скучно, длинно, можно накосячить.
List<String> names = new ArrayList<>();
for (User user : users) {
    if (user.getAge() > 18) {
        names.add(user.getName());
    }
}

// Новый, функциональный способ. Кратко, ясно, красиво, блядь.
List<String> filteredNames = users.stream()
        .filter(user -> user.getAge() > 18) // Отфильтровали стариков
        .map(User::getName)                 // Вытащили из них имена
        .toList();                          // Собрали в кучку

И почему это, сука, охуенно:

  • Читается как книга. Сразу видно: фильтруем, мапим, собираем. Не надо вникать в логику индексов и условий.
  • Тестируется на раз-два. Каждую лямбду отдельно можно проверить.
  • Параллелизм — раз плюнуть. Заменил .stream() на .parallelStream() и сиди, наблюдай, как всё летает на всех ядрах.

Но без фанатизма, ёпта! Мы не упёртые монахи, которые всё пытаются запихнуть в чистые функции. Сложная бизнес-логика с кучей состояний — это по-прежнему царство ООП. А ФП — это наш острый и точный инструмент, когда нужно данные обработать, преобразовать, отфильтровать. В общем, чтобы не изобретать велосипед, а делать дело быстро и элегантно.