Кодовые базы разрастаются, становясь все сложнее и запутаннее, что не может не пугать разработчиков. Как обнаружить код, изменяющий состояние вашей системы? Как сделать код таким, чтобы он не увеличивал сложность и запутанность кодовой базы?
Большую часть «действий», изменяющих состояние, можно превратить в «вычисления», чтобы ваш код стал проще и логичнее.
Вы научитесь бороться со сложными ошибками синхронизации, которые неизбежно проникают в асинхронный и многопоточный код, узнаете, как компонуемые абстракции предотвращают дублирование кода, и откроете для себя новые уровни его выразительности.
Книга предназначена для разработчиков среднего и высокого уровня, создающих сложный код. Примеры, иллюстрации, вопросы для самопроверки и практические задания помогут надежно закрепить новые знания.
Author(s): Эрик Норманд
Series: Библиотека программиста
Edition: 1
Publisher: Питер
Year: 2023
Language: Russian
Commentary: Publisher's PDF
Pages: 608
City: СПб.
Tags: Software Engineering; JavaScript; Web Applications; Concurrency; Functional Programming; Asynchronous Programming; Distributed Systems; Callback Functions; Software Architecture; Complexity; Architecture Patterns; Design Thinking
Предисловие
Вступление
Благодарности
О книге
Об авторе
От издательства
Глава 1. Добро пожаловать в мир функционального мышления
Что такое функциональное программирование
Недостатки определения при практическом применении
Определение ФП сбивает с толку руководителей
Функциональное программирование рассматривается как совокупность навыков и концепций
Действия вычисления и данные
Функциональные программисты особо выделяют код для которого важен момент вызова
Функциональное программирование отличает инертные данные от работающего кода
Функциональные программисты разделяют действия вычисления и данные
Три категории кода в ФП
Как нам помогают различия между действиями вычислениями и данными
Чем эта книга отличается от других книг о ФП
Что такое функциональное мышление
Основные правила для идей и навыков представленных в книге
Итоги главы
Резюме
Что дальше?
Глава 2. Функциональное мышление в действии
Добро пожаловать в пиццерию Тони!
Часть 1. Проведение различий между действиями вычислениями и данными
Организация кода по частоте изменений
Часть 2. Использование первоклассных абстракций
Временные линии наглядно представляют работу распределенных систем
Действия на временных линиях могут выполняться в разном порядке
Особенности распределенных систем: урок полученный дорогой ценой
Сегментация временной линии: заставляем роботов ожидать друг друга
Положительные уроки
Итоги главы
Резюме
Что дальше?
ЧАСТЬ I. ДЕЙСТВИЯ ВЫЧИСЛЕНИЯ И ДАННЫЕ
Глава 3. Действия вычисления и данные
Действия вычисления и данные
Действия вычисления и данные применимы в любых ситуациях
Что мы узнали при моделировании процесса покупки
Применение функционального мышления в новом коде
Наглядное представление процесса рассылки купонов по электронной почте
Реализация процесса отправки купонов
Применение функционального мышления в существующем коде
Распространение действий в коде
Действия могут принимать разные формы
Итоги главы
Резюме
Что дальше?
Глава 4. Извлечение вычислений из действий
Добро пожаловать в MegaMart.com!
Вычисление бесплатной доставки
Вычисление налога
Необходимо упростить тестирование
Необходимо улучшить возможности повторного использования кода
Различия между действиями вычислениями и данными
У функций есть ввод и вывод
Тестирование и повторное использование связаны с вводом и выводом
Извлечение вычислений из действий
Извлечение другого вычисления из действия
Весь код в одном месте
Итоги главы
Резюме
Что дальше?
Глава 5. Улучшение структуры действий
Согласование структуры с бизнес-требованиями
Приведение функции в соответствие с бизнес-требованиями
Принцип: минимизация неявного ввода и вывода
Сокращение неявного ввода и вывода
Проверим код еще раз
Классификация наших расчетов
Принцип: суть проектирования в разделении
Улучшение структуры за счет разделения add_item()
Выделение паттерна копирования при записи
Использование функции add_item()
Классификация вычислений
Уменьшение функций и новые вычисления
Итоги главы
Резюме
Что дальше?
Глава 6. Неизменяемость в изменяемых языках
Может ли неизменяемость применяться повсеместно
Классификация операций чтения и/или записи
Три этапа выполнения копирования при записи
Преобразование записи в чтение с использованием копирования при записи
Сравнение двух версий
Операции копирования при записи обобщаются
Знакомство с массивами в JavaScript
Что делать с операциями чтения/записи
Разделение функции выполняющей чтение и запись
Возвращение двух значений одной функцией
Операции чтения неизменяемых структур данных являются вычислениями
Приложения обладают состоянием которое изменяется во времени
Неизменяемые структуры данных достаточно быстры
Операции с копированием при записи для объектов
Кратко об объектах JavaScript
Преобразование вложенных операций записи в чтение
Что же копируется?
Наглядное представление поверхностного копирования и структурного совместного использования
Итоги главы
Резюме
Что дальше?
Глава 7. Сохранение неизменяемости при взаимодействии с ненадежным кодом
Неизменяемость при работе с унаследованным кодом
Наш код копирования при записи должен взаимодействовать с ненадежным кодом
Защитное копирование позволяет сохранить неизменяемый оригинал
Реализация защитного копирования
Правила защитного копирования
Упаковка ненадежного кода
Защитное копирование которое вам может быть знакомо
Сравнение копирования при записи с защитным копированием
Глубокое копирование затратнее поверхностного
Трудности реализации глубокого копирования в JavaScript
Диалог между копированием при записи и защитным копированием
Итоги главы
Резюме
Что дальше?
Глава 8. Многоуровневое проектирование: часть 1
Что такое проектирование программной системы
Что такое многоуровневое проектирование
Развитие чувства проектирования
Паттерны многоуровневого проектирования
Паттерн 1. Прямолинейная реализация
Три уровня детализации
Выделение цикла for
Обзор паттерна 1. Прямолинейная реализация
Итоги главы
Резюме
Что дальше?
Глава 9. Многоуровневое проектирование: часть 2
Паттерны многоуровневого проектирования
Паттерн 2. Абстрактный барьер
Абстрактные барьеры скрывают реализацию
Игнорирование подробностей симметрично
Замена структуры данных корзины
Повторная реализация корзины в виде объекта
Абстрактный барьер позволяет игнорировать подробности
Когда следует (или не следует!) использовать абстрактные барьеры
Обзор паттерна 2. Абстрактный барьер
Код становится более прямолинейным
Паттерн 3. Минимальный интерфейс
Обзор паттерна 3. Минимальный интерфейс
Паттерн 4. Удобные уровни
Паттерны многоуровневой архитектуры
Что можно узнать из графа о коде?
Код в верхней части графа проще изменять
Важность тестирования кода нижних уровней
Код нижних уровней лучше подходит для повторного использования
Итоги: что можно узнать о коде по графу вызовов
Итоги главы
Резюме
Что дальше?
ЧАСТЬ II. ПЕРВОКЛАССНЫЕ АБСТРАКЦИИ
Глава 10. Первоклассные функции: часть 1
Отдел маркетинга все еще должен согласовываться с разработчиками
Признак «кода с душком»: неявный аргумент в имени функции
Рефакторинг: явное выражение неявного аргумента
Определение того что является и что не является первоклассным значением
Не приведут ли строки с именами полей к новым ошибкам?
Усложнят ли первоклассные поля изменения API?
Мы будем использовать множество объектов и массивов
Первоклассные функции могут заменить любой синтаксис
Пример цикла for: еда и уборка
Рефакторинг: замена тела обратным вызовом
Что это за синтаксис
Почему мы упаковали код в функцию
Итоги главы
Резюме
Что дальше?
Глава 11. Первоклассные функции:часть 2
Одна проблема два метода рефакторинга
Рефакторинг копирования при записи
Рефакторинг копирования при записи для массивов
Возвращение функций функциями
Итоги главы
Резюме
Что дальше?
Глава 12. Функциональные итерации
Один признак «кода с душком» и два рефакторинга
MegaMart создает группу взаимодействия с клиентами
map() в примерах
Инструмент функционального программирования: map()
Три способа передачи функций
Пример: адреса всех клиентов
filter() в примерах
Инструмент функционального программирования: filter()
Пример: клиенты без покупок
reduce() в примерах
Инструмент функционального программирования: reduce()
Пример: конкатенация строк
Что можно сделать с reduce()
Сравнение трех инструментов функционального программирования
Итоги главы
Резюме
Что дальше?
Глава 13. Сцепление функциональных инструментов
Группа взаимодействия с клиентами продолжает работу
Улучшение цепочек способ 1: присваивание имен шагам
Улучшение цепочек способ 2: присваивание имен обратным вызовам
Улучшение цепочек: сравнение двух способов
Пример: адреса клиентов с одной покупкой
Преобразование существующих циклов for в инструменты функционального программирования
Совет 1. Создавайте данные
Совет 2. Работайте с целыми массивами
Совет 3. Используйте много мелких шагов
Совет 3. Используйте много мелких шагов
Сравнение функционального кода с императивным
Советы по сцеплению
Советы по отладке
Другие функциональные инструменты
reduce() для построения значений
Творческий подход к представлению данных
О выравнивании точек
Итоги главы
Резюме
Что дальше?
Глава 14. Функциональные инструменты для работы с вложенными данными
Функции высшего порядка для значений в объектах
Явное выражение имени поля
Построение update()
Использование update() для изменения значений
Рефакторинг: замена схемы «чтение — изменение — запись» функцией update()
Функциональный инструмент: update()
Наглядное представление значений в объектах
Наглядное представление обновлений вложенных данных
Применение update() к вложенным данным
Построение updateOption()
Построение update2()
Наглядное представление update2() с вложенными объектами
Четыре варианта реализации incrementSizeByName()
Построение update3()
Построение nestedUpdate()
Анатомия безопасной рекурсии
Наглядное представление nestedUpdate()
Сила рекурсии
Конструктивные особенности при глубоком вложении
Абстрактные барьеры для глубоко вложенных данных
Сводка использования функций высшего порядка
Итоги главы
Резюме
Что дальше?
Глава 15. Изоляция временных линий
Осторожно ошибка!
Пробуем кликать вдвое чаще
Временные диаграммы показывают что происходит с течением времени
Два фундаментальных принципа временных диаграмм
Две неочевидные детали порядка действий
Построение временной линии добавления товара в корзину: шаг 1
Асинхронным вызовам необходимы новые временные линии
Разные языки разные потоковые модели
Поэтапное построение временной линии
Изображение временной линии добавления товара в корзину: шаг 2
Временные диаграммы отражают две разновидности последовательного кода
Временные диаграммы отражают неопределенность в упорядочении параллельного кода
Принципы работы с временными линиями
Однопоточная модель в JavaScript
Асинхронная очередь JavaScript
AJAX и очередь событий
Полный пример с асинхронными вызовами
Упрощение временной линии
Чтение завершенной временной линии
Упрощение временной диаграммы добавления товара в корзину: шаг 3
Рисование временной линии (шаги 1–3)
Резюме: построение временных диаграмм
Сопоставление временных диаграмм помогает выявить проблемы
Два медленных клика приводят к правильному результату
Два быстрых клика приводят к неправильному результату
Временные линии с совместным использованием ресурсов создают проблемы
Преобразование глобальной переменной в локальную
Преобразование глобальной переменной в аргумент
Расширение возможностей повторного использования кода
Принцип: в асинхронном контексте в качестве явного вывода вместо возвращаемого значения используется обратный вызов
Итоги главы
Резюме
Что дальше?
Глава 16. Совместное использование ресурсов между временными линиями
Принципы работы с временными линиями
Корзина все еще содержит ошибку
Необходимо гарантировать порядок обновлений DOM
Реализация очереди в JavaScript
Принцип: берите за образец решения по совместному использованию из реального мира
Совместное использование очереди
Анализ временной линии
Принцип: чтобы узнать о возможных проблемах проанализируйте временную диаграмму
Пропуск задач в очереди
Итоги главы
Резюме
Что дальше?
Глава 17. Координация временных линий
Принципы работы с временными линиями
Ошибка!
Как изменился код
Идентификация действий: шаг 1
Представление каждого действия: шаг 2
Упрощение диаграммы: шаг 3
Анализ возможных вариантов упорядочения
Почему эта временная линия выполняется быстрее
Ожидание двух параллельных обратных вызовов
Примитив синхронизации для нарезки временных линий
Использование Cut() в коде
Анализ неопределенных упорядочений
Анализ параллельного выполнения
Анализ для нескольких кликов
Примитив для однократного вызова
Неявная и явная модель времени
Резюме: манипулирование временными линиями
Итоги главы
Резюме
Что дальше?
Глава 18. Реактивные и многослойные архитектуры
Два архитектурных паттерна
Связывание причин и эффектов изменений
Что такое реактивная архитектура
Плюсы и минусы реактивной архитектуры
Ячейки как первоклассное состояние
Переменную ValueCell можно сделать реактивной
Обновление значков доставки при изменении ячейки
FormulaCell и вычисление производных значений
Изменяемое состояние в функциональном программировании
Как реактивная архитектура изменяет конфигурацию систем
Отделение эффектов от причин
Центр связей между причинами и эффектами
Интерпретация последовательности шагов как конвейера
Гибкость временной линии
Второй архитектурный паттерн
Что такое многослойная архитектура
Краткий обзор: действия вычисления и данные
Краткий обзор: многоуровневое проектирование
Традиционная многоуровневая архитектура
Функциональная архитектура
Упрощение изменений и повторного использования
Понятия используемые для размещения правила в слое
Анализ удобочитаемости и громоздкости решения
Итоги главы
Резюме
Что дальше?
Глава 19. Путешествие в мир функционального программирования продолжается
План главы
Полученные профессиональные навыки
Главные выводы
Приобретение навыков: победы и разочарования
Параллельные пути к мастерству
Песочница: создание побочного проекта
Песочница: практические упражнения
Реальный код: устранение ошибок
Реальный код: постепенное улучшение проекта
Популярные функциональные языки
Функциональные языки с наибольшим количеством вакансий
Функциональные языки на разных платформах
Возможность получения знаний
Математическая основа
Литература
Итоги главы
Резюме
Что дальше?