Комментарии 8
Меня всегда в примерах про S из SOLID смущают примеры: нам показали как сделать 2 кирпича, которые ни от чего не зависят, а вот как из них дом стоить не показали. Ведь каждое использование такого кирпича тоже должно быть по S.
надо избегать повторения одного и того же кода в разных частях вашей программы.
На мой вкус сильно механистическое упрощение. Важно не то, что код одинаковый, а то что это один и тот же код. Разница в том, что один и тот же код должен всегда одинаково изменяться во всех своих копиях. А просто одинаковый код, может иметь разные причины для изменения. Сейчас одинаковый, а завтра разный. И усилия потраченные на объединение одинакового кода будут дополнены усилиями по его разделению. В общем нужно смотреть не только на код как на набор символов, но и вникать что это за код.
К сожалению статья довольно проходная, с уже оскомину набившими примерами. Определение S в частности и в оригинале и в 99 процентов материалов очень мутное, которое красиво звучит, но только если не задавать лишних вопросов. Небольшая ремарка касательно повторения сам же Мартин выделяет два типа дублирования - ложное и истинное. Так вот ложное дублирование не требует устранения и наоборот - вредно. Так что одержимо пытаться вырезать все дублирования значит привести в тому от чего хотелось уйти - к сильной связности. Если говорить про SRP, то тут как мне кажется, несколько уровней непонимания - первый трактовка в лоб, одна сущность должна делать что-то одно. Что одно и какая сущность остается за скобками. Мартин пишет, что этот принцип применим только к функциям/методам. Второй уровень как раз представлен в статье, одна причина для изменения. Опять же не понятно, очень завуалировано, если изменились бизнес требования, то одним изменением можно и не отделаться, кроме того как это бьется со вторым требованием, где изменения текущей функциональности не приветствуются (OCP). По разъяснениям самого Мартина итоговый верный вариант звучит так: "Модуль должен отвечать за одного и только за одного актора". Приведу тривиальный пример. Модуль должен быть спроектирован таким образом, что изменяется только по требованию стейкхолдера (владельца продукта, бизнес аналитика), но не скажем DBA. А там где изменяется по требованиям DBA не меняется по требованиям бизнеса. То есть каждая часть кода зависит от одного и только одного актора. Причем внутри бизнес требований это правило так же соблюдается, но чтобы это поддержать нужно уходить в проектирование по доменам (DDD), если делать все так тогда это работает.
Модуль должен отвечать за одного и только за одного актора
Интересный подход, не знал о таком. Плохо, что у меня у всех модулей 1 стекхолдер :)
На практике я делаю так: ответственность одна, если я могу вменяемо сформулировать эту ответственность. Так подход ставит рамки, на то что может содержаться в сущности и становится понятно, когда можно добавлять функционал, а когда пора делать новую сущность.
В go нет наследования.
Я конечно новичек на хабре.. Может здесь есть какое-то разделение на "рекламные" посты и полезные? Прихожу обычно за полезными...
Но выскажу свое субъективное мнение мнение - определения копи-паст из книг (название не скажу, но совсем недавно читал, у Фаулера что-ли), в применении к Го никак не объяснены, только через очень фантастические надуманные примеры.
Прочтение по примерам может нанести и вред. Потом начинают писать абстракции на абстракции и превращают Го в Java, читать код невозможно. Сотни интерфейсов там где они не нужны.
В этом плане мне нравится подход из ardanlabs - никаких "DI" и передачи через интерфейсов до тех пор, пока оно действительно не нужно будет. "Наследование" в Го также довольно интересная штука в плане проблем - если честно не так часто встречаю кейсы когда оно действительно нужно, чаще от него проблемы только. Дробление на функции и "вынос" функционала - тоже надо использовать с умом, иначе потом задолбаешься в ИДЕшке скакать по модулям, и быстрее забудешь зачем вообще зашел.
И вот эти все моменты, что выше обычно в нормальной литературе подсвечиваются, объясняются побочные моменты и варианты использования.
В общем, сорян за негатив, но от статей на хабре ожидаю большего импакта обычно. (знаю про "не нравится - напиши сам", но именно потому что не хочу писать подобные посты - не пишу их, а прихожу к умным людям)
На сколько знаю из описания языка, в Go by design отсутствуют классы, в Go by design отсутствует наследование, в Go by design реализована частичная поддержка парадигмы ООП. Поэтому такие выражения как "класс-родитель и класс-потомок" не имеют под собой смысла. Также трудно представить себе функцию, которая "меняется по нескольким причинам". Казалось бы, зачем это писать? Сейчас наблюдается чуть ли не повальный тренд перевода, переноса, переписывания проектов на Go, которые были написаны на ЯП с ООП, либо хуже того - скриптовых языках с поддержкой ООП и динамической типизацией. Люди упёрлись в быстродествие, масштабирование, устойчивость своего сервиса и решили попробовать что-то другое.
В итоге читают подобные статьи, решают что всё возможно будет так просто, легко и непринуждённо. Не так страшен последующий за этим хейт ЯП. Здесь периодически всплывают статьи подобного содержания. Хуже, что такие ошибочные и даже неверные знания потом начинают расползаться и приносить потом сплошной вред. Чему тогда хорошему можете научить на этом курсе?
Какого же невероятного монстра можно породить, если пытаться засунуть концепты ООП в язык, который специально был создан процедурным, чтобы избежать усложнений и лишних абстракций, которые часто привносят парадигмы ООП. Очень будет грустно если "ведущие эксперты" OTUS будут кому-то прививать "цифровые навыки" описанные в этой статье
SOLID и DRY в Go