В идеале хочу указывать, что надо залоггировать, в аннотации к методу :) Чтобы в коде не было ни одной строки, без которой он не мог бы обойтись, чтобы сделать свою главную (и единственную задачу).
Ну а в неидеальном мире мне хватает инъекции через конструктор интерфейса с методами info, warning и error. В продакшене этот интерфейс реализовывается логгером в GrayLog, в CI — записью в файл, а во время юнит-теста в IDE — заглушкой с выводом в никуда, если все ок, или на экран, если что-то не хочет заводится и мне нужен этот лог. Конкретная реализация выбирается бутстрапом приложения на основе переменной окружения, при этом бизнес-код не меняется, не ломается и вообще ничего не знает о логгере, кроме того, что он есть.
Класс — чтобы объявить его реализующим интерфейс, и в потребитель передать именно этот интерфейс. Думаю, не надо перечислять преимущества зависимости от инъектируемого интерфейса перед зависимостью.
А просто надо перед тем, как браться за работу, уточнить, пишем ли мы одноразовый скрипт, или что-то другое. Если что-то другое — то надо сразу делать нормально. Здесь, коли речь вообще зашла о сохраняемом логе, видно, что речь идет о продукте. Тем более, что выше автор говорит "… когда пришлось менять поведение".
И вообще KISS и заложенная гибкость являются противоположностями только для очень, очень простых программ. Вот скажите, нафига мне в коде перевода денег со счета на счет открывать файловый дескриптор, проверять результат, форматировать строку, делать запись, проверять результат, закрывать дескриптор?
А еще такой псевдо-KISS приводит к тому, что в одном блоке у нас оказывается бизнес-логика, работа с ФС, работа с БД, работа с UI. А что, там же все просто, пара строк всего.
Субъективность — это для говнокода. Чистый код тем и хорош, что маскимально объективен, ибо в каждом отдельно взятом модуле делается что-то одно и спорить там не о чем.
Или когда создается отдельный класс для очень узкой, специализированной задачи, которая вызывается ровно один раз ровно в одном месте. Реализуется простой процедурой, класс не нужен вообще, но он создается. Со всеми прелестями конструирования его и деинициализации.
Как раз специализированная задача и должна быть вынесена в отдельный класс. С единственной целью избавить класс-потребитель от знания деталей этой специализации.
Отдельным бонусом идет возможность протестировать специализированный класс отдельно, а его потребитель — отдельно.
Особенно это важно, когда эти два класса работают на разных уровнях абстракции, например один класс чисто логический, а другой — инфраструктурный, или один является жизненно важным, а другой — второстепенным. Как например, упомянутый Вами лог, попадающий под оба критерия.
вызывается ровно один раз ровно в одном месте
Уже много лет дубликация не является единственным, и даже основным, поводом выделения юнита. Гуглите SRP, и заодно IoC.
P.S. Сорри за резкость, но лог джуниор сделал правильно (включая выделение отдельного метода для форматирования), а Вы — нет. Логгирование, реализованное отдельным классом — это стандарт, даже если это просто обертка над записью в файл. Если хотите, могу подробно расписать, почему это так, без упоминания абрревиатур и ссылок на Гугл.
Пишите код так, будто бы его будет читать крайне неуравновешенный и жестокий человек, который знает где вы живёте, знает код от домофона и умеет открывать замки
Если вдуматься, то ничего хорошего в этом совете нет.
Вообще-то, ValueObject — это больше не против одержимости примитивами (которая побеждается соблюдением инкапсуляции — держите близкие данные и методы для их обработки рядом), а для иммутабельности. У Вас все сделано правильно, но стоило подчеркнуть этот момент в статье.
Если 3 бита, то это не 8 уровней заряда, а комбинация из ячеек с двумя уровнями
1) Там именно восемь уровней заряда в одной ячейке — написано ясно и в комменте, и в статье по ссылке.
2) С чего это вдруг «если хранит три бита информации, то сделано из ячеек с двумя уровнями»? Одна шестнадцатиричная цифра на бумаге хранит четыре бита информации, например.
По теме этой восьмиуровневой ячейки — интересно, как удается надежно различать эти уровни. Двоичная арифметика тем и ценна, что есть всего два состояния, которые трудно спутать. К сожалению, в топике об этом ни слова (только график, который не имеет к этому отношения).
Для клиента, который подключается в базе, нет никакой разницы, работает он с единственным инстансом PostgreSQL или с кластером Postgres-XL
, то я бы не так настаивал :)
А разносить таблицы по разным узлам, чтоб потом их потом сджойнить смысла не вижу
Это не совсем корректный тезиз. Вы нормализовывали базу как раз для того, чтобы потом можно было собирать данные любым необходимым образом. Более того, по Вашей логике, вынести на отдельный сервер можно только таблицу, на которую гарантированно никто не ссылается. А это либо странно для реляционной БД, либо это логически самостоятельное хранилище и тогда его спокойно можно подключить из приложения.
Ну а в неидеальном мире мне хватает инъекции через конструктор интерфейса с методами info, warning и error. В продакшене этот интерфейс реализовывается логгером в GrayLog, в CI — записью в файл, а во время юнит-теста в IDE — заглушкой с выводом в никуда, если все ок, или на экран, если что-то не хочет заводится и мне нужен этот лог. Конкретная реализация выбирается бутстрапом приложения на основе переменной окружения, при этом бизнес-код не меняется, не ломается и вообще ничего не знает о логгере, кроме того, что он есть.
Все просто и комфортно :)
А просто надо перед тем, как браться за работу, уточнить, пишем ли мы одноразовый скрипт, или что-то другое. Если что-то другое — то надо сразу делать нормально. Здесь, коли речь вообще зашла о сохраняемом логе, видно, что речь идет о продукте. Тем более, что выше автор говорит "… когда пришлось менять поведение".
И вообще KISS и заложенная гибкость являются противоположностями только для очень, очень простых программ. Вот скажите, нафига мне в коде перевода денег со счета на счет открывать файловый дескриптор, проверять результат, форматировать строку, делать запись, проверять результат, закрывать дескриптор?
А еще такой псевдо-KISS приводит к тому, что в одном блоке у нас оказывается бизнес-логика, работа с ФС, работа с БД, работа с UI. А что, там же все просто, пара строк всего.
Субъективность — это для говнокода. Чистый код тем и хорош, что маскимально объективен, ибо в каждом отдельно взятом модуле делается что-то одно и спорить там не о чем.
Как раз специализированная задача и должна быть вынесена в отдельный класс. С единственной целью избавить класс-потребитель от знания деталей этой специализации.
Отдельным бонусом идет возможность протестировать специализированный класс отдельно, а его потребитель — отдельно.
Особенно это важно, когда эти два класса работают на разных уровнях абстракции, например один класс чисто логический, а другой — инфраструктурный, или один является жизненно важным, а другой — второстепенным. Как например, упомянутый Вами лог, попадающий под оба критерия.
Уже много лет дубликация не является единственным, и даже основным, поводом выделения юнита. Гуглите SRP, и заодно IoC.
P.S. Сорри за резкость, но лог джуниор сделал правильно (включая выделение отдельного метода для форматирования), а Вы — нет. Логгирование, реализованное отдельным классом — это стандарт, даже если это просто обертка над записью в файл. Если хотите, могу подробно расписать, почему это так, без упоминания абрревиатур и ссылок на Гугл.
А вообще «тест Джоэля» о том же, только лучше. Хоть и был создан 15 лет назад.
Правда?
Сугубо личное мнение: их объединяет то, что они считают себя мистерами Вульфами :)
Если вдуматься, то ничего хорошего в этом совете нет.
1) Там именно восемь уровней заряда в одной ячейке — написано ясно и в комменте, и в статье по ссылке.
2) С чего это вдруг «если хранит три бита информации, то сделано из ячеек с двумя уровнями»? Одна шестнадцатиричная цифра на бумаге хранит четыре бита информации, например.
Пользуясь случаем, напомню, что сложная цифровая техника на самом деле и так имеет не два, а три состояния: https://ru.wikipedia.org/wiki/Высокоимпедансное_состояние
По теме этой восьмиуровневой ячейки — интересно, как удается надежно различать эти уровни. Двоичная арифметика тем и ценна, что есть всего два состояния, которые трудно спутать. К сожалению, в топике об этом ни слова (только график, который не имеет к этому отношения).
«В баре было только бутылочное пиво» звучит гораздо приятнее.
Это не совсем корректный тезиз. Вы нормализовывали базу как раз для того, чтобы потом можно было собирать данные любым необходимым образом. Более того, по Вашей логике, вынести на отдельный сервер можно только таблицу, на которую гарантированно никто не ссылается. А это либо странно для реляционной БД, либо это логически самостоятельное хранилище и тогда его спокойно можно подключить из приложения.
Так что вопрос остается открытым.