Принцип наименьшего знания или Закон Деметры - это предупреждение против запутывания вашего класса деталями других классов, которые пересекают слой за слоем. Он говорит вам, что лучше разговаривать только со своими «друзьями», а не с «друзьями друзей».
Представьте, что вас попросили приварить щит к статуе рыцаря в блестящей броне. Вы осторожно размещаете щит на левой руке, чтобы он выглядел естественно. Вы замечаете, что на предплечье, локте и плече есть три небольших места, где щит касается доспехов. Вы свариваете все три места, потому что хотите быть уверенными, что связь прочная. Теперь представьте, что ваш босс злится, потому что он не может сдвинуть локоть своей брони. Вы предполагали, что броня никогда не будет двигаться, и создали неподвижную связь между предплечьем и предплечьем. Щит должен подключаться только к его другу, предплечью. Не предплечья, друзья. Даже если вам нужно добавить кусок металла, чтобы они соприкасались.
Метафоры хороши, но что мы на самом деле подразумеваем под другом? Любая вещь, которую объект знает, как создать или найти, является другом. Кроме того, объект может просто попросить передать другие объекты , о которых он знает только интерфейс. Они не считаются друзьями, потому что не ожидают, как их получить. Если объект не знает, откуда он взялся, потому что что-то еще прошло / впрыснуло это, то это не друг друга, это даже не друг. Это то, что объект знает только как использовать. Это хорошая вещь.
Когда вы пытаетесь применять такие принципы, важно понимать, что они никогда не запрещают вам что-то делать. Они являются предупреждением о том, что вы, возможно, пренебрегаете дополнительной работой для достижения лучшего дизайна, который выполняет то же самое.
Никто не хочет делать работу без причины, поэтому важно понимать, что вы получаете после этого. В этом случае он сохраняет ваш код гибким. Вы можете вносить изменения и меньше беспокоиться о других классах. Это звучит хорошо, но не поможет вам решить, что делать, если вы не примете это за какую-то религиозную доктрину.
Вместо слепого следования этому принципу возьмите простую версию этой проблемы. Напишите решение, которое не следует этому принципу и которое соответствует. Теперь, когда у вас есть два решения, вы можете сравнить, насколько каждый восприимчив к изменениям, попытавшись внести их в оба.
Если вы не можете решить проблему, следуя этому принципу, скорее всего, вам не хватает другого навыка.
Одним из решений вашей конкретной проблемы является внедрение frame
чего-либо (класса или метода), который знает, как общаться с фреймами, чтобы вам не приходилось распространять все эти детали фрейма чата в вашем классе, который теперь знает только, как и когда получить кадр.
Это на самом деле следует другому принципу: отделить использование от строительства.
frame = encoder->WaitEncoderFrame()
Используя этот код, вы взяли на себя ответственность за то, чтобы каким-то образом приобрести Frame
. Вы еще не взяли на себя ответственность за разговор с Frame
.
frame->DoOrGetSomething();
Теперь вы должны знать, как разговаривать Frame
, но замените это на:
new FrameHandler(frame)->DoOrGetSomething();
И теперь вам нужно только знать, как разговаривать с вашим другом, FrameHandler.
Есть много способов достичь этого, и это, возможно, не самый лучший, но он показывает, как следование принципу не делает проблему неразрешимой. Это просто требует больше работы от вас.
У каждого хорошего правила есть исключение. Лучшие примеры, которые я знаю, это внутренние языки, специфичные для предметной области . A DSL сек цепной методпохоже, все время нарушает закон Деметры, потому что вы постоянно вызываете методы, которые возвращают разные типы, и используете их напрямую. Почему это нормально? Потому что в DSL все, что возвращается, это тщательно разработанный друг, с которым вам нужно поговорить напрямую. По замыслу вы получили право ожидать, что цепочка методов DSL не изменится. У вас нет этого права, если вы просто случайно копаетесь в кодовой базе, объединяя все, что найдете. Лучшие DSL - это очень тонкие представления или интерфейсы с другими объектами, в которые вы, вероятно, не должны углубляться. Я упоминаю об этом только потому, что обнаружил, что понял закон деметры гораздо лучше, когда узнал, почему DSL - хороший дизайн. Некоторые заходят так далеко, что говорят, что DSL даже не нарушают настоящий закон Деметры.
Другое решение состоит в том, чтобы позволить что-то еще внедрить frame
в вас. Если вы frame
пришли от сеттера или, предпочтительно, от конструктора, вы не берете на себя никакой ответственности за создание или приобретение фрейма. Это означает, что ваша роль здесь намного больше, чем FrameHandlers
должна была быть. Вместо этого теперь вы - тот, с кем общаетесь Frame
и заставляете что-то еще выяснить, как это сделать. Frame
В каком-то смысле это то же самое решение с простой сменой перспективы.
В SOLID принципов являются большим я стараюсь следовать. Здесь соблюдаются два принципа: принцип единой ответственности и принцип инверсии. Это действительно трудно уважать этих двоих и все же в конечном итоге нарушать закон Деметры.
Менталитет, который нарушает Деметру, подобен еде в буфете, где вы просто берете все, что хотите. Немного поработав заранее, вы можете предоставить себе меню и сервер, который доставит вам все, что вам понравится. Откиньтесь на спинку кресла, расслабьтесь и хорошо наклоните голову.