Когда лучше применять статические свойства, методы, классы? А когда их использовать не стоит?

AmdY

Пью пиво
Команда форума
Впрочем, в сервисах named constructor-ы нафиг не нужны.
Так в том и дело, что в посте http://phpclub.ru/talk/threads/Когда-лучше-применять-статические-свойства-методы-классы-А-когда-их-использовать-не-стоит.82884/#post-752004 была ссылка именно на сервисный класс Time, который помимо стати методов ещё и финализирован. При этом автор пишет, теперь у нас отличный путь для инстанцирования, просто юзай статик вызов, но если ты DDD-шник, то просто поменяй название методов и твой код станет клёвым. Плевать что в реальном проекте будут локализации для времени и будет меняться разделитель, это уже твоя проблема как обернуть мой клевый объект, гавно обёрнутое в бумажку пахнет малиной.
 

Вурдалак

Продвинутый новичок
Так в том и дело, что в посте http://phpclub.ru/talk/threads/Когда-лучше-применять-статические-свойства-методы-классы-А-когда-их-использовать-не-стоит.82884/#post-752004 была ссылка именно на сервисный класс Time, который помимо стати методов ещё и финализирован.
Какой же это сервис, это обычный value object, посмотри внимательнее, а потом маши руками. Ты разве не в состоянии понять, что там static method используется чисто для выразительности? Он абсолютно никак технически не отличается от обычного new Time(). Или ты не понимаешь что такое «сервис»?
Плевать что в реальном проекте будут локализации для времени и будет меняться разделитель
Модель, которая нужна в расчётах, совершенно не обязана отвечать требованиям модели, предназначенной для вывода.

Я теперь практически убеждён, что ты не троллишь, а ты просто деревянный. Годы тупого «херак-херак, пойду менять проект» дают о себе знать.
 

AmdY

Пью пиво
Команда форума
Какой же это сервис, это обычный value object, посмотри внимательнее, а потом маши руками. Ты разве не в состоянии понять, что там static method используется чисто для выразительности? Он абсолютно никак технически не отличается от обычного new Time(). Или ты не понимаешь что такое «сервис»?
В том то и дело, что эти статические методы превращают VO в сервис, они парсят и рассчитывают данные и лишь потом создают VO. Фактически эту логику вообще нужно выносить за пределы класса.

Модель, которая нужна в расчётах, совершенно не обязана отвечать требованиям модели, предназначенной для вывода.
Так строка со временем принимает на ВХОД и парсится внутри по определённым параметрам, которые жёстко описаны ВНУТРИ. Какой вывод?

Я теперь практически убеждён, что ты не троллишь, а ты просто деревянный. Годы тупого «херак-херак, пойду менять проект» дают о себе знать.
Скорее наоборот, я гибкий, т.к. пробую разные подходы и концепции, меня взгляды исходя из проекта и инструментария. Но я уверен, что статические методы вкупе с финализацией это ацкий гавнокод, который на порядок усложняет поддержку проекта. Я привёл примеры изменений на проекте к которым не готов этот кусок кода, без переписывания или декорирования. Хотя если цель стать незаменимым на проекте, то такой подход рулит.
 

Вурдалак

Продвинутый новичок
В том то и дело, что эти статические методы превращают VO в сервис, они парсят и рассчитывают данные и лишь потом создают VO. Фактически эту логику вообще нужно выносить за пределы класса.
Она не превращает в сервис, эта логика статична. По твоему мнению, я так полагаю, любая логика превращает объект в сервис? Зачем её нужно выносить, если она гармонично смотрится с самим объектом? Так сказать highly cohesive.

Так строка со временем принимает на ВХОД и парсится внутри по определённым параметрам, которые жёстко описаны ВНУТРИ. Какой вывод?
Не имеет значения, вход или выход, это детали представления. У нас есть какой-то внутренний DSL, в котором мы имеем право выбрать удобный формат для описания бизнес-логики. Если же требуется, чтобы при взаимодействии с клиентом (данные нам от него или от нас ему — не суть) мы использовали другой формат — без проблем, сконвертируй, отформатируй как тебе нужно. По той же самой причине мы не экранируем HTML перед записью в БД: HTML-экранирование — это деталь конкретного формата, пусть там и остаётся, нам на это пофиг.

Классический пример VO — это DateTime. Но без учёта системных часов, нужно представить, что мы не используем «now». Там много логики и она достаточно сложная, но она статична и григорианский календарь он и в Африке григорианский. DateTime можно создавать разными способами: через timestamp, через явное указание даты или даты/времени и т.д.
В Java 8, например, учли ошибки прошлого и сделали очень приятный immutable API для работы с датой/временем: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
Domain-driven design. The new API models its domain very precisely with classes that represent different use cases for Date and Time closely.
Там куча различных способов получения объекта:
LocalDate.of(2012, Month.DECEMBER, 12); // from values
LocalDate.ofEpochDay(150); // middle of 1970
LocalTime.of(17, 18); // the train I took home today
LocalTime.parse("10:15:30"); // From a String
— это и есть статические конструкторы, о которых мы говорим.

Но я уверен, что статические методы вкупе с финализацией это ацкий гавнокод, который на порядок усложняет поддержку проекта.
Какой-то религией попахивает, давай факты. А чем плох final в данном случае?

Я привёл примеры изменений на проекте к которым не готов этот кусок кода, без переписывания или декорирования.
По-моему, я от тебя не видел ещё ни одного примера. Когда это ты успел их привести? Я тебя спрашивал, но ты тупо игнорил мои вопросы, потому что тебе не нужно разбираться в проблеме, у тебя уже есть религия, тебе больше ничего не нужно.
 
Последнее редактирование:

AmdY

Пью пиво
Команда форума
Так если есть DSL и это трансформируется выше, зачем тогда ещё раз разбирать этот DSL в Time::fromString или Time::fromTime? А если класс использовать вне DSL, то надо лазить в код, чтобы смотреть этот формат?
По-моему, я от тебя не видел ещё ни одного примера. Когда это ты успел их привести?
Ты сам привёл ссылку в посте к которому был мой комментарий http://verraes.net/2014/06/named-constructors-in-php/

Классический пример VO — это DateTime. Но без учёта системных часов, нужно представить, что мы не используем «now».
Так системные часы это очень важный нюанс, в не знаю как в Java, но в php ещё и таймзоны берутся из php. А они периодически меняются и DateTime начинает работать не корректно, потому ни в коем случае не стоит использовать статик вызовы напрямую. Это реальный мир, а не теория.
 

Вурдалак

Продвинутый новичок
Ты сам привёл ссылку в посте к которому был мой комментарий http://verraes.net/2014/06/named-constructors-in-php/
Я эту фразу понимаю так, что ты оставлял комментарий в Disqus по ссылке. Но там единственное русскоязычное имя — Leonid Mamchenkov, комментарий оставлен 3 года назад. Или я пропустил его там где-то? Или ты имел в виду что-то другое? В рамках этой темы я от тебя примеров не видел, ты лишь голословно заявлял, что будут проблемы, что «финализирование» — это грех и всё в таком духе. И ни одной строчки кода.

Так системные часы это очень важный нюанс, в не знаю как в Java, но в php ещё и таймзоны берутся из php. А они периодически меняются и DateTime начинает работать не корректно, потому ни в коем случае не стоит использовать статик вызовы напрямую. Это реальный мир, а не теория.
Ты говоришь, что если в DateTime есть, грубо говоря, метод-синглтон, то статические методы использовать нельзя. Если сосед-Вася — алкоголик, то с Васями дружить нельзя — они алкоголики. Где логика? Нет, это лишь обозначает, что не нужно использовать конкретно этот метод-синглтон. Получение текущего системного времени тут — это исторически сложившийся хак. Там, где ты не хочешь зависимости от системного времени — не используй DateTime::now().

DateTime::now() — это всего лишь неявный SystemClock::getInstance()->getNow(): DateTime. А это, внимание, неявная статическая переменная DateTime::$systemClock. Возвращаемся к тому, с чего начали: проблема в static-переменных, а не в static method'ах как таковых.
 

Вурдалак

Продвинутый новичок
Если говорить другими словами, то у нас несколько конструкторов, каждому из которых мы дали какое-то имя. Ты выступаешь против этого, потому что как-то раз ты купил кроссовки, а тебе были не по размеру и с тех пор ты ходишь только в туфлях, потому что от кроссовок у тебя остался осадочек. Если капнуть глубже, то выходит, что ты против нескольких конструкторов в принципе. Так что говори прямым текстом: тебе не нравится перегрузка конструкторов. Причем тут static-то?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Ну - за пятницу!

Иногда просто лениво заниматься подобной декомпозицией, от неё должен быть какой-то толк. А если разницы нет, то я не хочу платить больше.
Нарушить SRP всегда проще. @TODO не забудь в коде оставить для будущих поколений.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
DateTime::now() — это всего лишь неявный SystemClock::getInstance()->getNow(): DateTime. А это, внимание, неявная статическая переменная DateTime::$systemClock. Возвращаемся к тому, с чего начали: проблема в static-переменных, а не в static method'ах как таковых.
В DateTime не может быть переменной $systemClock потому что значение приходит от системного вызова. DateTime - это именно сервис, драйвер.
Статическая переменная - локаль, она на уровне операционной системы, и для PHP это внешний сервис.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Такой же драйвер, как PDOStatement - получает внешние данные, и предоставляет API для работы с ними в php.
Но мы не пишем PDOStatement::fetch('current_statement');
Очевидно, что вместо массива можно внезапно получить объект.
 
Последнее редактирование:

Вурдалак

Продвинутый новичок
Такой же драйвер, как PDOStatement - получает внешние данные, и предоставляет API для работы с ними в php.
Но мы не пишем PDOStatement::fetch('current_statement');
Очевидно, что вместо массива можно внезапно получить объект.
Я не вполне понимаю о чём ты, но ты продолжай, мне интересно.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
О том, что если с Васей-алкоголиком проблемы, то и с Петей-алкоголиком можно ждать того же.

Твое утверждение, что в DateTime внутри статическая переменная - неверно. Состояние у внешнего сервиса, приложение не должно полагаться на его неизменность.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
@AmdY писал про локаль - это неявная переменная. Сервис "системные часы" - это сервис, а не переменная, это источник данных.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
@grigori, я потому и обобщил про наличие состояния
Не только у класса, а у любого компонента, включая источник и инфраструктуру ( os, файловая система) - все, чье состояние влияет на данные. У класса состояния может и не быть.

Это приводит нас к любым внешним и внутренним данным, кроме данных в непубличных полях.
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Ну да, сайд-эффекты сюда же, какая разница-то. Вот в статических методах такого и стоит избегать.
 

AmdY

Пью пиво
Команда форума
Если говорить другими словами, то у нас несколько конструкторов, каждому из которых мы дали какое-то имя. Ты выступаешь против этого, потому что как-то раз ты купил кроссовки, а тебе были не по размеру и с тех пор ты ходишь только в туфлях, потому что от кроссовок у тебя остался осадочек. Если капнуть глубже, то выходит, что ты против нескольких конструкторов в принципе. Так что говори прямым текстом: тебе не нравится перегрузка конструкторов. Причем тут static-то?
Вот ты каждый раз впадаешь в гадания о том, что я думаю, хотя конкретно написал в первом же посте - я против статик конструкторов, так как они хардкодят зависимости в проектах. вместо foo(Contact\User $user) будут использовать User::register(); При этом всё держится на архитектурной самоуверенности, что это настолько простой объект, что его никогда не придётся менять. Хотя в том же DateTime как минимум 2 зависимости от системы - системное время и таблицы с таймзонами. Да иногда даже чёртов integer приходится заменять, так как числа слишком большие. Не понимаю зачем делать статичный фабричный метод, когда его можно вынести отдельно и дать нормально расширять. Тогда никаких проблем с поддержкой не будет, а так понятно откуда берутся такие опасения о данном скучном этапе.
 
Сверху