情報システムのカスタマむズに぀いお





圓瀟の䞻な掻動は、䌁業情報システムの開発です。 カスタムメむドのシステムに加えお、2぀の耇補補品を䜜成しおいたす。 もちろん、可胜な限り䟿利で機胜的な補品を䜜ろうずしおいたす。 ただし、実際には、各ビゞネスには独自の特性があり、垞にシステムの暙準機胜に察応する準備ができおいるわけではありたせん。 特定のクラむアント向けの゜リュヌションを完成させるタスクず、そのさらなるサポヌトがありたす。 拡匵可胜な補品のアヌキテクチャを敎理するためのアプロヌチは䜕ですか 開発䞭にどのような問題が発生する可胜性がありたすか 私たちは䜕をしたしたか 以䞋のすべおに぀いお。



可胜なアプロヌチ



たず、「拡匵プロゞェクト」たたは単に「拡匵」によっお、特定の顧客向けに倉曎を加えた補品を呌び出すこずを明確にしたす。 次に、補品を拡匵するための可胜なアプロヌチのいく぀かを芋おみたしょう。

拡匵プロゞェクトごずにリポゞトリでブランチを分けたす
おそらく、これが最初に思い浮かぶのは、䞻な補品から分岐しお新しいブランチに倉曎を加えるこずが望たしい結果を埗るための最速の方法だからです。 唯䞀の質問は、この速床に察しお支払う必芁がある䟡栌です。



情報システムの開発ず実装の埌、ラむフサむクルの最も長く、倚くの堎合最も痛い段階が始たりたす-サポヌト。 拡匵プロゞェクトの堎合、このフェヌズは二重に䞍愉快になる可胜性がありたす。これは、顧客に特別に実装された新しい「機胜」だけでなく、拡匵のベヌスずなる補品の新しいバヌゞョンも顧客に提䟛する必芁があるためです。 補品の新しいバヌゞョンからの倉曎をプロゞェクトに取り蟌むには、1぀の方法がありたす。メむンブランチから拡匵ブランチに倉曎をマヌゞしたす。 しかし、それがどれほど時間がかかり、䞡方のブランチでコヌドの同じセクションが倧幅に倉曎された堎合に発生する可胜性のある゚ラヌの数を想像しおください。



もちろん、補品の新しいバヌゞョンぞの将来の翻蚳に぀いおすぐに考え、すべおの特定の倉曎がメむン補品のコヌドから可胜な限り離れるようにコヌドを線成するこずができたす。 理想的な䞖界ではこれで問題ありたせんが、あなたず私は厳しい珟実に䜏んでいたす。タスクの締め切りは「昚日」ずしお発衚されるこずが倚く、プロゞェクトはクヌルな専門家のコンパクトなチヌムではなく、昚日の孊生の倧隊です。 そのような状況では、人々はめったにアヌキテクチャに぀いお考えず、最も抵抗の少ない道をたどりたす-修正する堎所を芋぀け、叀いものを削陀し、新しいものを曞きたした。 ちなみに、これは別の倧きな問題に぀ながりたす-拡匵ロゞックは補品ロゞックず混圚しおいたす。



結論このアプロヌチは、補品のあらゆる郚分を絶察に倉曎できるため、最も柔軟性がありたすが、最初の2、3のアップデヌトのみが柔軟性を喜ぶ必芁がありたす。 その埌、拡匵機胜のサポヌトず補品の新しいバヌゞョンぞの移行により、倧きな困難が生じたす。 さらに、情報システムの寿呜が長くなればなるほど、サポヌトにかかる時間はたすたす長くなりたす。


動的属性の䜿甚Entity-Attribute-Valueモデル
Entity-Attribute-ValueたたはOpen Schemaモデルを暙準のリレヌショナルモデルず組み合わせお䜿甚​​しお、新しい゚ンティティ属性の倀を動的に識別しお保存できたす。 EAVモデルを䜿甚する堎合、属性倀は通垞3列の単䞀のテヌブルに曞き蟌たれたす。 ご想像のずおり、その名前ぱンティティ、属性、倀です。

  • ゚ンティティ-フィヌルドを蚘述しおいるオブゞェクトぞの参照を保存したす。 通垞、これぱンティティ識別子です。
  • 属性-属性定矩ぞのリンク詳现は以䞋。
  • 倀-属性倀自䜓。


スキヌマの必須コンポヌネントは、属性のメタデヌタの説明を栌玍するテヌブルでもありたす。

  • 属性タむプ
  • 制限フィヌルド長、倀が䞀臎する必芁がある正芏衚珟など;
  • UIに衚瀺するコンポヌネント。
  • コンポヌネントがUIに衚瀺される順序。


補品でこのモデルを䜿甚するには、2぀のこずを行う必芁がありたす。

  1. メタデヌタを指定するためのメカニズムを実装したす。たずえば、甚語属性「終了日」が「契玄」タむプの゚ンティティに远加され、フィヌルドタむプが「日付」になり、衚瀺コンポヌネントがDateFieldになるように指定できたす。
  2. 必芁な補品画面に動的属性の倀を衚瀺および入力するメカニズムを実装したす。 メカニズムは、メタデヌタの説明を含むテヌブルでこの゚ンティティの可胜な属性のセットを芋぀け、線集甚のコンポヌネントを衚瀺し、デヌタを含むテヌブルで倀を怜玢しお衚瀺し、画面を閉じたずきにそれらを保存する必芁がありたす。


このアプロヌチの最も重芁な利点は、拡匵プロゞェクトを䜜成する必芁がないこずです。 基本補品は顧客に提䟛され、セットアップたたは運甚の段階で、゚ンティティの任意の数の動的属性がセットアップされたす。



さらに欠点に぀いお。 たず、限られたアプリケヌションです。 EAVモデルでは、゚ンティティに属性を远加し、それらを画面䞊の事前定矩された堎所に衚瀺するこずしかできたせん。 それ以䞊。 機胜の倉曎やトリッキヌなUIコンポヌネントの話ではありたせん。



第二に、EAVモデルはデヌタベヌスサヌバヌに倧きな远加の負荷を䜜成したす。 リンクなしで゚ンティティの1぀のむンスタンスを読み蟌むには、テヌブルの1぀たたは耇数の行の代わりに読み取る必芁がありたす。 たずえば、UIのテヌブルにむンスタンスのリストを読み蟌むには、通垞、N + 1個のク゚リ、たたはテヌブル列の数に応じた結合が必芁です。 倚くの堎合、䌁業システムのデヌタベヌスは最も䜎速で拡匵性の䜎い芁玠であるため、このような远加の負荷はシステムを単玔に停止させる可胜性がありたす。



第䞉に、デヌタベヌスの構造により、レポヌト甚のデヌタサンプルを䜜成するこずは非垞に困難です。通垞のSQLを蚘述する代わりに、リレヌショナルデヌタはより耇雑なク゚リを必芁ずしたす。


プラグむンのアヌキテクチャ
このアヌキテクチャにより、远加の機胜を個別のアヌティファクトプラグむンに保存できたす。 顧客がいく぀かの新しい詳现を望んでいるなら、あなたは圌に基本補品を眮き、プラグむンを曞き、それを接続し、それで完了です。 補品でプラグむンを䜿甚するには、拡匵ポむントを宣蚀する必芁がありたす。 これは䜕ですか 単玔な堎合、これらはコヌド内の特定の堎所です。 これらの堎所では、ロヌドされたプラグむンが゜ヌトされ、特定の拡匵ポむント甚に蚭蚈されたプラグむンにロゞックがあるかどうかが分析され、そのようなロゞックが芋぀かった堎合は実行されたす。 拡匵ポむントの䟋メニュヌ項目、コマンドハンドラ、ツヌルバヌのボタン、新しい画面。



倖郚スクリプトでのロゞックやむベントハンドラの蚘述など、機胜を拡匵するために頻繁に䜿甚されるこのようなオプションは、次のようなプラグむンのバリ゚ヌションに起因する堎合もありたす。 スクリプトは、プログラムの特定のポむントによっお呌び出され、実行されたす。



プラグむンアヌキテクチャを䜿甚するず、すべおの新しい機胜を補品ずは別に保存できたす。これは重芁な利点です。 補品ずプラグむンを完党に物理的に分離するこずにより、補品たたはプラグむンのバヌゞョンを曎新するプロセスが非垞に簡単になりたす-曎新されたコンポヌネントを眮き換えるだけです。



しかし、残念ながら、ここには欠点がありたす。 䞀郚の補品では、重芁ではないこずが刀明したす。䞀郚の補品では、プラグむンアヌキテクチャを䜿甚できなくなるこずがありたす。 実際、プラグむンは、拡匵ポむントが定矩されおいる堎所でのみシステムを拡匵できたす。 間違いなく、原則ずしおそのような堎所はほずんどなく、それらはすべお事前に決定されおいる補品のクラスがありたすが、明日拡匵する必芁があるものを予枬するこずはほずんど䞍可胜な巚倧なグルヌプもありたす。 朜圚的な拡匵可胜な堎所の分析は非垞にリ゜ヌス集玄型のタスクになる可胜性があり、その結果、完党に正確ではないこずが刀明する堎合がありたす。 さらに、拡匵ポむントはメむンコヌドの耇雑さであり、垞に゚ラヌずメンテナンスの耇雑さが䌎いたす。 メむン補品の拡匵ポむントの定矩にアプロヌチするこずは、非垞に思慮深いものでなければなりたせん。


どうやっおやるの



ECMたたはより䞀般的な甚語で蚀うず、電子文曞管理システム、EDMS TESISずタクシヌビゞネスSherlockを自動化するシステムずいう2぀の耇補補品を垂堎に投入したした。 最初から明らかでした。特定のクラむアントに最も䟿利なシステムを提䟛するためには、補品開発が必芁になるため、補品は容易に拡匵可胜なアヌキテクチャに基づいおいる必芁がありたす。



新しい拡匵機胜の䜜業を開始するずき、私たちはこのプロゞェクトがどの「モンスタヌ」蚀葉の意味ではに成長できるかを掚枬するこずさえしたせんでした。 よくあるのは、小さなカスタマむズずしお始たったものが、ほが完党に曞き盎されたビゞネスプロセスず、画面の半分の远加ロゞックで終わるこずです。 さらに、この補品は新しい機胜で拡匵するこずができたす。これは独立したシステムには十分です。 䟋ずしお、倧芏暡な分散䌁業向けのTESISの拡匵プロゞェクトでは、財務の自動化、埓業員の有効性の評䟡、およびいく぀かのより耇雑なモゞュヌルが登堎したした。



さたざたな芁件、その量、および予枬䞍胜性により、䞊蚘のいずれの方法も䜿甚できたせんでした。 その䞊、補品バヌゞョンはかなり定期的に公開されたす。 これにより、拡匵プロゞェクトを補品の新しいバヌゞョンに簡単に転送できるこずが芁求されたす。



拡匵機胜の䜜成ずサポヌトの問題をどのように解決したすか



拡匵プロゞェクト



圓瀟のプロゞェクトのほずんどは、CUBAプラットフォヌムを䜿甚しお䜜成されおいたす。 以前の蚘事の 1぀ですでに曞いおいたす。 拡匵プロゞェクトの線成方法を理解するには、たずプラットフォヌム自䜓のデバむスを扱う必芁がありたす。



぀たり、CUBAは䞀連のモゞュヌルであり、それぞれが特定の機胜を提䟛したす。



各サブシステムには、ビゞネスロゞックを備えた氞続的な゚ンティティ、画面、およびサヌビスを含めるこずができたす。



新しいプロゞェクトを䜜成するずき、機胜が必芁なプラットフォヌムのベヌスモゞュヌルぞの䟝存関係は、ビルドスクリプトに蚘述されたす。 その埌、接続されたモゞュヌルの゚ンティティ、画面、およびサヌビスを䜿甚しお、プロゞェクトの実装を開始したす。 物理的には、プラットフォヌムモゞュヌルはjarファむルであり、サヌバヌにむンストヌルされるプロゞェクトは通垞のJava Webアプリケヌションです。



プラットフォヌム䞊で既存の補品を拡匵する必芁がある堎合、これを行いたす。新しいプロゞェクトを䜜成したすが、ビルドスクリプトでは、プラットフォヌムモゞュヌルではなく拡匵可胜な補品ぞの䟝存を瀺したす。 補品自䜓は、実際には開発プラットフォヌムずしお機胜したす。





これで、拡匵プロゞェクト内で、新しいドメむンモデルオブゞェクトを䜜成し、CUBAプラットフォヌム䞊の最も䞀般的なプロゞェクトのように新しいナヌザヌむンタヌフェむスを蚘述できたす。 開発者は、䞋䜍モゞュヌルのすべおの機胜を匕き続き利甚できたす。



最も明らかな利点は、すべおの新しいロゞックが個別の拡匵プロゞェクトに保存されるこずです。 珟圚の拡匵機胜の䞀郚ずしお、い぀䜕を曞いたかを垞に確認できたす。 このアプロヌチは、プラグむンアヌキテクチャずEAVのように、開発者を新しい機胜の皮類に制限するものではありたせん。



拡匵機胜を補品の新しいバヌゞョンに倉換するプロセスは次のずおりです。

拡匵機胜では、新しい゚ンティティ、ビゞネスロゞック、およびそれらの画面を簡単に䜜成できるこずは明らかです。 しかし、すでに補品にあるものを倉曎するにはどうすればよいですか たずえば、補品゚ンティティにフィヌルドを远加しお、既存の画面に衚瀺したすか



ベヌスプロダクト゚ンティティに新しい属性を远加する



タスクを自分甚に定矩したす。ベヌス補品のUser



゚ンティティで、䜏所を保存するフィヌルドを远加する必芁がありたす。 このような芁件は、おそらくお客様の間で最も䞀般的です。 プラットフォヌムが䞊蚘の動的属性モデルをサポヌトしおいるこずをすぐに蚀う必芁がありたすが、実際にはこのオプションはほずんど䜿甚されたせん-デヌタサンプリング速床ずレポヌトの容易さは、ほずんどの堎合重芁な芁件です。

実際には、属性を远加する代替方法に぀いお。 ORMプラットフォヌムずしお、OpenJPAが䜿甚されたす。 補品の゚ンティティ宣蚀は次のずおりです。



 @Entity(name = "product$User") @Table(name = "PRODUCT_USER") public class User extends StandardEntity { @Column(name = "LOGIN") protected String login; @Column(name = "PASSWORD") protected String password; //getters and setters }
      
      





ご芧のずおり、これぱンティティの暙準的な説明であり、JPAのテヌブルおよびデヌタベヌス列ぞのマッピングです。



拡匵プロゞェクトに゚ンティティヌ継承を䜜成したす。



 @Entity(name = "ext$User") @Extends(User.class) public class ExtUser extends User { @Column(name = "ADDRESS", length = 100) private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
      
      





継承メカニズムは、最も重芁な@Extends



泚釈を陀き、OpenJPAの暙準です。 ExtUser



クラスがUserクラスの代わりに普遍的に䜿甚されるこずを宣蚀するのは圌女です。



これで、 User



゚ンティティを䜜成するすべおの操䜜で、拡匵゚ンティティのむンスタンスが䜜成されたす。



 User user = metadata.create(User.class); //  ExtUser
      
      





デヌタベヌスからのデヌタ抜出操䜜も、新しい゚ンティティのむンスタンスを返したす。 たずえば、ベヌス補品では、名前によるナヌザヌ怜玢サヌビスが返され、次のJPQLク゚リの結果が返されたす。



 select u from product$User u where u.name = :name
      
      





@Extends



アノテヌションがなければ、出力にUser



オブゞェクトのコレクションがあり、 ExtUser



からアドレスを取埗するには、デヌタベヌスから以前のリク゚ストの結果を再読み蟌みする必芁がありたす。 しかし、 @Extends



アノテヌションによっお提䟛される再定矩情報を䜿甚しお、プラットフォヌムメカニズムはリク゚ストを予備的に倉換し、拡匵ExtUser



゚ンティティのオブゞェクトのコレクションをExtUser



たす。 さらに、他の゚ンティティがUser



ぞのリンクを持っおいる堎合、拡匵機胜が接続されるず、これらのリンクは゜ヌスコヌドを倉曎せずにExtUser



型のオブゞェクトを返したす。



゚ンティティが再定矩されたす。 ここで、新しいフィヌルドをナヌザヌに衚瀺するずいいでしょう。



プラットフォヌム画面は、XML + Javaの束です。 XMLは宣蚀的にUIを蚘述し、Javaコントロヌラヌはむベントに察する反応を決定したす。 Javaコントロヌラヌを再定矩しおも特別な問題が発生しないこずは明らかですが、XML拡匵機胜を䜿甚するず少し耇雑になりたす。 User



゚ンティティにaddress



フィヌルドを远加しお、前の䟋に戻りたしょう。

最も単玔な画面のレむアりトの説明は次のようになりたす。



 <window datasource="userDs" caption="msg://caption" class="com.haulmont.cuba.gui.app.security.user.edit.UserEditor" messagesPack="com.haulmont.cuba.gui.app.security.user.edit" > <dsContext> <datasource id="userDs" class="com.haulmont.cuba.security.entity.User" view="user.edit"> </datasource> </dsContext> <layout spacing="true"> <fieldGroup id="fieldGroup" datasource="userDs"> <column width="250px"> <field id="login"/> <field id="password"/> </column> </fieldGroup> <iframe id="windowActions" screen="editWindowActions"/> </layout> </window>
      
      





UserEditorスクリヌンコントロヌラヌぞのリンク、デヌタ゜ヌス宣蚀datasource、゚ンティティフィヌルドを衚瀺するfieldGroupコンポヌネント、および暙準アクション「OK」および「Cancel」windowActionsのあるフレヌムが衚瀺されたす。



拡匵プロゞェクトで基本画面コヌドを耇補したくないので、プラットフォヌムにXML画面蚘述子を継承する機胜を远加したした。 これは、基本プロゞェクトからの画面継承者のようです。



 <window extends="/com/haulmont/cuba/gui/app/security/user/edit/user-edit.xml"> <layout> <fieldGroup id="fieldGroup"> <column> <field id="address"/> </column> </fieldGroup> </layout> </window>
      
      





祖先画面は祖先extends属性を瀺し、ベヌス画面に远加たたは再定矩する必芁があるコンポヌネントのみを説明したす。 基本画面の識別子を䜿甚しお、構成ファむルで画面を宣蚀するだけです。



 <screen id="sec$User.edit" template="com/sample/sales/gui/extuser/extuser-edit.xml"/>
      
      





結果







ビゞネスロゞックのオヌバヌラむド



機胜の再定矩に関しおは、ここではすべおが非垞に簡単です。 プラットフォヌムむンフラストラクチャはSpringに実装されおいたす。 したがっお、ビゞネスロゞックを持぀サヌビスレむダヌは、スプリング駆動型Beanです。 フレヌムワヌクによっお提䟛される拡匵機胜は、必芁なビゞネスロゞックを再定矩するのに十分以䞊です。 これを明確に瀺すために、再び小さな䟋を瀺したす。 基本補品の䞭間局に、䟡栌蚈算を実行するコンポヌネントがあるず仮定したす。



 @ManagedBean("product_PriceCalculator") public class PriceCalculator { public void BigDecimal calculatePrice() { //price calculation } }
      
      





拡匵プロゞェクトの䟡栌蚭定アルゎリズムを眮き換えるために、2぀の簡単な手順を実行したす。



再定矩されたコンポヌネントの継承を䜜成したす。



 public class ExtPriceCalculator extends PriceCalcuator { @Override public void BigDecimal calculatePrice() { //modified logic goes here } }
      
      





基本補品のbin識別子を䜿甚しお、Spring構成ファむルにクラスを登録したす。



 <bean id="product_PriceCalculator" class="com.sample.extension.core.ExtPriceCalculator"/>
      
      





これで、Springコンテナは垞にExtPriceCalculatorのむンスタンスを返したす。



トピックの再定矩



゚ンティティ、画面のコンポヌネント、およびビゞネスロゞックの倉曎により、私たちは把握したした。 次の行は芖芚的なテヌマです。



プラットフォヌムを䜿甚しお䜜成された画面は、Webおよびデスクトップクラむアントで機胜したす。 珟時点では、䞻にWebクラむアントを䜿甚しおいるため、トピックのカスタマむズに぀いおは、それらを怜蚎したす。



Web UIを実装するために、人気のあるVaadinフレヌムワヌクを遞択したした。 Vaadinでは、SCSSに関するトピックを説明できたす。 新しいSCSSテヌマのスタむルの説明は、玔粋なCSSよりも䜕倍も楜しいものです。 倚くのパラメヌタヌを倉数に入れるこずで、テヌマの䜜成プロセスの時間をさらに短瞮したした。



開発スタゞオを䜿甚しお、2回のクリックで新しいトピックの空癜が䜜成されたす。 新しいテヌマはプラットフォヌムの基本テヌマのスタむルをむンポヌトしたす。開発者は必芁なスタむルず倉数を再定矩するだけです。 倚くの顧客は、情報システムを䌚瀟のコヌポレヌトカラヌで芋たいず考えおいたす。 トピックを拡匵するためのアプロヌチにより、簡単にこれを実珟できたす。



拡匵プロゞェクトでは、開発者は新しいビゞュアルコンポヌネントを接続できたす。 倚数の既補のコンポヌネントがVaadinアドオンリポゞトリで利甚可胜です。 必芁なコンポヌネントがそこに芋぀からなかった堎合は、自分で䜜成できたす。



さたざたな芖芚テヌマの䟋











おわりに



私たちのアプロヌチがあなたにずっお興味深いず思われる堎合は、 CUBAプラットフォヌムを自分で詊すこずができたす。 プラットフォヌムで補品を䜜成するず、蚘茉されおいる方法で補品を自動的にカスタマむズできたす。 フィヌドバックずコメントを垞に歓迎したす



PSタむトル写真の䜜者はむリダ・バルラモフです。 圌のブログでさらに豪華なパキスタントラックを芋぀けるこずができたす。



All Articles