Критерії простоти

Левова частка програмістів з чистою совістю заявить, що воліє вирішувати завдання просто, керуючись насамперед здоровим глуздом. Ось тільки це "просто" у кожного своє і, як правило, відмінний від інших. Після одного довгого і неконструтивного спору з колегою я вирішив викласти, що саме вважаю простим сам і чому. Це не призвело до негайного згоди, але дозволило зрозуміти логіку один одного і звести до мінімуму зайві дискусії.
Перший критерій
Особливості мозку людини такі, що він погано зберігає і відрізняє більш 7-9 елементів в одному списку при оптимальному їх кількості 1-3.
Звідси рекомендація — в ідеалі мати не більше трьох членів в інтерфейсі, трьох параметрів у методі і так далі і не допускати збільшення їх кількості понад дев'яти.
Цей критерій може бути реалізований засобами статичного аналізу.
Другий критерій
найважливіше — у перших двох рядках будь-якого класу.
  1. Ім'я, параметри типу, реалізовані інтерфейси.
  2. Параметри конструктора.
В результаті ми знаємо про класі все, що необхідно для його використання (ім'я, параметри, входи, виходи), навіть не заглядаючи в залишився код.
Зрозуміло, це працює за умови обмежень:
  1. Уникайте спадкування реалізацій
  2. Уникайте впровадження залежностей інакше, ніж через параметри конструктора.
І цей критерій може бути реалізований засобами статичного аналізу.
Третій критерій
Один тип — одна задача. Контракти — інтерфейсів, реалізації — класів, алгоритми — методам!
Мультітули гарні тільки якщо нічого іншого під рукою взагалі немає. Завдяки першим двом критеріям писати такі типи нескладно. Так, це принцип єдиної відповідальності, поділу інтерфейсів до купи)
А ось тут статичний аналіз доведеться довірити людині.
Четвертий критерій
Обмеження — така ж легальна частина контракту, як і сигнатури методів.
І отже...
  1. Коментарі в контракті — майже завжди корисні, коментарі у програмному коді реалізації майже завжди шкідливі.
  2. DTO — повноцінні об'єкти, чия примітивність поведінки винагороджується автоматичної серіалізацією.
  3. Незмінні об'єкти — винагороджують зручністю валідації, відсутністю гонок і зайвого копіювання.
  4. Статичний метод — повноцінний клас без стану, всі плюшки від незмінних об'єктів плюс менший трафік пам'яті.
  5. Анонімні делегати і лямбды — замінюють зв'язку інтерфейс-клас з одним методом, дозволяючи викинути два зайвих типу і продемонструвати сигнатуру виклику прямо в коді.
  6. Додайте решту "несправжні об'єкти" за вашим смаком.
Статичний аналіз тут може допомогти тільки рекомендаціями по використанню простіших варіантів типів, якщо їх побачить.
П'ятий критерій
Максимальну зручність для повторного використання.
Застосовуйте спадкування інтерфейсів, уникайте спадкування реалізацій і отримаєте відразу три джерела повторного використання коду
  1. Повторне використання контрактів — дуже корисно, навіть якщо жодна готова реалізація не підійшла.
  2. Повторне використання реалізацій — скрізь де приймається контракт можна задіяти вже написану реалізацію.
  3. Повторне використання клієнтського коду — весь код, який працює з інтерфейсом (включаючи тести), можна переиспользовать з кожною новою реалізацією.
Так, це принцип підстановки Лисков в максимально простій і практичною формою.
Статичний аналізатор може повідомляти про використання небажаного успадкування реалізації.
Також не варто ховати типи або методи "на всякий випадок". Публічним повинно бути все, крім того, що необхідно заховати як деталі реалізації.
Шостий критерій
Ваші типи повинні бути більш простими для композиції, декорування, адаптації, організації фасаду і т. п., ніж для зміни. При дотриманні попередніх критеріїв цього домогтися нескладно.
Це дозволить якомога більше змін звести до додавання нового коду замість переписування поточного, що зменшить регресію і необхідність правити ще й старі тести.
Ідеальний приклад — методи розширення інтерфейсів, що додають функціональність з одного боку і ніяк не змінюють вихідні контракт і реалізацію з іншого.
Так, це принцип відкритості-закритості.
Ні, статичний аналіз тут мало чим допоможе
Сьомий критерій
Типи параметрів конструктора повинні як можна більше говорити про те, як треба використовувати їх значення.
Наприклад:
  1. IService — служба, необхідна для реалізації
  2. Lazy<IService> — служба, якої може і не бути при старті, для початку використання треба прочитати властивість Value, при першому зверненні можлива пауза.
  3. Task<IResource> — ресурс, який виходить асинхронно
  4. Func<IArgument, IResource> — параметризується фабрика ресурсів
  5. Usable<IResource> — ресурс, який потрібен до певного моменту, про закінчення використання можна повідомити, викликавши метод Dispose.
на Жаль, статичний аналіз мало чим тут допоможе.
Восьмий критерій
Маленькі типи краще великих, так як навіть погано спроектовані або реалізовані маленькі типи набагато простіше виправити, переписати або видалити порівняно з великими.
Велика кількість маленьких типів не є саме по собі фатальною проблемою, так як типи — це не список, а граф. В голові одночасно достатньо тримати зв'язку поточного типу, а їх кількість обмежується першим критерієм.
Дев'ятий критерій
Залежно типів між собою необхідно обмежувати
  1. Циклів в графі типів треба уникати
  2. Також треба уникати прямих посилань реалізацій один на одного.
  3. Вкрай бажано використовувати патерни розбиття типів на шари, додаючи обмеження на залежності між типами різних шарів один на одного.
Метою є максимальне спрощення графа залежностей типів. Це допомагає як при навігації по коду, так і при визначенні можливого афекту від тих чи інших змін.
Так, цей критерій входить принцип інверсії залежностей.
Так, тут може допомогти статичний аналіз.
Десятий критерій
Те ж, що і дев'ятий критерій, але для збірок. Сильно спрощує життя і прискорює складання, особливо якщо відразу проектувати з його урахуванням. Для збірок з контрактами простіше підтримувати зворотний сумісність (опубліковані контракти не змінюються). Складання ж з реалізаціями можна заміняти цілком — вони все одно один від одного напряму не залежать.
Засобами статичного аналізу можна воспретить одним зборках посилатися на інші.
Одинадцятий критерій
Всі попередні критерії можуть бути порушені при необхідності оптимізації. Але одне, на мій погляд працює завжди:
Простіше оптимізувати коректний код, ніж коригувати оптимізований.
Підсумки
Письмовий виклад власних уявлень багато чого прояснила для мене самого.
Хотілося б побачити ваші критерії простоти в коментарях.
Згадки статичного аналізу означають можливість реалізації, а не її наявність на поточний момент.
Доповнення та критика традиційно вітаються.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.