<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ryu Xin</title>
    <description>The latest articles on DEV Community by Ryu Xin (@yuzhenxin).</description>
    <link>https://dev.to/yuzhenxin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F936399%2F40bb76f5-e8d9-4f12-935b-029200c99e56.jpeg</url>
      <title>DEV Community: Ryu Xin</title>
      <link>https://dev.to/yuzhenxin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yuzhenxin"/>
    <language>en</language>
    <item>
      <title>Clean Architecture Practice Based on Lattice Framework</title>
      <dc:creator>Ryu Xin</dc:creator>
      <pubDate>Mon, 14 Nov 2022 09:00:16 +0000</pubDate>
      <link>https://dev.to/yuzhenxin/clean-architecture-practice-based-on-lattice-framework-33hj</link>
      <guid>https://dev.to/yuzhenxin/clean-architecture-practice-based-on-lattice-framework-33hj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Lattice is a powerful, lightweight business extension invoke framework. By using the Lattice framework, complex business customization can be efficiently organized and managed. &lt;a href="https://dev.to/yuzhenxin/lattice-framework-introduction-28h0"&gt;https://dev.to/yuzhenxin/lattice-framework-introduction-28h0&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Clean Architecture, which is an architecture proposed by the famous software master Uncle Bob, is also the current development architecture of various languages. A clean architecture proposes a one-way dependency that logically forms an upward abstract system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yClyRDFW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/09/22fig01.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yClyRDFW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/09/22fig01.jpg" alt="" width="393" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The concentric circles represent different levels in the software system, and usually the closer to the center, the higher the software level. Basically, the outer circle represents the mechanics and the inner circle represents the strategy. Of course, there is a rule that runs through the entire architecture design, that is, its dependency rule: the dependencies in the source code must only point to the inner layer of the concentric circle, that is, the low-level mechanism points to the high-level strategy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entities: Through domain analysis and modeling, we can encapsulate domain entities and related business logic for life cycle management of these domain entities in this layer. For the analysis and identification process of domain entity objects, please refer to my other article "&lt;a href="https://www.ryu.xin/2018/04/08/domain/"&gt;Design Combat – Scene Analysis &amp;amp; Domain Division&lt;/a&gt;"&lt;/li&gt;
&lt;li&gt;Use Cases: In the use case layer, logic related to "specific scenarios" is generally placed, and these logics will aggregate information about entities defined in the entity layer. For example, let's take the scenario of "buyer places an order" in the e-commerce system as an example. In this scenario, the entities involved in placing an order include product objects, packages, coupons, buyer information, seller information, and service information (such as delivery service), etc. The order processing logic needs to process the information and aggregate it into order information for the user to confirm or create. The logic that orchestrates these entities according to a specific scenario, which does not belong to any one entity's domain.&lt;/li&gt;
&lt;li&gt;Interface adapter: Expose the information of the use case layer to the outside in some form. For example, in the scenario where a buyer places an order, we can expose the interface in the form of Restful for integration with the web front end.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recommendations for Hierarchical and Logical Build Partitions
&lt;/h2&gt;

&lt;p&gt;When building a complex business system, we need to consider the API and SPI design for entity access, and also consider the accumulation of reusable business assets in the scene. If reusable business assets can be reused across projects and customers, it is necessary to reserve scalability points SPI. For scene-level opening, please refer to &lt;a href="https://github.com/hiforce/lattice/wiki/UseCase-Precipitation-and-Reuse"&gt;UseCase Precipitation and Reuse&lt;/a&gt;. After the author's practice in many large-scale projects in the field of telecommunications, e-commerce, and smart cities, and referring to some suggestions for clean architecture, I have summarized a set of logical engineering division methods with reasonable layers and very suitable for team collaboration. The general engineering structure and logic modules are divided as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DjIOSC5D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/11/lattice-project-structure-sample.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DjIOSC5D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/11/lattice-project-structure-sample.png" alt="" width="880" height="1175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business entity layer: The interface definitions of entity services are exposed externally through domain-sdk, and in the process of entity processing, there will be some special customization requirements, which are also exposed in the form of SPI. The manifestation of SPI is exposed in the form of extension points, and the specific implementation is obtained through dynamic loading during runtime, so as to realize the expansion of the processing logic of business entities.&lt;/li&gt;
&lt;li&gt;Use case layer: In the use case layer, it is mainly composed of definitions of various scenarios and reusable business assets. During the execution of the scenario, these business assets can be installed to meet business needs. At the same time, in the process of cross-project and cross-industry reuse of these business assets, some extensibility points can also be reserved and exposed in the form of SPI. This achieves the separation of project-level customization and platform logic.&lt;/li&gt;
&lt;li&gt;Interface adapters (Endpoints): mainly exist in the form of various external interfaces such as various webs and interfaces, and are used to adapt to the access needs of related devices/systems in the outer layer.&lt;/li&gt;
&lt;li&gt;Business Plugins: Business plugins mainly implement the SPI of business assets, and realize the customization and enhancement of personalized business logic in different projects and different industries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  E-commerce trading system as an example
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Project samples can be obtained by visiting &lt;a href="https://github.com/hiforce/lattice-clean-arch-practice-sample"&gt;https://github.com/hiforce/lattice-clean-arch-practice-sample&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P0pWD8L2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/11/Jietu20221105-162747.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P0pWD8L2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/11/Jietu20221105-162747.png" alt="" width="784" height="1476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Module&lt;/th&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Entity&lt;/td&gt;
&lt;td&gt;domain-item&lt;/td&gt;
&lt;td&gt;domain-item-sdk&lt;/td&gt;
&lt;td&gt;The item domain SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;domain-item-common&lt;/td&gt;
&lt;td&gt;The item domain common model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;domain-item-service&lt;/td&gt;
&lt;td&gt;Item domain logic implemetation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;domain-trade&lt;/td&gt;
&lt;td&gt;domain-trade-sdk&lt;/td&gt;
&lt;td&gt;The trade domain SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;domain-trade-common&lt;/td&gt;
&lt;td&gt;The trade domain common model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;domain-trade-service&lt;/td&gt;
&lt;td&gt;Trade domain logic implemetation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use Case&lt;/td&gt;
&lt;td&gt;place-order-scenario&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Buyer place order scenario&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;place-order-client&lt;/td&gt;
&lt;td&gt;The client of buyer place order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;place-order-server&lt;/td&gt;
&lt;td&gt;The implemetation of buyer place order scenario&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;usecase-assets&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Reusable business assets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;presale-usecase-capability&lt;/td&gt;
&lt;td&gt;presale-usecase-sdk&lt;/td&gt;
&lt;td&gt;PreSale capability's SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;presale-usecase-capability&lt;/td&gt;
&lt;td&gt;presale-usecase-server&lt;/td&gt;
&lt;td&gt;Implemetation of pre-sale capability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adaptors&lt;/td&gt;
&lt;td&gt;sample-endpoints&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;buynow-web&lt;/td&gt;
&lt;td&gt;The web controller for buy now&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;business customization&lt;/td&gt;
&lt;td&gt;sample-business-apps&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sample-business-a&lt;/td&gt;
&lt;td&gt;Sample Busines A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In this project, we run org.hiforce.sample.buynow.web.starter.BuyNowWebStarter, then open the browser and enter &lt;a href="http://localhost:8080/buy/1"&gt;http://localhost:8080/buy/1&lt;/a&gt; , you can see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"orders"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"buyerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"rocky"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"orderLines"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="nl"&gt;"orderLineId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"itemId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2919311334001001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"buyQuantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"unitPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;}]}]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Continue to enter &lt;a href="http://localhost:8080/buy/2"&gt;http://localhost:8080/buy/2&lt;/a&gt; to further observe the changes in the output, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"orders"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"buyerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"rocky"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"orderLines"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="nl"&gt;"orderLineId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"itemId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2919311334001001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"buyQuantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"unitPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;}]}]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two results are mainly different in the unit price of the product, because the business customization package realizes the expansion point of the payment ratio of the pre-sale. In different scenarios, pre-sale assets will take effect, resulting in different unit prices. Interested students can debug by themselves for further observation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suggestions for the organization of extension points
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The definition of extension points in the entity layer
&lt;/h3&gt;

&lt;p&gt;In the entity layer, generally we will make a domain extension point facade, under which the extension point facade will be defined hierarchically according to the entity. For example, in the transaction domain, there are entities such as Order and OrderLine, then the transaction domain can be extended to the outside world, and we define it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;TradeEntityExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IBusinessExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;TradeOrderExt&lt;/span&gt; &lt;span class="nf"&gt;getTradeOrderExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;TradeOrderLineExt&lt;/span&gt; &lt;span class="nf"&gt;getTradeOrderLineExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;TradePageExt&lt;/span&gt; &lt;span class="nf"&gt;getTradePageExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The advantage of this definition is that developers and third-party ISVs can easily find their corresponding extension points by entity by browsing the extensible facade in the field. Let's continue to take the entity OrderLine as an example. The extension points provided by this entity are further classified according to the "behavior" of the entity, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;TradeOrderLineExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IBusinessExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @return The extension of Order Line entity in init behavior.
     */&lt;/span&gt;
    &lt;span class="nc"&gt;TradeOrderLineInitExt&lt;/span&gt; &lt;span class="nf"&gt;getTradeOrderLineInitExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @return The extension of Order Line entity in check behavior.
     */&lt;/span&gt;
    &lt;span class="nc"&gt;TradeOrderLineCheckExt&lt;/span&gt; &lt;span class="nf"&gt;getTradeOrderLineCheckExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @return The extension of Order Line entity in saving behavior.
     */&lt;/span&gt;
    &lt;span class="nc"&gt;TradeOrderLineSaveExt&lt;/span&gt; &lt;span class="nf"&gt;getTradeOrderLineSaveExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we want to extend an entity, a natural idea is to consider what behaviors need to be extended to the entity. For example, is the entity to be custom processed before saving, or to be supplemented with additional information after saving? and many more. Under the specific entity behavior extension point facade, is the specific extension point definition, such as the above OrderLine entity, we define the following extension points in its "save" behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;TradeOrderLineSaveExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IBusinessExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Extension&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reduceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReduceType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NONE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getCustomOrderLineAttributes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SaveOrderLineExtInput&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@Extension&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reduceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReduceType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NONE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Void&lt;/span&gt; &lt;span class="nf"&gt;processOrderLineBeforeSaving&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SaveOrderLineExtInput&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@Extension&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reduceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReduceType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NONE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Void&lt;/span&gt; &lt;span class="nf"&gt;finalProcessOrderLineAfterSaving&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SaveOrderLineExtInput&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The definition of extension points in the use case layer
&lt;/h3&gt;

&lt;p&gt;Different from the business entity layer, the scenarios defined in the business use case layer often span business activities and are organized and managed in the form of business processes. Therefore, at the business use case layer, I suggest that the extension point facade is aggregated according to the business activities defined in the scenario. When we discuss requirements, we often discuss how to implement them in terms of business activities. For example, we need to be able to customize an order prompt component when "buyer places an order"; we need to be able to define the latest delivery time when "seller ships", and so on. Therefore, organizing the extension points of the use case layer according to "business activities" will be more conducive to later maintenance and knowledge dissemination.&lt;/p&gt;

&lt;p&gt;Let's take pre-sale trading business assets as an example. The extension point facade it provides is PreSaleTradeExt, which is defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PreSaleTradeExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IBusinessExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @return The extensions of PreSale trade in buyer place order.
     */&lt;/span&gt;
    &lt;span class="nc"&gt;PreSalePlaceOrderExt&lt;/span&gt; &lt;span class="nf"&gt;getPreSalePlaceOrderExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @return The extensions of PreSale trade in fulfillment.
     */&lt;/span&gt;
    &lt;span class="nc"&gt;PreSaleFulfillmentExt&lt;/span&gt; &lt;span class="nf"&gt;getPreSaleFulfillmentExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @return The extensions of PreSale trade in refund.
     */&lt;/span&gt;
    &lt;span class="nc"&gt;PreSaleRefundExt&lt;/span&gt; &lt;span class="nf"&gt;getPreSaleRefundExt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have aggregated them according to several business activities such as seller ordering, seller performance, and buyer refund. We further take the buyer's order as an example, and we can see that the pre-sale transaction business asset defines the following extension points in this business activity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PreSalePlaceOrderExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IBusinessExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Extension&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Custom PreSale Down Payment Ratio"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reduceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FIRST&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="nf"&gt;getCustomDownPaymentRatio&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PreSaleOrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the pre-sale scenario, business developers and third-party ISVs can easily find this extension point according to business activities from the pre-sale transaction SDK facade, and realize business customization. I take a certain business A as an example, and its customized implementation is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Realization&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SampleBusinessA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CODE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BusinessAPreSaleExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BlankPreSaleTradeExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;BlankPreSalePlaceOrderExt&lt;/span&gt; &lt;span class="nf"&gt;getPreSalePlaceOrderExt&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BlankPreSalePlaceOrderExt&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="nf"&gt;getCustomDownPaymentRatio&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PreSaleOrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;};&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The clean structure is a structure that the author has experienced in various large-scale engineering projects, and has indeed gained a lot of insight and experience in actual combat. Based on the Lattice framework, it can manage business extension points well and accumulate business assets. I hope this article can be helpful to programmers and architects.&lt;/p&gt;




&lt;p&gt;中文版：&lt;a href="https://www.ryu.xin/2022/11/05/lattice-clean-arch-practice/"&gt;https://www.ryu.xin/2022/11/05/lattice-clean-arch-practice/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Concept Business in Lattice</title>
      <dc:creator>Ryu Xin</dc:creator>
      <pubDate>Tue, 18 Oct 2022 04:56:19 +0000</pubDate>
      <link>https://dev.to/yuzhenxin/concept-business-in-lattice-368n</link>
      <guid>https://dev.to/yuzhenxin/concept-business-in-lattice-368n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://dev.to/yuzhenxin/lattice-framework-introduction-28h0"&gt;Lattice&lt;/a&gt; is a powerful, lightweight business extension invoke framework. By using the Lattice framework, complex business customization can be efficiently organized and managed. refer: &lt;a href="https://dev.to/yuzhenxin/lattice-framework-introduction-28h0"&gt;https://dev.to/yuzhenxin/lattice-framework-introduction-28h0&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  What is business?
&lt;/h1&gt;

&lt;p&gt;Regarding what "business" is, I believe everyone will have their own views, and some people may even think that what they do is business. Wikipedia defines business as follows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A business, also known as an enterprise, or a firm, is an entity involved in the provision of goods and/or services to consumers.Businesses are prevalent in capitalist economies, where most of them are privately owned and provide goods and services to customers in exchange for other goods, services, or money.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In short: "Business" is the business activity of "selling a product/service for a profit".&lt;/p&gt;

&lt;p&gt;Since the ultimate goal of "business" is to "sell a product/service for profit". Then an enterprise's business operation activities will actually be carried out around this core theme. The difference between an idealistic and a short-sighted company is to obtain profits from sustainable development in the future industrial chain, or to obtain profits that are a little bit of profit now. Focusing on business operations, companies generally make business planning, organizational structure design, and business operations around two dimensions: how to increase profits and how to reduce costs.&lt;/p&gt;

&lt;p&gt;Here are some examples of business units:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hema Business: Innovating and trying e-commerce business models, moving offline to online, combining with supermarkets to seize the market, achieving break even through economies of scale, and opening up the entire chain of fresh food supply chain, quality assurance, and timely delivery. , and establish a standard system and access threshold to achieve long-term sustainable development. is a typical business operation&lt;/li&gt;
&lt;li&gt;Electronic vouchers Business: Through the innovation of delivery methods, the performance of contracts has been enhanced from physical delivery to fulfillment of contracts with "codes" through electronic vouchers, which can be more suitable for similar movie tickets, tickets, offline store pickup, service performance, etc. Wait. To a certain extent, it expands the applicable market scope of e-commerce transactions, improves the efficiency of transaction performance, promotes the achievement of business, and actually increases profits. In theory, if any item is supposed to be able to provide offline voucher pickup, then all businesses can use electronic vouchers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a company is designing its organizational structure, it generally designs two types of business units: profit centers and cost centers. The former is more (note: not only) to consider how to obtain profits through business model innovation, market preemption, and industrial chain construction; while the cost center is more to consider how to reduce costs and improve efficiency. Increase profits with the same market size.&lt;/p&gt;

&lt;h1&gt;
  
  
  Business Dimension Definition
&lt;/h1&gt;

&lt;p&gt;Because of the different types of business departments, the specific business forms have different dimensions. My personal point of view is to divide the business into two dimensions: vertical and horizontal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vertical Business
&lt;/h2&gt;

&lt;p&gt;Regarding vertical business, it can also be another word, called industry. As the saying goes, every line is like a mountain.&lt;br&gt;
Business rules and business assessments are often different or even contradictory between industries, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto finance business: no discount, no payment overtime for orders, but there are pre-authorization confirmation overtime requirements, no logistics, and its own special financial qualification verification mechanism, etc.&lt;/li&gt;
&lt;li&gt;General Taobao business: there is logistics and delivery, and the general delivery time is about 7 days; there are various marketing activities; the payment overtime is generally 1 day; it supports cash on delivery and freight insurance, etc.&lt;/li&gt;
&lt;li&gt;Hema business: there is no logistics, it is an offline delivery method; there are specific promotions; there is a payment overtime requirement after placing an order; in the delivery performance, there are higher real-time SLA requirements for delivery;&lt;/li&gt;
&lt;li&gt;......&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Business rules vary widely across industries. From the perspective of vertical business, it is inconceivable for the auto finance business to reuse the specific business rules of Ele.me.&lt;/p&gt;

&lt;p&gt;Even if the requirements of the two industries are the same in terms of a certain business rule, such as offline delivery time, then the more appropriate approach must be: business A configures a payment timeout rule of 10 minutes in its own business space; Business B also configures a business rule with a payment timeout of 10 minutes in its own business space. Rather than reuse the same rules for the two business of A and B. Because, if business rules are reused, business A changes the timeout configuration one day, which will definitely affect business B. This is not what business B wants to see.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Therefore, the business rules between vertical businesses are isolated from each other.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Horizontal Business
&lt;/h2&gt;

&lt;p&gt;Regarding horizontal business, the characteristic of horizontal business is that all vertical businesses can be used and superimposed. Therefore, I can also change the word for "horizontal business" and call it "platform business". Typical representatives of horizontal business are: electronic vouchers, group purchases, shopping guides, distribution.&lt;/p&gt;

&lt;p&gt;A horizontal business (platform business) will also have its own business rule. When a business is using a certain platform, some business rules will be rewritten:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Electronic vouchers: If the business wants to use electronic vouchers, when placing an order, the user needs to reserve a mobile phone number for voucher issuance and verification; electronic voucher products cannot enjoy freight insurance because no logistics is required;&lt;/li&gt;
&lt;li&gt;Group buying platform: If a business wants to be listed on our group buying platform, the price of commodities must be discounted and cannot be sold at the original price; the payment timeout must be set within 30 minutes;&lt;/li&gt;
&lt;li&gt;......&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can be seen that the horizontal business will change some existing business rules of the vertical business. Moreover, in contrast to the feature that vertical services cannot be superimposed, there may be superimposition among multiple horizontal services. For example, businesses that use electronic vouchers also allow group purchases; businesses that use group purchases also allow distribution platforms. so:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Horizontal business is a change to vertical business rules&lt;/p&gt;

&lt;p&gt;Multiple horizontal businesses can be superimposed on the same vertical business&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why do vertical businesses receive platform business adjustments to their business rules? Obviously, through these platform businesses, the business can have more ways to play, promote sales (increase profits), bring users a better experience, and so on. Therefore, in the face of the rules and requirements of the platform, it can also be compromised and accepted.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Therefore, for a business, the complete business rule set related to it is composed of a vertical business rule set + N horizontal business rule sets.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you can understand the above inference, it is not difficult to understand how the Lattice framework manages and manages multiple custom logics for business extension points.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conflict of vertical business overlaying horizontal business
&lt;/h1&gt;

&lt;p&gt;Since multiple horizontal businesses can be superimposed on the same vertical business, what if there is a conflict at the same business point? Here are some small examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example of reduce mode conflict resolution
&lt;/h2&gt;

&lt;p&gt;For an example of the quantity that can be purchased: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assume that the rule of a vertical business is that the purchase quantity cannot exceed the number of stocks&lt;/li&gt;
&lt;li&gt;But after superimposing the electronic voucher business, the electronic voucher business requires that the maximum number of purchases cannot exceed 250&lt;/li&gt;
&lt;li&gt;The definition of the spike business 's business rules, you can buy no more than 10 ultra-low specials&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a point, when generating multiple business rule declarations, what we need to do is to formulate a conflicting priority rule and reduce method. For this example, simply, the three rules have no particular priority requirements. It is only necessary to formulate a reduce method, whichever value is the smallest, whichever value is used.&lt;/p&gt;

&lt;h2&gt;
  
  
  An exclusive contradictory business rule
&lt;/h2&gt;

&lt;p&gt;As another example, a group buying platform requires that in some cases, the prices of these products ordered through the platform must be discounted. However, there may be a certain business A that is very strong. His business rule is that his commodity prices will not only not be discounted, but will also be higher than the original price, but will be lower than the market premium.&lt;/p&gt;

&lt;p&gt;Who has the final say in this conflict of rules? In fact, the owner of the vertical business and the owner of the platform business, the two bosses can negotiate. There is no need for the program to be hard-coded. After all, the business side has its own appeal and its rationality.&lt;/p&gt;

&lt;p&gt;For conflicts in business rules, you can formulate conflict priority rules, which are determined by the business owner. In the case of conflicts, whether the rules of the vertical business have higher priority or the priority of the vertical business.&lt;/p&gt;

&lt;p&gt;Therefore, for the superposition of vertical business and horizontal business, when business rules conflict occurs, our solution mode is reduce algorithm + conflict priority rule&lt;/p&gt;

&lt;p&gt;For an introduction to the types of reduce patterns that conflict with business rules after business overlay, see: &lt;a href="https://github.com/hiforce/lattice/wiki/Reduce-Strategy"&gt;Reduce Strategy&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;中文版：&lt;a href="https://www.ryu.xin/2021/08/20/lattice-concept-business/"&gt;https://www.ryu.xin/2021/08/20/lattice-concept-business/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dynamic Loading of Business Customization Packages in Lattice Framework</title>
      <dc:creator>Ryu Xin</dc:creator>
      <pubDate>Sun, 16 Oct 2022 06:25:35 +0000</pubDate>
      <link>https://dev.to/yuzhenxin/dynamic-loading-of-business-customization-packages-in-lattice-framework-5425</link>
      <guid>https://dev.to/yuzhenxin/dynamic-loading-of-business-customization-packages-in-lattice-framework-5425</guid>
      <description>&lt;p&gt;The dynamic loading mechanism of the business package can download and install the application plug-ins in the cloud market into the current container in some scenarios. Cloud market example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vh0fs2xJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/10/Jietu20221016-135432-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vh0fs2xJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/10/Jietu20221016-135432-1.png" alt="" width="880" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What you’ll learn
&lt;/h1&gt;

&lt;p&gt;This example mainly demonstrates how to dynamically load a business package based on Lattice, but does not include the construction of the cloud market itself.&lt;/p&gt;

&lt;p&gt;With this sample, you can learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic loading example of business plug-in package&lt;/li&gt;
&lt;li&gt;The extension mechanism of custom ClassLoader&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What you’ll need
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;An Integrated Developer Environment (IDE). Popular choices include &lt;a href="https://www.jetbrains.com/idea/"&gt;IntelliJ IDEA&lt;/a&gt;, &lt;a href="https://spring.io/tools"&gt;Spring Tools&lt;/a&gt;, &lt;a href="https://code.visualstudio.com/docs/languages/java"&gt;Visual Studio Code&lt;/a&gt;, or &lt;a href="https://www.eclipse.org/downloads/packages/"&gt;Eclipse&lt;/a&gt;, and many more.&lt;/li&gt;
&lt;li&gt;A Java™ Development Kit (JDK). We recommend &lt;a href="https://bell-sw.com/"&gt;BellSoft Liberica JDK&lt;/a&gt; version 8 or version 11.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Maven dependency
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.hiforce.lattice&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;lattice-model&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.11.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.hiforce.lattice&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;lattice-runtime&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.11.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.hiforce.lattice&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;lattice-dynamic-loading&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.11.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Dynamic Loading of Business Package Demo
&lt;/h1&gt;

&lt;p&gt;In lattice-sample, you can refer to the demo of lattice-dynamic-load-apps, the configuration Lattice plugin loading directory is defined, in application.properties, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lattice.plugin.dirs=/Users/rocky/code/plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we start the Starter org.hiforce.lattice.dynamic.LatticeDynamicStarter. In your browser, open &lt;a href="http://localhost:8080/business/install/1"&gt;http://localhost:8080/business/install/1&lt;/a&gt; and you will see the following input:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--33L0XwgT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/10/Jietu20221017-105338.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--33L0XwgT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/10/Jietu20221017-105338.png" alt="" width="880" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we continue to enter &lt;a href="http://localhost:8080/business/install/2"&gt;http://localhost:8080/business/install/2&lt;/a&gt; , we can see the following results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iJnKgKo8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/10/Jietu20221017-105348.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iJnKgKo8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/10/Jietu20221017-105348.png" alt="" width="824" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be seen that the dynamic loading of the business package has been replaced with a new version. The corresponding Controller code is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/business/install/1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;installBusinessPlugin_1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;urlStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/apps/lattice-business-cloth-1.0.0-SNAPSHOT.jar"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="no"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DynamicLoadTestController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlStr&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPath&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="nc"&gt;LatticeDynamic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;installPlugin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PluginFileInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;invokeBusinessPlugin&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/business/install/2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;installBusinessPlugin_2&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;urlStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/apps/lattice-business-cloth-1.0.1-SNAPSHOT.jar"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="no"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DynamicLoadTestController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlStr&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPath&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="nc"&gt;LatticeDynamic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;installPlugin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PluginFileInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;invokeBusinessPlugin&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Lattice custom ClassLoader
&lt;/h1&gt;

&lt;p&gt;In the Lattice framework, the SPI of the custom ClassLoader is provided, which is defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CustomClassLoaderSpi&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;ClassLoader&lt;/span&gt; &lt;span class="nf"&gt;getCustomClassLoader&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, I provide a very simple loading scheme based on URLClassLoader in the framework in Lattice. In lattice-dynamic-loading, LatticeDynamicClassLoaderBuilder is defined, which can realize the loading of plug-in packages in the specified directory, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@AutoService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CustomClassLoaderSpi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LatticeDynamicClassLoaderBuilder&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;CustomClassLoaderSpi&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ClassLoader&lt;/span&gt; &lt;span class="nf"&gt;getCustomClassLoader&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;dirs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LatticeDynamicProperties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getPluginDirs&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Lists&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newArrayList&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dirs&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buildJarURLList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;urlArrays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toArray&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;URLClassLoader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlArrays&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;LatticeDynamicClassLoaderBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClassLoader&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;buildJarURLList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;dirStr&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Lists&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newArrayList&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirStr&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isDirectory&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Lists&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newArrayList&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;jars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listFiles&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPath&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;endsWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".jar"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;jars&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jars&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPath&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Lists&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newArrayList&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lattice framework users can write more complex plugin loading schemes based on this mechanism. for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can be further enhanced to isolate the loading mechanism for different business identities&lt;/li&gt;
&lt;li&gt;Business plugins can be packaged into flat-jar, and each business can even introduce other third-party packages by itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These, will not be available in the official Lattice framework.&lt;/p&gt;

&lt;p&gt;This sample code:  &lt;a href="https://github.com/hiforce/lattice-sample/tree/main/lattice-dynamic-load-apps"&gt;https://github.com/hiforce/lattice-sample/tree/main/lattice-dynamic-load-apps&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Lattice Framework Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/hiforce/lattice"&gt;Lattice&lt;/a&gt; is a powerful, lightweight business extension invoke framework. By using the Lattice framework, complex business customization can be efficiently organized and managed.&lt;/p&gt;

&lt;p&gt;The main ideas of Lattice's architecture design are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The plug-in architecture that separates the business package from the platform:&lt;/strong&gt; The platform provides a plug-in package registration mechanism to realize the registration of the business-side plug-in package during runtime. The business code is only allowed to exist in the plugin package and is strictly separated from the platform code. The code configuration library of the business package is also separated from the code library of the platform, and is provided to the container for loading through the second-party package.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified business identity across the full-chain:&lt;/strong&gt; The platform needs to have the ability to logically isolate business from business according to "business identity", rather than the traditional SPI architecture that does not distinguish between business identities and simply filters. How to design this business identity has also become the key to the isolation architecture between businesses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of management domain and running domain:&lt;/strong&gt; Business logic cannot rely on dynamic calculation at run time, but can be defined and visualized at static time. The rules that appear in the business definition are superimposed and conflicted, and conflict decisions are also made in the static device. During the runtime, it is executed strictly according to the business rules and conflict decision policies defined by the static device.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;中文版：&lt;a href="https://www.ryu.xin/2022/10/11/lattice-dynamic-loading/"&gt;https://www.ryu.xin/2022/10/11/lattice-dynamic-loading/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>UseCase Precipitation and Reuse</title>
      <dc:creator>Ryu Xin</dc:creator>
      <pubDate>Thu, 13 Oct 2022 13:48:13 +0000</pubDate>
      <link>https://dev.to/yuzhenxin/usecase-precipitation-and-reuse-14ce</link>
      <guid>https://dev.to/yuzhenxin/usecase-precipitation-and-reuse-14ce</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Through this article, you can learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is a UseCase&lt;/li&gt;
&lt;li&gt;Why do UseCase level abstraction&lt;/li&gt;
&lt;li&gt;An example of a UseCase level SDK abstraction&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  What is the UseCase
&lt;/h1&gt;

&lt;p&gt;For an introduction to this concept, you can refer to the description of the "UseCase Layer" in Chapter 22 of "&lt;a href="https://learning.oreilly.com/library/view/clean-architecture-a/9780134494272/" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt;":&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The software in the use cases layer contains application-specific business rules. It encapsulates and implements all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities, and direct those entities to use their Critical Business Rules to achieve the goals of the use case.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fwww.ryu.xin%2Fwp-content%2Fuploads%2F2022%2F09%2F22fig01.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fwww.ryu.xin%2Fwp-content%2Fuploads%2F2022%2F09%2F22fig01.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Why do UseCase level abstraction
&lt;/h1&gt;

&lt;p&gt;At the use case layer, with the continuous enrichment of business scenarios, the complexity will increase dramatically. When the scene details change, we don't want the changes in this layer to affect business entities, UI, etc. If a scene is not well abstracted, it is difficult to achieve logical isolation and scene-level reuse of different scenes. In TOGAF, there is a concept of "Enterprise Continumm". The key point of this concept is how to precipitate components at different levels for reuse:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fwww.ryu.xin%2Fwp-content%2Fuploads%2F2022%2F09%2Ftogaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fwww.ryu.xin%2Fwp-content%2Fuploads%2F2022%2F09%2Ftogaf.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Architecture Continuum:&lt;/strong&gt; This continuum can extract reusable components from a specific architecture into a repository (Gerneralization for future re-use) for similar services. In specific applications, reusable components can be selected from the component repository and adapted to the actual application scenario (Adaptation for use)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solutions Continuum:&lt;/strong&gt; Similar to Architecture Continuum, in the face of different markets, it needs to be able to choose from a reusable solution library and quickly replicate. For delivery to emerging markets, it can also be extracted into a reusable solution into the asset library&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;UseCase level abstraction can be understood as a solution continuum. The biggest difference between it and function-level reuse is that at the UseCase level, it spans multiple business activities and multiple roles, and can achieve full-chain reuse in a certain scenario. For example, under the e-commerce system, we can summarize and summarize various transaction scenarios and transaction modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secured transaction mode: Secured transaction refers to the provision of a third-party guarantee account, the custody of transaction funds during the transaction process, and the transfer of funds is completed after the confirmation of the buyer and the seller. This method avoids online transactions, which may fail due to trust issues, and at the same time ensures the interests of both buyers and sellers&lt;/li&gt;
&lt;li&gt;Pre-sale transaction mode: The pre-sale transaction is a staged transaction. There will be two stages of deposit payment and final payment during the order placement process. Part of the cost is paid in the deposit payment stage, and the remaining cost is paid in the final payment stage. After the seller receives the balance payment, it will be shipped. This model is more commonly used in big promotion marketing activities, which can play a role in locking buyers, inventory certainty, etc.&lt;/li&gt;
&lt;li&gt;Electronic voucher transaction mode: Electronic voucher transaction refers to the transaction process of purchasing/receiving vouchers online, and then going offline to verify vouchers, and finally complete the transaction process of consumption or delivery. Its main feature is that it adopts an identity-based verification mechanism with credentials as the carrier. Common vouchers include: electronic exchange coupons, delivery coupons, electronic tickets, electronic membership cards, etc. The carrier of the certificate usually has the form of serial code, QR code, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take the online movie ticket purchase that is common in daily life as an example. In this kind of scene transaction, movie tickets are generally not mailed to consumers in the form of physical logistics, but are sent to consumers through SMS or App with a QR code or serial code. With this QR code or serial code, consumers can go to the cinema to collect tickets by themselves before watching the movie. Once the movie ticket is taken out, the electronic voucher will be cancelled and cannot be used again. This is a one-time write-off electronic voucher transaction mode.&lt;/p&gt;

&lt;p&gt;For another example, we can buy and book a car 4S maintenance service online. After the reservation is successful, the merchant will send the service redemption code to the consumer via SMS or App. Consumers can use this QR code to go to car 4S stores to enjoy maintenance services, such as car washing. A car maintenance service might be a package, such as a package that includes 12 car washes. Then, the rights and interests contained in this electronic certificate can be written off multiple times.&lt;/p&gt;

&lt;p&gt;It is not difficult to see that the electronic voucher transaction mode can be reused at the solution level by different forms of business. Business users do not need to complete the infrastructure for generating vouchers, issuing voucher codes, verifying vouchers, and returning vouchers. They just need to declare the use of this scenario/pattern and define rules on some special point, such as write off this point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Movie ticket business: It needs to be stated that when using the scene mode of electronic vouchers, his write-off method is "single write-off"&lt;/li&gt;
&lt;li&gt;Auto 4S maintenance service: It needs to be stated that when using the scene mode of electronic certificate, his write-off method is "multiple write-offs"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can define the scene-level development SDK on the scene template of the electronic certificate. Whether we allow multiple write-offs for a certificate can be defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ETicketTradeSDK&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IBusinessExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;EXT_ETICKET_IS_SUPPORT_MULTI_WRITE_OFF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"EXT_ETICKET_IS_SUPPORT_MULTI_WRITE_OFF"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Extension&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EXT_ETICKET_IS_SUPPORT_MULTI_WRITE_OFF&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Is Voucher support multiple write-off"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;reduceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReduceType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NONE&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="nf"&gt;isVoucherSupportMultiWriteOff&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the movie ticket business, when using the electronic voucher scenario, he can implement this extension point and declare that "multiple write-offs are not allowed", as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Realization&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HiMovieBusiness&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CODE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HiMovieETicketExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BlankETicketTradeSDK&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="nf"&gt;isVoucherSupportMultiWriteOff&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, we can also take the pre-sale transaction model as an example. The pre-sale transaction is divided into two stages: deposit payment and final payment. However, different businesses have different requirements for the deposit payment ratio, some require a 30% deposit, and some only require a 5% deposit. Therefore, the pre-sale transaction scenario mode can also extract the extension point of "custom deposit payment ratio", and let each business decide on its own. as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PreSaleTradeSDK&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IBusinessExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;EXT_PRE_SALE_CUSTOM_DOWN_PAY_RATIO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"EXT_PRE_SALE_CUSTOM_DOWN_PAY_RATIO"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Extension&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EXT_PRE_SALE_CUSTOM_DOWN_PAY_RATIO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Custom PreSale Down Payment Ratio"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;reduceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReduceType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FIRST&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="nf"&gt;getCustomDownPaymentRatio&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We assume that the movie ticket business also has pre-sale (such as large-scale live performances, concert scenes), and the pre-sale deposit ratio of movie tickets is required to be 40%. The business customization logic is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Realization&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HiMovieBusiness&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CODE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HiMoviePreSaleExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BlankPreSaleTradeSDK&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="nf"&gt;getCustomDownPaymentRatio&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above two examples, we should be able to easily see. Customized for the UseCase level SDK, it will be more logical thinking. Development and products can be well consistent with the language, and the code is consistent with the requirements. When the business conducts logic customization, it does not perceive the underlying entity structure. The conversion of this structure and data is encapsulated by electronic vouchers and pre-sale transaction scene templates.&lt;/p&gt;

&lt;p&gt;We all know that under massive data, the order structure stored in the database cannot be changed at will. We generally use some structured fields for business information storage, such as K/V structure, JSON structure, etc. Different business scenarios are finally stored on the order, and business information will be saved on this structured field. In the above example, whether the electronic certificate allows multiple write-offs is referred to the K/V structure. On the "save" behavior of the order entity, we can define an extension point called "custom order attribute", as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;OrderLineSaveExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IBusinessExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;EXT_ENTITY_ORDER_LINE_CUSTOM_ATTRIBUTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"EXT_ENTITY_ORDER_LINE_CUSTOM_ATTRIBUTES"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Extension&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EXT_ENTITY_ORDER_LINE_CUSTOM_ATTRIBUTES&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;reduceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ReduceType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NONE&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getCustomOrderAttributes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the electronic voucher transaction scenario, he can implement this extension point, so as to complete the expression with business semantics and complete the data mapping on the entity. as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Realization&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EticketTradeUseCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CODE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ETicketTradeBusinessExt&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BlankOrderLineSaveExt&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getCustomOrderAttributes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;EticketOrderLineAbility&lt;/span&gt; &lt;span class="n"&gt;ability&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EticketOrderLineAbility&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buildEticketOrderLine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="n"&gt;supportMultiWriteOff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ability&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isVoucherSupportMultiWriteOff&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Maps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newHashMap&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"e_multi_write_off"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;supportMultiWriteOff&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;......&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way, the code logic of the underlying entity layer will be very clean, and it will not perceive the details of the upper-level scene changes. Moreover, in this way, it is easy to deal with the superposition and combination of multiple scenes. For example, in the sample attached to this article, I simply wrote a business that uses both the electronic voucher scene template and the pre-sale transaction scene template. You can run: org.hiforce.lattice.sample.starter.LatticeUseCaseSample to observe the running results, the results are as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[UseCase]PreSaleTrade load custom down payment ratio: .40
[UseCase]ETicketTrade is support multiple write-off: false
Save OrderLine id: 1, bizCode: hi.movie
-- Total Pay Price: 4000
-- Order Attributes: [e_multi_write_off:0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the sample code described in this article, you can visit: &lt;a href="https://github.com/hiforce/lattice-sample/tree/main/lattice-usecase-sample" rel="noopener noreferrer"&gt;https://github.com/hiforce/lattice-sample/tree/main/lattice-usecase-sample&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;中文版：&lt;a href="https://www.ryu.xin/2022/09/28/lattice-usecase-overlay/" rel="noopener noreferrer"&gt;https://www.ryu.xin/2022/09/28/lattice-usecase-overlay/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How the code is gradually corrupted</title>
      <dc:creator>Ryu Xin</dc:creator>
      <pubDate>Sun, 09 Oct 2022 08:02:27 +0000</pubDate>
      <link>https://dev.to/yuzhenxin/how-the-code-is-gradually-corrupted-421h</link>
      <guid>https://dev.to/yuzhenxin/how-the-code-is-gradually-corrupted-421h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In the first half of the year when I joined a company in early 2015, I observed that the platform at that time was unable to provide agile support for the business: insufficient manpower and serious overtime; long scheduling time and frequent delays; co-construction mechanism, difficulties in coordination and other issues. This article is in the context of that time, recording the problems I observed and some initial thoughts. PS: The sample code of this article has nothing to do with the actual code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;E-commerce business is diverse, and each department has different business positioning. Some businesses are for specific "vertical" industries, such as clothing business, electrical business, automobile business, vacation business, communication business, etc. Some businesses are also positioned as platform-based businesses that provide business support for all industries, such as group buying business, shopping guide business, etc. In the early days, the processing logic of each business was consistent, but with the development needs of their respective businesses, business processing logic produced differentiated requirements.&lt;/p&gt;

&lt;p&gt;As the business becomes more and more, the code gradually begins to corrode locally, and eventually the system becomes overwhelmed and unsustainable.&lt;/p&gt;

&lt;h1&gt;
  
  
  Code corruption
&lt;/h1&gt;

&lt;p&gt;Let's take the "inventory reduction strategy" as an example. In the early stage of the platform's inventory reduction processing logic, the inventory reduction strategy is "reduce inventory before payment of goods". However, for some commodities with relatively small inventory and relatively expensive prices, such as air conditioners, refrigerators and other major appliances, if the strategy of "reducing inventory before payment of the goods" is adopted, it will lead to bad auctions by some competing merchants, that is, only order Goods, but no payment. In this case, there will be no goods to sell in the inventory of the seller of electricity, and the actual goods are still backlogged in the warehouse, resulting in a large amount of capital occupation and warehouse occupation. Therefore, in the electrical appliance business, they hope to customize the inventory reduction strategy of this business as "reduce inventory after payment". At this time, the original code with consistent processing logic has evolved into the following form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt; &lt;span class="nf"&gt;getProductInventoryReducePolicy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;hasTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9527&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt; 
        &lt;span class="c1"&gt;//If the item ordered is appliance&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AFTER_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BEFORE_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The development of the business is so rapid that the above code cannot be stabilized at all. When some virtual goods appear, some virtual goods have no inventory limit and do not require inventory deduction after purchase by buyers. At this point, the above code becomes like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt; &lt;span class="nf"&gt;getProductInventoryReducePolicy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;

     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isVirtual&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt; &lt;span class="c1"&gt;//If it is a virtual commodity&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NO_REDUCATION&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;hasTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9527&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt; &lt;span class="c1"&gt;//If the item ordered is appliance&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AFTER_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BEFORE_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding this logic while doing the virtual commodity business, it will be released after verification and no problem. However, after a few months, the major appliance business added a "store pickup" method of receiving goods. For some home appliances, consumers hope that they can choose a satisfactory and flawless product in the store. For the goods picked up by the store, the virtual delivery code is also issued instead of physical logistics. However, in order to ensure that the goods can be picked up in the store after receiving the pick-up code, the inventory of the goods corresponding to the pick-up code is still to be deducted. However, the code after the above changes is invalid for this scenario, because the logic of not reducing the inventory of virtual goods is always in front of the big home appliance business. After the business development analysis of major appliances, the above code is further adjusted as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt; &lt;span class="nf"&gt;getProductInventoryReducePolicy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;

     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isVirtual&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt; &lt;span class="c1"&gt;//If it is a virtual commodity&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;hasTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9527&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt;
             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NO_REDUCATION&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;hasTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9527&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt; &lt;span class="c1"&gt;//If the item ordered is appliance&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AFTER_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BEFORE_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the categories of goods in the electrical appliance business become more and more abundant and the number of goods increases, the uniform use of "payment to reduce inventory" in the home appliance business to reduce inventory cannot meet the demand. The inventory reduction strategy of the home appliance business has become "if the unit price of the product is greater than 5,000, it is the after payment reduction, otherwise it is the before payment reduction". The above code is further corrupted into the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt; &lt;span class="nf"&gt;getProductInventoryReducePolicy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;

     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isVirtual&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;hasTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9527&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt;
             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NO_REDUCATION&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;hasTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9527&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getPrice&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getCent&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;500000L&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AFTER_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BEFORE_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BEFORE_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corruption process of the above code was not formed in a day, it also accumulated over many years. This is still a very simple customization of a business's inventory reduction strategy. The most extreme method I have ever seen is thousands of lines long, filled with a large number of branch logic judgments, and the code is indented and nested very deeply. When faced with a new deduction scenario, every programmer carefully finds a seemingly suitable position, adds his own if statement, and prays that it will not affect other unrelated businesses.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introducing design patterns, but still no silver bullet
&lt;/h1&gt;

&lt;p&gt;With more and more customized business logic, aspiring programmers began to consider how to introduce design patterns to solve the problem of code corruption. Let’s take the above business customized inventory reduction strategy as an example. Experienced programmers will define an SPI interface for this customization point, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;GetCustomInventoryReducePolicySpi&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;ReducePolicySettingReq&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;ReducePolicySettingReq&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since there will be multiple implementation classes that implement the SPI interface, in order to accurately execute the correct interface implementation class, the SPI interface will define two methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;filter: used to judge whether the implementation class of the current SPI is in effect according to the current context request parameters&lt;/li&gt;
&lt;li&gt;execute: When the current SPI implementation class takes effect, the platform will call the execute method of the current SPI instance to obtain a custom inventory reduction strategy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this way, we can define each if statement in the corrupt code as an SPI implementation class, and the platform is responsible for traversing these SPI implementation classes and finding the first one whose return value is not null. as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VirtualProductReduceInventoryPolicyImpl&lt;/span&gt; 
     &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;GetCustomInventoryReducePolicySpi&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;ReducePolicySettingReq&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderLine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isVirtual&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;ReducePolicySettingReq&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NO_REDUCATION&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BigSellerAppliancesReduceInventoryPolicyImpl&lt;/span&gt; 
     &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;GetCustomInventoryReducePolicySpi&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;ReducePolicySettingReq&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderLine&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;hasTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9527&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;ReducePolicySettingReq&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="nc"&gt;OrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderLine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getPrice&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getCent&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;500000L&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AFTER_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BEFORE_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InventoryReduceProcessor&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;SpiProcessor&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetCustomInventoryReducePolicySpi&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;reducePolicySpis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nc"&gt;Lists&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newArrayList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BigSellerAppliancesReduceInventoryPolicyImpl&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;VirtualProductReduceInventoryPolicyImpl&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;......&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt; &lt;span class="nf"&gt;getProductInventoryReducePolicy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderLine&lt;/span&gt; &lt;span class="n"&gt;orderLine&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reducePolicySpis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
             &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
             &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findFirst&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
             &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ReduceTypeEnum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AFTER_PAYMENT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After processing this way, the platform's core processing code eliminates a lot of if..else... , everyone rejoices. Facts have also proved that when there are not many implementation classes of an SPI interface, this method is still very effective, and it can indeed greatly improve the scalability of the system. However, there are many industries supported by the e-commerce platform, which will eventually lead to the continuous growth and expansion of the list of SPI implementation class registrations. Subsequently, whenever a requirement involves the logic customization of the inventory reduction strategy, it is necessary to carefully analyze and evaluate how to modify the SPI registration tree. like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do I need to modify the existing SPI implementation, or do I need to register a new SPI instance?&lt;/li&gt;
&lt;li&gt;For SPI instances that need to be added, in which order should they be registered?&lt;/li&gt;
&lt;li&gt;How to assess the impact on other SPIs after newly added SPIs or changes to existing SPIs?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the increase of SPI implementation classes, how to add SPI instances without affecting existing implementations has become a huge challenge. Technicians need to read the code carefully to see how the filter method of each registered SPI instance is written to ensure that the effective conditions of the newly added SPI instances are not too large to affect other SPI instances, and the effective conditions cannot be If it is too small, its own SPI instance will never take effect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our technicians are very smart, they will use more advanced technology, such as rules engine, remote RPC calls, etc. to write filter methods. At this point, it is almost impossible to read the code to assess when these SPI instances will take effect.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a complex business system, there are nearly a thousand interface definitions for SPIs like this, &lt;strong&gt;and dozens of implementation classes are registered on each SPI interface&lt;/strong&gt;. The SPI implementation class registered in this way, whether it is registered explicitly or dynamically registered by the configuration file, will find and execute the matched SPI implementation class in a traversal manner during runtime. This mechanism leads to a huge coupling between different businesses and businesses. Any addition or modification of SPI will have huge uncertainty on whether it will affect other businesses. As the scale of the business continues to grow, this SPI registration and management mechanism begins to fail and becomes a key obstacle to the rapid iteration and development of the business.&lt;/p&gt;




&lt;p&gt;中文版：&lt;a href="https://www.ryu.xin/2021/07/20/bad-code/"&gt;https://www.ryu.xin/2021/07/20/bad-code/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Challenges of Business Agile</title>
      <dc:creator>Ryu Xin</dc:creator>
      <pubDate>Sun, 09 Oct 2022 04:28:25 +0000</pubDate>
      <link>https://dev.to/yuzhenxin/challenges-of-business-agile-287e</link>
      <guid>https://dev.to/yuzhenxin/challenges-of-business-agile-287e</guid>
      <description>&lt;p&gt;Whether a platform is mature or not has many considerations, such as whether the platform is stable, whether it is easy to expand, and whether it can support complex business well. In my opinion, to judge whether the platform supports the business well, in addition to the above points, it also depends on whether it supports the new small business well.&lt;/p&gt;

&lt;p&gt;For a rapidly developing industry, innovative businesses are released every year or even every month. If the entry threshold of the platform is high, each innovative business needs to spend a lot of time in research and development, integration, and debugging to run on the platform, and it is likely to lose a valuable window of opportunity.&lt;/p&gt;

&lt;h1&gt;
  
  
  The platform can not only support mature businesses, but also support the rapid trial of new small businesses
&lt;/h1&gt;

&lt;p&gt;New small businesses have a law of growth. In the early stage of business model verification, the required gameplay is relatively simple, and it is hoped that rapid trial can be released frequently. Let's take the e-commerce field as an example. Under the mature e-commerce system, there are many complex and huge platforms, such as trading platforms, commodity platforms, and marketing platforms. Although these platforms support various business models and gameplay well, for new small businesses, these models and gameplay are not applicable in the early stage. They hope that the platform can make some tailoring according to their own requirements.&lt;/p&gt;

&lt;p&gt;Let's take the business of "auto finance" as an example. In the months of trial and error of the initial concept, this business does not need to provide coupons, nor does it involve the process of physical logistics and delivery, nor does it involve gold standard-related assets. content. Instead of following the platform’s weekly release rhythm, he wants to be able to iterate quickly and self-publish early on. But this very reasonable requirement is difficult to meet on the early trading platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The order placement process of the early trading platforms was hard-coded. The whole process, no matter what business, must be connected with the preferential system, logistics system, card and coupon platform and other systems. When developing a new business, it is necessary to ensure that the integration of the entire order placing process with these services will not cause call exceptions. Once an exception occurs, it is necessary to coordinate with the relevant system to see how to shield the error.&lt;/li&gt;
&lt;li&gt;The commodity unit price calculation logic is not well decoupled in the platform, nor does it provide an extensible mechanism. The unit price of the auto finance business comes from a micro-loan system. In the end, this business can only be hard-coded, where the platform calculates the unit price of goods, and mixes it with other business codes to write related calculation logic. Because this part of the code may affect other businesses, before the code is released online, it must undergo strict network-wide regression verification to ensure that it will not affect other businesses or cause capital losses.&lt;/li&gt;
&lt;li&gt;Therefore, the release rhythm of the auto finance business must also follow the rhythm of the platform version, and can only be released after patiently waiting for the weekly network-wide regression verification, and cannot be released at any time according to one's own wishes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The technical staff of the auto finance business team do not know the implementation details of each platform. They believe that these platforms are mature and powerful. These requirements should be very simple, and they should be integrated and released in a week or two. But in the end, after repeated communication between the business and the platform team, clarification of requirements, and evaluation of the plan, it was discovered that the functions that were thought to be supported by "as a matter of course" were originally uncertain or unsupported. The plan has also changed from the previous one or two weeks to at least three months, and the workload has also changed from the previous 2 person weeks to 4 person months, and the delivery time promised in the previous business is also imminent...&lt;/p&gt;

&lt;p&gt;Such stories are repeated every day. How can the platform not become a bottleneck supporting the business team? The key lies in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether the capabilities of the platform can be externalized and exposed, business teams in various industries can clearly know what capabilities the platform has;&lt;/li&gt;
&lt;li&gt;Whether the external scalability provided by the platform is sufficient, and the business team can customize business logic in a self-service and non-intrusive manner&lt;/li&gt;
&lt;li&gt;The business logic customized by each industry cannot affect each other, and the business customization of each industry can be released independently and independently;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The platform needs to support the business in a reusable mode and help the development of the business
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Story 1: A product and platform conversation about business needs
&lt;/h2&gt;

&lt;p&gt;An e-commerce platform currently supports a large number of vertical industries. These industries have roughly the same main transaction process, but have their own industry characteristics in some branch scenarios. There was once an industry where products communicated with platform designers to see if the platform could meet business demands.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Platform: "What do you want to do in your business? What functions do you need? What specific scenarios and constraints are there?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Business: "Well, our business is nothing special. Our business scenarios and rules are basically the same as XX supermarket business, but there are some differences in these places...blablabla..."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;platform:"......"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The above dialogue scenario occurs frequently between the business team and the platform team. When the students on the platform further asked: "Which scenarios are the same between you and the XX supermarket business?" When this question is asked, the business team often does not know what the "XX supermarket" business is.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Platform: "This section of XX supermarket has customized business logic, do you also need it?".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Business: "Well, I'm not sure about this business logic, so I shouldn't need it."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The business team in this industry only sees that XX supermarket has a certain degree of business similarity with them, but they only understand some external performances of XX supermarket's business model and business scenarios.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vg25500L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/09/b2155b1b073c6442fbdd9b9815d377dc.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vg25500L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.ryu.xin/wp-content/uploads/2022/09/b2155b1b073c6442fbdd9b9815d377dc.jpeg" alt="" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Story 2: The process from a demand analysis to the launch
&lt;/h3&gt;

&lt;p&gt;When I first joined the trading platform, I was in charge of a demand called the second-stage logistics of Village Amoy. This demand roughly refers to the delivery of orders that some courier companies could not deliver to the village before, to the village Taoist station in the county, and then the village Taoist partner in the village Taoist station is responsible for secondary distribution, including the delivery of the village to the village. , At the same time, the partner of Village Tao will charge a fee for the second delivery as a commission. This requirement differs from the previous transaction fulfillment process in these ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The logistics distribution is divided into two stages, the first stage is the courier company responsible for the distribution, and the second stage is the village Tao partner responsible for the distribution;&lt;/li&gt;
&lt;li&gt;The total logistics cost consists of two parts, one part is paid to the courier company, and the other part is paid to the village Taoist partner;&lt;/li&gt;
&lt;li&gt;Once the Village Tao partner starts to deliver, the delivery service has already taken effect, and the delivery fee will be charged to the Village Tao partner. If there is a return or exchange of goods in the later stage, the partner of Village Tao will not refund the delivery fee that has been incurred;&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This requirement is indeed not very complicated. I followed my senior brother from the trading team to participate in the requirement review meeting and the technical solution review meeting. After introducing the business requirements of the product, my brother thought for a while, and mentioned that this requirement is very similar to the requirement for "freight insurance" that he had done before. For example, the fee is divided into two, and once the service is performed, it will not be refunded; the fee is two different payees, and so on. Then, &lt;strong&gt;the conclusion of the technical solution is that the requirement refers to the technical solution of the previous "freight insurance" requirement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The product is very happy, my boss is very happy, and I am also very happy. After all, a very similar requirement has already been done, which is definitely technically feasible, and it can also be used for reference. It seems that this requirement can be solved in a week.&lt;/p&gt;

&lt;p&gt;After returning to my seat, I began to inquire how the previous requirement of "freight insurance" was designed and implemented. Suddenly, I found that the main designer who had done the "freight insurance" before had retired from the arena. There are not many other colleagues who have participated in this requirement before and do not know much about the details. The last suggestion you can give me is "search for the word insurance and see where the code has this keyword". In the end, it turned out that this trick was not very effective. In the transaction order system, I found more than 2,000 places with this keyword. After inspection, I found that most of them have nothing to do with "freight insurance". Moreover, some services that supported "freight insurance" at that time have been restructured and taken offline and replaced by another service/system.&lt;/p&gt;

&lt;p&gt;In the end, I can only honestly return to the original business requirements, start to do scene analysis, start to design the main entity objects, analyze the processing sequence, and define the main upstream and downstream services and related interface parameters. It was estimated that the demand to be completed in a week was finally completed by two people for more than a month.&lt;/p&gt;

&lt;p&gt;Stories like this happen every day. For example, a pre-sale game has been made in China, and the international team also hopes to introduce pre-sale on its own platform. In the end, it was found that there is no other package that has been formed, has nothing to do with the industry, and is highly abstracted and reusable. There are only some original requirements description documents that can be used for reference, and based on these original requirements documents, analysis, design, coding, and testing are done again.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Therefore, how the platform can accumulate assets that can be quickly reused at the scene level is the key to helping new small businesses go online quickly and agilely!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For information on how to precipitate scene-level reusable assets based on Lattice, see: &lt;a href="https://github.com/hiforce/lattice/wiki/UseCase-Precipitation-and-Reuse"&gt;UseCase Precipitation and Reuse&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;中文版：&lt;a href="https://www.ryu.xin/2021/07/22/lattice-small-biz-support/"&gt;https://www.ryu.xin/2021/07/22/lattice-small-biz-support/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Lattice Framework Introduction</title>
      <dc:creator>Ryu Xin</dc:creator>
      <pubDate>Mon, 03 Oct 2022 08:33:25 +0000</pubDate>
      <link>https://dev.to/yuzhenxin/lattice-framework-introduction-28h0</link>
      <guid>https://dev.to/yuzhenxin/lattice-framework-introduction-28h0</guid>
      <description>&lt;h1&gt;
  
  
  Lattice Framework Introduction
&lt;/h1&gt;

&lt;p&gt;Lattice is a powerful, lightweight business extension invoke framework. By using the Lattice framework, complex business customization can be efficiently organized and managed.&lt;/p&gt;

&lt;p&gt;The main ideas of Lattice's architecture design are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The plug-in architecture that separates the business package from the platform:&lt;/strong&gt; The platform provides a plug-in package registration mechanism to realize the registration of the business-side plug-in package during runtime. The business code is only allowed to exist in the plugin package and is strictly separated from the platform code. The code configuration library of the business package is also separated from the code library of the platform, and is provided to the container for loading through the second-party package.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified business identity across the full-chain:&lt;/strong&gt; The platform needs to have the ability to logically isolate business from business according to "business identity", rather than the traditional SPI architecture that does not distinguish between business identities and simply filters. How to design this business identity has also become the key to the isolation architecture between businesses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of management domain and running domain:&lt;/strong&gt; Business logic cannot rely on dynamic calculation at run time, but can be defined and visualized at static time. The rules that appear in the business definition are superimposed and conflicted, and conflict decisions are also made in the static device. During the runtime, it is executed strictly according to the business rules and conflict decision policies defined by the static device.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Development Guide
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/Quickstart-Guide"&gt;Quickstart Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/Business-Overlay-Product"&gt;Business Overlay Product&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/Register-Business-Configuration"&gt;Register Business Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/Load-Local-Configuration"&gt;Load Local Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/Reduce-Strategy"&gt;Reduce Strategy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/UseCase-Precipitation-and-Reuse"&gt;UseCase Precipitation and Reuse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/RPC-Invoke-Extension"&gt;RPC Invoke Extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Key Concepts
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/Key-Concept---Business"&gt;Business&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hiforce/lattice/wiki/Key-Concept--%E2%80%94%E2%80%94-Ability"&gt;Ability&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/hiforce/lattice"&gt;https://github.com/hiforce/lattice&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
