ソフトウェア設計-インターフェース設計、コード最適化
序文
製品ビジネスの発展に伴い、製品やユーザーの数は増え続けています。各製品は一連のインターフェースに対応しているため、インターフェースの数は急速に増加しており、メンテナンスのコストも増加しています。コードの再利用とコードの堅牢性の観点から、優れたインターフェイス設計が特に必要です。また、複雑な製品から一連の共通インターフェイスを抽象化することも不可欠です。
設計開始時
まず、Big Talking Design Patternsの本を勉強しました。ケーブルのデザインパターンを統一した後、製品デザインの観点から分析しました。特にシンプルなファクトリーは使いやすいですが、具体的な実装内容はクラスcase when
で判断するので、ファクトリーメソッドで実装します。インスタンス化するクラスを決定しspring
、対応するオブジェクトをコンテナに直接取得します。この
設計で使用される設計モードには、ファクトリモード+コマンドモードがあります。
達成を開始
- インターフェイス基本クラスを定義します
ProductInterface
。このクラスには、基本的な実装として使用される、ほとんどの製品に必要なインターフェイスサービスが主に含まれています。 - 抽象クラスの
AbstractProductInterface
実装を定義します。抽象クラスProductInterface
では、SMS送信などの基本的なサービスを提供できます。 - デフォルトの実装
DefaultProduct
と拡張された実装を定義し、AppProduct
さまざまな製品コードとチャネルソースに従って、コンテナから対応する製品の実装を選択します - コマンドモードは、サービス呼び出しと実際のサービス実現インターフェースの分離を実現し、インターフェース
LoanCommand
と特定のサービス実現クラスを定義することによって実現されるデカップリングの目的を実現するために採用されていますAppCreditApplyCommand
。
拡張機能の実装
- 拡張インターフェースを定義します
ExtendProductInterface
。このクラスは主にインターフェース基本クラスを継承し、ProductInterface
拡張実装用の特別なインターフェースサービスを追加します。 - 抽象クラスの
AbstractExtendProductInterface
実装を定義します。抽象クラスExtendProductInterface
では、SMS送信などの基本的なサービスを提供できます。 - デフォルトの実装を定義し、
DefaultExtendProduct
さまざまな製品コードとチャネルソースに従って、コンテナから対応する製品実装を選択します - コマンドモードは、サービス呼び出しと実際のサービス実現インターフェースの分離を実現し、インターフェース
LoanCommand
と特定のサービス実現クラスを定義することによって実現されるデカップリングの目的を実現するために採用されていますExtendOpenPersonAccountCommand
。
デザイン思考
この設計により、新サービスを追加するという目的を達成し、機能を実現するために新製品を追加するだけで済みますが、今日の機能設計の急速な発展により、新製品やサービスが追加されるたびに新製品実装クラスを追加する慣行は依然として残っています。まだ合格する洗練、DefaultProduct
またはDefaultExtendProduct
、カップリングある程度の依存関係を作成するには、多くのがあるだろうxxxProduct.java
作成した、だけでなく、同じ機能の多くを提供し授信申请
、放款申请
最初の2または3から、製品の数の急速な成長に、ようにと十数、さらには二十以上に拡大する傾向があります。よく考えた結果、インターフェース設計を再度最適化することにしました。
機能的なインターフェース設計
名前の観点からは非常に背が高いですが、実際には背が高いものはありません。主な実装はJava8+
基本の実装に基づいています。機能プログラミングの実装はLambda
、式の深い理解と使用であり、関数の実装を読みやすくし、簡潔に、呼び出しと呼び出し先の間の結合を減らします
設計を開始
- 機能インターフェイスサービスクラスを定義します
FunctionProduct
。メインメソッドはProductInterface
、インターフェイスでのサービスのプロキシ実装です。これは、機能メソッド呼び出しを実装する特定の実装クラスです。委任モードを介して、サービス呼び出しを直接達成する目的が実現され、それによって緩い結合が実現されます。 - 特定のサービス実現、クレジットアプリケーション
AppCreditApplyFunction
、およびAppCreditLimitSelectFunction
特定のサービス実現クラスを定義します - サービスの拡大ローン事業の発展の観点からは、新しいインターフェースや新しいサービスの出現が不可欠ですが、ここではルーズカップリングを実装しているため、基本インターフェースに
ProductInterface
パブリックサービスのdoServicexxx
説明を追加して、さまざまな製品で使用できます。 、特定のdoServicexxx
サービスを動的に実装します。まったく新しいサービスのバッチである場合は、
たとえばExtendProductInterface
、さまざまな製品の対応するサービスでサービスインターフェイスを拡張することで実現できます。 - 注:機能的なルーズカップリングが実装されているため、製品部門と製品対応サービス名部門の統一された計画を実現することが特に重要です。計画方法:
产品名+product
製品パッケージの名前产品名+接口中对应的服务名+Command
特定のサービス実装クラスとして名前が付けられています- 特定のサービスの実装として
LoanCommand
インターフェイスexecute
メソッドを使用して、サービス呼び出しの将来の埋め込みと統合されたインターセプトを容易にします
- インターフェイスの目的は、特定の製品の特定のサービス実装をエコーすることです。これは、コードの読み取りと拡張に役立ち、問題の特定に便利です。
設計の最適化
上記の設計では、インターフェイスの抽象化から機能の機能集約への変換が実現されているため、beanName
ハードコードされた問題は、最終的なサービス実現の選択によって引き起こされます。コードをより読みやすく柔軟にするために、インターフェイスパラメータから対応するbeanName
関数を取得するように設計されています。具体的な実装のアイデアは何か、具体的な実装は何か。
おそらく次のようなものがあります。
実装のアイデア:
App 产品相关服务 BeanName 维护
维护方式: 交易码 + productCode + channelId = 对应产品对应的服务名
实现意义: 为了实现不同产品不同渠道来源对于不同服务的精确定位
当前产品 1000 -> App 01-> 内部
交易码描述,不同产品,交易码含义一样,可扩展交易码
例如: ln1001 -> appCreditApply (授信申请)
例如: ln1002 -> appCreditLimitSelect (额度查询)
実現する方法
- 1つ目:データベースに保存
- オプション1:データベースから直接読み取る
- 解決策2:データベースに保存
spring
され、コンテナの起動時にメモリにロードされます
- 2番目のタイプ:メモリに保存
- オプション1:
java
ファイルへのMap<key,value>
保存と同様 - 解決策2:ストア内
properties
の設定ファイルkey=value
- 解決策3:プロジェクト自体が統合されている
携程 Apollo
場合、オンラインのサービス動的ルーティングスイッチとサービス選択を実現できます
- オプション1:
beanName
取得する
属性ロードクラスを定義しBeanNameUtils
、コンテナの起動時に対応する場所から構成情報をロードし、特定のトランザクションが到着した後、要求パラメータ情報に従って
対応するものを動的に取得しますbeanName
。これにより、特定のサービス選択の機能を実現できます。
- 利点は次のとおりです。
- 1.メモリ内で直接操作する方が効率的です
- 2.構成ファイルに
beanName
冗長なコードがないこと、読みやすさ、統合されたメンテナンス、間違いを犯しにくいことを説明します - 3.製品が多すぎる場合は、製品の性質に応じて、強力なスケーラビリティで構成ファイルを分割、結合、追加、または削除できます。
コード
由于本文代码量比较大,请关注博主GitHub,获取完整代码