Тех кто понимают, что в коде проблема — не надо уже учить, сами знают что делать. А те кого надо учить — не понимают, им надо показать и рассказать.
Перевести из «не осознанной некомпетентности» в «осознанную»
Поддерживаю! Это как чистописание. Прописи для программистов.
Вот только у школ и вузов другая задача стоит.
Школы учат азам, там нет задачи из каждого сделать программиста.
А в вузах все всегда на одноразовых задачках. Преподаватели обычно горе-теоретики, так что скорее всего и код не читают. Главное чтоб работало. А это не способствует развитию хорошего стиля кода/архитектуры. Теоретически это можно автоматизировать сбором метрик, но кто там заморачиваться будет?
Та же ситуация в веб студиях — там проект делается левой ногой на выброс, никто там долго поддерживать его не собирается.
По этому там недостаточно боли от плохого кода. Тесты не пишутся. Призрак архитектуры унаследованный от фреймворка.
Только в компании разрабатывающей свой продукт или там где ценится качество(принципиально), люди могут дойти до осознания что надо что-то менять.
К сожалению, если это дойдет до одного, но он не сможет объяснить другим — все пропало.
Под разжевывать — я предлагаю рассказать про все эти принципы на примере рефакторинга какого-либо типового проекта. Но чтоб там изначально была боль, которую народ не понимает. Рассказать как это влияет на эволюцию проекта, с примерами, как это лечится. Пошагово, вводя принципы и практики по одной. Чтоб новички увидели что-то знакомое, поняли что не так с этим и научились как делать хорошо.
Желательно при этом сделать это на примере JS UI приложения. Ибо имхо это самый большой пласт начинающих разрабов.
Мне пришлось приложить не мало усилий, чтобы мои коллеги осознали, что надо учиться и начали хотя бы статьи читать. Мне повезло с техлидом. Обычно народ боится брать толстую книжку в руки ) А толковая литература обычно 300-1к страниц.
Так что сомневаюсь что они вот так сразу, не дочитав статью, а скорее всего они ее не дочитали, рванули читать что-то :)
Обратите внимание на кол-во комментариев к статье. Все ведь по делу написано, но никто из новичков не задает уточняющие вопросы. Они еще не понимают зачем это нужно. Зато с удовольствием посмакуют новый плагин к реакту. Так что формат статей нужно менять. Надо разжевывать зачем это нужно. Чтоб и школьнику стало понятно.
Спасибо за перевод.
Идея статьи правильная, но, как обычно, в интернете кто-то не прав есть замечания.
В основном претензии к примерам. Так автор в статье говорит о SRP и Coupling, а потом в примере к SRP приводит код, который имеет не хилый такой Coupling, причем разных типов.
Возможно идея была в том, чтобы от раздела к разделу применять к коду описанные принципы. Но тогда стоило бы использовать один и тот же код и пошагово применять к нему их, а не приводить разные примеры.
Про сам каплинг, начал автор за здравие, закончил за упокой.
Только заголовок про каплинг, остальное все нужно удалить, дабы не создавать неправильное понимание у начинающих. Вот более правильный пример (первое что показал гугл) одного вида каплинга. Но есть и другие.
Интерфейсы методов — это не каплинг. Это документация для пользователя класса. Оно там для того чтобы можно было быстро понять как класс использовать. Когда автор заменил конструктор с явным обьявлением параметров на объект — он ухудшил «девелопер экспириенс». Теперь IDE не подскажет какие параметры ждет класс. А каплинг остался на месте. Если вдруг этому классу потребуется новый обязательный параметр в конструкторе — разработчику, все так же, придется лезть во все места где этот класс используется и добавлять его. Если вдруг какой-то параметр заменится, или поменяется его смысл — разработчику придется лезть и менять код во всех местах. Если параметр уберется — то код конечно будет работать, но разработчик открывший этот код, будет в замешательстве — «Что этот параметр значит? А не баг ли это?». Еще больше он обрадуется, когда в коде будет 2-3 разных вызова этого конструктора с разным набором параметров.
Чтобы решить эту проблему умные люди давным давно придумали паттерн Фабрика. Но просто заменить new Class на new ClassFactory — не достаточно. Надо таки разобраться что такое каплинг и принцип инверсии зависимостей. И передавать фабрику туда, где требуется создавать объекты.
Хотя есть правильный случай, когда объединение параметров в объект имеет смысл — это когда параметров больше 5 (зависит от соглашений в команде, основано на особенностях человеческого мозга держать в фокусе 5 +- 2 параметра). И то, тогда они объединяются не просто в объект, а в специальный класс, который проверит, что все параметры переданы и корректны.
Про связанность начиналось хорошо, но под конец просто бессмыслица. Хотелось бы обратить внимание на то, что повторяющийся код — это не всегда плохо. Есть разница между DRY и SRP.
В общем Cohesion и Coupling это очень важные метрики кода. И отличный показатель качества кода. Но материал в этой статье не дает хорошего понимания что это и как этим пользоваться. SOLID наше все.
Сначала мы не знаем ничего (Неосознанная Некомпетентность).
Читаем туториал. С абсолютной уверенностью, что мы делаем лучшую реализацию в мире, запиливаем это в проект.
Глаза горят, добавляем соседу в проект. Выделяем в пакет.
Потом, набив шишки в 2-3 проектах, идем искать ответы на новые вопросы.
Оказывается что проблем то не мало.
И тут мы понимаем что чего-то не знаем (Осознанная Некомпетентность).
Начинаем усиленно читать, смотреть конференции. Всеми путями получаем как можно больше знаний.
И когда познаем дзен — переходим в состояние Осознанной Компетенции.
Умеем использовать Репозитории, пилить CQRS и EventSourcing.
Видим правильные проблемы. И умеем их правильно решать.
Это естественный процесс. И очень длительный, если конечно у вас под рукой нет компетентного наставника.
Я не один проект написал с жирными репозиториями, пока научился этому.
Главное задавать как можно больше вопросов и искать ответы. Критически мыслить.
А зависимость от своего интерфейса лучше тем, что:
это наш интерфейс, и только мы можем его менять. Никакой сторонний пакет вдруг не скажет что метод депрекейтед или изменит порядок аргументов. Даже если что-то и поменяется — внутри нашего приложения ничего не изменится, т.к. мы только изменим имплементацию этого интерфейса а одном месте.
в интерфейсе будут только те методы, которые нам действительно нужны. Тогда когда мы заходим переехать с MySQL на NoSql — мы будем знать точно обьем работ.
это просто тестировать
NIH синдром — это если бы мы пилили действительно всю ОРМ с дата мепперами и юнит оф ворк. А с Репозиторием чаще всего получается как я описал в комменте выше. Т.е. затраты на поддержку === 0. Ведь мы по факту используем то что предоставляет фреймворк, просто внутрь нашего приложения не просочится инородный интерфейс.
Весь паттерн Репозиторий — это про интерфейс, а не про реализацию.
Верный вопрос и предложение. CQRS как раз об этом.
Только не надо добавлять методы с использующие SQL в репозиторий. Это совершенно другая зона ответственности. И назначение другое.
В целом тут на лицо не правильный подход к использованию Репозитория как паттерна. Отсюда и не верное и переусложненное решение.
Да немного сумбурно получилось. Но я не призываю ничего переизобретать.
Речь про то что надо думать о зависимостях в проекте.
Я тут капитана очевидность включу не на долго:
Обычно создается класс наследующий репозиторий из ОРМ и имплементирующий наш интерфейс.
Но интерфейс определяется в самом приложении. Нельзя использовать интерфейс из ОРМ. Т.к. это будет нарушение принципа инверсии зависимостей.
Формулировка:
Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций.
Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Первый пункт как раз об этом.
кэп офф.
И это конфликтует с Вашим выводом:
Уважаемые коллеги, не пытайтесь абстрагироваться от выбранного Вами фреймворка! Как правило, фреймворк уже предоставляет достаточный уровень абстракции. А иначе зачем он нужен?
Я это к тому что — не стоит выдавать такие утверждения. В интернетах полно неопытных ребят. И вы можете наблюдать их в комментариях к статье тоже. И если они без понимания проблемы рванут прикручивать ваше решение — это до добра не доведет.
Автор не потрудился почитать описание паттерна Репозиторий, какие проблемы он решает, а так же не понял где у него проблема в принципе(в разных источниках). Хотя с QueryObject еще не все так плохо и они вполне жизнеспособны, но в другом месте.
Начну с хорошего:
В папочке с QueryObject в принципе легче ориентороваться.
Их проще писать, проще внедрять в сервисы.
Проще вводить новые версии.
Проще моки писать в тестах — не надо все зависимости репозотория переопределять.
Еще отлично встроятся в read часть вашего приложения, если вы запилили CQRS.
На этом все.
Теперь о плохом. Репозиторий.
В первую очередь Репозиторий — это интерфейс коллекции доменных объектов. Он абстрагирует нашу систему хранения данных. А ORM — Это вообще не про это. ORM про маппинг сток из базе на объекты.
Эти 2 паттерна решают разные проблемы и используются по разному.
Использование класса из ORM вместо интерфейса репозитория — это циклическая зависимость в вашем коде. Если вы захотите заменить систему хранения данных — вы попали. Хотя в некоторых случаях такое упрощение в полне себе решение. Никому эти репозитории в блоге или сайте визитке не нужны.
Пример из реального проекта.
Одним из решений для задачи — было запилить EventSourcing. В качестве первого решения, было решено использовать MySQL как хранилище данных. Так было проще начать.
Со временем оказалось что:
все события просто напросто физически не влезут в него, хард не резиновый.
использовать MySQL финансово не выгодно.
По этому было решено переехать на DynamoDB. Если бы я использовал использовал репозитории ORM — мне бы пришлось выпилить его полностью. А так — я просто запилил новый класс, имплементировал пару методов и готово — в продакшин.
Это то что касается Репозиториев.
Теперь про количество методов в Репозиториях.
Репозиторий используется совместно с ОРМ. Сейчас мы обратим внимание на то что он используется именно для Маппинга Доменных Объектов. И возвращает коллекцию доменных объектов.
Большинство методов, от которых растет Репозиторий и на которые грешит автор — это методы для чтения данных.
Так вот. Если вы подумали хорошо, когда проектировали ваше приложение — то наверное запилили бы CQRS. Тогда в вашем слое C были бы UseCase, которые использовали бы Репозитории с ОРМ.
А в слое Q были бы ваши QueryObject или что по проще, без ОРМ. Он там нафиг не впился.
Другими словами — Репозитории с ОРМ вам нужны там, где бизнесс логика. Там где просто вывод данных — вам и ОРМ не впилась, используйте SQL.
Вы можете посмотреть видео Marco Pivetta "Doctrine Best Practices". Не надо плеваться что это Доктрина, принципы в ОРМ одни и те же.
А нафиг оно вообще все надо? Зачем усложнять?
Все эти дела с перозиториями, орм, интерфейсам, и т.д. и т.п. порой появляются на ровном месте.
Ваше решение должно быть обосновано, внимание, ТРЕБОВАНИЯМИ К ПРОЕКТУ, а не личными хотелками.
Если вы пишите блог — не надо там квери обьекты городить или отдельные репозитории вводить. Берите репозиторий ОРМ и в продакшин. А если у вас что-то больше — обязательно проверьте не будет ли меняться система хранения данных в конкретной части приложения. Ведь мы можем писать в мускуль, а клиенту отдавать из редиса. И то и то можно спрятать в репозитории. И когда прийдет время заменить имплементацию на что-то еще — вы не будете плакать.
Для лучшего понимания рекомендовал бы посмотреть видео Евгения Кривошеева "Осознанность проектирования" и "Как не угробить архитектуру сразу же". Можно найти тут же на хабре. Там еще интересное.
Перевести из «не осознанной некомпетентности» в «осознанную»
sergeykorol.ru/blog/competence
Вот только у школ и вузов другая задача стоит.
Школы учат азам, там нет задачи из каждого сделать программиста.
А в вузах все всегда на одноразовых задачках. Преподаватели обычно горе-теоретики, так что скорее всего и код не читают. Главное чтоб работало. А это не способствует развитию хорошего стиля кода/архитектуры. Теоретически это можно автоматизировать сбором метрик, но кто там заморачиваться будет?
Та же ситуация в веб студиях — там проект делается левой ногой на выброс, никто там долго поддерживать его не собирается.
По этому там недостаточно боли от плохого кода. Тесты не пишутся. Призрак архитектуры унаследованный от фреймворка.
Только в компании разрабатывающей свой продукт или там где ценится качество(принципиально), люди могут дойти до осознания что надо что-то менять.
К сожалению, если это дойдет до одного, но он не сможет объяснить другим — все пропало.
Под разжевывать — я предлагаю рассказать про все эти принципы на примере рефакторинга какого-либо типового проекта. Но чтоб там изначально была боль, которую народ не понимает. Рассказать как это влияет на эволюцию проекта, с примерами, как это лечится. Пошагово, вводя принципы и практики по одной. Чтоб новички увидели что-то знакомое, поняли что не так с этим и научились как делать хорошо.
Желательно при этом сделать это на примере JS UI приложения. Ибо имхо это самый большой пласт начинающих разрабов.
Так что сомневаюсь что они вот так сразу, не дочитав статью, а скорее всего они ее не дочитали, рванули читать что-то :)
Идея статьи правильная, но, как обычно, в
интернете кто-то не правесть замечания.В основном претензии к примерам. Так автор в статье говорит о SRP и Coupling, а потом в примере к SRP приводит код, который имеет не хилый такой Coupling, причем разных типов.
Возможно идея была в том, чтобы от раздела к разделу применять к коду описанные принципы. Но тогда стоило бы использовать один и тот же код и пошагово применять к нему их, а не приводить разные примеры.
Про сам каплинг, начал автор за здравие, закончил за упокой.
Только заголовок про каплинг, остальное все нужно удалить, дабы не создавать неправильное понимание у начинающих. Вот более правильный пример (первое что показал гугл) одного вида каплинга. Но есть и другие.
Интерфейсы методов — это не каплинг. Это документация для пользователя класса. Оно там для того чтобы можно было быстро понять как класс использовать. Когда автор заменил конструктор с явным обьявлением параметров на объект — он ухудшил «девелопер экспириенс». Теперь IDE не подскажет какие параметры ждет класс. А каплинг остался на месте. Если вдруг этому классу потребуется новый обязательный параметр в конструкторе — разработчику, все так же, придется лезть во все места где этот класс используется и добавлять его. Если вдруг какой-то параметр заменится, или поменяется его смысл — разработчику придется лезть и менять код во всех местах. Если параметр уберется — то код конечно будет работать, но разработчик открывший этот код, будет в замешательстве — «Что этот параметр значит? А не баг ли это?». Еще больше он обрадуется, когда в коде будет 2-3 разных вызова этого конструктора с разным набором параметров.
Чтобы решить эту проблему умные люди давным давно придумали паттерн Фабрика. Но просто заменить new Class на new ClassFactory — не достаточно. Надо таки разобраться что такое каплинг и принцип инверсии зависимостей. И передавать фабрику туда, где требуется создавать объекты.
Хотя есть правильный случай, когда объединение параметров в объект имеет смысл — это когда параметров больше 5 (зависит от соглашений в команде, основано на особенностях человеческого мозга держать в фокусе 5 +- 2 параметра). И то, тогда они объединяются не просто в объект, а в специальный класс, который проверит, что все параметры переданы и корректны.
Про связанность начиналось хорошо, но под конец просто бессмыслица. Хотелось бы обратить внимание на то, что повторяющийся код — это не всегда плохо. Есть разница между DRY и SRP.
В общем Cohesion и Coupling это очень важные метрики кода. И отличный показатель качества кода. Но материал в этой статье не дает хорошего понимания что это и как этим пользоваться. SOLID наше все.
Ну так и качается скил :)
Сначала мы не знаем ничего (Неосознанная Некомпетентность).
Читаем туториал. С абсолютной уверенностью, что мы делаем лучшую реализацию в мире, запиливаем это в проект.
Глаза горят, добавляем соседу в проект. Выделяем в пакет.
Потом, набив шишки в 2-3 проектах, идем искать ответы на новые вопросы.
Оказывается что проблем то не мало.
И тут мы понимаем что чего-то не знаем (Осознанная Некомпетентность).
Начинаем усиленно читать, смотреть конференции. Всеми путями получаем как можно больше знаний.
И когда познаем дзен — переходим в состояние Осознанной Компетенции.
Умеем использовать Репозитории, пилить CQRS и EventSourcing.
Видим правильные проблемы. И умеем их правильно решать.
Это естественный процесс. И очень длительный, если конечно у вас под рукой нет компетентного наставника.
Я не один проект написал с жирными репозиториями, пока научился этому.
Главное задавать как можно больше вопросов и искать ответы. Критически мыслить.
А зависимость от своего интерфейса лучше тем, что:
NIH синдром — это если бы мы пилили действительно всю ОРМ с дата мепперами и юнит оф ворк. А с Репозиторием чаще всего получается как я описал в комменте выше. Т.е. затраты на поддержку === 0. Ведь мы по факту используем то что предоставляет фреймворк, просто внутрь нашего приложения не просочится инородный интерфейс.
Весь паттерн Репозиторий — это про интерфейс, а не про реализацию.
Только не надо добавлять методы с использующие SQL в репозиторий. Это совершенно другая зона ответственности. И назначение другое.
В целом тут на лицо не правильный подход к использованию Репозитория как паттерна. Отсюда и не верное и переусложненное решение.
Да немного сумбурно получилось. Но я не призываю ничего переизобретать.
Речь про то что надо думать о зависимостях в проекте.
Я тут капитана очевидность включу не на долго:
Обычно создается класс наследующий репозиторий из ОРМ и имплементирующий наш интерфейс.
Но интерфейс определяется в самом приложении. Нельзя использовать интерфейс из ОРМ. Т.к. это будет нарушение принципа инверсии зависимостей.
Первый пункт как раз об этом.
кэп офф.
И это конфликтует с Вашим выводом:
Я это к тому что — не стоит выдавать такие утверждения. В интернетах полно неопытных ребят. И вы можете наблюдать их в комментариях к статье тоже. И если они без понимания проблемы рванут прикручивать ваше решение — это до добра не доведет.
Самое печельное, что они искренне уверены, что они знают как надо использовать фреймворк.
http://sergeykorol.ru/blog/competence/
Автор не потрудился почитать описание паттерна Репозиторий, какие проблемы он решает, а так же не понял где у него проблема в принципе(в разных источниках). Хотя с QueryObject еще не все так плохо и они вполне жизнеспособны, но в другом месте.
Начну с хорошего:
На этом все.
Теперь о плохом. Репозиторий.
В первую очередь Репозиторий — это интерфейс коллекции доменных объектов. Он абстрагирует нашу систему хранения данных. А ORM — Это вообще не про это. ORM про маппинг сток из базе на объекты.
Эти 2 паттерна решают разные проблемы и используются по разному.
Даже Фарулер говорит:
Data Mapping Layer — это как раз таки Ваша ORM.
Использование класса из ORM вместо интерфейса репозитория — это циклическая зависимость в вашем коде. Если вы захотите заменить систему хранения данных — вы попали. Хотя в некоторых случаях такое упрощение в полне себе решение. Никому эти репозитории в блоге или сайте визитке не нужны.
Пример из реального проекта.
Одним из решений для задачи — было запилить EventSourcing. В качестве первого решения, было решено использовать MySQL как хранилище данных. Так было проще начать.
Со временем оказалось что:
По этому было решено переехать на DynamoDB. Если бы я использовал использовал репозитории ORM — мне бы пришлось выпилить его полностью. А так — я просто запилил новый класс, имплементировал пару методов и готово — в продакшин.
Это то что касается Репозиториев.
Теперь про количество методов в Репозиториях.
Репозиторий используется совместно с ОРМ. Сейчас мы обратим внимание на то что он используется именно для Маппинга Доменных Объектов. И возвращает коллекцию доменных объектов.
Большинство методов, от которых растет Репозиторий и на которые грешит автор — это методы для чтения данных.
Так вот. Если вы подумали хорошо, когда проектировали ваше приложение — то наверное запилили бы CQRS. Тогда в вашем слое C были бы UseCase, которые использовали бы Репозитории с ОРМ.
А в слое Q были бы ваши QueryObject или что по проще, без ОРМ. Он там нафиг не впился.
Другими словами — Репозитории с ОРМ вам нужны там, где бизнесс логика. Там где просто вывод данных — вам и ОРМ не впилась, используйте SQL.
Вы можете посмотреть видео Marco Pivetta "Doctrine Best Practices". Не надо плеваться что это Доктрина, принципы в ОРМ одни и те же.
А нафиг оно вообще все надо? Зачем усложнять?
Все эти дела с перозиториями, орм, интерфейсам, и т.д. и т.п. порой появляются на ровном месте.
Ваше решение должно быть обосновано, внимание, ТРЕБОВАНИЯМИ К ПРОЕКТУ, а не личными хотелками.
Если вы пишите блог — не надо там квери обьекты городить или отдельные репозитории вводить. Берите репозиторий ОРМ и в продакшин. А если у вас что-то больше — обязательно проверьте не будет ли меняться система хранения данных в конкретной части приложения. Ведь мы можем писать в мускуль, а клиенту отдавать из редиса. И то и то можно спрятать в репозитории. И когда прийдет время заменить имплементацию на что-то еще — вы не будете плакать.
Для лучшего понимания рекомендовал бы посмотреть видео Евгения Кривошеева "Осознанность проектирования" и "Как не угробить архитектуру сразу же". Можно найти тут же на хабре. Там еще интересное.