Здравствуйте, fddima, Вы писали:
F>Здравствуйте, sharez, Вы писали:
S>>В общем, всё это делается, да, но не кажется ли, что мы излишне усложнили архитектуру просто из-за надуманного ограничения на задание полей класса до вызова суперконструтора? F> Не кажется. F> Вне зависимости от возможности делать виртуальный вызов в конструкторе — контрол (кнопка) будет: F> 1. Иметь состояние attached/detached (to DOM). Особенно в тех фреймворках кто может аттачится на уже существующий элемент и/или достраивать дом с плэйсхолдеров. F> 2. Свойства на подобии title и color — они или бесполезные поля, или же имеют аксессоры и ими можно пользоваться как до так и после аттача с отражением изменений в DOM. Опционально — вычитка значений из DOM. F> 3. События — аналогичны (2) — подписываемся/отписываемся в любое время, но в DOM они должны подписываться/отписываться железобетонно. Иначе ликать будет. (Хотя современные браузеры если ещё нет, то скоро и с этим справятся). F> Я вообще не вижу зачем тут метод fill особенно в конструкторе. F> Конструктор должен создавать объект в консистентном состоянии и только. Таким образом все параметры необходимые для конструкции объекта — необходимо передавать через параметры конструктора (парадокс?). F> Для того что бы не вызывать тонну пропертей после конструкции объекта — можно соорудить ControlParams, ButtonParams или вообще безликий/динамический объект-холдер с настройками при инициализации. Заодно это могло бы упростить создание контрола фабрикой по уже готовому DOM с параметрами (или частью) которые лежат в атрибутах элемента. F> Собственно нечто подобное я "изобретал" для себя, достаточно неплохо имхо организовано в google closure tools (library).
В таком случае все setTitle(), setColor() внутри помимо изменения DOM-дерева должны будут ещё и проверять, создано ли оно — тоже неплохое такое усложнение, особенно, если таких методов много (а их много).
Основная задумка была в том, что удобно создать this.el со всей внутренней структурой без аттача к DOM-дереву непосредственно документа, и добавлять его только при явном вызове, как-то так:
element.appendChild(button.getElement());
При этом нам ничего не помешает уже на этапе вызова конструктора задавать Title, Color в дереве, хранящемся во внутреннем поле this.el. Можно даже делать addEventListener/removeEventListener.
К сожалению, с Google Closure Tools я не знаком, но посмотрю на досуге.
Re[2]: Присвоение свойств и вызов виртуального метода из конструктора
Второй пример вышел слишком сложным (это он пока там кода нет кажется простым, но это оверинжинеринг на мой взгляд).
А вот первый имеет следующий недостаток: базовый класс AButton предполагается, что будет использован именно как базовый, и поставляться в виде SDK.
В нём уже заложен abstract getColor(), который помимо всего прочего може менять цвет (например в зависимости от проверки getParentToolbar() == null). Мы в базовом классе можем сделать constructor(color) только если уже знаем, что именно эта вещь нужна будущей реализации.
Можно вообще сделать в базовом классе передачу Map параметров, я уже об этом писал — это чуть лучше чем передавать лямбды, но тоже плохо: как минимум потому что всесто простого
this.prop = value;
мы вынуждены делать
super(new Map({"prop": "value"}));
Здесь в конструкторе будет использование Reflections (в случае Java, к примеру) со всемы вытекающими (опечатку/ошибку можно будет поймать только в run-time).
Можно ещё ввести конечно третий класс (уже третий!) ButtonParameters, но помимо того, что у нас уже и так три класса, мы добавим ещё около 50 строк (по одной на каждое свойство) в конструктор AButton (нужно же все эти значения присвоить). Соответственно введение нового изменяемого свойства потребует изменений в трёх местах, в трёх, Карл! Это вовсе не называется сокрытием реализации.
Re[3]: Присвоение свойств и вызов виртуального метода из констр
Здравствуйте, Carc, Вы писали:
C>Здравствуйте, netch80, Вы писали:
N>>Там, где можно вызвать конструктор в виде явного конструктора, можно вызвать и что-то вроде public static Button make(), которое само вызывает конструктор (возможно, объявленный private, чтобы не показывать незавершённое состояние), вызывает нужные методы и возвращает готовый результат. Такой себе конструктор, не выглядящий синтаксически как конструктор. (В родной библиотеке Java есть множество методов с неинтуитивным названием valueOf(), которые делают что-то похожее.) После этого специфика потрохов будет скрыта только внутри данного класса и его потомков, которые должны будут отразить специфику такого формирования у себя, но не у пользователей. C>А по моему это называется Фабрика? Не?
Видимо, таки не:
In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created.
В том, что я описал, точно известно, объект какого класса будет создан.
Можно попробовать поспорить, но обычно бесполезно. Лучше попытаться подобрать похожее имя, но другое.
The God is real, unless declared integer.
Re[3]: Присвоение свойств и вызов виртуального метода из конструктора
Здравствуйте, sharez, Вы писали:
S>Второй пример вышел слишком сложным (это он пока там кода нет кажется простым, но это оверинжинеринг на мой взгляд). S>А вот первый имеет следующий недостаток: базовый класс AButton предполагается, что будет использован именно как базовый, и поставляться в виде SDK.
Тут противоречие. Судя по твоему описанию для конструирования AButton нужно знать цвет. Значит конструктор зависит от цвета, а значит его туда надо передать. А ты пытаешься огранизовать вычисление цвета в классах-потомках.
S>В нём уже заложен abstract getColor(), который помимо всего прочего може менять цвет (например в зависимости от проверки getParentToolbar() == null). Мы в базовом классе можем сделать constructor(color) только если уже знаем, что именно эта вещь нужна будущей реализации. S>Можно вообще сделать в базовом классе передачу Map параметров, я уже об этом писал — это чуть лучше чем передавать лямбды, но тоже плохо: как минимум потому что всесто простого
Тебе нужно разорвать циклическую зависимость базового класса от класса потомка. Можно например убрать зависимость от цвета в базовом классе. А работу с цветом писать только в потомке:
class AButton {El getEl() {...}}
class ButtonWithColor : AButton
{
public ButtonWithColor(color)
{setColor(color);}
public setColor(color)
{ getEl().addColorInfo(color);}
}
Циклическая зависимость ещё разрывается введением третьего класса, который инкапсулирует свойства, используемые обоими.
S>Здесь в конструкторе будет использование Reflections (в случае Java, к примеру) со всемы вытекающими (опечатку/ошибку можно будет поймать только в run-time).
Мапа очевидным образом заменяется на pojo-класс с геттерами/сеттерами, например.
S>Можно ещё ввести конечно третий класс (уже третий!) ButtonParameters, но помимо того, что у нас уже и так три класса, мы добавим ещё около 50 строк (по одной на каждое свойство) в конструктор AButton (нужно же все эти значения присвоить). Соответственно введение нового изменяемого свойства потребует изменений в трёх местах, в трёх, Карл! Это вовсе не называется сокрытием реализации.
Давай так. Начни с юнит-тестов. Накидай примерный код того, как ты хочешь использовать свои классы.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Присвоение свойств и вызов виртуального метода из кон
Здравствуйте, sharez, Вы писали:
S>В таком случае все setTitle(), setColor() внутри помимо изменения DOM-дерева должны будут ещё и проверять, создано ли оно — тоже неплохое такое усложнение, особенно, если таких методов много (а их много).
Сложность не такая уж и большая, и это скорее вопрос требований. Если хотим иметь такого рода свойства — в любом случае проверять. Можно конечно и не проверять и всегда менять/читать из DOM, но, имхо, возможность аттача выгоднее. (*)
S>Основная задумка была в том, что удобно создать this.el со всей внутренней структурой без аттача к DOM-дереву непосредственно документа, и добавлять его только при явном вызове, как-то так:
Не-не-не, связывание объекта и DOM элемента это уже и есть тот самый аттач. Только, с разницей что элемент строится безусловно самим контролом.
S>При этом нам ничего не помешает уже на этапе вызова конструктора задавать Title, Color в дереве, хранящемся во внутреннем поле this.el. Можно даже делать addEventListener/removeEventListener.
Помешает: как их задавать если условный createElement ещё не вызван? Возвращаемся к началу (*), и нам всё равно надо контроллировать создан он или нет в аксессорах. Если же речь о задании только значений по умолчанию в наследниках — то объект-шаблон/параметров поможет.
Опять же, установка новых значений по умолчанию в наследниках — имхо плохой вариант сам по себе: это местами может быть неожиданно (равно как и наоборот).
На самом деле куда интереснее, что делать если наследник хочет предоставить своё DOM tree, а базовый setTitle не виртуальный и пишет текст не туда.
А в финале — цепочка Control — Button сложна сама по себе. Я имею ввиду, что Control будет жутко перегружен в любом случае, а допиливаться будут все связанные классы сразу (и те которые не button тоже). Я делал себе Button и LinkButton, но LinkButton устанавливал только дефолтное базовое имя стиля (а точнее префикс). А вот в процессе пиляния такого фреймворка с 10-15 контролами — перетрушивал байду эту не раз, и в итоге пришел к тому, что напрямую я их в омновном все равно не создавал, а создавал на основе шаблона (dom tree), где спец элементы (скажем xcontrol) раскрывались в уже настоящий dom. А код уже обращался к ним по именам. Я к тому — что ну вот не вижу необходимости обсуждаемой возможности хоть убей. Или мы заранее знаем набор/значений свойств и свободно можем их передать в конструктор, или мы используем аксессоры после. Внутри конструктора аксессоры вполне могут быть использованы — ведь пока элемент не приатачен — ломаться нечему (разумеется, если свойства не виртуальные). Кроме того, не стоит и забывать, что DOM — это всегда интероп, поэтому подход: изменения только через контрол а не в DOM напрямую работает немножко лучше. (Ведь поверх этого надо ещё биндинг построить, так ведь?).
В общем, закончу пожалуй тем, что я на уровне веры считаю, что базовый класс не должен вызывать наследника. Но, признаюсь, что изредка в упоротых мною же случаях в шарпе грешу.
А создать удобный фреймворк — сложная задача. Удачи в этом.
Кстати половина новомодных с легкостью делают долбанный туду лист и тут же фейляться где-нибудь в самом неудобном месте.
S>К сожалению, с Google Closure Tools я не знаком, но посмотрю на досуге.
Без фанатизма только, там много кода + длинная история. Примеры могут грузятся долго т.к. нескомпилированный js состоит из большого кол-ва модулей/файлов. Но они (модули) там хотя бы есть... а не профанация как в TS.
Я не со всем там согласен, но вдохновение в свое время почерпнул и не мало. Особенно система модулей и disposable (в дебаге) понравился. Кое что из идей перенес и себе.
Мне кажется это самый взрослый набор тулзов, но нетипизированность JS отталкивает, а его для их компилятора ещё и правильно писать надо. И реально нормальных редакторов нету, подпорки везде одни.