Для тех самых настроек (http://18delphi.blogspot.ru/2013/09/uml_5682.html):
// перекрытие базового стереотипа UseCase::Class %f _DoSpell //#UC START# *4E302A8B026Cfor4E30ECBB004D* %S%[inherited]\ <{}{%LS=VCMUseCaseRealization}\ %L<{}{%GS=VCMFormsPack}\ %1%f_SpellToMod(%G,%G%P,%S)\ >\ >\ <{}{%LS=SettingsHolder}\ %S%f_SpellToMod(%L,%L%P,%L)\ >\ %f _SpellToMod %{SELF}%f_set_var(HasNestedSettings,"false")\ [{"%S{CodeName}"!=""&%Cx=true}\ %f_set_var(SELF,S)\ %{SELF}%f_set_var(VALUES_COUNT,"%{SELF}<{}{%CS=UseCaseSettingValue&"%C{CodeName}"!=""}{C}>")\ [{%{SELF}%{VALUES_COUNT}N!=0}\ [{%{SELF}%{VALUES_COUNT}N=2}{\ %{SELF}%f_set_var(IsBool,"false")\ }\ %{SELF}%f_set_var(IsBool,"true")\ ]\ %{SELF}<{}{%CS=UseCaseSettingValue&"%C{CodeName}"!=""}%C<{}{%CS=UseCaseSetting&"%C{CodeName}"!=""}%{SELF}%f_set_var(HasNestedSettings,"true")>>\ [{"%{BOOLEAN}N"=""}%f_find_element(46A603BB0391,BOOLEAN)]\ [{"%{Integer}N"=""}%f_find_element(46A606AC03B2,Integer)]\ [{"%{TddComboBoxConfigItem}N"=""}%f_find_element(TddComboBoxConfigItem,TddComboBoxConfigItem)]\ [{"%{TddAppConfiguration}N"=""}%f_find_element(TddAppConfiguration,TddAppConfiguration)]\ [{"%{TddBaseConfigItem}N"=""}%f_find_element(TddBaseConfigItem,TddBaseConfigItem)]\ [{"%{TddConfigValue}N"=""}%f_find_element(TddConfigValue,TddConfigValue)]\ [{"%{l3FillChar}N"=""}%f_find_element(l3FillChar,l3FillChar)]\ [{"%{Tafw}N"=""}%f_find_element(Tafw,Tafw)]\ %f_set_var(SELF,S)\ %f_set_var(MOD,1)\ %f_set_var(PAR,2)\ %{PAR}%f_add_class(%{SELF}U_%{MOD}U_Res,UtilityPack,%f_N(%{MOD})%{SELF}{CodeName}SettingRes,Pack_Inst)\ [{%{SELF}%{IsBool}N=true}{\ %{Pack_Inst}%f_add_class(%{Pack_Inst}U_Enum,Enum,%{SELF}{CodeName}Enum,Enum_Inst)\ %{Enum_Inst}%f_set_documentation(Ключи для настройки "%{SELF}N")\ %{SELF}<{}{%CS=UseCaseSettingValue&"%C{CodeName}"!=""}\ %{Enum_Inst}%f_add_attribute(%{SELF}U_%{MOD}U_%CU_SettingValue_Key,,\ KEY_%{SELF}{CodeName}_%C{CodeName},\ Attr_Inst)\ %{Attr_Inst}%f_set_documentation(%CN)\ >\ }\ ]\ [{%{MOD}S=SettingsHolder}{\ %f_set_var(METHOD,"FactoryMethod")\ %f_set_var(METHODN,"%f_N(%{MOD})")\ }\ %f_set_var(METHOD,"method")\ %f_set_var(METHODN,"")\ ]\ [{%{SELF}%{HasNestedSettings}N=true}{\ %{MOD}%f_add_class(%{SELF}U_%{MOD}U_FM,%{METHOD}N,%{METHODN}N%{SELF}{CodeName}Setting,FM_Inst)\ %{FM_Inst}%f_set_visibility_type(PublicAccess)\ %{FM_Inst}%f_set_abstraction_type(final)\ %{FM_Inst}%f_set_documentation(Метод для получения значения настройки "%{SELF}N")\ %{FM_Inst}%f_make_accessable(%{SELF}U)\ %{FM_Inst}%f_add_realized(%{SELF}U)\ %{FM_Inst}%f_make_accessable(%{Tafw}U)\ %{FM_Inst}%f_add_dependency(%{FM_Inst}U_%{Tafw}U_uses,%{Tafw}U,uses,,USES_Inst)\ %{FM_Inst}%f_set_up(NO_FACTORY_BRACKECTS,true)\ %{FM_Inst}%f_set_up(is static,true)\ %{FM_Inst}%f_add_operation(%{FM_Inst}U_DoIt,,DoIt (): \ [{%{SELF}%{IsBool}N=true}{\ %{Integer}U}\ %{BOOLEAN}U\ ]\ ,Op_Instance)\ %{Op_Instance}%f_set_documentation(%{FM_Inst}D)\ %{FM_Inst}%f_set_uc_content(intf.pas,_%f_pas_MethodOwnerID(%{FM_Inst},%{MOD})_var,\ {-}\ )\ %{FM_Inst}%f_set_uc_content(intf.pas,_%f_pas_MethodOwnerID(%{FM_Inst},%{MOD})_impl,\ if (afw.Settings = nil) then Result := dv_%f_N(%{MOD})_%{SELF}{CodeName} else Result := afw.Settings.\ [{%{SELF}%{IsBool}N=true}{\ LoadInteger\ }\ LoadBoolean\ ]\ (pi_%f_N(%{MOD})_%{SELF}{CodeName}, dv_%f_N(%{MOD})_%{SELF}{CodeName});\ )\ %{MOD}%f_add_class(%{SELF}U_%{MOD}U_FM_W,%{METHOD}N,Write%{METHODN}N%{SELF}{CodeName}Setting,FM_Inst_W)\ %{FM_Inst_W}%f_set_visibility_type(PublicAccess)\ %{FM_Inst_W}%f_set_abstraction_type(final)\ %{FM_Inst_W}%f_set_documentation(Метод для записи значения настройки "%{SELF}N")\ %{FM_Inst_W}%f_make_accessable(%{SELF}U)\ %{FM_Inst_W}%f_add_realized(%{SELF}U)\ %{FM_Inst_W}%f_make_accessable(%{Tafw}U)\ %{FM_Inst_W}%f_add_dependency(%{FM_Inst_W}U_%{Tafw}U_uses,%{Tafw}U,uses,,USES_Inst)\ %{FM_Inst_W}%f_set_up(NO_FACTORY_BRACKECTS,true)\ %{FM_Inst_W}%f_set_up(is static,true)\ %{FM_Inst_W}%f_add_operation(%{FM_Inst_W}U_DoIt,,DoIt (aValue : \ [{%{SELF}%{IsBool}N=true}{\ %{Integer}U}\ %{BOOLEAN}U\ ]\ ),Op_Instance)\ %{Op_Instance}%f_set_documentation(%{FM_Inst_W}D)\ %{FM_Inst_W}%f_set_uc_content(intf.pas,_%f_pas_MethodOwnerID(%{FM_Inst_W},%{MOD})_var,\ {-}\ )\ %{FM_Inst_W}%f_set_uc_content(intf.pas,_%f_pas_MethodOwnerID(%{FM_Inst_W},%{MOD})_impl,\ if (afw.Settings \<\> nil) then afw.Settings.\ [{%{SELF}%{IsBool}N=true}{\ SaveInteger\ }\ SaveBoolean\ ]\ (pi_%f_N(%{MOD})_%{SELF}{CodeName}, aValue);\ )\ }\ %f_set_var(FIRST,"true")\ %{SELF}<{}{%CS=UseCaseSettingValue&"%C{CodeName}"!=""}\ %{MOD}%f_add_class(%{SELF}U_%{MOD}U_%CU_FM,%{METHOD}N,%{METHODN}N%{SELF}{CodeName}%C{CodeName}Setting,FM_Inst)\ %{FM_Inst}%f_set_visibility_type(PublicAccess)\ %{FM_Inst}%f_set_abstraction_type(final)\ %{FM_Inst}%f_set_documentation(Метод для получения значения настройки "%{SELF}N"."%CN")\ %{FM_Inst}%f_make_accessable(%{SELF}U)\ %{FM_Inst}%f_add_realized(%{SELF}U)\ %{FM_Inst}%f_make_accessable(%{Tafw}U)\ %{FM_Inst}%f_add_dependency(%{FM_Inst}U_%{Tafw}U_uses,%{Tafw}U,uses,,USES_Inst)\ %{FM_Inst}%f_set_up(NO_FACTORY_BRACKECTS,true)\ %{FM_Inst}%f_set_up(is static,true)\ %{FM_Inst}%f_add_operation(%{FM_Inst}U_DoIt,,DoIt (): \ %{BOOLEAN}U\ ,Op_Instance)\ %{Op_Instance}%f_set_documentation(%{FM_Inst}D)\ %{FM_Inst}%f_set_uc_content(intf.pas,_%f_pas_MethodOwnerID(%{FM_Inst},%{MOD})_var,\ {-}\ )\ %{FM_Inst}%f_set_uc_content(intf.pas,_%f_pas_MethodOwnerID(%{FM_Inst},%{MOD})_impl,\ if (afw.Settings = nil) then Result := [{%{FIRST}N=true}{false}true] else Result := afw.Settings.\ LoadBoolean\ (pi_%f_N(%{MOD})_%{SELF}{CodeName}_%C{CodeName}, [{%{FIRST}N=true}{false}true]);\ )\ %f_set_var(FIRST,"false")\ >\ ]\ %{MOD}%f_add_dependency(%{MOD}U_%{Pack_Inst}U_uses,%{Pack_Inst}U,uses,,USES_Inst)\ %{Pack_Inst}%f_set_documentation(Ресурсы для настройки "%{SELF}N")\ %{Pack_Inst}%f_make_accessable(%{SELF}U)\ %{Pack_Inst}%f_add_realized(%{SELF}U)\ %{Pack_Inst}%f_add_class(%{Pack_Inst}U_Key,Constants,%{SELF}{CodeName}Key,Const_Inst)\ %{Const_Inst}%f_add_attribute(%{Const_Inst}U_Key,,\ pi_%f_N(%{MOD})_%{SELF}{CodeName} = '%{MOD}D/%{SELF}N',\ Attr_Inst)\ %{Attr_Inst}%f_set_documentation(Идентификатор настройки "%{SELF}N")\ [{%{SELF}%{HasNestedSettings}N=true}\ %{SELF}<{}{%CS=UseCaseSettingValue&"%C{CodeName}"!=""}\ %{Const_Inst}%f_add_attribute(%{Const_Inst}U_%CU_Key,,\ pi_%f_N(%{MOD})_%{SELF}{CodeName}_%C{CodeName} = '%{MOD}D/%{SELF}N/%CN',\ Attr_Inst)\ %{Attr_Inst}%f_set_documentation(Идентификатор настройки "%{SELF}N"."%CN")\ >\ ]\ [{%{SELF}%{HasNestedSettings}N!=true}\ %{Const_Inst}%f_add_attribute(%{Const_Inst}U_DefaultValue,,\ dv_%f_N(%{MOD})_%{SELF}{CodeName} = \ [{%{SELF}%{IsBool}N=true}{\ 0\ }\ false\ ]\ ,\ Attr_Inst)\ %{Attr_Inst}%f_set_documentation(Значение по-умолчанию настройки "%{SELF}N")\ ]\ %{Pack_Inst}%f_add_class(%{Pack_Inst}U_Name,LocalConst,%{SELF}{CodeName}Name,Local_Inst)\ %{Local_Inst}%f_set_documentation(Имя настройки "%{SELF}N")\ %{Local_Inst}%f_set_visibility_type(PublicAccess)\ %{Local_Inst}%f_add_attribute(%{SELF}U_%{MOD}U_%SU_SettingName,,\ %{SELF}{CodeName} = '%{SELF}N',\ Attr_Inst)\ %{Attr_Inst}%f_set_documentation(%{SELF}N)\ %{Pack_Inst}%f_add_class(%{Pack_Inst}U_Values,LocalConst,%{SELF}{CodeName}Values,Local_Inst)\ %{Local_Inst}%f_set_documentation(Значения для настройки "%{SELF}N")\ %{Local_Inst}%f_set_visibility_type(PublicAccess)\ [{%{SELF}%{HasNestedSettings}N!=true}\ [{%{SELF}%{IsBool}N=true}{\ %{Local_Inst}%f_add_inheritable(%{Enum_Inst}U)\ }\ %{Local_Inst}%f_add_inheritable(%{BOOLEAN}U)\ ]\ %{Local_Inst}%f_set_up(Need mapping support,true)\ %{Local_Inst}%f_set_up(Need map interface,true)\ ]\ %{Local_Inst}%f_set_up(elements prefix,%{SELF}{CodeName})\ %{SELF}<{}{%CS=UseCaseSettingValue&"%C{CodeName}"!=""}\ %{Local_Inst}%f_add_attribute(%{SELF}U_%{MOD}U_%CU_SettingValue,,\ %C{CodeName} = '%CN',\ Attr_Inst)\ %{Attr_Inst}%f_set_documentation(%CN)\ >\ [{%{SELF}%{HasNestedSettings}N!=true}\ %f_set_var(Hack,"false")\ [{%{PAR}N=StyleTable}\ %f_set_var(Hack,"true")\ %f_set_var(PAR,{TddComboBoxConfigItem}%P%P)\ ]\ %{PAR}%f_add_class(%{SELF}U_%{MOD}U_AppConfig,SimpleClass,Tst%f_N(%{MOD})%{SELF}{CodeName}Item,Class_Inst)\ %{Class_Inst}%f_set_documentation(Визуализатор для настройки "%{SELF}N")\ %{Class_Inst}%f_make_accessable(%{SELF}U)\ %{Class_Inst}%f_add_realized(%{SELF}U)\ %{Class_Inst}%f_make_accessable(%{Pack_Inst}U)\ %{Class_Inst}%f_add_dependency(%{Class_Inst}U_%{Pack_Inst}U_uses,%{Pack_Inst}U,uses,,USES_Inst)\ %{Class_Inst}%f_make_accessable(%{TddComboBoxConfigItem}U)\ %{Class_Inst}%f_make_accessable(%{l3FillChar}U)\ %{Class_Inst}%f_make_accessable(%{TddConfigValue}U)\ %{Class_Inst}%f_add_inheritable(%{TddComboBoxConfigItem}U)\ %{Class_Inst}%f_add_dependency(%{Class_Inst}U_%{l3FillChar}U_uses,%{l3FillChar}U,uses,,USES_Inst)\ %{Class_Inst}%f_add_dependency(%{Class_Inst}U_%{TddConfigValue}U_uses,%{TddConfigValue}U,uses,,USES_Inst)\ %{Class_Inst}%f_add_operation(%{Class_Inst}U_Create,ctor,Create (aMasterItem : %{TddBaseConfigItem}U = nil),Op_Instance)\ %{Op_Instance}%f_set_uc_content(intf.pas,_%f_pas_MethodOwnerID(%{Op_Instance},%{Class_Inst})_var,\ var l_Value : TddConfigValue;\ )\ %{Op_Instance}%f_set_uc_content(intf.pas,_%f_pas_MethodOwnerID(%{Op_Instance},%{Class_Inst})_impl,\ l3FillChar(l_Value, SizeOf(l_Value)); l_Value.Kind := \ [{%{SELF}%{IsBool}N=true}{\ dd_vkInteger\ }\ dd_vkBoolean\ ]\ ; [{%{SELF}%{IsBool}N=true}{\ l_Value.AsInteger\ }\ l_Value.AsBoolean\ ]\ := dv_%f_N(%{MOD})_%{SELF}{CodeName}; inherited Create(pi_%f_N(%{MOD})_%{SELF}{CodeName}, str_%{SELF}{CodeName}.AsStr, l_Value, T%{SELF}{CodeName}ValuesMapImpl.Make, aMasterItem);\ )\ [{%{Hack}N!=true}\ %{MOD}%f_add_dependency(%{MOD}U_%{Class_Inst}U_uses,%{Class_Inst}U,uses,,USES_Inst)\ ]\ ]\ ]\ ]\ [{%S%{HasNestedSettings}N=true}\ %f_clear_list(CHILDREN_TO_SPELL)\ <{}{%CS=UseCaseSettingValue&"%C{CodeName}"!=""}%C<{}{%CS=UseCaseSetting&"%C{CodeName}"!=""}\ %f_set_var(THIS_UCMOD,3)\ %f_set_var(REALIZE_COUNT,"%C<{}{%LU=%{THIS_UCMOD}U}{%LC}>")\ [{%{REALIZE_COUNT}N=0}\ %f_add_to_list(CHILDREN_TO_SPELL,C)\ ]\ >\ >\ %f_set_var(THIS_MOD,1)\ %f_set_var(THIS_PAR,2)\ %f_set_var(THIS_UCMOD,3)\ %{CHILDREN_TO_SPELL}<{}{}{%C}\ %C%f_SpellToMod(%{THIS_MOD},%{THIS_PAR},%{THIS_UCMOD})\ >\ %f_clear_list(CHILDREN_TO_SPELL)\ ] //#UC END# *4E302A8B026Cfor4E30ECBB004D*Немного расшифрую:
%{Class_Inst}%f_make_accessable(%{TddComboBoxConfigItem}U)\ %{Class_Inst}%f_make_accessable(%{l3FillChar}U)\ %{Class_Inst}%f_make_accessable(%{TddConfigValue}U)\ %{Class_Inst}%f_add_inheritable(%{TddComboBoxConfigItem}U)\ => Class_Inst.make_accessable(TddComboBoxConfigItem); Class_Inst.make_accessable(l3FillChar); Class_Inst.make_accessable(TddConfigValue); Class_Inst.add_inheritable(TddComboBoxConfigItem);
%f _DoSpell //#UC START# *4E302A8B026Cfor4E30ECBB004D* %S%[inherited]\ <{}{%LS=VCMUseCaseRealization}\ %L<{}{%GS=VCMFormsPack}\ %1%f_SpellToMod(%G,%G%P,%S)\ >\ >\ <{}{%LS=SettingsHolder}\ %S%f_SpellToMod(%L,%L%P,%L)\ >\ => UseCaseSetting.DoSpell; begin //#UC START# *4E302A8B026Cfor4E30ECBB004D* inherited; for (L in Self.Realizers) do if L.StereotypeIs(VCMUseCaseRealization) then for (G in L.Ancestors) do if G.StereotypeIs(VCMFormsPack) then self.SpellToMod(G, G.Parent, L); for (L in Self.Realizers) do if L.StereotypeIs(SettingsHolder) then self.SpellToMod(L, L.Parent, L); end;
%{PAR}%f_add_class(%{SELF}U_%{MOD}U_AppConfig,SimpleClass,Tst%f_N(%{MOD})%{SELF}{CodeName}Item,Class_Inst) => Class_Inst := PAR.add_class(self.UID + MOD.UID + '_AppConfig', SimpleClass, 'Tst' + Name(MOD) + self.CodeName + 'Item');
[{"%{TddConfigValue}N"=""}%f_find_element(TddConfigValue,TddConfigValue)]\ [{"%{l3FillChar}N"=""}%f_find_element(l3FillChar,l3FillChar)]\ => if not Assigned(TddConfigValue) then TddConfigValue := find_element('TddConfigValue'); if not Assigned(l3FillChar) then l3FillChar := find_element('l3FillChar');
В каком контексте это перекрытие используется, Александр?
ОтветитьУдалитьВероятно, Вы привели фрагмент шаблона, связанного с мета-моделью.
Объясните, хотя бы, для чего он служит? Какой стереотип порождается из каких? Какими соображениями мотивировано такое порождение?
"Какими соображениями мотивировано такое порождение?"
Удалить-- был взят СУЩЕСТВУЮЩИЙ код. МНОГО раз написанный и переписанный. РАЗНЫМИ людьми и в разное время. В том или ином качестве. И отличающийся лишь "параметрами инстанцирования" и некоторыми условиями.
И этот код был ШАБЛОНИЗИРОВАН.
Никаких "новых велосипедов" не изобреталось. Лишь шаблонизировались старые.
Можно было конечно пойти по другому пути - тотально всё отрефакторить. Но это - дорого и не факт, что эффективнее.
Но нами были лишь шаблонизированы УЖЕ существующие решения. Конечная система об этом - "не узнала".
"В каком контексте это перекрытие используется, Александр?"
Удалить-- это "перекрытие" - банально вызывается генератором. Как метод на соответствующем объекте. На экземпляре стереотипа. UseCaseSetting.
"Вероятно, Вы привели фрагмент шаблона, связанного с мета-моделью."
Удалить-- нет - с мета-моделью это не связанно. Это преобразование элемента модели в другие элементы модели. А мета-модель - выше по уровню находится.
"Объясните, хотя бы, для чего он служит?"
Удалить-- например для порождения класса-визуализатора соответствующей настройки в диалоге настроек. А также - методов доступа к соответствующей настройке.
«"Какими соображениями мотивировано такое порождение?"
Удалить-- был взят СУЩЕСТВУЮЩИЙ код. МНОГО раз написанный и переписанный. РАЗНЫМИ людьми и в разное время. В том или ином качестве. И отличающийся лишь "параметрами инстанцирования" и некоторыми условиями.
И этот код был ШАБЛОНИЗИРОВАН.
Никаких "новых велосипедов" не изобреталось. Лишь шаблонизировались старые.
Можно было конечно пойти по другому пути - тотально всё отрефакторить. Но это - дорого и не факт, что эффективнее.
Но нами были лишь шаблонизированы УЖЕ существующие решения. Конечная система об этом - "не узнала".»
-- Я не знаю, Александр, почувствовали Вы это, или нет... Но здесь Вы сказали нечто настолько важное, что мне нужно будет подумать над этим, боюсь даже, не пару дней...
Понимаете в чём дело... В классическом программировании, в сущности, рекомендуется один путь - рефакторинг, целью которого является устранение дублирования.
Это настолько привычная вещь, что многими людьми (и мною, в том числе) она принимается за аксиоматику.
Альтернативы известны давно - это подход C++ с его шаблонами и, появившаяся позже методология параметризации с обобщёнными типами (generics).
Я давно обратил внимание на частое упоминание Вами mixin-ов, техники, которая довольно давно была предложена Акжаном Абдулиным, но, насколько мне известно, не нашедшая широкого применения.
Как я понимаю, Вы с коллегами включили эту технику не только в инструментарий, но и в методологию. Это очень, очень непривычно. Особенно, если учесть, что сама техника Акжана Абдулина выглядит несколько э-э-э... вычурно, что-ли...
Но безусловно, это не говорит о неправильности. Тем более, у Вас это работает и, как я понимаю, используется в фундаменте мета-модели.
Очень, очень занятно... Очень!
«"Вероятно, Вы привели фрагмент шаблона, связанного с мета-моделью."
Удалить-- нет - с мета-моделью это не связанно. Это преобразование элемента модели в другие элементы модели. А мета-модель - выше по уровню находится.»
-- Т.е. шаблоны применяются не тоько на уровне мета-модели, но и на уровне модели тоже?
«"Объясните, хотя бы, для чего он служит?"
-- например для порождения класса-визуализатора соответствующей настройки в диалоге настроек. А также - методов доступа к соответствующей настройке.»
-- Ok. Спасибо. Пока непонятно, но мне нужно сначала разобраться, как поставить дальнейшие вопросы... :-)
"Понимаете в чём дело... В классическом программировании, в сущности, рекомендуется один путь - рефакторинг, целью которого является устранение дублирования.
УдалитьЭто настолько привычная вещь, что многими людьми (и мною, в том числе) она принимается за аксиоматику."
-- именно так. И тут ВЫ ПРАВИЛЬНО всё написали. Именно.
Мимикрия под СУЩЕСТВУЮЩИЙ код. Чтобы "не разломать".
Некоторым этот путь кажется тупиковым. И с ними я как "чистый" программист - согласен. Но как практик - нет. Чаще прощё "залатать", чем переделывать архитектуру. Хотя я и не сторонник этого.
Но столько людей "латают", что это тоже - лучше шаблонизировать, нежели "латать на коленке".
"Я давно обратил внимание на частое упоминание Вами mixin-ов, техники, которая довольно давно была предложена Акжаном Абдулиным, но, насколько мне известно, не нашедшая широкого применения."
Удалить-- эту технику к сожалению мало кто понял :-(
"Очень, очень занятно... Очень!"
Удалить-- это - не "занятно"... это в некотором смысле "грустно"... Это просто текущие процессы так устроены.. и далеко не только в нашей организации...Возьму на себя смелость предположить, что даже в MS - Так же.. а уж в России - в каждой второй конторе...
"Как я понимаю, Вы с коллегами включили эту технику не только в инструментарий, но и в методологию"
Удалить-- включили. Скажем так.. в методологию "первоначального рефакторинга".
Так - проще, чем каждую версию перетряхивать всю архитектуру...
Да и проектов - НЕ ОДИН.. Как вам может показаться..
"Я не знаю, Александр, почувствовали Вы это, или нет... Но здесь Вы сказали нечто настолько важное, что мне нужно будет подумать над этим, боюсь даже, не пару дней...
УдалитьПонимаете в чём дело... В классическом программировании, в сущности, рекомендуется один путь - рефакторинг, целью которого является устранение дублирования."
-- если вы хотите это услышать - да мы "ставим костыли на промышленной основе", с возможностью в ОДИН МОМЕНТ их убрать.
Почувствовал.
УдалитьЭто - ВАЖНЫЙ момент.
Я до сих пор его воспринимал - "банальным".
А Вы уверены в читабельности такого решения? Боюсь, даже подсветка синтаксиса не спасёт.
ОтветитьУдалитьВиктор, спасибо. Про вас - тоже всё давно понятно.
УдалитьВиктор, язык шаблонов поддаётся доработке.
ОтветитьУдалитьВероятно, он развивался эволюционно, возможно, на него оказали влияние какие-то существовавшие ранее решения. То, что он нечитабелен, конечно не гут, но Александр уже не раз упоминал, что они работают над этой проблемой. Лично у меня нет сомнений в том, что они её успешно решат.
Вместе с тем, по модулю текущей нечитабельности, для меня представляет живейший интерес задачи, которые возлагаются на шаблоны. Выше Александр ответил по-существу.
Не хотел отвечать.. Но личные обиды меркнут перед профессиональным интересом...
УдалитьНу что вы за человек.. То "задеваете", то наоборот.. Играете "доброго" и злого" следователя в одном лице...
Вот вы ПРАВИЛЬНО всё тут написали.
Именно - так. Эволюционно. И никто не стремился к "криптованности". "Криптованность" - зло. Она исходит из желания "сделать быстро и просто".
Да и "ошибки молодости".
%{Class_Inst}%f_make_accessable(%{TddComboBoxConfigItem}U)\
Удалить%{Class_Inst}%f_make_accessable(%{l3FillChar}U)\
%{Class_Inst}%f_make_accessable(%{TddConfigValue}U)\
%{Class_Inst}%f_add_inheritable(%{TddComboBoxConfigItem}U)\
Class_Inst.make_accessable(TddComboBoxConfigItem);
Class_Inst.make_accessable(l3FillChar);
Class_Inst.make_accessable(TddConfigValue);
Class_Inst.add_inheritable(TddComboBoxConfigItem);
-- Так ведь стало понятнее?
%f _DoSpell
Удалить//#UC START# *4E302A8B026Cfor4E30ECBB004D*
%S%[inherited]\
<{}{%LS=VCMUseCaseRealization}\
%L<{}{%GS=VCMFormsPack}\
%1%f_SpellToMod(%G,%G%P,%S)\
>\
>\
<{}{%LS=SettingsHolder}\
%S%f_SpellToMod(%L,%L%P,%L)\
>\
=>
UseCaseSetting.DoSpell;
begin
//#UC START# *4E302A8B026Cfor4E30ECBB004D*
inherited;
for (L in Self.Realizers) do
if L.StereotypeIs(VCMUseCaseRealization) then
for (G in L.Ancestors) do
if G.StereotypeIs(VCMFormsPack) then
self.SpellToMod(G, G.Parent, L);
for (L in Self.Realizers) do
if L.StereotypeIs(SettingsHolder) then
self.SpellToMod(L, L.Parent, L);
end;
Так ведь тоже стало понятнее?
http://18delphi.blogspot.ru/2013/09/blog-post_5343.html
УдалитьВнизу поста это же приведено с подсветкой синтаксиса и отступами.
«-- Так ведь стало понятнее?»
Удалить-- На порядок. Или нет - даже на два :-)
Хотя могу только догадываться и домысливать...
«Class_Inst.make_accessable(TddComboBoxConfigItem);
Class_Inst.make_accessable(l3FillChar);
Class_Inst.make_accessable(TddConfigValue);»
-- Вероятно, нечто вводится в пространство имён. При кодогенерации будет подключён соответствующий модуль и, возможно, в класс будут добавлены поля соответствующих типов.
«Class_Inst.add_inheritable(TddComboBoxConfigItem);»
-- Очень похоже, что здесь создаётся наследование от базового класса TddComboBoxConfigItem, не исключено, что примесное (mix-in)...
Таким образом, код порождаемого класса (или набора классов) будет "оснащён" соответствующими свойствами и примесями...
"На порядок. Или нет - даже на два"
Удалить-- ну вот видите. Я а просто перевёл с одного языка на другой.
"Очень похоже, что здесь создаётся наследование от базового класса TddComboBoxConfigItem, не исключено, что примесное"
-- конкретно в ДАННОМ случае - даже и не примесное. А вполне обычное.
"Таким образом, код порождаемого класса (или набора классов) будет "оснащён" соответствующими свойствами и примесями..."
Удалить-- именно так.
именно кстати "набора" - потому, что там - цикл присутствует
Удалить%{PAR}%f_add_class(%{SELF}U_%{MOD}U_AppConfig,SimpleClass,Tst%f_N(%{MOD})%{SELF}{CodeName}Item,Class_Inst)
Удалить=>
Class_Inst := PAR.add_class(self.UID + MOD.UID + 'AppConfig', SimpleClass, 'Tst' + Name(MOD) + self.CodeName + 'Item')
TddConfigValue - НАРИСОВАН на мета-модели (1) но он используется самой мета-моделью. Т.е. мета-модель становится мета-моделью (2). Вот и "раскрутка".
Удалить"Вероятно, нечто вводится в пространство имён. При кодогенерации будет подключён соответствующий модуль и, возможно, в класс будут добавлены поля соответствующих типов."
Удалить-- именно так. Главное, что "конечный" программист этого всего "не знает".