Pull to refresh

Comments 21

Делаем абстрактный обобщённый класс ParameterBase, который заключает в себе вышеописанную логику.

если вы действительно хотели реализовать:

один из самых простых паттернов — шаблонный метод.

(который я бы постеснялся назвать простым честно говоря), вы бы логику реализовали в методе, а не в конструкторе.

Конструктор вроде как должен только объект создать, вы уже тут нарушили:

SRP: совместив логику разных ...

совместив некоторую логику и создание объекта (это вроде как тоже логика, хоть и примитивная) который нужен для реализации этой логики, в конструкторе, или нет?

который я бы постеснялся назвать простым честно говоря

Это всё, конечно, моё имхо, но я с радостью послушаю других претендентов на это звание

вы бы логику реализовали в методе, а не в конструкторе.

А что, конструктор это не метод? :)
Плюс вольную трактовку я действительно мог где-то себе позволить, но тут сошлюсь на вводный параграф той же книжки GoF по паттернам. Там всё-таки сказано, что это не какой-то строгий свод правил :)

Конструктор вроде как должен только объект создать, вы уже тут нарушили SRP

Честно говоря, не совсем понял к чему это - в конструкторе действительно происходит создание и инициализация объекта. Т.е. буквально то, для чего он нужен. Хотя даже если я что-то упустил - нет, не нарушил. SRP говорит о классах, а не о методах

Хотя даже если я что-то упустил - нет, не нарушил.

А если у вас объект фабрикой классов должен создаваться или не дай бог через Dependency Injection, что тогда получится? Фабрика класов должна создать объект и отдать его тому кто его будет использовать по назначению, а у вас получилось что объект все закончил уже внутри фабрики классов, и по назначению его уже нельзя использовать тому кому это нужно, как же так-то? Если для вас шаблонный метод - один из самых простых паттернов, то такая логика тоже не должна вроде казаться сложной? Паттерны проектирования обычно используются в комбинации друг с другом, иначе в них мало смысла.

Много мыслей, а центральную я не уловил. Давайте по отдельности.

А если у вас объект фабрикой классов должен создаваться, что тогда получится?

Не понял. Если будет - тогда и посмотрим. Тут фабрика не рассматривается.

или не дай бог через Dependency Injection

DI никакие объекты не создаёт, оно их передаёт (не могу подобрать лучшую замену inject). Создаются они где-то в другом месте.

Фабрика класов должна создать объект и отдать его тому кто его будет использовать по назначению, а у вас получилось что объект все закончил уже внутри фабрики классов, и по назначению его уже нельзя использовать тому кому это нужно, как же так-то?

Не совсем уловил, что именно тут понимается под "фабрикой классов". Класс сам себя инициализирует, что в простых случаях является нормальной практикой. Использование какой-либо фабрики в приведённых случаях будет оверинжинирингом. К слову, фабрикам не надо заниматься передачей объекта куда бы то ни было, это уже не их задача (если мы говорим про IoC, то этим занимаются отдельные контейнеры). Про "по назначению его уже нельзя использовать тому кому это нужно" совсем не понял.

Шаблоны обычно используются в комбинации друг с другом, иначе в них мало смысла.

Согласен, что очень часто они идут рука об руку. Даже в моём примере с логгером я ненароком использовал стратегию, а в коде с ParameterBase упоминался хранитель. Но вот невозможность их независимого использования тезис очень спорный. Тут я сторонник KISS. Ну и

Если для вас шаблонный метод - один из самых простых паттернов, то такая логика тоже не должна вроде казаться сложной

Отдаю себе отчёт, что в контексте моего недопонимания по многим пунктам звучит забавно, но имеем что имеем :)

Создаются они где-то в другом месте.

вот именно на это я пытался обратить ваше внимание, что мы даже можем не знать в каком другом месте они создаются, поэтому вопрос:

вы уверены что в этом другом месте надо (или даже просто можно) выполнять логику которую вы поместили в конструктор? Вы уверены что это надежное решение?

Поэтому мне кажется это решение засунуть логику в конструктор очень надуманным, мягко говоря.

Я всё ещё немного теряюсь в теме обсуждения, но если мы говорим о ParameterBase и о том, не является ли плохой идеей оставить в конструкторе инициализацию - нет, не кажется. Как архитектору модуля нам должно быть известно, как и где объект должен создаваться (в данном случае объект-клиент создаёт конкретную реализацию абстрактного класса, которая ему нужна). Мы же это пишем для конкретного таска, а не в вакууме.
Если логика станет достаточно сложной/понадобится нужда в разных типах объектов в рамках одних и тех же объектов-клиентов то да, порождающий паттерн станет необходимым. Собственно, это я и предлагаю как один из вариантов решения найденного бага.

я честно говоря не очень понимаю как эта логика связана с описанной вами задачей:

Причём нужно запоминать их версию до и после изменений, чтобы при закрытии страницы уведомлять пользователя о том, что он их не сохранил.

то есть где у вас запоминание до, а где запоминание после, и только потом, вроде как, должно произойти сравнение, а после еще и уведомление. Я что-то не вижу как ваш код в конструкторе мапится на эту задачу. У вас даже возвращаемого значения нет, как же понять где сформированное уведомление?

Если бы вы это разъяснили я бы наверно смог вам предоставить альтернативный вариант, который, возможно, был бы более функциональным и в то же время более простым.

А, мы об этом. Конечно, задачу сравнения конструктор не выполняет и выполнять не может (впрочем, там было начальное создание мементо, но я его не включил во фрагмент из-за небольшой мудрёности), этим занимается класс в целом.
В пример был приведён только конструктор c инициализацией объекта как конкретный случай использования опасной практики, что и является предметом статьи.

А что, конструктор это не метод? :)

https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.8

Можете прочитать спецификацию и попробовать указать нам, в каком именно месте указано, что конструктор является методом. Ну или, например, посмотреть что getDeclaredMethods и getDeclaredConstructors - это два разных метода класса java.lang.Class.

Разговор ведётся в плоскости проектирования, а не типов данных в рефлексии. В этом контексте определение метода это процедура, связанная с объектом, чему конструктор соответствует.

Вы можете любые определения придумывать, но в спецификации языка Java, в плоскости которого ведётся разговор, этого нет.

Ответ на ваш изначальный вопрос - нет, конструктор - это не метод.

Ну а вы можете сколько угодно придумывать контекст разговора, будто обобщённого программирования не существует. К слову, в статье помимо Java есть и C#, давайте посмотрим определение из его документации:

A constructor is a method whose name is the same as the name of its type

Если уж докопались до определения, то по вашей ссылке его вообще нет, она ведёт на спецификацию по рефлексии :)

Если уж докопались до определения, то по вашей ссылке его вообще нет, она ведёт на спецификацию по рефлексии :)

По моей ссылке - спецификация языка. Прямого определения метода там нет, но определения конструктора и метода там не пересекаются и разделены.

В C# же любой блок кода - метод, что весьма расплывчато, как по мне.

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/methods

A method is a code block that contains a series of statements.

Ну, я этим буквоедством занялся шутки ради. Меня вполне устраивает определение, вычитанное мною ещё в университетском курсе по программированию. В целом, оно же продублировано в википедии если такой источник данных, конечно, устроит.

Какой-то спор тут разводить бесцельно, ибо использование термина я пояснил.

Пока вы шутили, многие поняли уровешь вашей логики. Поспешное обобщение это называется, вроде.

Как доказать, что у мужика есть сиськи?

Мужик - это человек, женщина - это человек, у женщины есть сиськи, значит у человека есть сиськи, значит у мужика есть сиськи)

У вас что-то похожее) В жаве конструктор - не метод))) Финишд. Выше обобщаться запрещено, а то легко доказать, что конструктор - это собака-пудель моей бабушки)

Не знаю, что вы пытаетесь доказать. Давайте ещё отделять обобщённые методы. И абстрактные. И любой другой частный случай, который можно придумать. А можно вчитаться в данное мною выше определение и сказать, что все эти частные случаи действительно ему соответствуют.
З.Ы. В вашем примере определения, например, нет :)

А что мешает свести ООП (с шаблонами GoF) к максимально необходимому минимуму и перестать сталкиваться с такими проблемами?

И ведь даже в этом минимуме можно ошибиться, если мы полностью не отказываемся от ООП. Не говоря о том, идея шаблонного метода достаточно интуитивна. Из-за этого такую ошибку можно совершить, даже если не знаешь с чем имеешь дело.

:-D даже если мы полностью откажемся от ООП (в Java это вообще возможно?) мы не избавимся от возможностей совершать ошибки.

в Java это вообще возможно?

Если использовать только статические классы, то мы можем опасно к этому приблизиться :)

мы не избавимся от возможностей совершать ошибки.

Я уже однажды писал в комментариях, программирования без производства багов не бывает :)

Надо было на уровне языка запретить вызов переопределяемых методов в конструкторе, но уже поздно.

Sign up to leave a comment.