Advertisement
Advertisement

More Related Content

Similar to "Elements of functional programming in C# based on Language-Ext library as an example", Yurii Naurynskyi(20)

More from Fwdays(20)

Advertisement

Recently uploaded(20)

"Elements of functional programming in C# based on Language-Ext library as an example", Yurii Naurynskyi

  1. Елементи функціонального програмування в C# на прикладі бібліотеки Language-Ext Автор: Юрій Науринський
  2. 1. Процес моделювання маршруту за допомогою функціональних елементів 2. Керування функціональними елементами 3. Типові питання 4. Висновки Зміст
  3. Дисклеймер – яку мову програмування ми використовуємо? Ми використовуємо C# Чому не F#? Це буде зрозуміло наприкінці презентації
  4. Guard – для валідування НЕ бізнес-логіки Language-Ext — бібліотека скарбничка функціональних елементів, про яку саме йде річ Дисклеймер — які бібліотеки ми використовуємо?
  5. Специфіка домену MapService 1. Практично немає внутрішньої поведінки класів 2. Дуже багато інваріантів 3. Все залежить від зовнішніх сервісів (налаштувань, БД) 4. Контроль типів як наслідок 5. Контроль валідності стану системи
  6. Де це все використовувати? HERE! Мова йде тільки про домен Гарне питання про те, як використовувати функціональні елементи в інфраструктурі: https:/ /github.com/louthy/language-ext/ discussions/1102
  7. Процес моделювання маршруту за допомогою функціональних елементів ● Звичайний клас ● Record ● Засилля примітивних типів ● Вічний Null ● Discriminated Union ● Опціональні значення ● Створення нового об’єкту
  8. Звичайний клас Немає дотримання інваріантів Мутабельність Що тут потрібне, а що ні?
  9. Неможливо порівняти один маршрут з іншим Неявні винятки Іммутабельно А як цей клас тоді змінювати? Звичайний клас
  10. Record З переваг – компілятор за нас написав Equals & Compare & ToString Елегантно (ні) вирішуємо всі наявні проблеми одним ключовим словом Все ще маршрут відповідає за інваріанти своїх дистанції та довжини З таким записом змінювати рекорд за допомогою with не можна
  11. На жаль конструктор не генерує, тому створення лише через init Насправді, саме так правильно дотримуватись інваріантів у випадку рекордів Record
  12. Суттєвий мінус — використовує застарілий кодген Виглядає практично так само як і нативний рекорд, але просто з’явився раніше Практично всі ті самі фічі як і в нативному. Але є Лінзи, що зручно Record
  13. Недоліки: Висновок: не є зараз актуальним, так як з’явився нативний рекорд. Буде більш актуальним тоді, коли в ньому з’являться перевірки на Null, та буде використовувати Source Generators. ● Допускає запис Null https:/ /github.com/louthy/language-ext/issues/1105 ● Використовує застарілий кодген Record — Language Ext
  14. Засилля примітивних типів Кожен раз де є дистанція так перевіряти? Можемо помилятися в порядку при створенні маршруту Це метри, кілометри, сантиметри, чи що?
  15. Проблема подвійної валідації Невже це все знову потрібно валідувати в методі? Щось там обчислює…
  16. Техніка “X-ing” Чим ці два методи відрізняються?
  17. Відпадає питання одиниць вимірювання Клас обгортка На практиці надзвичайно зручна валідація внутрішніх значень Засилля примітивних типів
  18. NewType — зручне створення нових типів обгорток NumType & FloatType — все те ж саме, але для цілих чисел, або чисел з рухомою комою Сигнатура: а. NewType<NEWTYPE, A, PRED> i. NEWTYPE — реалізуємий тип ii. A – внутрішній тип iii. PRED — предикат, який валідує внутрішній тип За замовчуванням викидає виняток, якщо предикат повертає false Є статичний метод NewOption з результатом у вигляді типу Option Засилля примітивних типів
  19. Ніякої подвійної валідації. Гарантовано валідні дистанція та тривалість Проблема подвійної валідації
  20. Кришталево зрозуміло, що тепер відбувається Техніка “X-ing”
  21. Переваги та недоліки типів обгорток проти засилля примітивних типів Переваги ● Зникає проблема подвійної валідації ● Зникає проблема “X-ing” ● Неможливо переплутати багато однакових аргументів місцями Недоліки ● Необхідно постійно створювати ці типи обгортки ● Більше навантаження на GC? (треба вимірювати)
  22. Вічний Null Ідеально? Ні, про null забули…
  23. Зручний Fluent спосіб валідування на null Тільки для інфраструктурної валідації !!! Використовується бібліотека Dawn.Guard Вічний Null
  24. Discriminated Union Приходить бізнес-аналітик і каже: “Дистанція маршруту тепер може бути розділена за ознакою в місті, або за містом. Але таке розділення не завжди потрібне.”!
  25. А ось тут кодген вже корисний, бо нативної підтримки типів сум (юніонів) в C# ще (сподіваюсь) немає Тут можливі два випадки (кейси): ● АБО загальна дистанція ● АБО розділена дистанція Чи потрібно тут створювати нові класи обгортки DistanceInsideCIty & DistanceOutsideCity? Залежить від вимог Discriminated Union
  26. Елегантно вирішена проблема кількох станів Discriminated Union
  27. Автоматично генерується клас конструктор юніону Compile-time safe обробка всіх станів Discriminated Union
  28. Ніби емуляція нативними засобами мови Але Compile-time safe обробку прийдеться писати власноруч, кожен раз Discriminated Union
  29. Недоліки: Висновок: є зараз актуальним, бо нативних аналогів немає. Можна емулювати, але емулювання не дає compile-time safe гарантію обробки всіх станів. Елегантно вирішує проблему опису кількох одночасних станів. ● Допускає запис Null https:/ /github.com/louthy/language-ext/issues/1105 ● Використовує застарілий кодген Discriminated Union — Language Ext
  30. Аксіома - Null означає відсутність об'єкта в застосунку, а не в бізнес-логіці!
  31. З C# 8 можна навіть класи помітити як ті, які опціонально містять null Але так моделювати опціональні значення незручно Опціональні значення
  32. Семантична коректність та гарантія обробки, але що таке Option? Опціональні значення
  33. Семантично означає опціональне значення Один з найвикористовуваніших типів для моделювання домену Не потрібно писати власноруч, вже є в бібліотеці, разом з низкою корисних методів Опціональні значення
  34. Самописний Option з бібліотеки Uklon.Nul Справжній Option повинен: ● Бути структурою ● Реалізовувати всі інтерфейси порівняння та серіалізації ● Мати такі методи: - Option<A>.Some(...) - Option<A>.None - Map - Bind Option з бібліотеки Language-Ext Опціональні значення
  35. Переваги та недоліки моделювання опціональних значень за допомогою Option чи null Option ● Зникає проблема подвійної валідації ● Коректна семантика опціональності ● Ідеально для бізнес-логіки ● Захаращує код Null ● Помилка часу виконання ● Семантика існування посилання ● Ідеально для інфраструктури на кордонах застосунку (адаптери, контролери) ● Захаращує пам’ять та час розробника
  36. Як маючи ці два примітивні значення створити маршрут? Створення нового об’єкту
  37. Оптимістичний підхід Ціле виключення на таку незначну дрібницю як невалідна дистанція/тривалість? Багато честі Але який тип тоді потрібен, щоб показати, що створення не вдалось? Створення нового об’єкту
  38. Виглядає практично як імперативний код Як тільки зустрічаємо перший None ● наступні кроки НЕ обробляються ● значення всього виразу стає None Монадична обробка Порядок обробки: ● повертає валідну дистанцію або None ● повертає валідну тривалість або None ● повертає валідний маршрут або None Створення нового об’єкту
  39. Але я хочу знати, яка саме помилка при створенні об'єкта!
  40. Дуже зручно помилки моделювати юніонами Практично те саме, що й з Option, але замість None буде CreateRouteError Створення нового об’єкту
  41. Зазвичай це стан помилки Два стани: або лівий, або правий Створення нового об’єкту
  42. Але я хочу знати ВСІ помилки при створенні об’єкту!
  43. Аплікативний стиль Збираємо ВСІ помилки. Гарно працює коли всі помилки один від одного незалежні Створення нового об’єкту
  44. Колекція помилок Створення нового об’єкту
  45. Переваги та недоліки функціонального рішення створення нового об’єкту Переваги ● Ніяких раптових винятків ● Даний підхід ЗМУШУЄ подумати про обробку помилок Недоліки ● Неясно ● Незрозуміло ● Не прийнято суспільством ● Достатньо високий поріг входження ● Через брак підтримки в мові, потребує використання самописних бібліотек
  46. Висновки по створенню об’єктів ● Зовнішня простота приховує за собою внутрішню складність ● Винятки – лише для виняткових ситуацій в програмі! ● Якщо бізнес-логіка об’єкта передбачає можливість невдалого створення об’єкта (наприклад, під час валідації) – це не виняткова ситуація! ● Можливі три різні підходи для створення об’єктів в функціональному стилі: а. використовуючи тип Option – якщо нам важливо лише те, чи був створений об’єкт, чи ні b. використовуючи тип Either – якщо важлива лише перша помилка при створенні об'єкта с. використовуючи тип Validation – якщо важливо зібрати всі помилки при створенні об'єкта
  47. Головні функції для керування елементами Так робити некоректно, Option не стикаються! Якщо потрібно перетворити Option і в результаті перетворення отримуємо новий Option Якщо внутрішнє значення Option потрібно в щось перетворити Єдиний вірний варіант отримати внутрішнє значення (крім Match) Всі ці функції стандартні, також є в Either & Validation
  48. Стандартна функція, яка також є в Either & Validation Оброблюємо всі можливі стани Головні функції для керування елементами
  49. Практично імперативний код! Гуглити “do notation” Функціонально еквівалентні варіанти запису
  50. ● Це інша мова зі своїм специфічним синтаксисом та особливостями ● Вибір мови – це не твій персональний вибір ● Простіше вивчити нову бібліотеку ніж мову? ● C# вже дуже гарний та майже функціональний (але зрозуміло ООП підхід перш за все) ● Вчити елементи та концепції функціонального програмування на початку простіше в знайомому оточенні Чому б просто не використовувати F#?
  51. Чому саме ця бібліотека? ● Або писати самому – або брати вже готове ● На прикладі бібліотеки Uklon.Null ми побачили що буде, якщо писати це все самому ● До того ж, є неймовірно багато речей, які можуть бути корисними, але про них треба знати. Якщо писати самому — про них не дізнаєшся
  52. Навіщо це взагалі потрібно? ● Дані методи дають змогу безпечно моделювати складний домен, де багато зовнішніх залежностей ● Ці методи НЕ замінюють тести, сонар та інше, а лише ДОПОВНЮЮТЬ!
  53. Висновки ● Спробуйте на практиці змоделювати свою бізнес-логику за допомогою описаних методів ● Насправді порядок моделювання не дуже важливий, до кінцевого результату ви врешті решт прийдете використавши всі потрібні вам та описані методи ● Так в чому ж основна перевага? Ми ЗАВЖДИ знаємо, як комбінувати наші типи декларативним способом, що автоматично робить наш код більш простим та підтримуваним
  54. Корисні посилання https:/ /github.com/louthy/language-ext https:/ /github.com/louthy/language-ext/wiki https:/ /fsharpforfunandprofit.com https:/ /fsharpforfunandprofit.com/posts/13-ways-of-looking-at-a-turtle http:/ /blog.ezyang.com/2010/05/design-patterns-in-haske https:/ /enterprisecraftsmanship.com/ps-func https:/ /enterprisecraftsmanship.com/posts/functional-c-immutability/ https:/ /blog.ploeh.dk/ https:/ /www.youtube.com/watch?v=Nrp_LZ-XGsY
  55. Дякую за увагу!
  56. Q&A
Advertisement