|
25.07.2020, 18:03 | #1 |
Участник
|
Почему так? new без параметров, инициализация через parm-методы
Некоторые классы следуют шаблону:
new без параметров, инициализация через parm-методы например, класс SysClrType в ax2009, ax2012 авторы таких классов как правило еще и "закрывают" метод new модификатором protected. вопрос: а почему так делают? где почитать об этом шаблоне? =============== 1. знаю о сериализации/десериализации в .net 2. у таких классов как правило нет мтеодов pack/unpack (классы не реализуют интерфейс SysPackable) 3. sysDictClass.makeObject() и classFactory.createClass() игнорируют модификатор protected и вполне создают класс с "закрытым" new 4. что удивительно, у таких классов и конструктор тоже без параметров |
|
25.07.2020, 18:51 | #2 |
северный Будда
|
А что в этом подходе плохого?
__________________
С уважением, Вячеслав |
|
|
За это сообщение автора поблагодарили: Pandasama (1). |
25.07.2020, 22:11 | #3 |
Участник
|
Я думаю это сделано для использования различных порождающих шаблонов проектирования (Порождающие шаблоны проектирования).
Для того чтобы такие объекты было удобнее создавать другим более высокоуровневые объектам, а не программистам. Точнее чтобы программистам было удобнее программировать эти высокоуровневые объекты на создание таких объектов. Ну вы поняли |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
26.07.2020, 08:06 | #4 |
Участник
|
Почему плохого?
А что плохого, например, в ноже? Инструмент и инструмент. У всего есть область применения. Лучше расскажите что хорошего. Цитата:
Сообщение от S.Kuskov
Я думаю это сделано для использования различных порождающих шаблонов проектирования (Порождающие шаблоны проектирования).
Для того чтобы такие объекты было удобнее создавать другим более высокоуровневые объектам, а не программистам. Точнее чтобы программистам было удобнее программировать эти высокоуровневые объекты на создание таких объектов. Ну вы поняли ============= Накину в обсуждение: * стиль с parm-методами "скрывает" обязательные для объекта параметры * стиль с parm-методами вынуждает добавлять валидацию внутреннего состояния объекта в начале каждого метода Поясню что имею в виду. Возьмем класс DictTable. У него в методе new явно указан обязательный для объекта параметр tableId. Во-первых, сразу видно какой параметр обязателен. Во-вторых, в методах класса можно не делать проверку "пропущен ли tableId", достаточно сделать такую проверку в new Последний раз редактировалось mazzy; 26.07.2020 в 08:19. |
|
|
За это сообщение автора поблагодарили: ta_and (4). |
26.07.2020, 08:30 | #5 |
Участник
|
|
|
26.07.2020, 08:34 | #6 |
Участник
|
Цитата:
правда я бы опасался за термин "атомарность" в результате может получиться полусобранный объект, в котором некоторые параметры пропущены. собственно и вопрос - а что с таким полусобранным (не гарантированным) объектом делать? и не превысят ли затраты на валидацию преимущества такой гибкости? может быть, я еще каких-нибудь преимуществ не знаю? |
|
26.07.2020, 08:52 | #7 |
Участник
|
Цитата:
Это вечный вопрос из разряда, что лучше строгая типизация или динамическая. Нет универсального ответа. Для каждой задачи своё решение. |
|
26.07.2020, 07:00 | #8 |
Участник
|
Цитата:
https://docs.microsoft.com/en-us/dyn...lid-principles Цитата:
Liskov substitution – Derived classes must be able to be substituted for their base classes. For example, this substitution can be done by providing factories, by using SysExtension, and by using simple construct methods.
|
|
26.07.2020, 09:42 | #9 |
Участник
|
Кто говорил про автогенерацию кода? Авто-генерация кода это вообще не про это.
Порождающие шаблоны проектирования - это не про генерацию кода, это про генерацию объектов. Если вы разработчик и семейства прикладных объектов и фабрики которая эти объекты инициализирует, то вы на этапе проектирования закладываете в свою схему классов такие правила работы с ними, которые помогут избежать написания кода в стиле кучи if else. Вы спрашиваете почему куча if else - это плохо? |
|
26.07.2020, 10:14 | #10 |
Участник
|
Цитата:
Сообщение от S.Kuskov
Кто говорил про автогенерацию кода? Авто-генерация кода это вообще не про это.
Порождающие шаблоны проектирования - это не про генерацию кода, это про генерацию объектов. Если вы разработчик и семейства прикладных объектов и фабрики которая эти объекты инициализирует, то вы на этапе проектирования закладываете в свою схему классов такие правила работы с ними, которые помогут избежать написания кода в стиле кучи if else. Вы спрашиваете почему куча if else - это плохо? нет, я спросил то, что спросил: Почему так? new без параметров, инициализация через parm-методы |
|
26.07.2020, 11:25 | #11 |
Боец
|
1. Потому что класс может быть широко используемый, с тем или иным набором необходимых параметров. Затолкать все параметры в new() - получится мусорка, супер универсальный конструктор, который непонятно как использовать. Понятнее иметь несколько конструкторов construct*(). Яркий пример суперперегруженного конструктора у классов PrceDisc*. Каждый раз плюешься.
2. New() нельзя использовать в CoC со всеми вытекающими. 3. Чисто синтаксически, когда в коде пишеся ClassName:: - вываливается спсок всемвозможных конструкторов, из которых понятно, что больше подходит. как использовать класс. Если написать myObject = new Object( , то вывалится 10 непонятных параметров. вдобавок, половина которых по-дефолту, а мне еще нужно установить значение десятного, повторив дэфолты тех, что в середине.... По-моему, MS рекомендовал уходить от new() в сторону consеruct() еще лет 10 тому. Что касается методов parm() - это неудачный артефакт X++, породивший миллионы бесполезного parm-кода. К счастью, от него уже избавились в D365 в пользу модификаторов доступа. Последний раз редактировалось DSPIC; 26.07.2020 в 11:35. |
|
|
За это сообщение автора поблагодарили: mazzy (5). |
26.07.2020, 12:36 | #12 |
Участник
|
Цитата:
Цитата:
заталкивать в new конечно стоит только обязательные параметры. Цитата:
в смысле? другими словами, это "достоинство new без параметров" или "недостак CoC"? Цитата:
но взгляни на тот же SysCLRType. в нем constuct оставляет объект в полусобранном состоянии. да, там есть newFromTypeName, который полностью инициализирует. Но зачем такой construct(), который готовит полуфабрикат? если поискать строку 'protected void new(' в акс2009 то будет найдено порядка 1000 вхождений. да, большинство - это старые классы, где есть конструкторы с нормальными параметрами. Но есть и такие как SysCLRType. Цитата:
Да, я понял про PriceDisc. Надо подумать. Цитата:
Ну... мысль понятна. Не буду спорить со словом "избавились" в прошедшем времени |
|
26.07.2020, 12:49 | #13 |
Участник
|
Справедливости ради стоит заметить, что во многих классах, в которых new защищенный так же защищенным (или приватным) является construct. А создание и инициализация выполняется методами-фабриками классов (типа newPurchInvoice и т.п.) которые конструируют и настраивают класс.
Так что какой-то проблемы вроде бы и нет. Хорошо это или плохо наверное и не сказать - ну есть такой подход. Насколько помню, было даже время, когда Best practic ругался на код внутри метода с наименованием construct, если там было что-то помимо new. |
|
26.07.2020, 13:04 | #14 |
Участник
|
Если у вас есть фабрика\фабричный метод то его можно переписать (расширить в D365) и вернуть другой класс, а если вызывается new то прейдеться сначало переписать весь вызывающий код на вызов чего-то другого, что в реалиях расширений проблематично.
|
|
26.07.2020, 15:24 | #15 |
Участник
|
Цитата:
На мой взгляд, есть просто потрясающий пример плюса данного подхода. В DAX есть семейство классов SysExcel*, работает через COM. Уважаемый gl00mie создал семейство, работающее через более надежный NET (ну точнее COM тожеможно сделать боле-менее надежным при помощи Dispatch, но речь не про это). Переключение старого на новое потребовало только изменить фабричный метод. А вот если взять ComOfficeDocument_RU, то реализация на NET в общем-то несложная, но вот переключение на его использование уже напрягает. Последний раз редактировалось Raven Melancholic; 26.07.2020 в 15:30. |
|
28.07.2020, 19:56 | #16 |
Участник
|
Parm-методы это аналоги свойств в дотнете - они отличаются не только модификаторами доступа, но и тем, что внутрь можно запихнуть любую реализацию (сегодня он присваивает какое-то поле, завтра - конвертит и присваивает в другое)
Комитетов хороши тем, что без них не создашь объект. Поэтому в него хорошо передать обязательные параметры создания. Конструкторы плохи тем что: в отличие от C# нет оверлоадов - то есть несколько конструкторов с разными наборами параметров не создашь; Он не может вернуть инстанс другого класса. Оба недостатка можно обойти созданием приватного или протектед конструктора и набора фабричных методов под разные случаи. Набор может состоять из одного метода конструкт, например. Последний раз редактировалось belugin; 28.07.2020 в 20:03. |
|
27.08.2020, 17:55 | #17 |
Участник
|
Цитата:
Сообщение от belugin
Parm-методы это аналоги свойств в дотнете - они отличаются не только модификаторами доступа, но и тем, что внутрь можно запихнуть любую реализацию (сегодня он присваивает какое-то поле, завтра - конвертит и присваивает в другое)
Комитетов хороши тем, что без них не создашь объект. Поэтому в него хорошо передать обязательные параметры создания. Конструкторы плохи тем что: в отличие от C# нет оверлоадов - то есть несколько конструкторов с разными наборами параметров не создашь; Он не может вернуть инстанс другого класса. Оба недостатка можно обойти созданием приватного или протектед конструктора и набора фабричных методов под разные случаи. Набор может состоять из одного метода конструкт, например. Не соглашусь здесь: То, что конструктор не может вернуть инстанс другого класса, это не есть недостаток. Это единственно правильное поведение, не позволяющее выходить за рамки дозволенного, как во всех нормальных языках со строгой типизацией. Как и везде, именно для возврата нужного инстанса из семейства подклассов служат фабричные методы. И это не недостаток, и даже не воркэраунд. В Java, кстати, считается, что если количество параметров в конструкторе больше трех, значит стоит завести класс, объединяющий некоторые поля по смыслу. Таким образом можно даже нормализовать таблицы, а также выделить в классе набор полей в единую сущность.
__________________
// no comments |
|
27.08.2020, 18:15 | #18 |
Banned
|
Цитата:
X++: class ProdTableReservIndicatorEvaluator { public ProdId prodId; public WHSReleaseStatus releaseStatus, oldReleaseStatus; private boolean inactivated; ProdBOMReservIndicatorTolerance indicatorTolerance; public static ProdTableReservIndicatorEvaluator constuctFromProdTable(ProdTable _prodTable) { ProdTableReservIndicatorEvaluator indicatorCalc; indicatorCalc = new ProdTableReservIndicatorEvaluator(); indicatorCalc.oldReleaseStatus = _prodTable.WHSReleaseStatus; indicatorCalc.prodId = _prodTable.ProdId; indicatorCalc.init(); return indicatorCalc; } } |
|
27.08.2020, 18:40 | #19 |
Участник
|
Прошу прощения, еще не имел возможности работать в D365.
__________________
// no comments |
|
27.08.2020, 16:43 | #20 |
Участник
|
отвечаю сам себе:
в c# принято использовать публичные проперти. в языке придуман специальный синтакис для инициализации публичных пропертей https://docs.microsoft.com/ru-ru/dot...ct-initializer в результате, в c# доступны такие конструкции для инициализации Код: StudentName student4 = new StudentName { FirstName = "Craig", LastName = "Playstead", ID = 116 }; причем в конструкторе будут только позиционные параметры. Код: StudentName student4 = new StudentName("private1", new DateTime(2001, 09, 11), 3.0) { FirstName = "Craig", LastName = "Playstead", ID = 116 }; с инициализатором возможны даже такие смешные конструкции Код: var team = new BaseballTeam { ["RF"] = "Mookie Betts", [4] = "Jose Altuve", ["CF"] = "Mike Trout" }; вот, что угодно, лишь бы не делать в C# именованные параметры. https://kotlinlang.ru/docs/reference/functions.html Цитата:
Код: fun reformat(str: String, normalizeCase: Boolean = true, upperCaseFirstLetter: Boolean = true, divideByCamelHumps: Boolean = false, wordSeparator: Char = ' ') { ... } Код: reformat(str, normalizeCase = true, upperCaseFirstLetter = true, divideByCamelHumps = false, wordSeparator = '_' ) Код: reformat(str, wordSeparator = '_') по-любому, в X++ нет ни пропертей, ни синтаксического сахара вокруг них. поэтому конструктор с пустыми параметрами и кучей parm-методов в Аксапте скорее нонсенс. хотя такая конструкция может появится в интеграционном фунционале. parm-методы в Аксаптовском функционале допустимы если в классе есть большое число параметров, как писал DSPIC. если в классе есть обязательные параметры, то они должны присутствовать в конструкторе. если класс написал в концепции иммутабельности, то параметры должны присутствовать в конструкторе. Пример правильной реализации из ax2012 - метод AifWcfProcessor.createAifMessage() Последний раз редактировалось mazzy; 27.08.2020 в 17:36. |
|