пятница, 27 сентября 2013 г.

Пример кода порождения стереотипов из других стереотипов

Для тех самых настроек (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');

27 комментариев:

  1. В каком контексте это перекрытие используется, Александр?
    Вероятно, Вы привели фрагмент шаблона, связанного с мета-моделью.
    Объясните, хотя бы, для чего он служит? Какой стереотип порождается из каких? Какими соображениями мотивировано такое порождение?

    ОтветитьУдалить
    Ответы
    1. "Какими соображениями мотивировано такое порождение?"
      -- был взят СУЩЕСТВУЮЩИЙ код. МНОГО раз написанный и переписанный. РАЗНЫМИ людьми и в разное время. В том или ином качестве. И отличающийся лишь "параметрами инстанцирования" и некоторыми условиями.

      И этот код был ШАБЛОНИЗИРОВАН.

      Никаких "новых велосипедов" не изобреталось. Лишь шаблонизировались старые.

      Можно было конечно пойти по другому пути - тотально всё отрефакторить. Но это - дорого и не факт, что эффективнее.

      Но нами были лишь шаблонизированы УЖЕ существующие решения. Конечная система об этом - "не узнала".

      Удалить
    2. "В каком контексте это перекрытие используется, Александр?"

      -- это "перекрытие" - банально вызывается генератором. Как метод на соответствующем объекте. На экземпляре стереотипа. UseCaseSetting.

      Удалить
    3. "Вероятно, Вы привели фрагмент шаблона, связанного с мета-моделью."
      -- нет - с мета-моделью это не связанно. Это преобразование элемента модели в другие элементы модели. А мета-модель - выше по уровню находится.

      Удалить
    4. "Объясните, хотя бы, для чего он служит?"
      -- например для порождения класса-визуализатора соответствующей настройки в диалоге настроек. А также - методов доступа к соответствующей настройке.

      Удалить
    5. «"Какими соображениями мотивировано такое порождение?"
      -- был взят СУЩЕСТВУЮЩИЙ код. МНОГО раз написанный и переписанный. РАЗНЫМИ людьми и в разное время. В том или ином качестве. И отличающийся лишь "параметрами инстанцирования" и некоторыми условиями.

      И этот код был ШАБЛОНИЗИРОВАН.

      Никаких "новых велосипедов" не изобреталось. Лишь шаблонизировались старые.

      Можно было конечно пойти по другому пути - тотально всё отрефакторить. Но это - дорого и не факт, что эффективнее.

      Но нами были лишь шаблонизированы УЖЕ существующие решения. Конечная система об этом - "не узнала".»
      -- Я не знаю, Александр, почувствовали Вы это, или нет... Но здесь Вы сказали нечто настолько важное, что мне нужно будет подумать над этим, боюсь даже, не пару дней...
      Понимаете в чём дело... В классическом программировании, в сущности, рекомендуется один путь - рефакторинг, целью которого является устранение дублирования.
      Это настолько привычная вещь, что многими людьми (и мною, в том числе) она принимается за аксиоматику.
      Альтернативы известны давно - это подход C++ с его шаблонами и, появившаяся позже методология параметризации с обобщёнными типами (generics).
      Я давно обратил внимание на частое упоминание Вами mixin-ов, техники, которая довольно давно была предложена Акжаном Абдулиным, но, насколько мне известно, не нашедшая широкого применения.
      Как я понимаю, Вы с коллегами включили эту технику не только в инструментарий, но и в методологию. Это очень, очень непривычно. Особенно, если учесть, что сама техника Акжана Абдулина выглядит несколько э-э-э... вычурно, что-ли...
      Но безусловно, это не говорит о неправильности. Тем более, у Вас это работает и, как я понимаю, используется в фундаменте мета-модели.
      Очень, очень занятно... Очень!

      Удалить
    6. «"Вероятно, Вы привели фрагмент шаблона, связанного с мета-моделью."
      -- нет - с мета-моделью это не связанно. Это преобразование элемента модели в другие элементы модели. А мета-модель - выше по уровню находится.»
      -- Т.е. шаблоны применяются не тоько на уровне мета-модели, но и на уровне модели тоже?

      «"Объясните, хотя бы, для чего он служит?"
      -- например для порождения класса-визуализатора соответствующей настройки в диалоге настроек. А также - методов доступа к соответствующей настройке.»
      -- Ok. Спасибо. Пока непонятно, но мне нужно сначала разобраться, как поставить дальнейшие вопросы... :-)

      Удалить
    7. "Понимаете в чём дело... В классическом программировании, в сущности, рекомендуется один путь - рефакторинг, целью которого является устранение дублирования.
      Это настолько привычная вещь, что многими людьми (и мною, в том числе) она принимается за аксиоматику."

      -- именно так. И тут ВЫ ПРАВИЛЬНО всё написали. Именно.
      Мимикрия под СУЩЕСТВУЮЩИЙ код. Чтобы "не разломать".

      Некоторым этот путь кажется тупиковым. И с ними я как "чистый" программист - согласен. Но как практик - нет. Чаще прощё "залатать", чем переделывать архитектуру. Хотя я и не сторонник этого.

      Но столько людей "латают", что это тоже - лучше шаблонизировать, нежели "латать на коленке".

      Удалить
    8. "Я давно обратил внимание на частое упоминание Вами mixin-ов, техники, которая довольно давно была предложена Акжаном Абдулиным, но, насколько мне известно, не нашедшая широкого применения."

      -- эту технику к сожалению мало кто понял :-(

      Удалить
    9. "Очень, очень занятно... Очень!"

      -- это - не "занятно"... это в некотором смысле "грустно"... Это просто текущие процессы так устроены.. и далеко не только в нашей организации...Возьму на себя смелость предположить, что даже в MS - Так же.. а уж в России - в каждой второй конторе...

      Удалить
    10. "Как я понимаю, Вы с коллегами включили эту технику не только в инструментарий, но и в методологию"
      -- включили. Скажем так.. в методологию "первоначального рефакторинга".
      Так - проще, чем каждую версию перетряхивать всю архитектуру...

      Да и проектов - НЕ ОДИН.. Как вам может показаться..

      Удалить
    11. "Я не знаю, Александр, почувствовали Вы это, или нет... Но здесь Вы сказали нечто настолько важное, что мне нужно будет подумать над этим, боюсь даже, не пару дней...
      Понимаете в чём дело... В классическом программировании, в сущности, рекомендуется один путь - рефакторинг, целью которого является устранение дублирования."
      -- если вы хотите это услышать - да мы "ставим костыли на промышленной основе", с возможностью в ОДИН МОМЕНТ их убрать.

      Удалить
    12. Почувствовал.
      Это - ВАЖНЫЙ момент.
      Я до сих пор его воспринимал - "банальным".

      Удалить
  2. А Вы уверены в читабельности такого решения? Боюсь, даже подсветка синтаксиса не спасёт.

    ОтветитьУдалить
    Ответы
    1. Виктор, спасибо. Про вас - тоже всё давно понятно.

      Удалить
  3. Виктор, язык шаблонов поддаётся доработке.
    Вероятно, он развивался эволюционно, возможно, на него оказали влияние какие-то существовавшие ранее решения. То, что он нечитабелен, конечно не гут, но Александр уже не раз упоминал, что они работают над этой проблемой. Лично у меня нет сомнений в том, что они её успешно решат.
    Вместе с тем, по модулю текущей нечитабельности, для меня представляет живейший интерес задачи, которые возлагаются на шаблоны. Выше Александр ответил по-существу.

    ОтветитьУдалить
    Ответы
    1. Не хотел отвечать.. Но личные обиды меркнут перед профессиональным интересом...

      Ну что вы за человек.. То "задеваете", то наоборот.. Играете "доброго" и злого" следователя в одном лице...

      Вот вы ПРАВИЛЬНО всё тут написали.

      Именно - так. Эволюционно. И никто не стремился к "криптованности". "Криптованность" - зло. Она исходит из желания "сделать быстро и просто".

      Да и "ошибки молодости".

      Удалить
    2. %{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);

      -- Так ведь стало понятнее?

      Удалить
    3. %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;

      Так ведь тоже стало понятнее?

      Удалить
    4. http://18delphi.blogspot.ru/2013/09/blog-post_5343.html

      Внизу поста это же приведено с подсветкой синтаксиса и отступами.

      Удалить
    5. «-- Так ведь стало понятнее?»
      -- На порядок. Или нет - даже на два :-)
      Хотя могу только догадываться и домысливать...

      «Class_Inst.make_accessable(TddComboBoxConfigItem);
      Class_Inst.make_accessable(l3FillChar);
      Class_Inst.make_accessable(TddConfigValue);»
      -- Вероятно, нечто вводится в пространство имён. При кодогенерации будет подключён соответствующий модуль и, возможно, в класс будут добавлены поля соответствующих типов.

      «Class_Inst.add_inheritable(TddComboBoxConfigItem);»
      -- Очень похоже, что здесь создаётся наследование от базового класса TddComboBoxConfigItem, не исключено, что примесное (mix-in)...

      Таким образом, код порождаемого класса (или набора классов) будет "оснащён" соответствующими свойствами и примесями...

      Удалить
    6. "На порядок. Или нет - даже на два"
      -- ну вот видите. Я а просто перевёл с одного языка на другой.

      "Очень похоже, что здесь создаётся наследование от базового класса TddComboBoxConfigItem, не исключено, что примесное"
      -- конкретно в ДАННОМ случае - даже и не примесное. А вполне обычное.

      Удалить
    7. "Таким образом, код порождаемого класса (или набора классов) будет "оснащён" соответствующими свойствами и примесями..."

      -- именно так.

      Удалить
    8. именно кстати "набора" - потому, что там - цикл присутствует

      Удалить
    9. %{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')

      Удалить
    10. TddConfigValue - НАРИСОВАН на мета-модели (1) но он используется самой мета-моделью. Т.е. мета-модель становится мета-моделью (2). Вот и "раскрутка".

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

      -- именно так. Главное, что "конечный" программист этого всего "не знает".

      Удалить