Завантажити застосунок

Функціональний дизайн: принципи, патерни і практики

Функціональний дизайн: принципи, патерни і практики

Функціональний дизайн: принципи, патерни і практики — Роберт С. Мартін

Видавництво: Видавничий дім «Фабула»
Автор: Роберт С. Мартін
Жанр: Саморозвиток і мислення
Де читати: У застосунку Наша Книга — детальніше
ISBN: 978-617-522-322-2
  • 620.00 грн


Опис

У книжці «Функціональний дизайн: принципи, патерни і практики» відомий інженер-програміст Роберт С. Мартін (Дядечко Боб) пояснює, чому варто використовувати функціональне програмування для створення кращих систем для реальних користувачів. Він порівнює традиційні об’єктно-орієнтовані структури кодування на Java зі структурами функціональних мов, визначає найкращі ролі для кожної з них і показує, як створювати довершені системи, розумно використовуючи їх у контексті. Р. Мартін мінімізує теорію на користь розв’язання нагальних проблем, і завдяки цьому прагматичному підходу діючі розробники на яскравих прикладах дізнаються, як мова Clojure, проста для вивчення і семантично багата, зможе допомогти їм підвищити чистоту коду, покращити дизайн і досягти найкращих результатів. Також автор розглядає принципи SOLID і дизайн-патерни з погляду функціональності, показуючи, чому саме патерни залишаються надзвичайно цінними для функціональних програмістів.

Про видання

Вікові обмеження
16+
Мова
Українська
Мова оригіналу
Англійська
Назва оригіналу
Functional Design: Principles, Patterns, and Practices
Рівень складності
Складний
Рік написання
2024
Опубліковано
2025
Кількість сторінок
320
Обсяг
≈ 51 000 слів
Час читання
≈ 4 год 45 хв
Перекладач
Кирило Горбушко
Передмова
Джанет А. Карр
Післямова
Джина Мартіні
Формат
Електронна книга

Зазирнути в книгу

Уривок

Якщо ви запитаєте середньостатистичного програміста, що таке функціональне програмування, ви можете отримати будь-яку з таких відповідей:

Хоча ці твердження можуть виявитися правдивими, вони не є особливо корисними. Я думаю, що краща відповідь буде такою:

Це програмування без операторів присвоювання.

Можливо, це визначення не здається вам набагато кращим. Можливо, воно вас навіть лякає. Зрештою, яке відношення оператори присвоювання мають до функцій, і як узагалі можна програмувати без них?

Хороші запитання. Саме на них я маю намір відповісти в цьому розділі.

Розглянемо наступну просту програму на C:

int main(int ac, char** av) {

while(!done())

doSomething();

}

Ця програма є основним циклом практично кожної будь-коли написаної програми. Вона буквально говорить: «Роби щось, поки не закінчиш». Навіть більше, у цій програмі немає видимих операторів присвоювання. Чи є вона функціональною? І якщо так, то чи означає це, що кожна будь-коли написана програма є функціональною?

Змусимо цю функцію щось робити. Нехай вона обчислює суму квадратів перших десяти цілих чисел [1..10]:

int n=1;

int sum=0;

int done() {

return n›10;

}

void doSomething() {

sum+=n*n;

++n;

}

void sumFirstTenSquares() {

while(!done())

doSomething();

}

Ця програма не є функціональною, тому що вона використовує два оператори присвоювання у функції doSomething. Крім того, ці дві глобальні змінні виглядають просто потворно. Тож покращимо її:

int sumFirstTenSquares() {

int sum=0;

int i=1;

loop:

if (i>10)

return sum;

sum+=i*i;

i++;

goto loop;

}

Це вже краще; дві глобальні змінні стали локальними. Але це все ще не функціонально. Можливо, вас турбує цей goto. На те є вагома причина. Потерпіть, поки ми розглядаємо цю невелику модифікацію, що використовує робочу функцію для перетворення локальних змінних на аргументи функції:

int sumFirstTenSquaresHelper(int sum, int i) {

loop:

if (i>10)

return sum;

sum+=i*i;

i++;

goto loop;

}

int sumFirstTenSquares() {

return sumFirstTenSquaresHelper(0, 1);

}

Ця програма ще не функціонує, але це важлива віха, до якої ми ще повернемося. Але зараз, з останньою зміною, відбувається щось магічне:

int sumFirstTenSquaresHelper(int sum, int i) {

if (i›10)

return sum;

return sumFirstTenSquaresHelper(sum+i*i, i+1);

}

int sumFirstTenSquares() {

return sumFirstTenSquaresHelper(0, 1);

}

Усі оператори присвоювання зникли, і програма працює. Вона також рекурсивна. І це не випадково. Якщо ви хочете позбутися операторів присвоювання, ви повинні використовувати рекурсію. Рекурсія дозволяє замінити присвоювання локальних змінних на ініціалізацію аргументів функції.

Це дійсно спалює багато місця на стеку. Однак є невеликий трюк, що допоможе розв’язати цю проблему.

Зверніть увагу, що останній виклик sumFirstTenSquaresHelper є також останнім використанням sum та і у цій функції. Тримати ці дві змінні у стеку після ініціалізації двох аргументів рекурсивного виклику безглуздо; вони ніколи не будуть використані. А що як замість того, щоби створювати новий кадр стеку (stack frame) для рекурсивного виклику, ми просто повторно використаємо поточний кадр стеку, повернувшись до початку функції за допомогою goto, як ми це зробили у віховій програмі?

Цей симпатичний маленький трюк називається оптимізацією хвостових викликів (tail call optimization, TCO), і всі функціональні мови використовують його{8}.

Зверніть увагу, що TCO фактично перетворює цю останню програму на програму етапу. Останні три рядки sumFirstTenSquaresHelper у проміжній програмі є, по суті, рекурсивним викликом функції. Чи означає це, що проміжна програма також є функціональною? Ні, вона просто поводиться ідентично. На рівні вихідного коду ця програма не є функціональною, тому що в ній є оператори присвоювання. Але якщо ми зробимо крок назад і проігноруємо той факт, що локальні змінні змінилися, а не були відновлені в новому кадрі стеку, то програма поводиться як функціональна.

Зміст

  • Присвята
  • Вступне слово
  • Передмова
  • Коротка історія функціонального і процедурного програмування
  • Про Clojure
  • Про архітектуру та дизайн
  • Про об’єктну орієнтацію
  • Про «функціональність»
  • Подяки
  • Про автора
  • Частина І Функціональні основи
  • 1 Незмінність
  • Що таке функціональне програмування?
  • Проблема із присвоюванням
  • То чому ж воно називається функціональним?
  • Без зміни стану?
  • Незмінність
  • 2 Постійні дані
  • Про шахрайство
  • Виготовлення копій
  • Структурний розподіл
  • 3 Рекурсія та ітерація
  • Ітерація
  • Рекурсія
  • 4 Лінь
  • Ліниве накопичення
  • Гаразд, але чому?
  • Кода
  • 5 Стабільний стан
  • Коли ми мусимо мутувати
  • Програмна транзакційна пам’ять (STM)
  • Життя складне, програмне забезпечення іще складніше
  • Частина ІІ Порівняльний аналіз
  • 6 «Prime Factors»
  • Версія Java
  • Версія на Clojure
  • Висновок
  • 7 «Гра у боулінг»
  • Версія Java
  • Версія на Clojure
  • Висновок
  • 8 «Плітки водіїв автобусів»
  • Рішення на Java
  • Clojure
  • Висновок
  • 9 Об’єктно-орієнтоване програмування
  • Функціональна реалізація Payroll (Розрахунок заробітної платні)
  • Простори імен та вихідні файли
  • Висновок
  • 10 Типи
  • Висновок
  • Частина ІІІ Функціональний дизайн
  • 11 Потік даних
  • 12 Solid
  • Принцип єдиної відповідальності (SRP)
  • Принцип відкритості-закритості (OCP)
  • Принцип заміщення Лісков (LSP)
  • Принцип розділення інтерфейсів (ISP)
  • Принцип інверсії залежностей (DIP)
  • Частина ІV Функціональна прагматика
  • 13 Тести
  • А як щодо REPL?
  • А що з моками?
  • Тестування на основі властивостей
  • Метод діагностики
  • Функціональний підхід
  • 14 Графічний інтерфейс
  • Turtle-Graphics у Quil
  • 15 Конкурентність
  • Висновок
  • Частина V Дизайн-патерни
  • 16 Огляд дизайн-патернів
  • Патерни у функціональному програмуванні
  • Абстрактний сервер
  • Адаптер
  • Command
  • Composite
  • Декоратор
  • Візитер
  • Абстрактна фабрика
  • Висновок
  • Постскриптум: отруєне ОП?
  • Частина VІ Приклад із життя
  • 17 Wa-Tor
  • Позбавляємося сверблячки
  • Душ вирішує проблеми
  • Час дикого розмноження
  • А як щодо shark?
  • Висновок
  • Післямова від Джини Мартіні

Про твір і автора

Для кого ця книга

  • розробникам, які пишуть на Java, C# чи C++ і хочуть зрозуміти, що з функціонального підходу можна забрати у щоденну роботу;
  • тим, хто береться за Clojure: увесь код прикладів — на ній, а репозиторій книжки відкритий;
  • читачам «Чистого коду» й «Чистої архітектури», яким цікаво, як ті самі принципи SOLID виглядають без об’єктів.

Чому варто прочитати

  • автор свідомо оминає теорію монад, моноїдів і категорій і розбирає задачі, які трапляються в роботі: «Prime Factors», гру в боулінг, розрахунок зарплатні, симуляцію Wa-Tor;
  • кожен приклад дано двічі — версія на Java і версія на Clojure, тому видно, що змінюється в дизайні, а не лише в синтаксисі;
  • окремі розділи присвячено тому, що вважають слабким місцем функціонального підходу, — тестам, конкурентності й графічному інтерфейсу;
  • передмову написала незалежна консультантка з Clojure Джанет А. Карр, а післямову — донька автора Джина Мартіні, яка прийшла в програмування з хімічної інженерії.
Роберт С. Мартін
Роберт С. Мартін

Історія написання

До функціонального програмування Мартін ішов довго: у подяках він згадує, що років двадцять тому Майкл Фізерс порадив йому придивитися до Haskell, а поштовхом стала класична «Структура та інтерпретація комп’ютерних програм»; до Clojure він узявся після книжки Стюарта Гелловея й, за словами в інтерв’ю 2024 року, тепер програмує переважно нею. «Функціональний дизайн» він писав як книжку для програмістів «в окопах»: замість теорії монад і категорій — одна й та сама задача поруч на Java і на Clojure. Передмову написала Джанет А. Карр, чиї дописи про патерни в Clojure Мартін випадково побачив у твіттері й виявив, що вона дійшла тих самих висновків, що й він. Післямова — від його доньки Джини Мартіні: у березні 2020 року, під час карантину, вона попросила батька навчити її програмувати, він показав їй свій тодішній проєкт — автоматичний графік захворюваності на COVID-19, написаний на Clojure, — і трохи більш ніж за рік вона стала розробницею у студії Clean Coders.

Де читати книгу

У застосунку

Ця книга читається в застосунку Наша Книга: купили на сайті — вона одразу у вашій бібліотеці на телефоні, з офлайн-режимом і синхронізацією прогресу.

Часті питання

Чи треба знати Clojure, щоб читати книжку?
Ні. Мартін вибрав дві мови свідомо: Java — бо вона широко відома, Clojure — бо «надзвичайно проста у вивченні». Ту саму задачу він показує в обох, а весь код прикладів лежить у відкритому репозиторії github.com/unclebob/FunctionalDesign.
Чи означає ця книжка, що об’єктно-орієнтоване програмування відпрацювало своє?
Ні, автор пише прямо протилежне. За його словами, багато хто вважає ці два стилі несумісними, а він переконаний, що вони цілком сумісні й «хороші розробники можуть і повинні застосовувати їх разом»; приклади в книжці поєднують обидва підходи.
Хто така Джанет А. Карр, чиє ім’я стоїть на обкладинці?
Незалежна консультантка з Clojure, авторка передмови до книжки. Співавторкою вона не є: у подяках Мартін дякує їй саме за вступне слово, а на її дописи про патерни в Clojure натрапив у твіттері.
Чи є в книжці принципи SOLID і класичні дизайн-патерни?
Так, обом темам відведено окремі частини. Мартін перевіряє SRP, OCP, LSP, ISP і DIP у функціональному середовищі, а далі розбирає абстрактний сервер, адаптер, Command, Composite, декоратор, візитера й абстрактну фабрику — і показує, навіщо патерни потрібні й тут.

Написати відгук

будь Ласка авторизуйтесь або створити обліковий запис перед тим як написати відгук
Застосунок «Наша Книга» — зручніше читати з телефона Відкрити