На недавнем собеседовании я не смог ответить на вопрос о SOLID - помимо предоставления основного значения различных принципов. Это действительно беспокоит меня. Я потратил пару дней на то, чтобы покопаться и еще не нашел удовлетворительного резюме.
Вопрос интервью был:
Если бы вы посмотрели на проект .Net, который, как я вам сказал, строго следовал принципам SOLID, что бы вы ожидали увидеть в плане проекта и структуры кода?
Я немного барахтался, на самом деле не ответил на вопрос, а потом разбомбил.
Как я мог лучше справиться с этим вопросом?
Ответы:
S = принцип единой ответственности
Поэтому я ожидал увидеть хорошо организованную структуру папок / файлов и иерархию объектов. Каждый класс / часть функциональности должен быть назван так, чтобы его функциональность была очевидна, и он должен содержать только логику для выполнения этой задачи.
Если бы вы увидели огромные классы менеджера с тысячами строк кода, это было бы признаком того, что единственная ответственность не была соблюдена.
O = открытый / закрытый принцип
Это в основном идея, что новые функциональные возможности должны быть добавлены через новые классы, которые оказывают минимальное влияние на / требуют модификации существующих функциональных возможностей.
Я ожидал бы увидеть много использования наследования объектов, подтипов, интерфейсов и абстрактных классов, чтобы отделить дизайн части функциональности от фактической реализации, позволяя другим прийти и реализовать другие версии вместе, не затрагивая оригинал.
L = принцип подстановки Лискова
Это связано со способностью рассматривать подтипы как их родительский тип. Это происходит из коробки в C #, если вы реализуете правильную иерархию унаследованных объектов.
Я ожидаю увидеть код, обрабатывающий общие объекты как их базовый тип и вызывающий методы в базовых / абстрактных классах, а не создающий и работающий с самими подтипами.
I = принцип разделения интерфейса
Это похоже на SRP. По сути, вы определяете меньшие подмножества функциональных возможностей как интерфейсы и работаете с ними, чтобы поддерживать развязанность вашей системы (например,
FileManager
может иметь единственную ответственность при работе с Файловым вводом-выводом, но она может реализовыватьIFileReader
иIFileWriter
содержать конкретные определения методов для чтения и написание файлов).D = принцип обращения зависимостей.
Опять же, это относится к разделению системы. Возможно, вы будете в поисках использования библиотеки .NET Dependency Injection, используемой в решении, таком как
Unity
или,Ninject
или в системе ServiceLocator, такой какAutoFacServiceLocator
.источник
Множество небольших классов и интерфейсов с внедрением зависимостей повсюду. Вероятно, в большом проекте вы также использовали бы IoC-инфраструктуру, чтобы помочь вам построить и управлять временем жизни всех этих небольших объектов. См. Https://stackoverflow.com/questions/21288/which-net-dependency-injection-frameworks-are-worth-looking-into
Обратите внимание, что большой проект .NET, который СТРОГО следует принципам SOLID, не обязательно означает хорошую кодовую базу для работы со всеми. В зависимости от того, кем был интервьюер, он / она, возможно, хотел, чтобы вы показали, что вы понимаете, что значит SOLID, и / или проверьте, насколько догматично вы следуете принципам дизайна.
Видите ли, чтобы быть твердым, вы должны следовать:
S Ingle принцип ответственности, так что вы будете иметь много небольших классов каждый из них делает одно только
O ручка-замкнутый принцип, который в .NET обычно реализуется с инъекцией зависимости, что также требует ввода и ниже D ...
L принцип замещения Исек вероятно inmpossible объяснить в C # с однострочником. К счастью, есть другие вопросы, касающиеся этого, например, https://stackoverflow.com/questions/4428725/can-you-explain-liskov-substitution-principle-with-a-good-c-sharp-example
Я nterface Сегрегация Принцип работы в тандеме с открытым закрытым принципом. Если следовать буквально, это будет означать предпочтение большого количества очень маленьких интерфейсов, а не нескольких «больших» интерфейсов.
D ependency принцип инверсии классы высокого уровня не должны зависеть от классов низкого уровня, и должен зависеть от абстракций.
источник
Некоторые основные вещи, которые я ожидал бы увидеть в кодовой базе магазина, который поддерживал SOLID в своей повседневной работе:
Множество паттернов Adapter и Composite - я ожидаю использовать множество паттернов Adapter (класс, реализующий один интерфейс путем «перехода» к функциональности другого интерфейса), чтобы упростить включение зависимости, разработанной для одной цели, в слегка различные места, где его функциональность также необходима. Обновление, столь же простое, как замена логгера консоли файловым логгером, нарушит LSP / ISP / DIP, если интерфейс обновляется, чтобы предоставить средство для указания имени файла для использования; вместо этого класс файлового регистратора будет предоставлять дополнительных членов, а затем Adapter сделает файловый регистратор похожим на консольный регистратор, скрывая новый материал, поэтому только объект, соединяющий все это вместе, должен знать разницу.
Точно так же, когда классу необходимо добавить зависимость аналогичного интерфейса как существующего, чтобы избежать изменения объекта (OCP), обычный ответ - реализовать шаблон Composite / Strategy (класс, реализующий интерфейс зависимостей и потребляющий несколько других реализации этого интерфейса, с различной степенью логики, позволяющей классу передавать вызов одной, нескольким или всем реализациям).
источник
Отвлеките их обсуждением Джона Скита о том, что «О» в SOLID «бесполезно и плохо понято», и заставьте их поговорить об «защищенном варианте» Алистера Кокберна и «замысле Джоша Блоха о наследовании или запретите его».
Краткое резюме статьи Скита (хотя я бы не рекомендовал оставлять его имя без чтения оригинального сообщения в блоге!):
ФП спросил: «Как я мог лучше справиться с этим вопросом?» Будучи старшим инженером, проводящим собеседование, я был бы неизмеримо больше заинтересован в кандидате, который может разумно говорить о плюсах и минусах различных стилей разработки кода, чем о ком-то, кто может вычеркнуть список ключевых моментов.
Другим хорошим ответом было бы: «Ну, это зависит от того, насколько хорошо они это поняли. Если бы они знали только умные слова« SOLID », я бы ожидал злоупотребления наследованием, чрезмерного использования инфраструктур внедрения зависимостей, миллиона небольших интерфейсов, ни один из которых отражать словарь домена, используемый для связи с управлением продуктами .... »
источник
Вероятно, есть несколько способов ответить на это с разным количеством времени. Тем не менее, я думаю, что это больше похоже на "Знаете ли вы, что означает SOLID?" Таким образом, ответ на этот вопрос, вероятно, сводится к тому, чтобы привлечь внимание и объяснить это с точки зрения проекта.
Итак, вы ожидаете увидеть следующее:
источник
Это отличный вопрос, хотя я думаю, что это сложный вопрос для интервью.
Принципы SOLID действительно управляют классами и интерфейсами и тем, как они связаны друг с другом.
Этот вопрос действительно имеет отношение к файлам, а не к классам.
Краткое замечание или ответ, который я бы дал, состоит в том, что обычно вы видите файлы, которые содержат только интерфейс, и часто принято считать, что они начинаются с заглавной буквы. Кроме того, я бы упомянул, что в файлах не будет дублирующегося кода (особенно в модуле, приложении или библиотеке), и этот код будет аккуратно распространяться через определенные границы между модулями, приложениями или библиотеками.
Роберт Мартин обсуждает эту тему в области C ++ в разделе «Проектирование объектно-ориентированных приложений C ++ с использованием метода Booch» (см. Разделы «Сплоченность, замыкание и повторное использование») и в « Чистом коде» .
источник