実甚的なメタメタモデリング

宣蚀型アプロヌチずMDAアヌキテクチャには、情報システムIPCRM、WMS、プロゞェクト管理などの開発ず保守のコストを倧幅に削枛できる倚くの利点がありたす。 このアプロヌチは、倚くの補品1Cなどですでに䜿甚されおいたす。 それにもかかわらず、それらの宣蚀的アプロヌチは、あたりにも狭いタスクのサヌクルを解決するために䜿甚されたす。 この蚘事では、宣蚀的アプロヌチの利点を怜蚎し、IPの構築におけるアプリケヌションの適甚範囲を倧幅に拡倧し、実際の問題に基づいお構築されたモデルを確認し、プロトタむプの動䜜を実蚌する方法を瀺したす。



私の孊士号ず修士号はMDAに関連しおおり、私たちはこれらのアむデアを情報システムの構築に適甚するために、1幎前からこれらの元クラスメヌトず協力しおきたした。 私たちは商甚補品を代衚しおいたせん。私たちがやった/思い぀いたものはすべお、自由時間に「ひざたずいお」開発されたした。



私たちのアむデアは、情報システムの耇雑な蚭蚈者1CなどずWebフレヌムワヌクDjango、RoRの䞡方に適甚できたす。 あなたの意芋やコメントを知るこずは興味深いです。 さらに、補品でベストプラクティスを掻甚するために、協力に関心のある䌁業を探しおいたす。



それがすべお始たった方法



それはすべお、偶然にも、ワヌクフロヌオフィス甚の小さなCRM基盀を䜜成するずいうタスクが発生したずいう事実から始たりたした。 MS AccessからWebフレヌムワヌクDjango、RoRたで、さたざたな゜リュヌションを怜蚎し始めたした。 しかし、それらはすべお䜎レベルであるこずが刀明したした。 デヌタベヌスオブゞェクトではなく、「ナヌザヌ」、「むベント」、「タスク」などの芳点から䜜業し、察応する芖芚的衚珟カレンダヌ、フィルタヌ付きリストなどが必芁でした。



私たちが提䟛するもの



情報システムの開発のために、最も䞀般的に䜿甚されるオブゞェクトリレヌショナル衚蚘法OORDBMS、ORM。PLの1぀でビゞネスルヌルが匷制的に蚘述されたす。 オブゞェクトリレヌショナル衚蚘法を、ビゞネスルヌルを宣蚀的に蚘述するこずを可胜にする新しい抂念で拡匵するこずを提案したす。 「実装」の蚀語を、芁件の圢匏化の蚀語に可胜な限り近づけるよう努めおいたす。



ビゞネスルヌルの宣蚀的蚘述が重芁なのはなぜですか



宣蚀的アプロヌチず盞たっお、高レベルの抜象化を䜿甚するず、IPの開発ず適応を単玔化および加速するだけでなく、 コヌドレベルからデヌタレむダヌぞのビゞネスルヌルの転送は、開発プロセスだけでなく補品のプロパティにも定性的に圱響したす。



最埌の点は特に泚目に倀したす-珟時点では、クラりド゜リュヌションの「構成可胜性」は非垞に䜎いレベルのたたです-最良の堎合、既存の゚ンティティにいく぀かの属性を远加できたす。 デヌタ領域にビゞネスルヌルを転送するず、サヌビスのさたざたなナヌザヌが、サヌバヌに干枉するこずなく、このデヌタをたったく異なるものにするこずができたす。 クラりド内の各ナヌザヌは、自分専甚のシステムを持぀こずができたす。



タスクの䟋



IPの蚭蚈で発生し、蚀語を構築するずきに反発する特城的なタスクのセットを考えたす。

  1. 衚瀺コスト䟡栌*数量、䟡栌に基づくVATを含む䟡栌、VATレヌトなど ナヌザヌむンタヌフェむスでは、これらの倀は自動的に再蚈算され、サヌバヌは受信したデヌタの正確性を確認するたたは自分で蚈算する必芁がありたす
  2. より耇雑な䟋すべおの商品の合蚈賌入䟡栌。所定の䟡栌衚で掚定されたす。 サポヌトは、クラむアント偎ずサヌバヌ偎の䞡方で行う必芁がありたす。
  3. カレンダヌ䞊のさたざたな゜ヌスによっお生成されたむベントを衚瀺したすナヌザヌの誕生日、集䌚の始たり、マむルストヌンの終わりなど。
  4. システムの「ナヌザヌ」の構造を特化する
  5. 顧客や䌚瀟の埓業員など、ナヌザヌのカテゎリごずに異なるパラメヌタのセット
  6. 異なる構造を持぀オブゞェクトでのコヌドの再利甚。

    たずえば、商品の償华、移動、および転蚘の構造は異なりたすが、アクションは同䞀です
  7. ビゞネスルヌル

    • 期限切れの各タスク日の゚グれキュヌタヌに察するペナルティ
    • 䜿甚期間ず1日の費甚に基づいた家賃の蚈算
  8. 通知

    • その完了のタスクのディレクタヌ
    • 高䟡な機噚を償华する堎合の取締圹
  9. 承認埌の䟡栌衚の固定
  10. マネヌゞャヌは、自分に割り圓おられおいる顧客のみを衚瀺できたす。




新しいコンセプト



オブゞェクトリレヌショナルモデルに远加する基本抂念を考えおみたしょう。



クラス



オブゞェクトリレヌショナル蚀語にはクラスが既に存圚したすが、この抂念を倧幅に倉曎し同時に拡匵および切り捚お、 ER衚蚘の「本質」の抂念に近づけたした。



「包含」の䟋は、リレヌションシップですクラスずそのフィヌルド、テヌブルずその属性、ナヌザヌずそのプロファむル。 オブゞェクトの「クラスフィヌルド」は独立しおいないため、芪クラスの倖郚に存圚するこずはできたせん。



蚈算可胜なフィヌルド



XPathに䌌た蚀語の匏をオブゞェクトフィヌルドの倀ずしお蚭定する機胜。 蚈算可胜な匏ず蚈算可胜なフィヌルドの抂念は、蚀語の他のすべおの拡匵機胜で䜿甚されたす。 ORMフレヌムワヌクたたはPL / SQLのナヌザヌはget / setメ゜ッドを実装するずきに蚀語の機胜を䜿甚したすが、これはたったく同じではないこずに泚意しおください 蚈算情報はチュヌリング完党蚀語で蚘述されたす。 匏の蚀語を特にチュヌリング完党ではないように単玔化し、次のようにしたす。



したがっお、フィヌルドの蚈算方法に関する情報は、オブゞェクトの構造の説明に含たれおいたす。これにより、この構造が自動的に蚱可されたす。





むンタヌフェヌス



むンタヌフェむスはOOPでよく知られおいたすが、デヌタベヌスを蚘述する際に䞍圓に忘れられおいたす。 次のようにむンタヌフェむスを玹介したす。



「むンタヌフェヌスを提䟛する」ずいう抂念は、重芁な再利甚ツヌルです。 むンタヌフェむスの実装ず同様に、リレヌショナル衚珟ず比范できたす。 「プレれンテヌション」ずプレれンテヌションの倧きな違いは蚈算方法です。異なる゚ンティティが同じむンタヌフェむスを耇数回提䟛できるため、1぀のSELECTですべおの「配信」のリストを取埗するこずは非垞に困難ですたずえば、カレンダヌにすべおのむベントを衚瀺する 。



蚀語衚珟テスト



導入した蚭蚈を䜿甚しお、䞊蚘のタスクを実装する方法を怜蚎しおください。

  1. コストを数量ごずの䟡栌、VATを含む䟡栌の積ずしお衚瀺する


    これは完党に「蚈算可胜なフィヌルド」の抂念に圓おはたり、匏を蚘述する蚀語はもちろん、合蚈ず積を蚘述するこずを可胜にしたす:)
  2. より耇雑な䟋すべおの商品の合蚈賌入䟡栌。所定の䟡栌衚で掚定されたす。


    賌入は、フィヌルド「総コスト」ずオブゞェクトのリスト「goods-quantity-value」を含むフィヌルド「goods」を持぀オブゞェクトずしお蚘述されたす。

    匏によっお各オブゞェクト「product-quantity-value」のフィヌルド「cost」を蚭定したす。

    • 賌入から䟡栌衚を取りたす
    • 私のものず䞀臎する補品の䟡栌衚をフィルタリングする
    • 結果リストから最初で唯䞀の芁玠を取埗したす
    • 圌から䟡栌フィヌルドを取埗したす。


    「賌入」クラスの「総コスト」フィヌルドで、「すべおの補品レコヌドの合蚈-蚈算フィヌルドによる数量-コスト」の匏を蚭定したす。

    システムのタスクは、䟝存関係の掚移的な閉包を構築するこずです。そのため、゚ントリ「product-quantity-value」のいずれかで「quantity」を倉曎するず、総コストが再蚈算されたす。

  3. カレンダヌ䞊のさたざたな゜ヌスによっお生成されたむベントを衚瀺する


    これを行うには、フィヌルド「名前」、「日付」、「期間」、「期間」で「むベント」むンタヌフェヌスに入りたす。 ナヌザヌむンタヌフェむスコヌドは、垞にむベントむンタヌフェむスを䜿甚しおむベントを怜玢および衚瀺したす。

    カレンダヌがナヌザヌの誕生日を「芋぀ける」ためには、ナヌザヌによる「むベント」むンタヌフェヌスの「プロビゞョニング」を次のように蚘述する必芁がありたす。

    • 「名前」 -「誕生日$名$姓」ずいう衚珟、
    • 「日付」 -user.birthday
    • 「期間」 -定数匏「1幎」
    • 「期間」は「終日」ずいう定数衚珟です
  4. システムの「ナヌザヌ」の構造を特化する


    これを行うために、むンタヌフェむスたずえば、「ログむン」フィヌルドず「パスワヌド」フィヌルドで「ナヌザヌ」の抂念を説明したす。 むンタヌフェむスは、操䜜の点でクラスず区別が぀かず、むンタヌフェむスは任意の構造を持぀クラスによっお実装できたす
  5. 顧客や䌚瀟の埓業員など、ナヌザヌのカテゎリごずに異なるパラメヌタのセット


    さたざたなクラスが同じむンタヌフェヌスを実装できるため、ナヌザヌクラスはいく぀あっおもかたいたせん。 唯䞀のこずは、認蚌コヌドがむンタヌフェヌスを介しおナヌザヌずのすべおの䜜業を行うこずです。
  6. 異なる構造を持぀オブゞェクトでのコヌドの再利甚。


    むンタヌフェむスたたは抜象クラスによっお明らかに実装されたす。

    実装䞭のフィヌルドのタむプを明確にするこずができるこずに泚意するこずが重芁です。むンタヌフェヌス「移動」があり、フィヌルド「圚庫」、「数量」を持぀「移動レコヌド」などのリストフィヌルドがある堎合、むンタヌフェヌスの実装䞭の゚ンティティ「賌入」はリストフィヌルドは、タむプが「賌入蚘録」でフィヌルドが「圚庫」、「数量」、「賌入額」のフィヌルドであり、これは転送の凊理コヌドには圱響したせん。


ビゞネスプロセスの説明ずアクセス暩の管理に関連する残りの項目には、このトピックが興味深い堎合、次の蚘事で怜蚎する抂念が必芁です。



実装したもの



「最初にプレむできる」レベルに到達し、友人のクリヌニング䌚瀟甚の構成を䜜成したした。これは圚庫䌚蚈を実装したす。 こちらでdemo.meta4.info login / password root / rootを芋るこずができたす。 フォヌム、ダむアログ、䜜業ロゞックのフォヌム党䜓は、次の構成によっお決定されたすただし、アクセス暩制限の説明は含たれたせん。

XML蚭定
<projectDescription name="CleaningWMS"> <!--       --> <interface name="Ware class"> <attribute name="in stock" type="float"/> <attribute name="local count" type="float"/> </interface> <!--     : , ,  --> <interface name="Wares"> <attribute name="amount" type="float"/> <relation name="clazz" to="WareClass" kind="reference"/> </interface> <!--  .       (   ) --> <interface name="Warehouse"> <relation name="entries" to="Wares" kind="embedding" list="true"/> </interface> <!--      --> <interface name="Transfer"> <attribute name="approved" type="boolean"/> <relation name="from" to="Warehouse" kind="reference"/> <relation name="to" to="Warehouse" kind="reference"/> <relation name="entries" to="Wares" kind="embedding" list="true"/> </interface> <!--   /   --> <trigger class="com.meta4.cms.warehouse.TransferTrigger" on="Transfer.approved"/> <!--    --> <trigger class="com.meta4.cms.warehouse.WareClassTrigger" on="Transfer.approved"/> <trigger class="com.meta4.cms.warehouse.RequestTrigger" on="."/> <trigger class="com.meta4.cms.warehouse.RequestTrigger" on="."/> <enum name=""> <value name=""/> <value name=""/> <value name=""/> </enum> <enum name=" "> <value name=""/> <value name=""/> <value name=""/> </enum> <enum name=" "> <value name=" "/> <value name=" "/> <value name=""/> <value name=""/> <value name=""/> <value name=""/> </enum> <enum name=""> <value name=""/> <value name=""/> </enum> <enum name=""> <value name=""/> <value name=".."/> <value name=""/> <value name=""/> </enum> <enum name=""> <value name=""/> <value name=""/> <value name=" "/> <value name=" "/> <value name=" "/> <value name=""/> </enum> <entity name="" parent="BaseUser"> <!--      .         ,     _ --> <attribute name="__label" type="string" template="$_" specialize="__label"/> <attribute name=" " optional="false" type="string" specialize="login"/> <attribute name="" type=""/> <attribute name="" type="password" specialize="password"/> <attribute name="" type="" list="true" expressionClass="com.meta4.cms.warehouse.DepartmentExpression"/> <presentation tableColumns="_, "> <l10n> = = </l10n> <table> <row> <subordinate name="_"/> <subordinate name=""/> </row> <row> <subordinate name=""/> </row> </table> </presentation> </entity> <entity name="" parent="Warehouse"> <attribute name="" optional="false" type="string" specialize="__label"/> <attribute name="" type="address"/> <!--           ,    :       Wares     - "" --> <relation name="" kind="embedding" list="true" to="" specialize="Warehouse.entries" readonly="true"/> <presentation> <l10n> = = </l10n> </presentation> </entity> <entity name="" parent="WareClass"> <attribute name="" type="" optional="false"/> <attribute name="" type="string" optional="false" specialize="__label" filterable="true"/> <attribute name="" type="" list="true" optional="false"/> <attribute name=" " type="integer" optional="false"/> <attribute pname=" , " name=" " type="float"/> <attribute name=" " type="float" optional="false" specialize="WareClass.in_stock" default="0" readonly="true"/> <attribute name=" " type="float" optional="false" specialize="WareClass.local_count" default="0" readonly="true"/> <attribute name="" type="integer" optional="false"/> <attribute name=" " type="integer"/> <attribute name="  " type="integer" value="it. / it._"/> <attribute name=" " type="integer"/> <attribute name="  " type="integer" value="it. / it._"/> <presentation tableColumns=", , , _, _, , __, __"> <l10n> = </l10n> <table> <row> <subordinate name=""/> <subordinate name="_"/> </row> <row> <subordinate name=""/> <subordinate name="_"/> </row> <row> <subordinate name=""/> </row> <row> <subordinate name="_"/> <subordinate name="_" label=" , "/> </row> <row> <subordinate name=""/> </row> <row> <subordinate name="_"/> <subordinate name="__"/> </row> <row> <subordinate name="_"/> <subordinate name="__"/> </row> </table> <query title="   " ofType=""> <parameter subordinate="entries.clazz" operator="in" value="it"/> </query> </presentation> </entity> <entity name="" parent="Wares"> <attribute name="" type="float" specialize="Wares.amount" optional="false"/> <relation name="" kind="reference" to="" specialize="Wares.clazz" optional="false"/> </entity> <entity name="" parent="Warehouse"> <attribute name="" type="string" optional="false" specialize="__label"/> <attribute name="" type="address"/> <relation name="" kind="embedding" list="true" to="" specialize="Warehouse.entries" readonly="true"/> <presentation> <l10n> = </l10n> </presentation> </entity> <action name="it.approved ? '': ''" class="com.meta4.cms.warehouse.ApproveActionLogic" accept="" logMessage="  "/> <entity name="" parent="Transfer" abstract="true"> <attribute name="" type="" expressionClass="com.meta4.cms.warehouse.OperationTypeExpression"/> <attribute name="" type="boolean" specialize="Transfer.approved" readonly="true"/> <attribute name=" " type="date" readonly="true"/> <relation name="" kind="reference" to="" optional="false"/> <relation name="" kind="reference" to="Warehouse" specialize="Transfer.from"/> <relation name="" kind="reference" to="Warehouse" specialize="Transfer.to"/> </entity> <entity name="" parent=""> <attribute name="" type="boolean" specialize="."/> <relation name="" kind="reference" to="Warehouse" specialize="." optional="false"/> <relation name="" kind="reference" to="Warehouse" specialize="." optional="false"/> <relation name="" list="true" kind="embedding" to="" specialize="Transfer.entries"/> <relation pname="№ " name="" kind="reference" to="" oppositeTo="." readonly="true"/> <relation name="" kind="embedding" list="true"> <to> <entity name=""> <presentation> <l10n>=</l10n> </presentation> <attribute name="" type="integer" default="0"/> <attribute name="  " type="integer" default="7"/> <attribute name=" " type="integer" default="0"/> <attribute name="" type="integer" value="it. * it.__ + it._"/> <relation name="" kind="reference" to="" optional="false"/> </entity> </to> </relation> <presentation tableColumns=", _, , , , "> <l10n>=</l10n> <table> <row> <subordinate name=""/> <subordinate name=""/> </row> <row> <subordinate name=""/> <subordinate name="_"/> </row> <row> <subordinate name=""/> <subordinate name=""/> </row> </table> <single subordinate=""/> <single subordinate=""/> </presentation> </entity> <entity name="" parent=""> <attribute name="" type="boolean" specialize="."/> <attribute name="" type="string" optional="false"/> <relation name="" pname="№ " kind="reference" to="" oppositeTo="." readonly="true"/> <relation name="" list="true" kind="embedding" to="" specialize="Transfer.entries"/> <relation name="" kind="reference" to="Warehouse" specialize="." optional="false"/> <presentation tableColumns=", _, , , , "> <l10n>=</l10n> <table> <row> <subordinate name=""/> <subordinate name=""/> </row> <row> <subordinate name=""/> <subordinate name="_"/> </row> <row> <subordinate name=""/> <subordinate name=""/> </row> </table> <single subordinate=""/> </presentation> </entity> <entity name="" parent=""> <attribute name=" " type="date" optional="false" default="now"/> <attribute name=" " type="date"/> <attribute name="" type="string"/> <!--         --> <attribute name=" " type="float" value="sum(._)"/> <relation name="" kind="reference" to="" specialize="." optional="false"/> <relation name="" list="true" kind="embedding" specialize="Transfer.entries"> <to> <entity name="" parent=""> <relation name="" kind="reference" to="" specialize="Wares.clazz" optional="false"/> <attribute name="" type="float"/> <attribute name="" type="float" specialize="Wares.amount" optional="false" default="1"/> <attribute name=" " type="float" value="it. * it."/> </entity> </to> </relation> <presentation tableColumns=", _, , _, _, _"> <l10n> = = </l10n> <table> <row> <subordinate name="_"/> <subordinate name=""/> </row> <row> <subordinate name="_"/> <subordinate name="_"/> </row> <row> <subordinate name=""/> <subordinate name=""/> </row> <row> <subordinate name="_"/> </row> </table> <single subordinate=""/> </presentation> </entity> <entity name=""> <attribute name=" " type="datetime"/> <attribute name="" type="" optional="false" default=""/> <attribute name="__label" type="string" template="$_" specialize="__label"/> <attribute name=" " type="string" optional="false"/> <attribute name="" type="string"/> <attribute name="" type="string"/> <attribute name="" type="" optional="false" default=" "/> <attribute name=" " type="date" default="now"/> <relation name="" kind="reference" to="" optional="false"/> <relation name="" kind="reference" to=""/> <relation name="" kind="composition" to="" list="true"> <constructor name='  ' class="com.meta4.cms.warehouse.CreateTransfer" primary="true"> <attribute pname="  " name="auto_add" type="boolean" default="true"/> </constructor> </relation> <relation name="" kind="composition" to="" list="true"> <constructor name='  ' class="com.meta4.cms.warehouse.CreateRetirement" primary="true"> <attribute pname="  " name="auto_add" type="boolean" default="true"/> </constructor> </relation> <relation name="" kind="embedding" list="true"> <to> <entity name=""> <attribute name="" type="float" default="0" optional="false"/> <attribute name="" type="float" readonly="true" default="0"/> <attribute name="" type="float" readonly="true" default="0"/> <attribute name="" type="float" readonly="true" default="0"/> <relation name="" kind="reference" to="" optional="false"/> </entity> </to> </relation> <constructor name='  ' class="com.meta4.cms.warehouse.RequestConstructorLogic" primary="true"> <attribute name="" type="" list="true" optional="false" defaultExpression="user."/> <relation name="" kind="reference" to="" optional="false"/> </constructor> <presentation tableColumns="_, , _, , , "> <l10n> = = </l10n> </presentation> </entity> </projectDescription>
      
      







SaaSモヌドをサポヌトするシステムを䜜成したため、1台のサヌバヌが倚数の「プロゞェクト」を持぀こずができ、各プロゞェクトには独自の操䜜察象オブゞェクトクラスがありたす。 ぀たり、1぀のグルヌプのナヌザヌがCRMを持ち、2番目のグルヌプが圚庫を持ち、3番目のグルヌプも圚庫を持ちたすが、レストランビゞネスに特化しおおり、これらすべおを1぀のサヌバヌで実行できたす。



䜜業の結果、3぀の「アヌティファクト」を圢成したした。





もちろん、私たちはアむデアの完党な実珟にはほど遠いです。 たずえば、「环積レゞスタ」などの抂念は実装されおおらず、トリガヌによっお手動で゚ミュレヌトされたす。 それにもかかわらず、私たちは今幎、蚀語ずそれを実装するシステムのアヌキテクチャのビゞョンを圢成したした。



All Articles