Раніше я любив корисні класи, наповнені статичними методами. Вони зробили велику консолідацію допоміжних методів, які в іншому випадку могли б лежати, викликаючи надмірність та технічне обслуговування. Вони дуже прості у використанні, без встановлення інстанцій, без утилізації, просто забудьте. Я здогадуюсь, це була моя перша мимовільна спроба створити архітектуру, орієнтовану на сервіс - безліч служб без громадянства, які просто зробили свою роботу і нічого іншого. Коли система росте, проте дракони приходять.
Поліморфізм
Скажімо, у нас є метод UtilityClass.SomeMethod, який радісно гуде разом. Раптом нам потрібно трохи змінити функціональність. Більшість функціоналів однакові, але нам все-таки потрібно змінити пару деталей. Якби це не був статичний метод, ми могли б зробити клас похідної та змінити вміст методу за потребою. Оскільки це статичний метод, ми не можемо. Звичайно, якщо нам просто потрібно додати функціональність перед або після старого методу, ми можемо створити новий клас і викликати старий всередині нього - але це просто грубо.
Неприємності інтерфейсу
Статичні методи не можуть бути визначені через інтерфейси з логічних причин. А оскільки ми не можемо перекрити статичні методи, статичні класи марні, коли нам потрібно передати їх по інтерфейсу. Це не дає змоги використовувати статичні класи як частину стратегії. Ми можемо виправити деякі проблеми, передаючи делегатів замість інтерфейсів .
Тестування
Це, в основному, йде рука об руку із згаданими вище неприємностями інтерфейсу. Оскільки наша можливість взаємозамінних реалізацій дуже обмежена, ми також матимемо проблеми із заміною виробничого коду тестовим кодом. Знову ж таки, ми можемо їх завершити, але це вимагатиме від нас змінити велику частину нашого коду лише для того, щоб мати змогу приймати обгортки замість фактичних об'єктів.
Підтримка крапель
Оскільки статичні методи зазвичай використовуються як корисні методи, а утилітні методи зазвичай матимуть різні цілі, ми швидко закінчимося великим класом, наповненим некогерентною функціональністю - в ідеалі кожен клас повинен мати єдину мету в системі . Я вважаю за краще мати п’ять разів більше класів, якщо їх цілі чітко визначені.
Повзання параметра
Для початку цей маленький милий і невинний статичний метод може взяти єдиний параметр. У міру зростання функціональності додається пара нових параметрів. Незабаром додаються додаткові параметри, які є необов'язковими, тому ми створюємо перевантаження методу (або просто додаємо значення за замовчуванням на мовах, які їх підтримують). Невдовзі у нас є метод, який приймає 10 параметрів. Потрібні лише перші три, параметри 4-7 необов’язкові. Але якщо вказано параметр 6, також потрібно заповнити 7-9 ... Якби ми створили клас з єдиною метою робити те, що зробив цей статичний метод, ми могли б вирішити це, взявши потрібні параметри в конструктор і дозволяє користувачеві встановлювати необов'язкові значення за допомогою властивостей або методів встановлювати кілька взаємозалежних значень одночасно. Крім того, якщо метод виріс до такої кількості складності,
Вимагаючи від споживачів створити екземпляр класів без причини
Один з найпоширеніших аргументів: чому вимагають, щоб споживачі нашого класу створили екземпляр для виклику цього єдиного методу, не використовуючи при цьому для цього примірника? Створення екземпляра класу - дуже дешева операція на більшості мов, тому швидкість не є проблемою. Додавання споживачам додаткової лінійки коду - це низька вартість закладання фундаменту набагато більш досяжного рішення в майбутньому. І нарешті, якщо ви хочете уникати створення екземплярів, просто створіть однотонну обгортку свого класу, яка дозволяє легко повторно використовувати - хоча це вимагає, щоб ваш клас був без громадянства. Якщо це не без громадянства, ви все одно можете створити статичні методи обгортки, які впораються з усім, одночасно надаючи всі переваги в довгостроковій перспективі. Нарешті,
Лише Sith займається абсолютами.
Звичайно, є винятки з моєї неприязні статичних методів. Справжні класи утиліти, які не становлять ніякого ризику розростання, є прекрасними випадками для статичних методів - System.Convert як приклад. Якщо ваш проект є одноразовим і не потребує подальшого обслуговування, загальна архітектура насправді не дуже важлива - статична або нестатична, насправді не має значення - швидкість розробки, однак, має.
Стандарти, стандарти, стандарти!
Використання методів екземплярів не заважає вам також використовувати статичні методи, і навпаки. До тих пір, поки існують міркування щодо диференціації, і це стандартизується. Немає нічого гіршого, ніж переглядати бізнес-шар, розповсюджений різними методами реалізації.