Принцип найменших знань або Закон Деметера - це застереження від заплутування вашого класу деталями інших класів, які проходять шар за шаром. Це говорить вам про те, що краще говорити тільки зі своїми "друзями", а не з "друзями друзів".
Уявіть, що вас попросили прив'язати щит до статуї лицаря у блискучій бронзовій броні. Ви обережно розміщуєте щит на лівій руці, щоб він виглядав природним. Ви помічаєте, що на передпліччі, лікті та на надпліччі є три маленькі місця, де щит торкається броні. Ви зварюєте всі три місця, тому що хочете бути впевненими, що зв’язок міцний. А тепер уявіть, що ваш начальник божевільний, бо він не може рухати ліктям своєї броні. Ви припускали, що броня ніколи не рухатиметься, і тому створила нерухомий зв'язок між передпліччям та передпліччям. Щит повинен з'єднуватися лише з його другом, передпліччям. Не передпліч друзів. Навіть якщо вам доведеться додати шматок металу, щоб змусити їх торкатися.
Метафори приємні, але що ми маємо на увазі під товаришем? Будь-яка річ, яку об’єкт знає, як створити чи знайти - це друг. Крім того, об’єкт може просто попросити передати інші об'єкти , з яких він знає лише інтерфейс. Вони не вважаються друзями, тому що ніяких очікувань, як їх отримати, не нав'язується. Якщо об’єкт не знає, звідки вони взялися, тому що щось інше передав / ввів його, то це не товариш друга, це навіть не друг. Це те, що об'єкт знає лише як використовувати. Це гарна річ.
Намагаючись застосовувати такі принципи, важливо розуміти, що вони ніколи не забороняють вам щось робити. Вони є попередженням, що, можливо, ви нехтуєте робити більше роботи, щоб досягти кращого дизайну, який може виконати те саме.
Ніхто не хоче робити роботу без причини, тому важливо зрозуміти, що ви отримуєте після цього. У цьому випадку він зберігає ваш код гнучким. Ви можете внести зміни і мати менше інших класів, на які впливають зміни, які турбуються. Це звучить добре, але не допомагає вам вирішити, що робити, якщо ви не сприймаєте це як якусь релігійну доктрину.
Замість того, щоб сліпо слідувати цьому принципу, скористайтеся простою версією цієї проблеми. Напишіть рішення, яке не відповідає принципу та те, що це робить. Тепер, коли у вас є два рішення, ви можете порівняти, наскільки сприйнятливий кожен до змін, намагаючись зробити їх в обох.
Якщо ви не можете вирішити проблему, дотримуючись цього принципу, ймовірно, ще один навик вам не вистачає.
Одним з варіантів вашої конкретної проблеми є введення frame
в щось (клас чи метод), який вміє спілкуватися з кадрами, щоб вам не довелося поширювати всі ті деталі кадру в чаті у вашому класі, які тепер лише знають, як і коли робити отримати кадр.
Це наслідок іншого принципу: окреме використання від будівництва.
frame = encoder->WaitEncoderFrame()
Використовуючи цей код, ви взяли на себе відповідальність за те, щоб якось придбати Frame
. Ви ще не взяли на себе жодної відповідальності за спілкування зі службою Frame
.
frame->DoOrGetSomething();
Тепер ви повинні знати, як спілкуватися з a Frame
, але замінити це на:
new FrameHandler(frame)->DoOrGetSomething();
А тепер вам залишається лише знати, як спілкуватися зі своїм другом, FrameHandler.
Є багато способів досягти цього, і це, мабуть, не найкращий, але це показує, як дотримання принципу не робить проблему нерозв'язною. Це просто вимагає від вас більше роботи.
Кожне хороше правило має виняток. Найкращі мої приклади - це внутрішні мови, визначені для домену . A DSL сек ланцюгової методЗдається, весь час зловживають Законом Деметра, оскільки ти постійно називаєш методи, які повертають різні типи та використовують їх безпосередньо. Чому це нормально? Тому що в DSL все, що повертається, - це ретельно продуманий друг, з яким ви повинні прямо поговорити. Конструюючи, ви отримали право очікувати, що ланцюжок методів DSL не зміниться. Ви не маєте цього права, якщо просто випадковим чином заглибитесь у кодову базу, що з'єднує все, що ви знайдете. Найкращі DSL - це дуже тонкі уявлення або інтерфейси до інших об'єктів, до яких ви, мабуть, не повинні заглиблюватися. Я згадую це лише тому, що, коли я дізнався, чому DSL - це хороша конструкція, я зрозумів, що закон про деметер набагато краще. Деякі йдуть так далеко, що кажуть, що DSL навіть не порушує справжній закон про поводження.
Ще одне рішення - дозволити щось інше ввести frame
у вас. Якщо ви frame
прийшли із сетера або бажано з конструктора, ви не несете жодної відповідальності за створення або придбання кадру. Це означає, що ти тут роль набагато більше, як FrameHandlers
і раніше. Натомість зараз ви той, хто балакає Frame
і робить щось інше, з'ясовуйте, як отримати « Frame
Шляхом цього - це те саме рішення з простою зміною точки зору.
Принципи SOLID - це найважливіші принципи, які я намагаюся дотримуватися. Тут поважаються два принципи єдиної відповідальності та інверсії залежності. Поважати цих двох справді важко і все-таки порушувати Закон Деметера.
Менталітет, який переживає порушення Demeter, схожий на їжу в фуршетному ресторані, де ви просто захопите все, що завгодно. Завдяки невеликій роботі ви можете забезпечити собі меню та сервер, які принесуть вам все, що завгодно. Сядьте, розслабтесь і добре поскакайте.