<?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>Forem: canonical</title>
    <description>The latest articles on Forem by canonical (@canonical).</description>
    <link>https://forem.com/canonical</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%2F3578743%2Feccf1f85-53c3-4e4a-9948-7737f0c99a91.jpeg</url>
      <title>Forem: canonical</title>
      <link>https://forem.com/canonical</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/canonical"/>
    <language>en</language>
    <item>
      <title>The Essence of DDD: The Practice Guide from Philosophy to Mathematics to Engineering</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Sat, 21 Feb 2026 11:48:35 +0000</pubDate>
      <link>https://forem.com/canonical/the-essence-of-ddd-the-practice-guide-from-philosophy-to-mathematics-to-engineering-37gp</link>
      <guid>https://forem.com/canonical/the-essence-of-ddd-the-practice-guide-from-philosophy-to-mathematics-to-engineering-37gp</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: From Theory to Practice
&lt;/h2&gt;

&lt;p&gt;In the first half of this article, the &lt;a href="https://dev.to/canonical/the-essence-of-ddd-a-complete-guide-from-philosophy-to-mathematics-to-engineering-practice-the-4jfa"&gt;Theory Guide&lt;/a&gt;, we explored the philosophical background and mathematical principles of DDD, introducing (Generalized) Reversible Computation as its technical core. We recognized that DDD's effectiveness lies in its ability to guide us in building computational models that are closer to the essence of the domain, while Reversible Computation provides the mathematical foundation for system construction and evolution.&lt;/p&gt;

&lt;p&gt;The value of theory must be validated through practice. In this guide, we will focus on the concrete implementation of these ideas, highlighting how the &lt;strong&gt;Nop Platform&lt;/strong&gt; applies Reversible Computation theory to real-world DDD practice. We will see how, through a systematic engineering approach, DDD's strategic and tactical designs can be effectively implemented in code and architecture, thereby lowering the barrier to entry and enhancing the maintainability and evolutionary capabilities of systems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The (Generalized) Reversible Computation theory mentioned in this text is not the same as the concept of Reversible Computing in physics. It does not refer to the reverse execution of computational instructions but rather to an extended understanding of the concept of "reversibility" at the level of software construction. See &lt;a href="https://dev.to/canonical/reversible-computation-a-next-generation-theory-for-software-construction-27fk"&gt;Reversible Computation: The Next-Generation Software Construction Theory&lt;/a&gt; and &lt;a href="https://dev.to/canonical/generalized-reversible-computation-grc-the-naming-and-elucidation-of-a-software-construction-2cp"&gt;Generalized Reversible Computation: Naming and Explaining a Software Construction Paradigm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Nop Platform is an open-source reference implementation of (Generalized) Reversible Computation theory. Nop is a recursive acronym for "Nop is not Programming."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Chapter 9: Closing the Engineering Loop of DDD — The Reversible Computation Practice of the Nop Platform&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Introduction: From Theory to an Executable Engineering System
&lt;/h3&gt;

&lt;p&gt;In the preceding chapters, we constructed a cognitive framework for software design and evolution from the abstract heights of philosophy and mathematics. Its core is built upon the four pillars of "Space," "Time," "Coordinate System," and "Delta." However, no matter how grand a theory is, it will ultimately become a castle in the air if it cannot be translated into a rigorous, executable, and governable engineering system.&lt;/p&gt;

&lt;p&gt;Now, we must answer the final and most crucial question: &lt;strong&gt;How is this theory implemented?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Nop Platform was created to answer this very question. It does not simply provide a set of auxiliary tools for DDD; instead, it thoroughly integrates DDD's strategic and tactical patterns into the unified engineering paradigm of "&lt;strong&gt;Reversible Computation + DSL Atlas + Delta&lt;/strong&gt;." Its ultimate goal is to transform DDD from an "art for masters," dependent on team experience and individual enlightenment, into an "engineering science" that is orchestratable, verifiable, and evolvable.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.1 Institutionalizing Strategic Design: Boundary-First, Language as Coordinate System
&lt;/h3&gt;

&lt;p&gt;Strategic design is the essence of DDD. The Nop Platform ensures that the strategic blueprint can be accurately and losslessly mapped into the code structure through a series of hard engineering mechanisms.&lt;/p&gt;

&lt;h4&gt;
  
  
  9.1.1 Physicalizing the Bounded Context: From &lt;code&gt;Modular Directories&lt;/code&gt; to a &lt;code&gt;DSL Atlas&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;In the Nop Platform, a &lt;strong&gt;Bounded Context&lt;/strong&gt; is no longer a vague logical concept; it is precisely physicalized in engineering terms as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  An independent &lt;strong&gt;module root directory&lt;/strong&gt; (e.g., &lt;code&gt;/nop/iam&lt;/code&gt; for the Identity and Access Management context).&lt;/li&gt;
&lt;li&gt;  Within this directory, a set of DSLs specific to this context form a "&lt;strong&gt;DSL Atlas&lt;/strong&gt;." This atlas may include:

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Data Models&lt;/strong&gt;: &lt;code&gt;app.orm.xlsx&lt;/code&gt; or &lt;code&gt;*.orm.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;API and Metadata Models&lt;/strong&gt;: &lt;code&gt;*.xmeta&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;View Models&lt;/strong&gt;: &lt;code&gt;*.view.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Rule Models&lt;/strong&gt;: &lt;code&gt;*.rule.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Workflow Models&lt;/strong&gt;: &lt;code&gt;*.wf.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  ...and so on.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These DSLs, constrained by a unified &lt;code&gt;XDef&lt;/code&gt; meta-model, ensure that the &lt;strong&gt;Ubiquitous Language&lt;/strong&gt; is no longer a vocabulary floating in wikis or meeting minutes, but a living, parsable, verifiable, and code-generation-driving &lt;strong&gt;domain coordinate system&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All these DSLs can be freely converted between Excel and XML/JSON formats through configuration (no coding required). This allows many models to be expressed directly in the familiar Excel format, enabling business analysts to participate directly in the modeling process. The resulting Excel file is both an intuitive requirements document and a precise model that can be automatically parsed to drive code generation, eliminating the disconnect between documentation and code from the source.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  9.1.2 Engineering Context Mapping: &lt;code&gt;Events&lt;/code&gt;, &lt;code&gt;Services&lt;/code&gt;, and &lt;code&gt;Transformation DSLs&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;In the Nop Platform, the collaboration mechanisms between Bounded Contexts are concretized into the following executable engineering elements, with unified abstract interfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Asynchronous Event Communication&lt;/strong&gt;: Cross-context collaboration prioritizes &lt;strong&gt;Domain Events&lt;/strong&gt; for loose coupling. The platform provides a unified abstract interface &lt;code&gt;IMessageService&lt;/code&gt; for &lt;strong&gt;one-way messaging&lt;/strong&gt; and includes a default implementation based on mechanisms like the &lt;code&gt;SysEvent&lt;/code&gt; table, which integrates with database transactions to ensure reliable event publication.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Unified one-way message abstraction&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IMessageService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IMessageSender&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IMessageReceiver&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;CompletionStage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;sendAsync&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;topic&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
          &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MessageSendOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;IMessageSubscription&lt;/span&gt; &lt;span class="nf"&gt;subscribe&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;topic&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
          &lt;span class="nc"&gt;IMessageConsumer&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MessageSubscribeOptions&lt;/span&gt; &lt;span class="n"&gt;options&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;ul&gt;
&lt;li&gt;  &lt;strong&gt;Service Call Integration&lt;/strong&gt;: For request-response bidirectional communication, the platform provides a unified abstraction through the &lt;code&gt;IRpcService&lt;/code&gt; interface. &lt;strong&gt;NopRPC, its core implementation, offers a Feign-like strongly-typed client calling experience in about 3000 lines of code&lt;/strong&gt;. It supports creating proxy interfaces via runtime reflection or compile-time code generation, transparently mapping local method calls to remote &lt;code&gt;IRpcService&lt;/code&gt; calls.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Unified two-way RPC abstraction&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IRpcService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;CompletionStage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;callAsync&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;serviceMethod&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
          &lt;span class="nc"&gt;ApiRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&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;ICancelToken&lt;/span&gt; &lt;span class="n"&gt;cancelToken&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Standardized response wrapper for easy error handling and cross-protocol adaptation&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// For adapting command-line return codes&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;code&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;msg&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="n"&gt;data&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 platform also provides adapters like &lt;code&gt;MessageRpcClient&lt;/code&gt;/&lt;code&gt;MessageRpcServer&lt;/code&gt; to &lt;strong&gt;achieve flexible conversion of communication patterns&lt;/strong&gt;: the core mechanism is request-response correlation based on message IDs. The client generates a unique ID for each request, sends it to a request topic, and waits for a response with the corresponding ID on a response topic. The server subscribes to the request topic, processes the request, and sends the result (or error) along with the ID to the response topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Similarly, the capabilities of &lt;code&gt;IRpcService&lt;/code&gt; can be used to simulate a one-way &lt;code&gt;IMessageService&lt;/code&gt; interface over a two-way RPC channel&lt;/strong&gt;. This bidirectional adaptation capability demonstrates the flexibility and symmetry of the communication abstraction layer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distributed Transaction Coordination&lt;/strong&gt;: For business scenarios requiring strong consistency, the platform supports &lt;strong&gt;TCC (Try-Confirm-Cancel)&lt;/strong&gt; and &lt;strong&gt;Saga&lt;/strong&gt; patterns for distributed transactions through the &lt;strong&gt;&lt;code&gt;NopTcc&lt;/code&gt;&lt;/strong&gt; component. Transaction boundaries and compensation logic are defined via annotations or tcc configurations in the XBiz model, coordinating business operations across multiple services to ensure eventual consistency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DSL-izing and Dynamic Evolution of the Anti-Corruption Layer (ACL)&lt;/strong&gt;: When model transformation is needed, the &lt;strong&gt;Anti-Corruption Layer&lt;/strong&gt; is no longer scattered throughout the business code. The Nop Platform recommends using the &lt;strong&gt;&lt;code&gt;Xpl&lt;/code&gt; template language&lt;/strong&gt; or a dedicated &lt;strong&gt;transformation DSL&lt;/strong&gt; to perform model translation during load-time or compile-time, ensuring the runtime domain core remains unpolluted by external models.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Powerful Record Mapping&lt;/strong&gt;: The platform includes a dedicated &lt;strong&gt;&lt;code&gt;record-mapping&lt;/code&gt;&lt;/strong&gt; DSL for mapping between two complex objects. It supports conditional mapping, many-to-one/one-to-many transformations, dictionary lookups, and other advanced features, greatly simplifying model transformation logic.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Multi-format Codec and Batch Processing&lt;/strong&gt;: The &lt;code&gt;record&lt;/code&gt; model itself supports encoding and parsing of binary and text formats, which can be automatically used for parsing and generating TCP messages, data files, etc. Combined with the &lt;strong&gt;&lt;code&gt;NopBatch&lt;/code&gt;&lt;/strong&gt; model, it's easy to implement multi-machine, multi-threaded, chunked parallel data processing, providing powerful support for high-performance data integration and ETL scenarios.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Dynamically Evolving Anti-Corruption Logic&lt;/strong&gt;: The logic of the anti-corruption layer can also be dynamically evolved through the &lt;strong&gt;Delta customization mechanism&lt;/strong&gt;, ensuring that integration logic can adapt to changes in external systems without modifying the core domain model.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The decay of architecture essentially stems from the system being continuously eroded by random, accidental requirements, leading to an increase in system entropy. &lt;strong&gt;Various architectural methods are essentially trying to prevent this entropy increase, but the law of entropy in physics states that this is an unavoidable fate for any system. However, if we change our perspective, even if we cannot completely stop entropy from increasing, we can try to control where it occurs&lt;/strong&gt;. By isolating random and accidental requirements into independent Delta increments, the overall integrity of the core architecture is decoupled from ever-changing demands, thereby achieving long-term stability and systematically slowing down the process of decay.&lt;/p&gt;

&lt;h4&gt;
  
  
  9.1.3 Guardrails for Hexagonal Architecture: Descriptive Contracts Derived from &lt;code&gt;BizModel&lt;/code&gt; and &lt;code&gt;XMeta&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;After clarifying the collaboration mechanisms between contexts, we turn to architectural governance within a context. The core design principle of the Nop Platform is &lt;strong&gt;minimal information expression&lt;/strong&gt;: business descriptions should only contain core domain concepts (What), while delaying or omitting specific technical implementation details (How). This descriptive approach naturally possesses &lt;strong&gt;framework-neutrality&lt;/strong&gt; (independent of any specific runtime), providing an ideal engineering foundation for implementing Hexagonal Architecture.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Technology-Neutral Port Definitions&lt;/strong&gt;: The service &lt;strong&gt;ports&lt;/strong&gt; provided by a context are represented in code as plain Java classes based on &lt;code&gt;@BizModel&lt;/code&gt; (or equivalent XBiz DSL models). Annotations like &lt;code&gt;@BizMutation&lt;/code&gt;/&lt;code&gt;@BizQuery&lt;/code&gt; only declare business semantics, &lt;strong&gt;without containing any HTTP paths, methods, or other protocol-specific information&lt;/strong&gt;. This ensures the purity of the domain model and its potential for multi-protocol adaptation (e.g., GraphQL, gRPC) from the source.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Contracts Uniquely Derived from Models&lt;/strong&gt;: The complete contract for a port is uniquely derived from the &lt;strong&gt;XMeta model&lt;/strong&gt; as the Single Source of Truth (SSOT). This model defines data structures, validation rules, and permissions in a purely descriptive manner, and automatically generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  GraphQL Schema and OpenAPI documentation&lt;/li&gt;
&lt;li&gt;  Runtime input validation logic&lt;/li&gt;
&lt;li&gt;  Front-end page skeletons and form rules
This ensures &lt;strong&gt;source-of-truth consistency&lt;/strong&gt; from the model to various contract forms.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supplementing Implementation Details via &lt;code&gt;Delta&lt;/code&gt;&lt;/strong&gt;: Based on Reversible Computation theory, the platform allows for the &lt;strong&gt;non-invasive addition&lt;/strong&gt; of protocol-specific details through the &lt;code&gt;Delta&lt;/code&gt; mechanism. For example, a custom URL path can be specified in XMeta via the &lt;code&gt;rest:path&lt;/code&gt; extension attribute. This supplementary information is &lt;strong&gt;optional and localized&lt;/strong&gt;, achieving a unification of minimal expression and full customization.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configurable Replacement of Adapters&lt;/strong&gt;: All interactions with external infrastructure (databases, message queues, etc.) are handled through &lt;strong&gt;Adapters/Drivers&lt;/strong&gt;. These adapters are where framework dependencies are concentrated and can be replaced via Nop's IoC container in the &lt;code&gt;_delta&lt;/code&gt; directory through configuration, &lt;strong&gt;without modifying the core code&lt;/strong&gt;. This ensures the isolation of the domain core from external technical implementations at the architectural level.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Closing the Theoretical Loop: From Minimal Expression to Framework Neutrality&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Nop Platform's DSL models are a minimal, descriptive representation of business information. They capture the most stable and essential business structures, becoming the &lt;strong&gt;standard intermediate representation&lt;/strong&gt; for free transformation between different technical frameworks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Inner Logic of Minimal Information Expression&lt;/strong&gt;: It means describing only the goal (What) while omitting execution details (How). If multiple frameworks all achieve true minimal expression, their information content will inevitably converge toward uniqueness. This uniqueness guarantees that a &lt;strong&gt;reversible, equivalent transformation&lt;/strong&gt; must exist between the different framework representations. By inserting a formal transformation layer into the architecture and combining it with the principle of minimal expression, framework neutrality is naturally achieved.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This purely POJO-based, minimal information expression brings a direct engineering advantage: Nop Platform's API service functions can always be unit-tested in a pure fashion. Because its input parameters and return objects are plain Java objects, testing does not require simulating complex web containers or framework contexts. One can simply construct POJO inputs and validate POJO outputs, which greatly reduces testing costs and, in turn, proves the purity and framework-neutrality of its architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.2 Platformizing Tactical Design: Built-in Patterns and Emergent Robustness
&lt;/h3&gt;

&lt;p&gt;The Nop Platform internalizes the complex tactical patterns of DDD into standard platform capabilities, allowing developers to naturally follow best practices without conscious effort.&lt;/p&gt;

&lt;h4&gt;
  
  
  9.2.1 Aggregates, Entities, and Value Objects: Unified by &lt;code&gt;NopORM&lt;/code&gt; and &lt;code&gt;XMeta&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The Nop Platform provides a unified, efficient, and domain-aligned design foundation for DDD tactical modeling through its &lt;code&gt;NopORM&lt;/code&gt; engine and &lt;code&gt;XMeta&lt;/code&gt; metadata model. Its implementation retains the core value of these patterns while avoiding some of the rigid designs of traditional ORMs (like JPA), reflecting the "progressive" and "delta-based" philosophy guided by Reversible Computation theory.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Entity Generation and Extension: The Generation Gap Pattern&lt;/strong&gt;&lt;br&gt;
Entities in the Nop Platform are directly generated from the ORM model and adopt the classic &lt;strong&gt;Generation Gap Pattern&lt;/strong&gt;. Each entity is generated in two parts: a base class maintained by tools (e.g., &lt;code&gt;_NopAuthUser&lt;/code&gt;) and a subclass that developers can freely extend (e.g., &lt;code&gt;NopAuthUser&lt;/code&gt;). This pattern perfectly separates &lt;strong&gt;mechanical code&lt;/strong&gt; from &lt;strong&gt;business code&lt;/strong&gt;, ensuring that developer-added business methods are safely preserved when code is regenerated after model changes. Since &lt;code&gt;NopORM&lt;/code&gt; entities naturally support one-to-one and one-to-many associations and can directly map rich object graphs, the entity itself often naturally assumes the role of an aggregate root in many scenarios, eliminating the need for extra abstraction layers. Domain logic can operate directly on the association graph centered on the entity, and developers only need to add auxiliary domain methods to the entity (e.g., &lt;code&gt;order.calculateTotalAmount()&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pragmatic Handling of Associations: Re-examining "Many-to-Many"&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;NopORM&lt;/code&gt; was intentionally designed &lt;strong&gt;without built-in support for many-to-many associations&lt;/strong&gt;. This decision stems from an insight into the nature of relational databases—they do not directly support many-to-many relationships but implement them through an intermediate table. NopORM encourages developers to explicitly define the intermediate entity (e.g., &lt;code&gt;OrderLine&lt;/code&gt;), thereby preserving maximum flexibility and extensibility in the model. At the same time, to provide convenience at the domain layer, the platform supports the &lt;strong&gt;automatic generation of helper methods on entities that simulate many-to-many associations&lt;/strong&gt; through a marker during code generation. For example, the &lt;code&gt;order.getProducts()&lt;/code&gt; method can internally access the &lt;code&gt;order.getOrderLines()&lt;/code&gt; collection and then retrieve the &lt;code&gt;Product&lt;/code&gt; associated with each &lt;code&gt;OrderLine&lt;/code&gt; to compose the return value. This allows developers to program in a natural object-oriented way at the domain layer while maintaining precise mapping and control of relationships at the persistence layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Entities with Built-in Deltas: &lt;code&gt;OrmEntity&lt;/code&gt; and State Tracking&lt;/strong&gt;&lt;br&gt;
Unlike JPA's transparent lazy loading and implicit dirty checking, &lt;code&gt;NopORM&lt;/code&gt; provides an active &lt;code&gt;OrmEntity&lt;/code&gt; base implementation. This base class accurately tracks all changed properties through a &lt;code&gt;dirtyProps&lt;/code&gt; set and automatically records the values before and after modification. This means &lt;strong&gt;every &lt;code&gt;OrmEntity&lt;/code&gt; instance has a built-in "delta" representation of its own state changes&lt;/strong&gt;. This mechanism offers two core advantages:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.  **High-Performance Delta Updates**: When saving an entity, `NopORM` can generate and execute SQL only for the changed fields, rather than updating the entire object.
2.  **Safe Domain Data Merging**: Using the `OrmEntityCopier` tool, complex JSON data from the front end (which can be seen as a data delta `Δ`) can be safely and efficiently merged into the current aggregate root object. This achieves an effect similar to `aggregateRoot.merge(Δ)`, which is crucial for handling concurrent updates and command merging.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Essence and Implementation of Value Objects: &lt;code&gt;OrmComponent&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
The essence of a Value Object is not just its immutability, but more importantly, that it &lt;strong&gt;encapsulates a cohesive set of business rules and invariants&lt;/strong&gt;. NopORM implements this encapsulation through the &lt;code&gt;IOrmComponent&lt;/code&gt; interface, which is similar in role to JPA's &lt;code&gt;@Embeddable&lt;/code&gt; components. However, Nop's design philosophy is &lt;strong&gt;progressive and view-based&lt;/strong&gt;, in stark contrast to JPA's rigid "either-or" choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;JPA's Rigidity&lt;/strong&gt;: A field is either a native field or encapsulated in a Component; you must choose one.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;NopORM's Flexibility&lt;/strong&gt;: &lt;strong&gt;It always generates native get/set methods for every database field&lt;/strong&gt;, ensuring the most basic access capability. At the same time, &lt;code&gt;OrmComponent&lt;/code&gt; is designed as a &lt;strong&gt;computable, non-invasive "view"&lt;/strong&gt; built on top of the entity's fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This "view" model brings unprecedented flexibility:&lt;/p&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.  **A single field can be reused by multiple Components**: For example, a `latitude/longitude` field can belong to both a `Geolocation` Component and a `RegionBoundary` Component.
2.  **Robust handling of nulls**: When a Component is composed of multiple fields, a `null` value in one of them **does not cause the entire Component object to be `null`**. The Component always exists, and its internal methods can robustly handle partially missing data, avoiding the potential null pointer traps found in JPA.
3.  **Explicit lifecycle control**: The `IOrmComponent` interface defines methods like `flushToEntity` and `reset`, making the timing of data synchronization between the Component and its owning entity controllable and explicit. This is particularly useful for handling complex derived logic and temporary computed states.

Therefore, in NopORM, a Value Object is seen more as a **carrier of domain rules** and a **consistent view of data**, rather than a simple data container. Its immutability is not a mandatory requirement but is determined by the needs of the invariants it encapsulates.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamic Extension of Entity Models: Built-in Extension Fields Mechanism&lt;/strong&gt;&lt;br&gt;
To cope with frequent changes in business models and avoid the real-world challenge of frequent database table modifications, the Nop Platform has a built-in, comprehensive &lt;strong&gt;Extension Fields&lt;/strong&gt; mechanism in &lt;code&gt;NopORM&lt;/code&gt;. By simply adding a &lt;code&gt;use-ext-field&lt;/code&gt; tag to an entity in the Excel data model, you can dynamically add any number of extension fields to the entity without modifying the DDL. These fields are stored uniformly in a dedicated extension table (e.g., &lt;code&gt;nop_sys_ext_field&lt;/code&gt;) and, through the ORM engine, provide an &lt;strong&gt;access experience at the entity object level that is indistinguishable from native fields&lt;/strong&gt;. Whether in Java code, EQL queries, or GraphQL interfaces, extension fields can be used, filtered, and sorted just like regular fields. This mechanism provides a standardized solution for resolving customization conflicts in productized software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seamless Data Flow and Validation from Port to Entity&lt;/strong&gt;&lt;br&gt;
The Nop Platform builds an automated, metadata-driven data pipeline from external ports to internal domain entities. The core of this lies in a multi-layered, customizable meta-model system:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.  **ORM Model (`EntityModel`)**: An `OrmEntity` can directly access its `EntityModel`, which contains complete reflection information at the ORM layer. This is the metadata foundation that supports **persistence concerns** like multi-tenancy, logical deletion, and field encryption.
2.  **XMeta Model**: The **data contract and validation rules** for external ports (like GraphQL, RPC) are defined by the `XMeta` metadata model. `XMeta` can be automatically generated from the ORM entity model (e.g., generating `_NopAuthUser.xmeta`) and also follows the **Generation Gap Pattern**—developers can customize, override, or extend the auto-generated rules in the non-underscored `NopAuthUser.xmeta` file.
3.  **End-to-End Data Processing**: Data from the front end is first validated and transformed by the `ObjMetaBasedValidator`, which is based on `XMeta`. Configurations in `XMeta` like `mapToProp`, `getter`, and `setter` enable declarative implementation of needs like **front-end/back-end property name mapping**, **data format conversion**, and **complex logic computation**. The `validatedData` obtained after validation and transformation is finally merged into the domain entity object using the efficient `OrmEntityCopier` tool. This mechanism ensures the **security, correctness, and semantic consistency** of data as it crosses system boundaries, while liberating developers from tedious data glue code.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Domain-Driven Invariant Abstraction: &lt;code&gt;domain&lt;/code&gt; and Metaprogramming&lt;/strong&gt;&lt;br&gt;
The Nop Platform further deepens the "domain-driven" concept by introducing the concept of &lt;strong&gt;data domains (&lt;code&gt;domain&lt;/code&gt;)&lt;/strong&gt; at the field level. This is similar to a Domain in PowerDesigner and serves as an abstraction for field-level business semantics and invariants. For example, a field can be assigned a &lt;code&gt;domain&lt;/code&gt; like &lt;code&gt;currency&lt;/code&gt; or &lt;code&gt;createTime&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This simple configuration triggers a wide range of &lt;strong&gt;cascading semantic effects&lt;/strong&gt; across the platform, perfectly embodying Nop's design philosophy of "few assumptions, general mechanisms":&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.  **Persistence Behavior**: A field marked as `createTime` will **automatically** be set to the current time when the entity is saved, without any manual coding.
2.  **Front-end Control Binding**: Front-end tag libraries like `control.xlib` will automatically recognize the `domain` configuration and look for a corresponding dedicated control (e.g., `&amp;lt;editor-currency&amp;gt;`), achieving **automatic mapping from domain semantics to UI implementation**.
3.  **Interface Model Generation**: Even more powerfully, through metaprogramming rules defined in `meta-prop.xlib`, a `domain` can **dynamically generate or correct property definitions in XMeta**. For example, for a domain marked as a comma-separated list, the platform will automatically apply transformation rules to convert a `String` type to `List&amp;lt;String&amp;gt;` at the interface level and automatically inject serialization (`transformOut`) and deserialization (`transformIn`) logic.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Metaprogramming rule example: dynamically generate List&amp;lt;String&amp;gt; schema and transformation logic for the csv-list domain --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;domain-csv-list&lt;/span&gt; &lt;span class="na"&gt;outputMode=&lt;/span&gt;&lt;span class="s"&gt;"node"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;attr&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"propNode"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;prop&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"${propNode.getAttr('name')}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;schema&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"List&amp;lt;String&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;transformIn&amp;gt;&lt;/span&gt;return value?.$toCsvListString();&lt;span class="nt"&gt;&amp;lt;/transformIn&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;transformOut&amp;gt;&lt;/span&gt;return value?.$toCsvList();&lt;span class="nt"&gt;&amp;lt;/transformOut&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/prop&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/domain-csv-list&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The introduction of these rules is not hard-coded into the platform. Instead, they are dynamically implemented through metaprogramming segments like &lt;code&gt;x:post-extends&lt;/code&gt; in XMeta files, which call &lt;strong&gt;general metaprogramming directives&lt;/strong&gt; like &lt;code&gt;&amp;lt;meta-gen:GenPropFromDomain/&amp;gt;&lt;/code&gt;. &lt;strong&gt;The Nop Platform has very few built-in assumptions; a large number of features and rules are introduced and composed on-demand through general, reversible metaprogramming mechanisms like &lt;code&gt;x:gen-extends&lt;/code&gt; and &lt;code&gt;x:post-extends&lt;/code&gt;.&lt;/strong&gt; This allows the platform's core to remain extremely concise while possessing nearly limitless semantic extension capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.2.2 Transparent Services and Repositories: NopTaskFlow Orchestration and the Generic &lt;code&gt;EntityDao&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The Nop Platform internalizes DDD's complex tactical patterns into standard platform capabilities, with the transparent design of Repositories and Services being particularly prominent. Through the unified &lt;code&gt;IEntityDao&lt;/code&gt; interface, powerful &lt;code&gt;QueryBean&lt;/code&gt; capabilities, and the &lt;code&gt;NopTaskFlow&lt;/code&gt; logic orchestration engine, developers can naturally follow best practices without conscious effort.&lt;/p&gt;

&lt;h4&gt;
  
  
  Unified Repository Abstraction: The Complete &lt;code&gt;IEntityDao&lt;/code&gt; Interface
&lt;/h4&gt;

&lt;p&gt;In NopORM, repositories are completely transparent. Through the unified &lt;code&gt;DaoProvider&lt;/code&gt;, developers can obtain a strongly-typed &lt;code&gt;IEntityDao&amp;lt;T&amp;gt;&lt;/code&gt; interface (e.g., &lt;code&gt;IEntityDao&amp;lt;NopAuthUser&amp;gt;&lt;/code&gt;). Although each entity has a corresponding Dao interface, business logic typically &lt;strong&gt;only uses the Dao interface of the aggregate root&lt;/strong&gt;, which naturally reinforces the DDD concept of aggregate boundaries.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IEntityDao&lt;/code&gt; provides a very complete set of CRUD operations, &lt;strong&gt;eliminating the need to derive custom repositories&lt;/strong&gt;:&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="c1"&gt;// Query by equality&lt;/span&gt;
&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;example&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;User&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;IEntityDao&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;daoProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;daoFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&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="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;userList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAllByExample&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&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="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pageList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findPageByExample&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&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;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROP_NAME_status&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="kc"&gt;true&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="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findFirstByExample&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;countByExample&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveEntity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newEntity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Powerful &lt;code&gt;QueryBean&lt;/code&gt;: Standardized Encapsulation for Complex Queries
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;QueryBean&lt;/code&gt; provides rich query condition encapsulation, supporting various query scenarios from simple to complex:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Complex Condition Queries&lt;/strong&gt;&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="c1"&gt;// Similar to MyBatisPlus's LambdaQueryWrapper&lt;/span&gt;
&lt;span class="nc"&gt;QueryBean&lt;/span&gt; &lt;span class="n"&gt;query&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;QueryBean&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFilter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROP_NAME_username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Zhang San"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFilter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;or&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;between&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROP_NAME_age&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROP_NAME_gender&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&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="na"&gt;addOrderField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROP_NAME_createTime&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;userList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findPageByQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findFirstByQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Embedded Subqueries&lt;/strong&gt;&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="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFilter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;begin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"o.id in (select y.xx from tbl y where y.id=?)"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;asFilter&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Automatic Join Queries&lt;/strong&gt;&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="c1"&gt;// Composite properties are automatically expanded into join queries&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFilter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"product.productType.name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Unified Filter Model&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxva9hrurztreiscr344o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxva9hrurztreiscr344o.png" alt="FilterModel" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Filter provides a standard way to express complex conditional logic, reusable across multiple scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In Java code, built via the &lt;code&gt;FilterBeans&lt;/code&gt; utility class&lt;/li&gt;
&lt;li&gt;  In XML/Xpl templates, using syntax like &lt;code&gt;&amp;lt;eq name="status" value="1" /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Automatically converted to SQL statements or Java Predicates&lt;/li&gt;
&lt;li&gt;  Visually editable in the front-end via a Condition control&lt;/li&gt;
&lt;li&gt;  Used uniformly in rule engines, data permissions, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Unified SQL Management: The &lt;code&gt;sql-lib&lt;/code&gt; Mechanism Surpassing MyBatis
&lt;/h4&gt;

&lt;p&gt;Using the Nop Platform's built-in infrastructure, the &lt;code&gt;sql-lib&lt;/code&gt; model can be implemented in less than 1000 lines of code. It centrally manages all complex SQL/EQL/DQL statements, offering capabilities more powerful than MyBatis:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DQL is a multi-dimensional data query language for OLAP invented by the report vendor Ruqian, allowing business users to perform complex cross-table data analysis with simple syntax. See &lt;a href="http://c.raqsoft.com.cn/article/1653901344139?p=1&amp;amp;m=0" rel="noopener noreferrer"&gt;Say Goodbye to Wide Tables, Achieve a New Generation of BI with DQL - Qian Academy&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;1. Unified Management of Multiple Query Languages&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;sql-lib&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;sqls&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;sql&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"nativeSql"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/sql&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;eql&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"entityQuery"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/eql&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;query&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"dqlQuery"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/query&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/sqls&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/sql-lib&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Delta Customization Support&lt;/strong&gt;&lt;br&gt;
Customize SQL statements without modifying base product code, using delta files:&lt;br&gt;
&lt;/p&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;sql-lib&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"super"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;sqls&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;eql&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"yyy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/eql&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Overrides the base definition --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/sqls&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/sql-lib&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Powerful XPL Template Language&lt;/strong&gt;&lt;br&gt;
Compared to MyBatis's limited tags, XPL provides full programming capabilities and tag abstraction:&lt;br&gt;
&lt;/p&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;sql&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"complexQuery"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
    select &lt;span class="nt"&gt;&amp;lt;my:CustomFields/&amp;gt;&lt;/span&gt;
    from MyEntity o
    where &lt;span class="nt"&gt;&amp;lt;my:AuthFilter/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;c:if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"${!_.isEmpty(status)}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      and o.status = ${status}
    &lt;span class="nt"&gt;&amp;lt;/c:if&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/sql&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Macro Tag Metaprogramming&lt;/strong&gt;&lt;br&gt;
Simplify SQL writing through compile-time macro transformations:&lt;br&gt;
&lt;/p&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;sql:filter&amp;gt;&lt;/span&gt;and o.classId = :myVar&lt;span class="nt"&gt;&amp;lt;/sql:filter&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Expands at compile-time to --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;c:if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"${!_.isEmpty(myVar)}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  and o.classId = ${myVar}
&lt;span class="nt"&gt;&amp;lt;/c:if&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Secure SQL Output Mode&lt;/strong&gt;&lt;br&gt;
Automatic SQL injection prevention and intelligent parameter handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="c1"&gt;-- Automatically expands to id in (?,?,?) --&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="c1"&gt;-- Automatically parameterized --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Strongly-Typed Mapper Interfaces&lt;/strong&gt;&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;@SqlLibMapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/app/mall/sql/LitemallGoods.sql-lib.xml"&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;interface&lt;/span&gt; &lt;span class="nc"&gt;LitemallGoodsMapper&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;syncCartProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"product"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;LitemallGoodsProduct&lt;/span&gt; &lt;span class="n"&gt;product&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;h4&gt;
  
  
  Service Logic Orchestration: NopTaskFlow's Fine-Grained Flow Control
&lt;/h4&gt;

&lt;p&gt;NopTaskFlow is the Nop Platform's built-in logic orchestration engine. It adopts the design principle of &lt;strong&gt;minimal information expression&lt;/strong&gt; and can support both heavyweight distributed service orchestration and lightweight, fine-grained logic orchestration at the function level within a service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages Over Microservice Orchestration Engines&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Direct Local Function Calls&lt;/strong&gt;: No REST call serialization overhead, supports passing complex domain object references.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Local Environment Integration&lt;/strong&gt;: Supports executing multiple steps within the same database transaction or OrmSession.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Lightweight Execution&lt;/strong&gt;: Can run in a lightweight mode with no third-party dependencies and no persistence.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Asynchrony and State Recovery&lt;/strong&gt;: Built-in support for asynchronous processing, timeout retries, and breakpoint resumption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Seamless Integration of Service Functions and TaskFlow&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;In the xbiz model, a service function can be delegated to a TaskFlow with minimal configuration:&lt;br&gt;
&lt;/p&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;biz&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"/nop/biz/lib/common.xbiz"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;actions&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mutation&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"callTask"&lt;/span&gt; &lt;span class="na"&gt;task:name=&lt;/span&gt;&lt;span class="s"&gt;"test/DemoTask"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/actions&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/biz&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Through compile-time metaprogramming, the platform automatically infers the input and output parameter types and implementation code for the service function from the TaskFlow model, achieving &lt;strong&gt;responsive derivation&lt;/strong&gt;: when the TaskFlow model is modified, the dependent service function definition is automatically updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TaskFlow Example: Order Discount Rules&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xpl&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;book_discount_1&lt;/span&gt;
    &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order.getOriginalPrice()&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;100"&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;order.setRealPrice(order.getOriginalPrice());&lt;/span&gt;
      &lt;span class="s"&gt;logInfo("No discount");&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xpl&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;book_discount_4&lt;/span&gt;
    &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order.getOriginalPrice()&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;300"&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;order.setRealPrice(order.getOriginalPrice() - 100);&lt;/span&gt;
      &lt;span class="s"&gt;logInfo("Discount of 100");&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xpl&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;book_discount_2&lt;/span&gt;
    &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order.getOriginalPrice()&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;100&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order.getOriginalPrice()&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;200"&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;order.setRealPrice(order.getOriginalPrice() - 20);&lt;/span&gt;
      &lt;span class="s"&gt;logInfo("Discount of 20");&lt;/span&gt;
&lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;realPrice&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;order.realPrice&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Rule Engine Integration: NopRule for Professional Decision Handling
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7c7b5bf8djfbidlu42xd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7c7b5bf8djfbidlu42xd.png" alt="DecisionTree" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For complex business rules, the Nop Platform also provides a dedicated rule engine, NopRule, which integrates seamlessly with TaskFlow:&lt;br&gt;
&lt;/p&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;steps&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;xpl&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"calcDiscount"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;rule:Execute&lt;/span&gt; &lt;span class="na"&gt;ruleModelPath=&lt;/span&gt;&lt;span class="s"&gt;"/nop/demo/rule/discount.rule.xlsx"&lt;/span&gt;
                    &lt;span class="na"&gt;inputs=&lt;/span&gt;&lt;span class="s"&gt;"${{order}}"&lt;/span&gt; &lt;span class="na"&gt;xpl:return=&lt;/span&gt;&lt;span class="s"&gt;"outputs"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;c:script&amp;gt;&lt;/span&gt;
        order.setRealPrice(order.originalPrice - outputs.discount);
      &lt;span class="nt"&gt;&amp;lt;/c:script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/xpl&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NopRule supports decision tables and decision trees, which can be configured visually via Excel (or edited online), making it especially suitable for managing complex business rules.&lt;/p&gt;

&lt;h4&gt;
  
  
  Clear Division of Labor in the Service Layer
&lt;/h4&gt;

&lt;p&gt;Through the collaboration of the above components, the Nop Platform achieves a clear division of labor in the service layer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Repository Layer&lt;/strong&gt;: Unified abstraction by &lt;code&gt;IEntityDao&lt;/code&gt;, providing powerful data access.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Domain Logic&lt;/strong&gt;: Complex business rules handled by &lt;code&gt;NopRule&lt;/code&gt;, process orchestration managed by &lt;code&gt;NopTaskFlow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Application Service&lt;/strong&gt;: Hosted by the &lt;code&gt;XBiz&lt;/code&gt; model, responsible for use case orchestration and transaction management.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Query Abstraction&lt;/strong&gt;: All data queries managed uniformly through &lt;code&gt;QueryBean&lt;/code&gt; and &lt;code&gt;sql-lib&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;CRUD Automation&lt;/strong&gt;: The platform automatically handles templated CRUD operations, allowing developers to focus on business logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9.2.3 Natural Emergence of Event-Driven Architecture: Platform-wide Observability and Declarative Event Weaving
&lt;/h3&gt;

&lt;p&gt;Event-driven architecture is the soul of DDD, but traditional implementations often rely on developers manually publishing events in their code. This "deliberate" approach can easily lead to omissions and clutter domain code with technical concerns. The Nop Platform takes a different path: through &lt;strong&gt;system-wide model definitions&lt;/strong&gt; and a &lt;strong&gt;unified delta syntax&lt;/strong&gt;, it transforms the system into a "&lt;strong&gt;naturally observable&lt;/strong&gt;" organism. This allows event listening and triggering to become a side effect that can be &lt;strong&gt;seamlessly woven in at any level in a declarative manner&lt;/strong&gt;, letting an event-driven architecture "emerge" naturally from the platform.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Cross-Context Events: Reliable Event Bus and the &lt;code&gt;Outbox&lt;/code&gt; Pattern&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;For loosely coupled integration between Bounded Contexts, the platform provides a standardized asynchronous event communication abstraction, &lt;code&gt;IMessageService&lt;/code&gt;, with a built-in default implementation, &lt;strong&gt;&lt;code&gt;SysDaoMessageService&lt;/code&gt;&lt;/strong&gt;, based on mechanisms like the &lt;strong&gt;&lt;code&gt;SysEvent&lt;/code&gt;&lt;/strong&gt; table. This implementation is tightly integrated with database transactions, ensuring that domain events are published atomically within the &lt;strong&gt;same database transaction&lt;/strong&gt; as the business operation, providing a reliable engineering foundation for eventual consistency.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;System-wide Observability: A Standardized Coordinate System for Event Triggering&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;As a thoroughly model-driven architecture, the Nop Platform defines DSL models with clear lifecycles at &lt;strong&gt;every level&lt;/strong&gt; of the system. These models naturally standardize event trigger points, providing a unified "&lt;strong&gt;observation coordinate system&lt;/strong&gt;" for declarative event listening:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Service Layer Observation Points&lt;/strong&gt;: In the &lt;strong&gt;&lt;code&gt;XBiz&lt;/code&gt;&lt;/strong&gt; model, which hosts application services, developers can use the &lt;code&gt;observe&lt;/code&gt; section to declaratively configure listeners that trigger before or after a service function executes. These listeners can respond to events on a global EventBus, implementing cross-cutting concerns decoupled from business logic.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Declarative listening in an XBiz model: triggers when an action of the specified BizModel is executed --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;observe&lt;/span&gt; &lt;span class="na"&gt;from=&lt;/span&gt;&lt;span class="s"&gt;"MyBizObj"&lt;/span&gt; &lt;span class="na"&gt;event=&lt;/span&gt;&lt;span class="s"&gt;"createOrder"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Write Xpl template script here to respond to the event, e.g., send notifications, record audit logs --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/observe&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Persistence Layer Observation Points&lt;/strong&gt;: The &lt;code&gt;NopORM&lt;/code&gt; engine, through the &lt;strong&gt;&lt;code&gt;IOrmInterceptor&lt;/code&gt;&lt;/strong&gt; interface, provides extremely fine-grained, entity-level lifecycle events (e.g., &lt;code&gt;pre-save&lt;/code&gt;, &lt;code&gt;post-save&lt;/code&gt;, &lt;code&gt;pre-update&lt;/code&gt;, &lt;code&gt;post-delete&lt;/code&gt;). More importantly, the platform's &lt;strong&gt;&lt;code&gt;XplOrmInterceptorFactoryBean&lt;/code&gt;&lt;/strong&gt; mechanism allows developers to define "&lt;strong&gt;database trigger&lt;/strong&gt;"-style interception logic for specific entities using the Xpl template language, simply by configuring a &lt;code&gt;/_moduleId/orm/app.orm-interceptor.xml&lt;/code&gt; file, without writing any Java code.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;interceptor&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;entity&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"io.nop.auth.dao.entity.NopAuthUser"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;post-save&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"syncToEs"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Declarative implementation: automatically sync to Elasticsearch after a user entity is saved --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/post-save&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/entity&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/interceptor&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Process Layer Observation Points&lt;/strong&gt;: When business logic is finely orchestrated using the &lt;strong&gt;&lt;code&gt;NopTaskFlow&lt;/code&gt;&lt;/strong&gt; engine, the event mechanism becomes even more flexible. Developers can either directly insert &lt;strong&gt;observation steps&lt;/strong&gt; to trigger events at any point in the process or use the Step's &lt;strong&gt;&lt;code&gt;decorator&lt;/code&gt;&lt;/strong&gt; mechanism (which acts similarly to Java annotations) to non-invasively attach event-triggering side-effect logic to a step.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Declarative Event Weaving: Metaprogramming Injection Based on &lt;code&gt;Delta&lt;/code&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The most advanced manifestation of the Nop Platform's event-driven capabilities lies in its &lt;strong&gt;unified delta-based customization ability&lt;/strong&gt;. All DSL models follow the XLang delta syntax, supporting metaprogramming extensions through &lt;code&gt;x:gen-extends&lt;/code&gt; and &lt;code&gt;x:post-extends&lt;/code&gt;. This means that &lt;strong&gt;event listening logic itself can exist outside the base model and be "injected" into existing models during a later customization phase via a &lt;code&gt;Delta&lt;/code&gt; file&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, a standard product module might not initially include audit logging functionality. However, when deploying for a specific client, we can use a &lt;code&gt;_delta&lt;/code&gt; customization file to "apply a delta" to key service methods or entity persistence operations, declaratively adding the logic to trigger audit events. &lt;strong&gt;This approach achieves complete decoupling and on-demand composition of event concerns, making system observability a dynamically evolving feature rather than a fixed, static design.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Closing the Theoretical Loop: From "Deliberate Design" to "Natural Emergence"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the Nop Platform, event-driven is no longer just a tactical pattern in DDD; it is elevated to a &lt;strong&gt;system-level first principle&lt;/strong&gt; that permeates the entire architecture. Through:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Standardized observation points&lt;/strong&gt; (the lifecycles of models at every layer),&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;A unified listening mechanism&lt;/strong&gt; (Observe section, OrmInterceptor, TaskFlow Decorator),&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Delta-based weaving capabilities&lt;/strong&gt; (metaprogramming injection),&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;event listening becomes a "pluggable" capability that can be &lt;strong&gt;declared after the fact, precisely targeted, and non-invasively attached&lt;/strong&gt;. Developers can make the system "grow" event-driven nerve endings without modifying core business logic. This is a profound embodiment of Reversible Computation theory at the architectural level: using a delta (Δ) to superimpose new behavior (⊕) onto an already generated base system (F(X)), ultimately allowing complex event-response capabilities to naturally &lt;strong&gt;emerge&lt;/strong&gt; from the platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.2.4 Queries and Read Models: The Automation of &lt;code&gt;GraphQL&lt;/code&gt; and &lt;code&gt;DataLoader&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A long-standing dilemma in traditional API design is whether to create complex interfaces that lead to "over-fetching" or multiple simple interfaces that cause "under-fetching" and numerous network requests.&lt;/p&gt;

&lt;h4&gt;
  
  
  GraphQL as a Composable Information Algebra System
&lt;/h4&gt;

&lt;p&gt;NopGraphQL fundamentally &lt;strong&gt;reinterprets&lt;/strong&gt; GraphQL, elevating it from a mere API protocol to a &lt;strong&gt;universal engine for information decomposition, composition, and dispatch&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;GraphQL is essentially REST with a standardized, composable &lt;code&gt;@selection&lt;/code&gt; parameter.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;NopAuthDept__findAll&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&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;is equivalent to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/r/NopAuthDept__findAll?@selection=name,status,children{name,status}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means GraphQL is a &lt;strong&gt;natural superset&lt;/strong&gt; of REST: when &lt;code&gt;@selection&lt;/code&gt; is not provided, the system degrades to traditional REST behavior. This mathematically proves that &lt;strong&gt;REST is a special case of GraphQL in select-all mode&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Two-Phase Execution Model: Built-in Separation of Read/Write Concerns
&lt;/h4&gt;

&lt;p&gt;NopGraphQL employs a &lt;strong&gt;two-phase execution model&lt;/strong&gt;, naturally achieving an architectural separation of read and write operations, which aligns with the principles of CQRS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Phase One: Core Business Execution (within a transaction)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Automatically starts and commits a database transaction for &lt;code&gt;@BizMutation&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Executes the main service function to complete the state change.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The transaction is committed immediately&lt;/strong&gt;, releasing the database connection in the shortest possible time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Phase Two: Result Processing (read-only)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Invokes &lt;code&gt;@BizLoader&lt;/code&gt; on-demand based on the client's &lt;code&gt;FieldSelection&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  The ORM Session is forced into &lt;strong&gt;read-only mode&lt;/strong&gt; to prevent state pollution.&lt;/li&gt;
&lt;li&gt;  Performs field-level permission checks and data masking.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;CQRS Connection&lt;/strong&gt;: Through &lt;code&gt;@BizLoader&lt;/code&gt; and the &lt;code&gt;XMeta&lt;/code&gt; model, the system can define &lt;strong&gt;data structures and loading logic specifically for query scenarios&lt;/strong&gt;. This forms a natural separation of responsibilities from the write model, which primarily focuses on state changes and business rules. The read side can freely compose data across aggregates, define computed fields, and apply performance optimization strategies without being constrained by the write model's transaction boundaries or function signatures.&lt;/p&gt;

&lt;h4&gt;
  
  
  DataLoader Automation: Solving the N+1 Query Problem
&lt;/h4&gt;

&lt;p&gt;Achieve orthogonal decomposition of knowledge through the &lt;code&gt;@BizLoader&lt;/code&gt; mechanism:&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="c1"&gt;// Core query&lt;/span&gt;
&lt;span class="nd"&gt;@BizQuery&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NopAuthUser&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&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;id&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;userDao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Associated loader&lt;/span&gt;
&lt;span class="nd"&gt;@BizLoader&lt;/span&gt;
&lt;span class="kd"&gt;public&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;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;roles&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@ContextSource&lt;/span&gt; &lt;span class="nc"&gt;NopAuthUser&lt;/span&gt; &lt;span class="n"&gt;user&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;roleDao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findRolesByUserId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&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 a client queries &lt;code&gt;{ user(id:"123") { id, name, roles } }&lt;/code&gt;, the engine automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Calls &lt;code&gt;getUser&lt;/code&gt; to fetch the core object.&lt;/li&gt;
&lt;li&gt; Discovers the need for the &lt;code&gt;roles&lt;/code&gt; field and matches it to the &lt;code&gt;roles&lt;/code&gt; loader.&lt;/li&gt;
&lt;li&gt; Merges and batches queries through the DataLoader mechanism, &lt;strong&gt;solving the N+1 problem at its root&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Performance Optimization: Early Information Use and Execution Pruning
&lt;/h4&gt;

&lt;p&gt;Avoid unnecessary computations in phase one by checking the field selection:&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;@BizQuery&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="nf"&gt;getOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&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;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;FieldSelection&lt;/span&gt; &lt;span class="n"&gt;selection&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderDao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Perform expensive calculation only when the client needs it&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;selection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"salesAnalysis"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSalesAnalysis&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analysisService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;calculateAnalysis&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&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;order&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;h4&gt;
  
  
  The Dual Unity of Aggregate Roots and GraphQL
&lt;/h4&gt;

&lt;p&gt;The Nop Platform reinterprets the meaning of an Aggregate Root:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;An Aggregate Root is an information construction operation&lt;/strong&gt;: It builds a unified, highly cohesive "conceptual map."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;GraphQL is an information deconstruction operation&lt;/strong&gt;: It dynamically trims the required data through &lt;code&gt;FieldSelection&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dual unity of "aggregation" and "selection" ensures both the expressive power of the model and the efficiency of the runtime, allowing the front-end and back-end to evolve independently with clear contracts.&lt;/p&gt;

&lt;h4&gt;
  
  
  Security Assurance: Field-Level Permission Control
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Field-level security&lt;/strong&gt; is built into the &lt;code&gt;XMeta&lt;/code&gt; model.&lt;/li&gt;
&lt;li&gt;  Field-level ACLs and data masking policies pre-prune permissions during the query plan generation phase.&lt;/li&gt;
&lt;li&gt;  Unauthorized access and side-channel information leaks are prevented at the source.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Theoretical Value
&lt;/h4&gt;

&lt;p&gt;The innovation of NopGraphQL lies in &lt;strong&gt;elevating APIs from a "collection of endpoints" to a "composable information algebra system."&lt;/strong&gt; Business logic is written once and can be automatically adapted by the engine to multiple protocols like GraphQL, REST, and gRPC, creating a truly &lt;strong&gt;living information space&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.2.5 Eradicating Stubborn Problems: Solving &lt;code&gt;N+1&lt;/code&gt; and &lt;code&gt;Database Deadlocks&lt;/code&gt; at the Source
&lt;/h3&gt;

&lt;p&gt;In traditional DDD practice, the inherent conflict between object-oriented navigational queries and database transaction mechanisms often leads to the stubborn performance and concurrency problems of &lt;code&gt;N+1 queries&lt;/code&gt; and &lt;code&gt;database deadlocks&lt;/code&gt;. The Nop Platform addresses these issues with targeted mitigation and avoidance through the systematic design of its &lt;code&gt;NopORM&lt;/code&gt; engine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Farewell to N+1: Declarative Batch Loading&lt;/strong&gt;
The &lt;code&gt;batchLoadProps&lt;/code&gt; function provided by &lt;code&gt;IEntityDao&lt;/code&gt; allows developers to preload all necessary associated properties with a single batch query after fetching a list of entities. A simple declaration is all it takes to solve the N+1 problem without breaking the encapsulation of the aggregate.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&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;MyEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Preload multi-level associations with a single batch query&lt;/span&gt;
&lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;batchLoadProps&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"children"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"parent.parent"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Its internal mechanism is similar to GraphQL's `DataLoader` but is deeply optimized for the association graph characteristics of ORM entities. Compared to the dilemma in JPA—where using entity navigation is most natural, but performance bottlenecks force invasive rewrites of business code—NopORM's **descriptive batch loading** provides a **performance optimization path decoupled from business logic**.

This mechanism also broadens the applicability of aggregate roots. For scenarios like batch processing that require loading large amounts of data, developers do not need to abandon the object-oriented programming model. Simply executing `batchLoad` after loading each chunk is enough to efficiently assemble the complete object graph. More importantly, in higher-level frameworks like `NopGraphQL` and `SqlManager`, batch loading can be automatically analyzed and executed based on the client's Field Selection, achieving **performance optimization that is transparent and imperceptible** to the developer.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Systematically Avoiding Deadlocks: Globally Ordered Write Operations&lt;/strong&gt;&lt;br&gt;
NopORM abandons JPA's &lt;code&gt;auto-flush&lt;/code&gt; mode, which is prone to causing chaos. Write operations like &lt;code&gt;dao.save(entity)&lt;/code&gt; only register the entity's state with the current &lt;code&gt;OrmSession&lt;/code&gt; and do not immediately generate SQL. All actual database write operations are deferred until just before the transaction commits, to be executed in a single, unified &lt;code&gt;flush&lt;/code&gt; operation.&lt;/p&gt;

&lt;p&gt;During this process, NopORM &lt;strong&gt;globally sorts all pending INSERT, UPDATE, and DELETE operations based on table dependencies and entity primary keys&lt;/strong&gt;. This mechanism ensures that in any concurrent scenario, the order in which multiple transactions acquire database locks is &lt;strong&gt;deterministic and consistent&lt;/strong&gt;, thus greatly reducing the probability of deadlocks at a system level. The tricky concurrency problem of deadlocks is no longer solely reliant on developers following fragile best practices to avoid; it is largely "&lt;strong&gt;designed away&lt;/strong&gt;" through architectural design.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Addendum: OrmSession as a LoadingCache
&lt;/h4&gt;

&lt;p&gt;In essence, an &lt;code&gt;OrmSession&lt;/code&gt; can be viewed as a &lt;code&gt;LoadingCache&lt;/code&gt; specifically designed for ORM. When associated data is accessed through object navigation, if the target entity is not yet loaded, the Session automatically calls the corresponding &lt;code&gt;Persister&lt;/code&gt; to load it from the database. With NopORM, we can achieve &lt;strong&gt;data source transparency&lt;/strong&gt;: developers can manually "inject" entity objects obtained through any means (e.g., remote API calls, message queues, file parsing) into the Session using the &lt;code&gt;attach&lt;/code&gt; method. Once managed by the Session, these objects are indistinguishable from entities loaded from the database; all mechanisms for association access, state tracking, and persistence based on object navigation will work correctly. This ensures that &lt;strong&gt;when the data source changes, the core domain model code requires no modification&lt;/strong&gt;, truly achieving data-source-agnostic domain programming.&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;interface&lt;/span&gt; &lt;span class="nc"&gt;IOrmSession&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Attaches an entity from outside the session to the session.
     *
     * @param entity
     */&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOrmEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;cascade&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Assumes all data is in memory, directly finds collection elements in the session,
     * and assembles them into a collection object.
     *
     * @param collectionName
     */&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;assembleAllCollectionInMemory&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;collectionName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;assembleCollectionInMemory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IOrmEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;coll&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;
  
  
  &lt;strong&gt;Architectural Panorama: A Unified Technical Core and Platformized Capabilities&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Through the detailed analysis above, we have seen how the Nop Platform internalizes DDD's tactical patterns into standard platform capabilities. The following diagram provides a panoramic view of how these capabilities work together around a unified technical core to form a complete tactical design support system:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxofz1c17sfjbr9ihz37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxofz1c17sfjbr9ihz37.png" alt="NopGraphQL" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This architecture reflects the following core design principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Domain Model at the Center&lt;/strong&gt;: &lt;code&gt;BizObject&lt;/code&gt; and &lt;code&gt;ORM&lt;/code&gt; form a unified domain object model, hosting the core business logic.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Multi-Engine Platform Integration&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;GraphQL&lt;/code&gt; engine provides flexible query capabilities, automatically optimizing N+1 problems.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;Workflow&lt;/code&gt; and &lt;code&gt;StateMachine&lt;/code&gt; engines drive complex business processes.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;BizModel&lt;/code&gt; achieves organic composition of business logic through a "dispatch-extend" mechanism.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Transparent Data Access Enhancement&lt;/strong&gt;: The &lt;code&gt;ORM&lt;/code&gt; layer has built-in enterprise-grade features like lazy loading, batch loading, extension fields, and distributed transactions.&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Orthogonal Security Architecture&lt;/strong&gt;: Data permissions and operation permissions are treated as separate concerns, injected into business processes through standard interfaces.&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Diverse Integration Support&lt;/strong&gt;: Native support for integration patterns like &lt;code&gt;MessageQueue&lt;/code&gt;, &lt;code&gt;RPC&lt;/code&gt;, and &lt;code&gt;BatchFile&lt;/code&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This design allows developers to naturally achieve a robust and evolvable system architecture without consciously following DDD patterns—this is the engineering embodiment of "emergent robustness."&lt;/p&gt;

&lt;h2&gt;
  
  
  9.3 Programmable Evolution: The "Trinity" Paradigm of Reversible Computation
&lt;/h2&gt;

&lt;p&gt;Reversible Computation provides a solid mathematical and engineering foundation for the implementation and long-term evolution of DDD models through the unified paradigm &lt;code&gt;Y = F(X) ⊕ Δ&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.3.1 The Unified Evolution Formula: &lt;code&gt;Effective Model = Generator&amp;lt;Base Model&amp;gt; ⊕ Δ(Delta)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In the Nop Platform, the construction of any model follows this formula. Whether it's a data model, a UI model, or a process model, its final effective form is composed of a base model (often &lt;strong&gt;generated&lt;/strong&gt; from an upstream model) and one or more &lt;strong&gt;Delta&lt;/strong&gt; packages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Profound Mathematical Insight: Full Content is a Special Case of a Delta&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This design is rooted in a profound mathematical principle: &lt;strong&gt;a full representation is just a special case of a delta&lt;/strong&gt; (&lt;code&gt;A = 0 + A&lt;/code&gt;). In any system with a unit element, the full representation is equivalent to "the unit element + itself." For example, in software construction, the "do nothing" null operation is the unit element, and any operation can be seen as a delta on top of that null operation. This seemingly simple cognitive shift is actually a paradigm shift from "action-oriented thinking" to "noun-oriented thinking" and is the key breakthrough in treating &lt;strong&gt;delta as a first-class concept&lt;/strong&gt;. It completely unifies "building from scratch" and "customizing modifications" mathematically, providing unprecedented flexibility for software evolution.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The Engineering Value of Isomorphic Design&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The direct engineering manifestation of this principle is &lt;strong&gt;isomorphic design&lt;/strong&gt;: the format for expressing a delta is identical to that of the full model, eliminating the need for a special format for deltas. Compare JSON Patch with the Nop Platform's implementation:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;JSON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Patch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(Heterogeneous&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;design,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;special&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;format)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"add"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/columns/-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"newColumn"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/columns/2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Nop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Platform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(Isomorphic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;design,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;unified&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;format)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"columns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"newColumn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"column2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"x:override"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&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;JSON Patch uses a completely different syntax and relies on unstable array indices. The Nop Platform's delta maintains the same structure as the full model, using only a few extension attributes like &lt;code&gt;x:override&lt;/code&gt; to express the intent of the change and relying on stable semantic identifiers (like &lt;code&gt;name&lt;/code&gt;) to locate elements. This isomorphic design is consistent throughout the platform: from modified data submitted by the front-end to change records in the back-end database, all use a unified delta representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Breakthrough Insight: The Scope of a Delta Can Cover Any Granularity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recognizing that "full content is a special case of a delta" also shatters a common misconception: that deltas must be small, local changes. In reality, &lt;strong&gt;the scope of a delta can cover any granularity&lt;/strong&gt;—from modifying a single field to refactoring an entire module, and even building a brand new system, all can be expressed through deltas. In a mathematical context with inverse elements, a delta can even express the reverse operation of "from the current system to an empty state." This understanding liberates the mindset of software evolution, providing a unified theoretical framework for system refactoring and customization.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Built-in Delta Support in DSLs: All DSLs Follow a Unified Decomposition and Merge Mechanism&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;All DSLs in the Nop Platform natively support decomposition and merging, implementing complex model management through the standardized XLang Delta syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Inherit a base model via x:extends --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"_NopAuthUser.xmeta"&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xmeta.xdef"&lt;/span&gt;
      &lt;span class="na"&gt;xmlns:x=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdsl.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Dynamically generate model content via metaprogramming --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;x:post-extends&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;biz-gen:GenDictLabelFields&lt;/span&gt; &lt;span class="na"&gt;xpl:lib=&lt;/span&gt;&lt;span class="s"&gt;"/nop/core/xlib/biz-gen.xlib"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/x:post-extends&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/meta&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key mechanisms include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;x:extends&lt;/code&gt;&lt;/strong&gt;: Inherits from an existing model file.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;x:gen-extends&lt;/code&gt;/&lt;code&gt;x:post-extends&lt;/code&gt;&lt;/strong&gt;: Built-in metaprogramming mechanism, implementing the Generator part of Reversible Computation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;x:override&lt;/code&gt;&lt;/strong&gt;: Specifies the node merge strategy (merge, replace, remove, etc.).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Extension Attribute Support&lt;/strong&gt;: All DSL model objects support arbitrary extension attributes without modifying the platform's built-in meta-models.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9.3.2 The Deterministic Construction Phase: &lt;code&gt;S-N-V&lt;/code&gt; (Structure Merge - Normalization - Validation) Loading
&lt;/h3&gt;

&lt;p&gt;The construction process for all DSL models in the Nop Platform is decomposed into three deterministic phases: S (Structure Merge) &lt;strong&gt;→&lt;/strong&gt; N (Normalization) &lt;strong&gt;→&lt;/strong&gt; V (Validation). This layered principle, through clever "process decomposition" and "separation of concerns," solves the core challenges in designing a universal merge algorithm.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The Fundamental Insight: Retreating to Structural Unification&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Similar to how relational databases solve data consistency issues by &lt;strong&gt;retreating to a non-redundant, standardized table structure&lt;/strong&gt;, the Nop Platform achieves unified delta processing by &lt;strong&gt;retreating to a standardized XDSL structural layer&lt;/strong&gt;. That is, delta merging is not performed at the level of parsed, strongly-typed object models, but at a lower-level, standardized tree structure (XNode).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Relational Model Theory&lt;/th&gt;
&lt;th&gt;Reversible Computation Theory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Schema Definition&lt;/td&gt;
&lt;td&gt;XDefinition Meta-model Specification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-redundant Tabular Data&lt;/td&gt;
&lt;td&gt;Non-redundant Tree-like Information Structure: XDSL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On-the-fly computation on standardized data structures: SQL&lt;/td&gt;
&lt;td&gt;Compile-time computation on a generic XNode data structure: XLang&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This "one step back" design allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Decoupling of merge algorithms from business semantics&lt;/strong&gt;: A single universal algorithm can handle the merging of all DSLs.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Deterministic merge results&lt;/strong&gt;: The same input will always produce the same output structure.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Support for unified cross-domain processing&lt;/strong&gt;: DSLs from different business domains use the same merge mechanism.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;"Virtual Time" and Deferred Validation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The S-N-V principle introduces a philosophy of "Virtual Time," which boldly allows a model to exist in a &lt;strong&gt;temporary, semantically inconsistent intermediate state&lt;/strong&gt; during its construction. Before the final validation occurs, the system tolerates the model's "imperfections," thereby completely decoupling the generic "structural arrangement" from the complex "meaning check."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three-Phase Decomposition&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;S - Structure Merge: Generic Tree Structure Operations&lt;/strong&gt;&lt;br&gt;
This phase operates only at the &lt;strong&gt;structural layer&lt;/strong&gt;, executing domain-agnostic, universal algorithms. It mechanically merges the XNode tree based on meta-directives like &lt;code&gt;x:override&lt;/code&gt;, ensuring the merge process satisfies the &lt;strong&gt;associative law&lt;/strong&gt;. The output may be an intermediate model that does not yet satisfy semantic constraints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;N - Normalization: Domain-Specific Semantic Processing&lt;/strong&gt;&lt;br&gt;
On the basis of the merged structure, domain-specific semantic corrections are performed. This is analogous to view computation in relational databases and includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Parsing and applying default values&lt;/li&gt;
&lt;li&gt;  Computing derived properties&lt;/li&gt;
&lt;li&gt;  Expanding shorthand syntax&lt;/li&gt;
&lt;li&gt;  Automatically resolving benign semantic conflicts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;V - Validation: Final Legality Check&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
After all structural semantics have stabilized, a final, global validation is performed to ensure the output is a completely legal model.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Engineering Value: Determinism from Structural Unification&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Unified model loading process: Structure Layer =&amp;gt; Object Layer&lt;/span&gt;
&lt;span class="nx"&gt;modelPath&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;XDSL&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt; &lt;span class="nx"&gt;processing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;DslModel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure-layer-based unified processing ensures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Algorithmic Generality&lt;/strong&gt;: The S phase uses one set of algorithms for all models, with O(1) complexity.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Semantic Extensibility&lt;/strong&gt;: The N/V phases are attached as pluggable rules to specific domains.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;High Runtime Performance&lt;/strong&gt;: All complex transformations are completed at load-time.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Online Dynamic Updates&lt;/strong&gt;: Supports runtime model hot-swapping through a virtual file system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Dynamic Delta-based Updates
&lt;/h4&gt;

&lt;p&gt;How can we ensure runtime state consistency when a DSL model is updated with a delta? To answer this, we can look at the solution provided by microservices architecture.&lt;/p&gt;

&lt;p&gt;Microservices can achieve dynamic rolling updates because of their so-called stateless design. The traditional object-oriented approach encapsulates functions and the data they process into objects, leading to a tangled mess of functions and data—a spaghetti-like structure that is difficult to break down and, consequently, difficult to update partially. Ideally, we want a layered structure, like a mille-feuille pastry, where layers can be added or removed at will.&lt;/p&gt;

&lt;p&gt;The essence of stateless design is the decoupling of processing logic from the runtime state space. The "pure air" of static logic rises, and the "turbid air" of dynamic runtime state sinks. This dynamic state data is pushed out of the static logic structure, with some becoming parameters passed between functions and some becoming persistent data stored in shared storage. This way, the microservice's runtime structure itself no longer explicitly contains state data, so its dynamic updates are not entangled with state space data migration, becoming a problem that can be solved independently.&lt;/p&gt;

&lt;p&gt;When accessing a microservice, we first go to a service registry, dynamically look up the service instance by name, and then send it input parameters. The service instance then automatically loads persistent state data based on these parameters. In the abstract language of functional programming, the process of a microservice corresponds to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  serviceName =&amp;gt; Service =&amp;gt; input =&amp;gt; state =&amp;gt; Result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, in the Nop Platform, the processing of all models follows the same logical structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  modelPath =&amp;gt; XDSL =&amp;gt; DslModel =&amp;gt; arguments =&amp;gt; scope =&amp;gt; Result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like microservices, the dynamic updating of a DSL model can be independent of the structural migration of the state space.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.3.3 The Fractal Software Production Line: &lt;code&gt;XORM&lt;/code&gt; → &lt;code&gt;XMeta&lt;/code&gt; → &lt;code&gt;XView&lt;/code&gt; → &lt;code&gt;XPage&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiu7n4brr3t7h0l0uxg4m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiu7n4brr3t7h0l0uxg4m.png" alt="delta-product-line" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Nop Platform decomposes the process from data to page into a multi-stage &lt;strong&gt;fractal software production line&lt;/strong&gt;. Each transformation step on this line strictly follows the evolution formula of Reversible Computation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;XMeta = Generator&amp;lt;XORM&amp;gt; ⊕ Δ_meta&lt;/code&gt;&lt;br&gt;
&lt;code&gt;XView = Generator&amp;lt;XMeta&amp;gt; ⊕ Δ_view&lt;/code&gt;&lt;br&gt;
&lt;code&gt;XPage = Generator&amp;lt;XView&amp;gt; ⊕ Δ_page&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Essence of Fractal: Infinitely Recursive Decomposition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core of this fractal design is its &lt;strong&gt;self-similarity&lt;/strong&gt;: each component can be further decomposed into a combination of finer-grained generators and deltas. Not only does the final product follow this pattern, but the generators and deltas themselves also follow the same structure:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Generator&amp;lt;X&amp;gt; = Generator&amp;lt;Generator&amp;lt;X&amp;gt;&amp;gt; ⊕ Δ_generator&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Δ_meta = Generator&amp;lt;Δ_base&amp;gt; ⊕ Δ_custom&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Generators can be constructed in layers&lt;/strong&gt;: A base generator can be customized with a delta to create a more specialized generator.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Deltas can be defined recursively&lt;/strong&gt;: A delta itself can be composed from more fundamental deltas via a generator.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Unity at every granularity&lt;/strong&gt;: From the finest-grained field definition to a complete page layout, everything follows the same construction pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Complete Independence at Every Level&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Based on this fractal characteristic, each level possesses complete, independent capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;XMeta Level&lt;/strong&gt;: Can be entirely generated from XORM, written manually from scratch, or built from zero using &lt;code&gt;Generator&amp;lt;Empty&amp;gt; ⊕ Δ_meta&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;XView Level&lt;/strong&gt;: The generator itself can be &lt;code&gt;Generator&amp;lt;XMeta&amp;gt;&lt;/code&gt;, or it can be &lt;code&gt;Generator&amp;lt;Empty&amp;gt;&lt;/code&gt; plus a complete &lt;code&gt;Δ_view&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Arbitrary Combination&lt;/strong&gt;: Any level can selectively use information from the level below or be developed completely independently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This infinitely recursive fractal design completely solves the rigid constraints of traditional MDA (either fully automatic or fully manual), achieving a truly flexible software production line. Developers can intervene at any granularity and any level, using the delta mechanism to achieve all kinds of customization needs, from minor tweaks to fundamental refactoring, while the entire system maintains a unified mathematical structure and predictable behavior.&lt;/p&gt;
&lt;h3&gt;
  
  
  9.3.4 Full-Stack Delta Customization: The Path of Evolution Without Changing a Single Line of Base Code
&lt;/h3&gt;

&lt;p&gt;In the Nop Platform, the Reversible Computation concept of delta customization is systematically realized through the core technology of a &lt;strong&gt;Delta File System&lt;/strong&gt;. This mechanism turns the ideal of deep customization "without changing a single line of base code" into an engineering reality, fundamentally changing the software delivery and evolution model.&lt;/p&gt;
&lt;h4&gt;
  
  
  The Delta File System: The Cornerstone of System-Level Customization
&lt;/h4&gt;

&lt;p&gt;The Nop Platform's virtual file system provides capabilities similar to UnionFS in Docker technology, implementing system-level resource customization through layered overlays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;/_vfs/_delta/default/a.xml&lt;/code&gt; will automatically override &lt;code&gt;/_vfs/a.xml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  All code loaded via &lt;code&gt;ResourceComponentManager.loadComponentModel("/a.xml")&lt;/code&gt; will actually read &lt;code&gt;/_vfs/_delta/default/a.xml&lt;/code&gt; after the delta layer is enabled.&lt;/li&gt;
&lt;li&gt;  Multiple delta layers can be supported by configuring &lt;code&gt;nop.core.vfs.delta-layer-ids&lt;/code&gt;, enabling more complex customization strategies.&lt;/li&gt;
&lt;li&gt;  Model records in the database (e.g., &lt;code&gt;wf:MyWf/1.0&lt;/code&gt;) can also be mapped to virtual file paths, bringing dynamically created models under the management of the delta mechanism.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Full-Stack Customization Example: Seamless Overlays from Data Model to Front-end UI
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmuymbs2cxh9hmophqbj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmuymbs2cxh9hmophqbj4.png" alt="full stack delta" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;_delta&lt;/code&gt; directory, by using delta files with the same names as the base models, any layer of the system can be non-invasively modified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Data Model Delta&lt;/strong&gt;: In &lt;code&gt;orm/app.orm.xml&lt;/code&gt;, use &lt;code&gt;x:override="remove"&lt;/code&gt; to delete fields from the base product, or directly add new business entities.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Business Logic Delta&lt;/strong&gt;: Through an &lt;code&gt;xbiz/app.xbiz&lt;/code&gt; file, declaratively add new business methods to the base entity's CRUD services or override existing logic.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;IoC Configuration Delta&lt;/strong&gt;: Override &lt;code&gt;beans/app.beans.xml&lt;/code&gt;, using &lt;code&gt;x:extends="super"&lt;/code&gt; to append new beans, modify the properties of existing beans, or even replace an entire bean's implementation class.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Front-end UI Delta&lt;/strong&gt;: In &lt;code&gt;pages/MyEntity/MyEntity.view.xml&lt;/code&gt;, add new action buttons to a base list page or modify the layout of a form through delta merging.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Engine Capability Delta&lt;/strong&gt;: All engine models (rules, reports, workflows) are XDSLs, and extension nodes can be injected or existing definitions modified via the &lt;code&gt;Delta&lt;/code&gt; mechanism.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Paradigm Shift: From "1 Core + N Forks" to "1 Base + N Deltas"
&lt;/h4&gt;

&lt;p&gt;The delta mechanism of Reversible Computation brings about a fundamental paradigm shift, upgrading the software construction and delivery model from the traditional branching model to a delta-stacking model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traditional Model (1 Core + N Forks)&lt;/strong&gt;: Based on a core version, multiple independent branches (Forks) are created to meet the needs of different customers or markets. This leads to an &lt;strong&gt;exponential increase in maintenance costs&lt;/strong&gt;, makes it difficult to synchronize features between branches, and ultimately results in merge hell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reversible Computation Model (1 Base + N Deltas)&lt;/strong&gt;: Based on a unified base product, the final system is generated by stacking multiple independent, composable delta packages (Δ). The unified formula is:&lt;br&gt;
&lt;code&gt;Effective System = Base ⊕ Δ_Industry ⊕ Δ_Region ⊕ Δ_Customer&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  The Sustainability of Customization and Evolution
&lt;/h4&gt;

&lt;p&gt;This full-stack, delta-based customization method ensures the sustainability of software evolution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;The base product can be upgraded independently&lt;/strong&gt;: Delta customizations are physically isolated from the base code. Bug fixes and feature enhancements to the base product can be released independently, and custom projects can safely merge these changes by updating their dependency versions.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Customization logic can be accumulated and reused&lt;/strong&gt;: Customization logic for specific industries or customers can be packaged as independent Delta modules and reused in different projects.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Customization conflicts can be visually traced&lt;/strong&gt;: Thanks to the metadata preserved by XNode during the merge process, the origin of every custom element can be precisely traced. When conflicts occur between multiple Delta modules, they can be quickly located and resolved.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Through this systematic delta customization mechanism, the Nop Platform achieves the ideal goal of "retaining the efficiency of automation without losing the flexibility of customization," providing a solid technical foundation for the long-term evolution of complex business systems.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Platformized Multi-tenancy: The Tenant as a Coordinate Dimension&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This full-stack delta customization mechanism provides an exceptionally elegant, platform-level solution for the complex requirement of multi-tenancy. In the Nop Platform, multi-tenancy is not a "special case" that requires special coding but a natural consequence of its core architecture. Based on the idea that "extensibility is dimension extension," a &lt;strong&gt;Tenant is treated as an independent dimension in the system's coordinate space&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When the system needs to load any resource (like an ORM model, a business process, or a UI page), its core model loader (&lt;code&gt;Loader&lt;/code&gt;) automatically adds a &lt;code&gt;tenantId&lt;/code&gt; dimension, extending the loading function from &lt;code&gt;Model = Loader(resourcePath)&lt;/code&gt; to &lt;code&gt;Model = Loader(resourcePath ⊗ tenantId)&lt;/code&gt;. &lt;strong&gt;This is analogous to extending a single-variable function in mathematics to a function acting on a tensor product space.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This abstraction is seamlessly implemented in engineering terms through the platform's &lt;strong&gt;Delta File System&lt;/strong&gt;: when the &lt;code&gt;Loader&lt;/code&gt; loads &lt;code&gt;a.xml&lt;/code&gt;, it automatically considers the "current tenant ID" as a dimension, prioritizing searching and merging from the tenant-specific delta layer (e.g., &lt;code&gt;/_delta/tenantA/a.xml&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Therefore, whether implementing simple &lt;strong&gt;data isolation&lt;/strong&gt; (by customizing the &lt;code&gt;NopORM&lt;/code&gt; model under a tenant delta layer to automatically add a tenant ID filter to all queries) or implementing complex &lt;strong&gt;tenant-specific business logic&lt;/strong&gt; (by customizing &lt;code&gt;NopTaskFlow&lt;/code&gt; or &lt;code&gt;NopRule&lt;/code&gt; models), everything is accomplished under the unified delta paradigm of &lt;code&gt;Y = F(X) ⊕ Δ&lt;/code&gt;. Multi-tenancy is no longer a collection of scattered &lt;code&gt;if-else&lt;/code&gt; statements but a universal, predictable system behavior that &lt;strong&gt;emerges&lt;/strong&gt; from the platform's first principles.&lt;/p&gt;
&lt;h3&gt;
  
  
  9.4 Contract-First: From "Living Documents" to "Living Systems"
&lt;/h3&gt;

&lt;p&gt;The Nop Platform elevates the DDD principles of "Ubiquitous Language" and "Model-Driven" to a truly automated, contract-first software production line.&lt;/p&gt;
&lt;h4&gt;
  
  
  9.4.1 Contract is Model, Model is Contract: An Automated Production Pipeline Starting with &lt;code&gt;Excel&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;In Nop, Contract-First is implemented in its most thorough form. All key designs, such as data models and API interfaces, are clearly defined in an &lt;strong&gt;Excel model&lt;/strong&gt; during the requirements phase. This model is no longer a static document but an "&lt;strong&gt;executable contract&lt;/strong&gt;," the single source of truth that drives all subsequent automated processes. Once the "contract" is established, the platform can automatically generate database DDL, back-end entities and services, API documentation, and even front-end page skeletons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-Enhanced Model Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Nop Platform's DSL-driven architecture is naturally suited for AI-assisted development. By interacting with large AI models, one can directly generate DSLs like &lt;code&gt;orm.xml&lt;/code&gt; and &lt;code&gt;xmeta&lt;/code&gt;, which can then be automatically converted to Excel format using the platform's built-in converters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Generation =&amp;gt; orm.xml =&amp;gt; Automatic Conversion =&amp;gt; Excel Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  9.4.2 Reversible Transformation of Multiple Representations: Lossless Conversion and Delta Merging of Excel, XML, JSON
&lt;/h4&gt;

&lt;p&gt;Reversible Computation theory states that information has multiple representations that are mutually convertible. The Nop Platform engineers this: &lt;strong&gt;any model naturally has multiple forms, such as Excel, XML, JSON, and YAML, and can be automatically converted back and forth&lt;/strong&gt;. A technical person can enjoy the syntax checking of XML in an IDE, while a business person can review and even edit the same model in the familiar environment of Excel.&lt;/p&gt;

&lt;p&gt;More importantly, these representations are also &lt;strong&gt;delta-based&lt;/strong&gt;. A business person can define only the changes in an &lt;code&gt;app-delta.orm.xlsx&lt;/code&gt; file, and then, using command-line tools, safely merge multiple &lt;code&gt;Delta&lt;/code&gt; models with the base model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# XML → XLSX&lt;/span&gt;
java &lt;span class="nt"&gt;-jar&lt;/span&gt; nop-cli.jar convert app.orm.xml  &lt;span class="nt"&gt;-o&lt;/span&gt; app.orm.xlsx

&lt;span class="c"&gt;# XLSX + Delta XLSX → XML&lt;/span&gt;
java &lt;span class="nt"&gt;-jar&lt;/span&gt; nop-cli.jar convert app.orm.xlsx app-delta.orm.xlsx &lt;span class="nt"&gt;-o&lt;/span&gt; app.orm.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9.4.3 Unified Governance and Quality Assurance: Full-Link &lt;code&gt;Traceability&lt;/code&gt; and &lt;code&gt;Snapshot Testing&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The Nop Platform provides powerful governance capabilities for this complex automated system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Full-Link Traceability&lt;/strong&gt;: Thanks to the rich metadata preserved by XNode during the merge process, any final result in the system (like a button on a page) can be &lt;code&gt;_dump&lt;/code&gt;ed with a single command to precisely trace its complete "generation history": in which base file and on which line it was originally defined, and which delta files modified it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contract is Test&lt;/strong&gt;: Through &lt;code&gt;JunitAutoTestCase&lt;/code&gt; and the &lt;code&gt;@EnableSnapshot&lt;/code&gt; annotation, the platform can automatically record service call requests, responses, and all observable side effects as a "snapshot." Subsequent test runs automatically compare against this snapshot, achieving "&lt;strong&gt;contract as test&lt;/strong&gt;." This can dramatically reduce the cost of creating and maintaining automated tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Complete Observability and Deterministic Side Effects&lt;/strong&gt;: Reversible Computation theory posits that a well-designed system should have complete observability. The key criterion for this is that &lt;strong&gt;all side effects (such as database state changes, message queue sends, cache updates, file system operations, external API calls, etc.) should be observable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The complete behavior of a software system can be abstracted as:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Complete System Behavior &lt;span class="o"&gt;=&lt;/span&gt; Input + Output + Side Effects
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Traditional unit tests often focus only on inputs and outputs, ignoring various side effects, which leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Non-deterministic test results&lt;/li&gt;
&lt;li&gt;  Fragility due to environmental dependencies&lt;/li&gt;
&lt;li&gt;  Difficult-to-reproduce intermittent issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Nop Platform, through its systematic observation mechanisms, can capture and record all key side-effect data. When we supplement the input/output dataset with this observed side-effect data, we get the &lt;strong&gt;complete information set&lt;/strong&gt; of the system's behavior:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;Deterministic Test Case &lt;span class="o"&gt;=&lt;/span&gt; Input + Output + Observed Side Effects
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This complete observability &lt;strong&gt;eliminates all unknown side-effect influences, restoring a test case that was once disturbed by its environment into a purely deterministic function&lt;/strong&gt;. This fundamentally overcomes the problem of test fragility caused by incomplete information.&lt;/p&gt;

&lt;p&gt;Based on this principle, the Nop Platform implements reliable &lt;strong&gt;record-and-replay unit testing&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Recording Phase&lt;/strong&gt;: The system completely records input parameters, return values, and all observable side effects (including database change logs, message sending records, cache operations, etc.).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Replay Phase&lt;/strong&gt;: By replaying the same input, the test verifies the complete consistency of the output and all side effects.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Environment Isolation&lt;/strong&gt;: The test does not depend on a real external environment; all side effects are replayed in a controlled, simulated environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This testing method is particularly suitable for verifying complex systems after multiple &lt;code&gt;Delta&lt;/code&gt; layers have been applied, ensuring that customizations do not break original business logic and providing a solid guarantee for the reliable evolution of the system.&lt;/p&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;From an architectural perspective, complete observability provides a solid technical foundation for event-driven architecture.&lt;/strong&gt; As mentioned earlier, through system-wide standardized observation points, the system can automatically trigger events at the precise moment of a state change, making declarative event weaving possible and thus achieving a complete decoupling of business logic from cross-cutting concerns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This also inversely proposes an important criterion for judging architectural design: is the system's observability sufficient to enable automated record-and-replay testing, transforming complex business logic processing into a deterministic pure function?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Chapter 10: The Final Paradigm Revolution — From "Applying DDD" to "Emergent DDD"&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Introduction: The "No-Move Is the Best Move" State of Architecture
&lt;/h3&gt;

&lt;p&gt;At this point, we have detailed from an engineering perspective how the Nop Platform solidifies DDD's strategic and tactical patterns into a rigorous, executable, and closed-loop system. However, to truly understand the change that the Nop Platform brings, we must answer a deeper question: what is the fundamental difference between it and other frameworks that attempt to standardize DDD?&lt;/p&gt;

&lt;p&gt;The answer lies in a profound &lt;strong&gt;paradigm revolution&lt;/strong&gt;: from &lt;strong&gt;consciously "Applying DDD"&lt;/strong&gt; to &lt;strong&gt;unconsciously "Emergent DDD."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This transformation is akin to the paradigm shift in physics from Newtonian mechanics to relativity. &lt;strong&gt;Newtonian mechanics relies on detailed force analysis&lt;/strong&gt;, requiring us to precisely calculate every action and reaction—just as traditional DDD practice demands that developers constantly maintain design vigilance, consciously partitioning boundaries, defining entities, and building aggregates. It is an "architectural design" based on external rules and active effort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But Einstein's relativity showed that spacetime itself is curved by mass and energy, and the motion of objects is simply them following the shortest path (a geodesic) in this curved spacetime.&lt;/strong&gt; It no longer focuses on isolated "forces" but describes the intrinsic geometric properties of spacetime itself. Similarly, the ultimate goal of the Nop Platform is not to provide a more refined set of "DDD design tools," but to shape a "curved space" through its meta-model system and delta-merge mechanism, a space where domain models can grow naturally. In this "space," defined by Reversible Computation theory, the organization of code, the partitioning of boundaries, and the evolution of models spontaneously tend toward the form that best fits the essence of the domain.&lt;/p&gt;

&lt;p&gt;Just as the highest level of martial arts is "the best move is no move," the ideal endpoint of DDD practice may well be to "forget DDD" itself. When the construction space of the system inherently contains all the evolutionary possibilities of domain models, the deliberate "application" of specific design patterns is no longer necessary. Structures that are true to the domain's essence will emerge naturally within it.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.1 From Application-Layer Abstractions to First-Principle Support
&lt;/h3&gt;

&lt;p&gt;A fine example of traditional DDD architecture is the Explicit Architecture proposed by Herberto Graca. See &lt;a href="https://www.jianshu.com/p/d3e8b9ac097b" rel="noopener noreferrer"&gt;Explicit Architecture (01): Fusing DDD, Onion Architecture, Clean Architecture, CQRS...&lt;/a&gt;. The Nop Platform aims to achieve similar technical goals, but through a different path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgitee.com%2Fcanonical-entropy%2Fnop-entropy%2Fraw%2Fmaster%2Fdocs%2Ftheory%2Fddd%2Fexplicit-arch-diagram.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgitee.com%2Fcanonical-entropy%2Fnop-entropy%2Fraw%2Fmaster%2Fdocs%2Ftheory%2Fddd%2Fexplicit-arch-diagram.png" alt="explicit arch" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most frameworks that attempt to engineer DDD are essentially providing &lt;strong&gt;fixed abstractions at the application layer&lt;/strong&gt;. They offer a series of base classes or interfaces like &lt;code&gt;AggregateRootBase&lt;/code&gt;, &lt;code&gt;AbstractRepository&lt;/code&gt;, and &lt;code&gt;DomainEvent&lt;/code&gt;. Developers must consciously inherit from and implement them, as if they were building an application with a set of "DDD building blocks." The intention is good, but it still requires the developer to first be a competent DDD thinker and then "translate" that thinking into calls to the framework's specific APIs.&lt;/p&gt;

&lt;p&gt;The Nop Platform takes a radically different path. It &lt;strong&gt;does not provide fixed DDD patterns at the application layer but instead provides the first principles at the underlying level of software construction that support the natural emergence of these patterns&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  10.1.1 The Internalization of Patterns: A Comparison with the Evolution of the &lt;code&gt;Singleton&lt;/code&gt; Pattern and &lt;code&gt;DI&lt;/code&gt; Frameworks
&lt;/h4&gt;

&lt;p&gt;This is like the history of modern high-level languages and frameworks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Once upon a time, developers had to manually implement the "Singleton Pattern" and constantly be wary of concurrency pitfalls like double-checked locking. But with the advent of modern Dependency Injection (DI) frameworks (like Spring or NopIoC), a developer simply declares a component's scope (&lt;code&gt;@Singleton&lt;/code&gt;), and the "singleton" becomes a natural result; we no longer need to care about its complex underlying implementation. Similarly, we once had to manually implement the "Observer Pattern," but today's reactive programming frameworks allow us to simply declare data streams and transformation relationships, and the complex event propagation and subscription management are made transparent by the framework.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The Nop Platform elevates this idea of "pattern internalization" to the level of the entire DDD system.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  10.1.2 The Protocol-Neutral BizModel: Dissolving the Redundant &lt;code&gt;Controller/Service/DTO&lt;/code&gt; Layers
&lt;/h3&gt;

&lt;p&gt;In traditional layered architectures (like Controller-Service-DAO), concepts like &lt;code&gt;Controller&lt;/code&gt;, &lt;code&gt;Service&lt;/code&gt;, and &lt;code&gt;DTO&lt;/code&gt; form explicit, mandatory layers. This leads to a large amount of glue code and "translation loss": domain objects need to be converted and encapsulated at each layer, and the rich domain objects returned by a &lt;code&gt;Service&lt;/code&gt; are "flattened" or converted into specialized &lt;code&gt;DTOs&lt;/code&gt; in the &lt;code&gt;Controller&lt;/code&gt; layer to adapt to front-end requirements or hide internal details.&lt;/p&gt;

&lt;p&gt;The Nop Platform, through its unified &lt;code&gt;NopGraphQL&lt;/code&gt; engine and &lt;strong&gt;protocol-neutral BizModel&lt;/strong&gt;, completely dissolves these redundant boundaries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A &lt;code&gt;BizModel&lt;/code&gt; is a pure expression of business logic, independent of any external interface protocol.&lt;/strong&gt; A developer simply uses &lt;code&gt;@BizModel&lt;/code&gt; and &lt;code&gt;@BizMutation&lt;/code&gt;/&lt;code&gt;@BizQuery&lt;/code&gt; annotations on a plain Java class (POJO) to define the core business logic. This method directly returns domain entities, aggregate roots, or other complex domain objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key to achieving protocol neutrality lies in its minimalist interface signature.&lt;/strong&gt; Unlike many traditional MVC frameworks that allow or even encourage exposing runtime-specific objects like &lt;code&gt;HttpServletRequest&lt;/code&gt; or &lt;code&gt;WebContext&lt;/code&gt; in Controller methods, NopGraphQL service function input parameters are strictly limited to &lt;strong&gt;pure POJOs&lt;/strong&gt; (or primitive types), and an optional &lt;code&gt;FieldSelection&lt;/code&gt; (to sense client query needs). It does not need, and cannot access, any runtime objects specific to the HTTP protocol or any other transport protocol.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This design brings fundamental benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Automatic Decoupling&lt;/strong&gt;: Business logic is decoupled from any specific interface protocol (like HTTP, gRPC, or message queues) at its source. The same &lt;code&gt;BizModel&lt;/code&gt; can be exposed as GraphQL, REST, RPC, and other endpoints without any modification.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Purity and Testability&lt;/strong&gt;: Since it does not depend on any web container or framework context, the service function can be unit-tested in a pure fashion. Testing simply involves constructing POJO inputs and validating POJO outputs, drastically reducing the complexity and cost of testing.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Clear Intent&lt;/strong&gt;: The function signature clearly expresses the business input and output, with no "noise" related to technical implementation, making the domain logic the absolute core.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;So, with such a pure interface, how are complex interface adaptation needs met? The fundamental reason is that the &lt;code&gt;NopGraphQL&lt;/code&gt; engine provides a powerful, standardized "post-processing pipeline" that replaces the hand-written, scattered glue code of traditional architectures.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a &lt;code&gt;BizModel&lt;/code&gt;'s service function returns a result, the engine's subsequent processing is far from simple JSON serialization. This substantial post-processing layer automatically executes a series of complex and critical logic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;On-Demand Loading and N+1 Optimization&lt;/strong&gt;: The engine parses the client's &lt;code&gt;FieldSelection&lt;/code&gt;, automatically identifies associated properties that need to be lazy-loaded, and uses the &lt;code&gt;DataLoader&lt;/code&gt; mechanism for batch loading, solving the N+1 query problem at its root.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Field-Level Post-Processing&lt;/strong&gt;: Based on configurations like &lt;code&gt;transformOut&lt;/code&gt; and &lt;code&gt;getter&lt;/code&gt; defined in the &lt;code&gt;XMeta&lt;/code&gt; meta-model, it performs complex transformations, calculations, and formatting on field values. This allows the interface to return &lt;strong&gt;computed fields&lt;/strong&gt; or &lt;strong&gt;derived fields&lt;/strong&gt; that do not directly exist on the entity model.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Field-Level Security Control&lt;/strong&gt;: It automatically applies data permission checks and data masking policies at the field level. Based on the current user's permissions, it dynamically decides which fields can be returned (field pruning) and how sensitive fields (like phone numbers, ID cards) should be returned (field masking).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Multi-Protocol Adaptation&lt;/strong&gt;: The same &lt;code&gt;BizModel&lt;/code&gt; can be simultaneously exposed as GraphQL, REST, gRPC, and other protocols. The post-processing pipeline will appropriately wrap the response according to the protocol's characteristics.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Therefore, the return value of a &lt;code&gt;BizModel&lt;/code&gt; does not need to be a DTO specially prepared and "pre-processed" for a specific interface. It only needs to return the most natural and richest domain object.&lt;/strong&gt; All the adaptation, trimming, security, and optimization work for the interface is handled uniformly and declaratively by the engine's post-processing pipeline. The &lt;code&gt;BizModel&lt;/code&gt; becomes a &lt;strong&gt;protocol-neutral domain core&lt;/strong&gt;, and the &lt;code&gt;NopGraphQL&lt;/code&gt; engine acts as the single, powerful &lt;strong&gt;universal adapter&lt;/strong&gt;, completely eliminating tedious DTOs and manual glue code.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.1.3 Separating the CRUD Subspace: From the &lt;code&gt;Repository&lt;/code&gt; Pattern to &lt;code&gt;IEntityDao&lt;/code&gt; and "Complement Space" Programming
&lt;/h3&gt;

&lt;p&gt;A widely held view in the DDD community is that "simple CRUD systems are not suitable for DDD." This reflects the powerlessness of the &lt;code&gt;Repository&lt;/code&gt; pattern when faced with large amounts of templated CRUD code. The traditional approach requires defining a dedicated &lt;code&gt;Repository&lt;/code&gt; interface for each aggregate root, which leads to an inherent contradiction: &lt;strong&gt;CRUD operations themselves form a highly unified mathematical subspace with a complete set of operations, yet they are artificially segregated by different object types.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Nop Platform proposes a solution derived from mathematical thinking: &lt;strong&gt;separate the CRUD subspace&lt;/strong&gt;. Since CRUD operations (Create, Read, Update, Delete) have a unified structure and a complete set of operations, they should be addressed with a unified, generic solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. A Unified Entity Space and Descriptive Persistence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In NopORM, we no longer need to define a separate &lt;code&gt;Repository&lt;/code&gt; for each entity. The platform provides a generic &lt;code&gt;IEntityDao&amp;lt;T&amp;gt;&lt;/code&gt; interface, which serves as a complete tool applicable to all entity types. More importantly, NopORM reinterprets persistence operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;The traditional &lt;code&gt;Repository.save&lt;/code&gt; carries an imperative execution semantic&lt;/strong&gt;; calling it means immediately or scheduled execution of a database operation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;In NopORM, &lt;code&gt;session.save&lt;/code&gt; is essentially descriptive&lt;/strong&gt;: It merely registers the entity object with the current &lt;code&gt;OrmSession&lt;/code&gt;, a unified &lt;strong&gt;entity space&lt;/strong&gt;, for management. The entity is brought under the Session's jurisdiction, its state changes are tracked (via the built-in &lt;code&gt;dirtyProps&lt;/code&gt; delta), but the actual database operations are deferred until the transaction commits, to be handled uniformly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The direct benefit of this descriptive management is that &lt;strong&gt;the composition of operations has mathematical determinism&lt;/strong&gt;. For example, saving an entity and then immediately deleting it will result in these two operations canceling each other out during the final flush, producing no database calls. This reflects the "delta stacking" idea in Reversible Computation: &lt;code&gt;(+Δ) ⊕ (-Δ) = 0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Subspace Decomposition: Long-Wave Background and Short-Wave Foreground&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can understand this design using an analogy from wavelet analysis in signal processing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;CRUD operations&lt;/strong&gt; are like the &lt;strong&gt;long-wave background&lt;/strong&gt; of a signal. They change slowly, have a uniform structure, and can be perfectly predicted and automated.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Unique domain logic&lt;/strong&gt; is like the &lt;strong&gt;short-wave foreground&lt;/strong&gt; of a signal. It carries the main information content, changing rapidly and unpredictably.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The traditional &lt;code&gt;Repository&lt;/code&gt; pattern attempts to decompose the entire signal using the same "basis" (i.e., one Repository per aggregate root), which causes the background noise (CRUD template code) to interfere with the foreground information (domain logic). Nop Platform's approach is to perform an &lt;strong&gt;orthogonal subspace decomposition&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;CRUD Subspace&lt;/strong&gt;: Handled automatically by the generic &lt;code&gt;IEntityDao&lt;/code&gt; and the built-in &lt;code&gt;CrudBizModel&lt;/code&gt;. This subspace chooses a set of "standard orthogonal bases" (create, delete, update, find, paginate, etc.), providing a unified and complete solution for all entity types.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Domain Logic Complement Space&lt;/strong&gt;: This is where the truly valuable, non-standard, and unique business logic resides. Developers are refocused here, in the &lt;code&gt;XBiz&lt;/code&gt; model or domain services, to concentrate on writing that unique business logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can be expressed with an elegant Reversible Computation formula:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Complete Domain Behavior = Generator&amp;lt;CRUD Subspace&amp;gt; ⊕ Δ(Domain Complement Space)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: Developers do not need to have all their business classes inherit from interfaces like &lt;code&gt;CrudRepository&lt;/code&gt;. &lt;code&gt;IEntityDao&lt;/code&gt; is used as a &lt;strong&gt;complete tool&lt;/strong&gt; to solve the uniform CRUD background problem. The developer's core job is to work in the &lt;code&gt;XBiz&lt;/code&gt; "delta (Δ)" model, within the &lt;strong&gt;domain complement space&lt;/strong&gt;, focusing on implementing the unique logic that truly defines the core business value, thereby being completely liberated from boilerplate CRUD code.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.2 From "Deployment Decision" to "Compositional Freedom"
&lt;/h3&gt;

&lt;p&gt;DDD emphasizes that a microservice is a deployment decision, while a Bounded Context is a logical boundary. The Nop Platform brings this philosophy to its ultimate practice through its modularization mechanism.&lt;/p&gt;

&lt;h4&gt;
  
  
  10.2.1 Module as Bounded Context: A Physical Carrier with an Independent &lt;code&gt;DSL Atlas&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;In Nop, a &lt;strong&gt;module&lt;/strong&gt; is the physical carrier of a Bounded Context. Each module has its own independent ORM model, permission model, business service model (BizModel), and a whole set of other models, forming its own "&lt;strong&gt;DSL Atlas&lt;/strong&gt;." They are self-contained and have their own "intrinsic coordinate system."&lt;/p&gt;

&lt;h4&gt;
  
  
  10.2.2 Composition as Architecture: Free Switching Between &lt;code&gt;Modular Monolith&lt;/code&gt; and &lt;code&gt;Microservices&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Nop's IoC container has powerful capabilities for automatic module discovery and assembly, which brings unprecedented architectural flexibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When you package your application and &lt;strong&gt;include multiple module dependencies&lt;/strong&gt;, they run in the same process, automatically forming a high-performance "&lt;strong&gt;modular monolith&lt;/strong&gt;."&lt;/li&gt;
&lt;li&gt;  When you &lt;strong&gt;package only one module&lt;/strong&gt;, it independently becomes a "&lt;strong&gt;microservice&lt;/strong&gt;" application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  10.2.3 Location-Transparent Communication: Automatic Adaptation Between &lt;code&gt;Local Calls&lt;/code&gt; and &lt;code&gt;Remote RPC&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Interaction between modules always occurs through defined &lt;strong&gt;API interfaces (ports)&lt;/strong&gt;. The underlying Nop framework automatically handles the communication details: if the called module is in the same process, it's an efficient &lt;strong&gt;local method call&lt;/strong&gt;; if the called module is remote, it automatically switches to an &lt;strong&gt;RPC call&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means that architectural evolution—from monolith to microservices—is no longer a painful, major refactoring effort, but merely a matter of changing the application's packaging composition.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.3 From "Data-Centric" to "Information Flow Inversion"
&lt;/h3&gt;

&lt;p&gt;The design philosophy of the Nop Platform also triggers a fundamental shift in how business logic is implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.3.1 Refocusing the Aggregate Root: From "Write Boundary" to "Information Access Center"
&lt;/h3&gt;

&lt;p&gt;In traditional DDD, the primary responsibility of an Aggregate Root is established as the &lt;strong&gt;write boundary&lt;/strong&gt; for "consistency" and "transactions." This design has its merits in a monolithic architecture, often manifesting as a black-box command method (e.g., &lt;code&gt;order.confirm()&lt;/code&gt;) that is internally responsible for synchronously and atomically transitioning the aggregate from one consistent state to another.&lt;/p&gt;

&lt;p&gt;However, this pattern reveals its limitations in microservices architectures and complex business scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Stateless, service-oriented architectures reduce the need for strong in-memory consistency&lt;/strong&gt;: Domain objects are temporarily reconstructed from persisted data that is already consistent. A brief inconsistency within a process is not observable externally. The key guarantee lies at the &lt;strong&gt;commit threshold&lt;/strong&gt;—ensuring that the final persisted &lt;strong&gt;delta change (Δ)&lt;/strong&gt; satisfies database constraints and business rules.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Black-box methods are not conducive to orchestrating and understanding complex logic&lt;/strong&gt;: Encapsulating a complex business operation involving multiple entities and invariants within a single method on the aggregate root turns that method into a large, difficult-to-test and maintain "God function." More importantly, &lt;strong&gt;the very concept of using a single function to guarantee all invariants is inappropriate&lt;/strong&gt;. A business consistency constraint (invariant) typically involves only a few objects and properties within the aggregate, which could have been described and validated independently.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Nop Platform, through its &lt;code&gt;NopTaskFlow&lt;/code&gt; orchestration engine, provides a more expressive "gray-box" modeling approach. The function that modifies a business entity does not have to be a black-box method on the aggregate root. A service function (or a large business action) can be decomposed into multiple clearly defined &lt;strong&gt;Steps&lt;/strong&gt;, each responsible for handling a local state transition or validating a specific invariant. This decomposition makes the process of guaranteeing complex consistency transparent, traceable, and easily composable.&lt;/p&gt;

&lt;p&gt;To understand this shift, we need to re-examine the essence of a &lt;strong&gt;domain model&lt;/strong&gt;. A domain model is expressed through a domain language, and the &lt;strong&gt;aggregate root is the most direct and cheapest carrier for implementing that domain language&lt;/strong&gt;. The so-called ubiquitous language first provides a vocabulary (class names, method names, property names), and the aggregate root then defines the feasible organization of these words. &lt;strong&gt;The aggregate root provides a stable "base space" (data structure and associations), while domain services represent the "dynamics" (business behavior) that occur in this base space.&lt;/strong&gt; This clear separation of roles can be seen as an improvement on traditional DDD after absorbing ideas from functional programming.&lt;/p&gt;

&lt;p&gt;Based on this understanding, the Nop Platform fundamentally reinterprets and refocuses the responsibilities of the aggregate root:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The core value of an aggregate root lies in defining a stable "domain structure space" (base space) and ensuring "optimal information accessibility."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This structure space is composed of the following elements, which remain highly stable throughout the product's lifecycle, across deployments for different customers, and through various customizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Core data structures&lt;/strong&gt;: The entity and its key properties.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Rich intrinsic associations&lt;/strong&gt;: Stable relationships between entities (one-to-one, one-to-many, etc.).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fixed computed properties&lt;/strong&gt;: A small number of derived calculations that are independent of specific business logic and are purely determined by the entity's own properties (e.g., &lt;code&gt;totalPrice = unitPrice × quantity&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The primary responsibility of the aggregate root shifts from maintaining a "write boundary" and providing "black-box consistency methods" back to building a logically unified, richly associated, and freely navigable object graph. This object graph becomes the &lt;strong&gt;information access center&lt;/strong&gt; for the entire Bounded Context, providing the most natural and complete source of information for various &lt;strong&gt;read-side&lt;/strong&gt; needs (like condition checks in the &lt;code&gt;NopRule&lt;/code&gt; engine, data extraction for reporting engines, data sources for complex queries) and for the steps of &lt;strong&gt;write-side&lt;/strong&gt; processes.&lt;/p&gt;

&lt;p&gt;Under this model, the consistency guarantee for write operations is moved up, decomposed, and "&lt;strong&gt;platformized&lt;/strong&gt;":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Transaction Boundaries&lt;/strong&gt;: Defined by service methods (i.e., Actions in &lt;code&gt;@BizModel&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Consistency Constraints&lt;/strong&gt;: Guaranteed step-by-step by process steps and ultimately validated by database constraints, forming a multi-layered safety net.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This refocusing brings a fundamental advantage: &lt;strong&gt;the aggregate root no longer sacrifices its structural clarity and evolutionary flexibility to accommodate an outdated consistency encapsulation model&lt;/strong&gt;. It returns to its essence as a rich "information source," while complex state transition logic is elegantly implemented through orchestratable process steps. This clear &lt;strong&gt;separation of structure (base space) and behavior (dynamics)&lt;/strong&gt; is the architectural cornerstone that supports the deep customization and long-term evolution of productized software.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.3.2 Decoupling Business Logic: From "Pushing Data (DTOs)" to "Pulling Information (Expression Language - EL)"
&lt;/h3&gt;

&lt;p&gt;In the traditional approach, each business function (like a rule or a report) requires its own carefully prepared parameters (DTOs). When the logic is slightly adjusted, it often requires modifying multiple function signatures along the call chain. The essence of this pattern is: &lt;strong&gt;we are always writing code for a specific requirement, so we need to prepare and push dedicated data for each requirement.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Nop Platform, by establishing the aggregate root as a stable "information center," achieves an &lt;strong&gt;inversion of information flow&lt;/strong&gt;. The key lies in a philosophical shift:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Nop's design, the domain model expressed by the aggregate root is not tailored for specific business requirements but exists as an objective, directly usable, universal information source.&lt;/strong&gt; It provides a unified, semantically rich information space where various business logics can freely explore and retrieve the information they need.&lt;/p&gt;

&lt;p&gt;Based on this design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;From "Push" to "Pull"&lt;/strong&gt;: When the rule engine (&lt;code&gt;NopRule&lt;/code&gt;) or report engine executes, what is passed in is the entire aggregate root object or object graph. The engine internally uses expressions (like &lt;code&gt;order.customer.address.city&lt;/code&gt;) to &lt;strong&gt;actively pull&lt;/strong&gt; the required information from this rich, universal information source.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Localized Changes&lt;/strong&gt;: When the logic of a report or rule needs to be adjusted (e.g., changing from basing it on the customer's address to the shipping address), we &lt;strong&gt;do not need to modify any caller's code&lt;/strong&gt;. Because what is passed in is always that complete, objective information source, we only need to modify the local data-fetching expression within the report/rule model itself. This "pull" model greatly enhances the system's decoupling and evolutionary capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This inversion of information flow completely decouples business logic from the method of data supply.&lt;/strong&gt; Business components no longer depend on the outside world to prepare data in a specific structure; instead, they declaratively extract what they need from a unified information space. This significantly reduces the coupling between components, making the system much more flexible in responding to business changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Chapter 11: Case Study — The Reversible Computation Transformation of a Large Bank's Core System&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The value of theory lies in guiding practice. To prove that Reversible Computation is not an "ivory tower" theory tied exclusively to the Nop Platform but a universal, implementable technical philosophy, we examine the transformation of a large bank's core system. This project, &lt;strong&gt;without fully adopting the Nop Platform&lt;/strong&gt;, systematically introduced the core ideas of Reversible Computation into a standard technology stack of &lt;strong&gt;SpringBoot + MyBatis + SpringMVC + GraphQL Java&lt;/strong&gt;, and achieved remarkable results.&lt;/p&gt;

&lt;h3&gt;
  
  
  11.1 Lightweight Implementation of Core Principles: &lt;code&gt;Loader as Generator&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The Reversible Computation formula, &lt;code&gt;App = Generator&amp;lt;DSL&amp;gt; ⊕ Δ&lt;/code&gt;, hinges on treating the superposition of "generation" and "delta" as a unified construction process. In the bank project, this idea was realized through the lightweight principle of &lt;strong&gt;"Loader as Generator."&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Load-Time Implementation of Delta Merging&lt;/strong&gt;: The project team developed a &lt;strong&gt;&lt;code&gt;Delta Aware&lt;/code&gt; model loader&lt;/strong&gt; to replace standard JSON/XML parsers. When this loader reads a base model file (e.g., &lt;code&gt;cms.beans.xml&lt;/code&gt;, &lt;code&gt;User.mapper.xml&lt;/code&gt;), it automatically finds and merges the corresponding file in the delta directory (e.g., &lt;code&gt;/_delta/default/beans/cms.beans.xml&lt;/code&gt;). This means the merge logic of &lt;code&gt;Generator&amp;lt;DSL&amp;gt; ⊕ Δ&lt;/code&gt; is encapsulated within the loader, making it &lt;strong&gt;completely transparent to the runtime engines&lt;/strong&gt;. What Spring's IoC container and MyBatis see is the final, merged model.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Separation of Compile-Time and Run-Time&lt;/strong&gt;: Drawing inspiration from Nop Platform's &lt;code&gt;nop-cli&lt;/code&gt; tool, they moved some complex model transformations (like Excel to JSON conversion, &lt;code&gt;x:gen-extends&lt;/code&gt; expansion, and &lt;code&gt;xdef&lt;/code&gt; meta-model validation) to the &lt;strong&gt;Maven packaging phase&lt;/strong&gt;. The runtime engine did not need to be aware of these concepts, keeping the technology stack pure and high-performing. This perfectly illustrates the profound value of &lt;strong&gt;separating the "construction phase" from the "run-time phase"&lt;/strong&gt; in Reversible Computation theory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  11.2 Handling Major Model Changes: The Power of Delta Customization
&lt;/h3&gt;

&lt;p&gt;During the project implementation, the system underwent major model change requirements, which fully validated the resilience of the Reversible Computation architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;External System Integration and Table Structure Changes&lt;/strong&gt;: Key configuration tables and account tables were required to reuse content from external systems, involving destructive changes like table naming conventions and field reductions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Zero-Code-Change Data Layer Adaptation&lt;/strong&gt;: Through &lt;strong&gt;Delta customization&lt;/strong&gt;, without modifying the core system's code, the database mapping relationships in MyBatis's &lt;code&gt;mapper.xml&lt;/code&gt; were changed solely through delta data model definitions. After merging the Delta models, the system automatically generated a data access layer that conformed to the new specifications.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Mixed Data Source Support&lt;/strong&gt;: When fetching business objects (BOs), the system could transparently combine multiple data sources:

&lt;ul&gt;
&lt;li&gt;  Some information was fetched from the local database.&lt;/li&gt;
&lt;li&gt;  Other information was fetched from remote APIs.&lt;/li&gt;
&lt;li&gt;  All data was managed uniformly in a &lt;code&gt;DataCache&lt;/code&gt;, forming a complete domain object view.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  11.3 Elastic Extension of Process Orchestration
&lt;/h3&gt;

&lt;p&gt;Based on the Reversible Computation process orchestration mechanism, the system achieved flexible extension of business logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Automatically Generated Calling Skeletons&lt;/strong&gt;: The system automatically generated the basic calling structure for process orchestration based on the API model.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Delta Customization of Processes&lt;/strong&gt;: Non-invasive modifications were made to the process orchestration definitions through delta files.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Pre and Post Adapters&lt;/strong&gt;: Pre-adapter steps were added for request data transformation (like dictionary mapping), and post-transformation steps handled response data.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Distributed Transaction Support&lt;/strong&gt;: At the end of the process, changes in the &lt;code&gt;DataCache&lt;/code&gt; were automatically synchronized to remote systems via API calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Outcome&lt;/strong&gt;: Despite major changes to the business model, the &lt;strong&gt;core business processing code remained almost entirely unchanged&lt;/strong&gt; (some processing steps were added, and parameters of existing steps were adjusted), fully demonstrating the stability of the delta-stacking architecture in the face of business changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  11.4 Purifying the Domain Model: Modifying MyBatis to Enable "Aggregate Root Programming"
&lt;/h3&gt;

&lt;p&gt;The core of DDD tactical design is object-oriented programming centered on the Aggregate Root. However, in traditional MyBatis practice, developers often get bogged down in "anemic models" and a proliferation of DAO calls. This project made a key modification to MyBatis to support a domain programming model similar to JPA.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Introducing a &lt;code&gt;DataCache&lt;/code&gt; Context&lt;/strong&gt;: They created a &lt;strong&gt;&lt;code&gt;DataCache&lt;/code&gt;&lt;/strong&gt; component, similar to the &lt;code&gt;OrmSession&lt;/code&gt; in NopORM. Within the lifecycle of a business operation (typically corresponding to a GraphQL request or a Service method), it acts as a cache and change tracker for entity objects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Management and Dirty Checking&lt;/strong&gt;: State properties (like &lt;code&gt;_state&lt;/code&gt;) and a dirty properties set (&lt;code&gt;_dirtyProps&lt;/code&gt;) were introduced to the entity objects. When an entity property is modified, it is automatically marked as "dirty."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A Revolution in Programming Model&lt;/strong&gt;: After this transformation, the way back-end business logic was written changed fundamentally:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Get the aggregate root from the Manager (Application Service) entry point&lt;/span&gt;
&lt;span class="nc"&gt;IAccountBo&lt;/span&gt; &lt;span class="n"&gt;accountBo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accountManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAccountBo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accountBo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAccount&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Pure object programming: Navigate within the aggregate root to execute business logic&lt;/span&gt;
&lt;span class="nc"&gt;ICustomerBo&lt;/span&gt; &lt;span class="n"&gt;customerBo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accountBo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCustomerBo&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;IAccountBo&lt;/span&gt; &lt;span class="n"&gt;foreignCurrencyBo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accountBo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getForeignCurrencyBo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currencyCode&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ... Complex business logic, all accomplished through object method calls ...&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Declare the intent to save&lt;/span&gt;
&lt;span class="n"&gt;dataCache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 4. At the transaction boundary (e.g., at the end of @Transactional), DataCache automatically flushes.&lt;/span&gt;
&lt;span class="c1"&gt;// At this point, based on dirty checking, it generates and executes SQL only for the changed fields and handles associated objects.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Core Value of This Transformation&lt;/strong&gt;: It established a strict programming discipline—&lt;strong&gt;absolutely avoid direct use of DAOs in business logic code&lt;/strong&gt;. When writing business logic, developers only need to, and &lt;strong&gt;can only&lt;/strong&gt;, program against the pure domain concept of the aggregate root. All data access is done through object navigation.&lt;/p&gt;

&lt;p&gt;This "Aggregate Root Programming" model brought significant advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Clear Code Intent&lt;/strong&gt;: Business logic revolves entirely around domain concepts, no longer cluttered with database access details.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Decoupling from Persistence Implementation&lt;/strong&gt;: Business code does not depend on specific DAO implementations, facilitating testing and architectural evolution.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Transparent Performance Optimization&lt;/strong&gt;: The &lt;code&gt;DataCache&lt;/code&gt;'s dirty checking mechanism automatically avoids unnecessary SQL execution while ensuring data consistency.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Clear Architectural Constraints&lt;/strong&gt;: DAOs are used only at the application service entry point to fetch aggregate roots; within the business logic layer, work is done entirely on the object model.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  11.5 Unification and Automation of the Service Layer: Enhancing GraphQL Java
&lt;/h3&gt;

&lt;p&gt;At the service layer, the project chose GraphQL as the unified API gateway and enhanced the standard GraphQL Java library.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;RESTful Mapping&lt;/strong&gt;: To facilitate calls from traditional front-ends, a REST-style mapping layer was provided for GraphQL Java, allowing complex GraphQL queries to be invoked via simple HTTP POST requests.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Automation of Standard CRUD&lt;/strong&gt;: Based on the Reversible Computation idea of "generation," they developed a set of &lt;strong&gt;code generators&lt;/strong&gt; that could automatically generate GraphQL Schema and corresponding CRUD Resolver implementations from the data model (metadata). This drastically reduced repetitive coding for simple entities, allowing the team to focus on complex business rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  11.6 Delta-based Configuration for the Front-end: Modular Governance of AMIS JSON
&lt;/h3&gt;

&lt;p&gt;The front-end used the low-code platform AMIS, but its JSON configurations tended to become bloated as the business grew. The project team applied the delta-based thinking of Reversible Computation to manage front-end configurations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Delta JSON Loader&lt;/strong&gt;: A generic &lt;strong&gt;Delta JSON loader&lt;/strong&gt; was developed, capable of recognizing extension markers like &lt;code&gt;x:extends&lt;/code&gt; in the JSON configuration.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Decomposition and Merging of Configurations&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Vertical Decomposition&lt;/strong&gt;: A large page JSON was &lt;strong&gt;split into multiple sub-files&lt;/strong&gt; by UI components (like tables, forms, dialogs).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Horizontal Generation and Customization&lt;/strong&gt;: First, basic view skeletons like &lt;code&gt;_form_view.json&lt;/code&gt; were &lt;strong&gt;automatically generated&lt;/strong&gt; from the back-end model (e.g., &lt;code&gt;XMeta&lt;/code&gt;). Then, developers could create a hand-written &lt;code&gt;form_view.json&lt;/code&gt; file to &lt;strong&gt;correct, override, and extend&lt;/strong&gt; the auto-generated content using the &lt;code&gt;x:extends&lt;/code&gt; mechanism.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  11.7 Lessons from the Case Study: Thought Over Form
&lt;/h3&gt;

&lt;p&gt;The successful transformation of this bank's core system provides us with crucial insights:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Reversible Computation is an architectural philosophy, not a specific product&lt;/strong&gt;: Its core principles—&lt;strong&gt;delta stacking, generative programming, and the separation of construction and run-time&lt;/strong&gt;—can permeate different technology stacks. The Nop Platform is a complete and self-consistent implementation of this philosophy, but you can also extract its essence to empower your existing systems.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;A Path of Gradual Evolution&lt;/strong&gt;: Enterprises do not need to undergo "shock therapy" by replacing their entire technology stack. They can start by focusing on individual dimensions, such as &lt;strong&gt;delta-based management of configuration files&lt;/strong&gt; or &lt;strong&gt;purification of the domain layer&lt;/strong&gt;, to gradually enjoy the improvements in maintainability and evolvability that the theory brings.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;It Solves Fundamental Pain Points&lt;/strong&gt;: Whether it's the customization of back-end configurations, the anemia of domain models, or the bloating of front-end configurations, these are all fundamental challenges in software engineering. Reversible Computation provides a unified mental model and a tool paradigm to systematically address these challenges.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This case study eloquently demonstrates that the laws of software construction revealed by Reversible Computation theory are being, and will inevitably be, validated and adopted by a wider range of engineering practices, regardless of their specific form of implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion: The End of DDD Is to "Forget DDD"
&lt;/h3&gt;

&lt;p&gt;What the Nop Platform has initiated is a quiet revolution. It doesn't give you a more complex DDD toolbox; instead, it provides a simpler, more powerful "physics" of software.&lt;/p&gt;

&lt;p&gt;In this physics, &lt;strong&gt;DDD is not a discipline to be learned, but a destination that is naturally reached&lt;/strong&gt;. When you use a set of construction tools derived from first principles, you no longer need to constantly constrain yourself with the rules and patterns of design. Your energy will shift completely from the technical problem of "&lt;strong&gt;how to build correctly&lt;/strong&gt;" to the fundamental question of "&lt;strong&gt;what the business being built actually is&lt;/strong&gt;."&lt;/p&gt;

&lt;p&gt;Developers need only focus on using DSLs to sketch the blueprint of the business, and a robust, evolvable, and clearly bounded system will emerge as naturally as the stars move in their orbits. This, perhaps, is the most ideal future for DDD in the realm of engineering.&lt;/p&gt;

</description>
      <category>ddd</category>
      <category>softwareengineering</category>
      <category>programming</category>
      <category>springboot</category>
    </item>
    <item>
      <title>The Essence of DDD: A Complete Guide from Philosophy to Mathematics to Engineering Practice—The Theory Part</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Tue, 03 Feb 2026 13:07:27 +0000</pubDate>
      <link>https://forem.com/canonical/the-essence-of-ddd-a-complete-guide-from-philosophy-to-mathematics-to-engineering-practice-the-4jfa</link>
      <guid>https://forem.com/canonical/the-essence-of-ddd-a-complete-guide-from-philosophy-to-mathematics-to-engineering-practice-the-4jfa</guid>
      <description>&lt;p&gt;The prevalence of microservices has sparked a renaissance for Domain-Driven Design (DDD). However, a profound debate persists in the industry about whether, and how, its best practices can or should be standardized into a unified technical framework. In the process of implementing DDD, many design meetings are filled with pointless arguments over technical details, with no one able to convince the others.&lt;/p&gt;

&lt;p&gt;So, what exactly are the advantages of DDD? Is it about better adapting to the object-oriented ecosystem? Or is it about aligning the team's mental model and clearly mapping managerial resistance into the technical world, thereby bridging the chasm between technology and business? Or perhaps, does it possess a certain technical inevitability that can be proven at a mathematical level? This article, combining the theory of (Generalized) Reversible Computation and the technical implementation of the open-source low-code platform, Nop Platform, will dissect the technical core of DDD.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The (Generalized) Reversible Computation theory mentioned in this article is not the same as the concept of Reversible Computing in physics. It does not refer to the reverse execution of computational instructions but rather to an expanded understanding of the concept of "reversibility" at the level of software construction. See &lt;a href="https://dev.to/canonical/reversible-computation-a-next-generation-theory-for-software-construction-27fk"&gt;Reversible Computation: The Next-Generation Software Construction Theory&lt;/a&gt; and &lt;a href="https://dev.to/canonical/generalized-reversible-computation-grc-the-naming-and-elucidation-of-a-software-construction-2cp"&gt;Generalized Reversible Computation: Naming and Interpretation of a Software Construction Paradigm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Nop Platform is an open-source reference implementation of the (Generalized) Reversible Computation theory. Nop is a recursive acronym for "Nop is not Programming."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  I. The Standard Understanding of DDD: Strategic and Tactical Design
&lt;/h2&gt;

&lt;p&gt;If we were to ask a large AI model: Do you understand DDD? Do you know why it works?&lt;/p&gt;

&lt;p&gt;GPT-5 would likely provide the following standard answer:&lt;/p&gt;




&lt;p&gt;Yes, I do. Domain-Driven Design (DDD) is both a mindset and a set of practices used in complex business domains to closely align software design with domain knowledge, enabling the faster and more stable delivery of evolvable systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Is (A Two-Layered Perspective)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Strategic Design: Mapping the Business Landscape, Defining Boundaries, and Team Collaboration
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Domain/Subdomain:&lt;/strong&gt; Decompose business capabilities (Core, Supporting, Generic).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Bounded Context:&lt;/strong&gt; Use a consistent model and terminology within a clear boundary. Contexts communicate through integration patterns (e.g., Anti-Corruption Layer).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ubiquitous Language:&lt;/strong&gt; Business and technical teams share a common language to avoid "translation loss."&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tactical Design: How to Model and Implement within a Boundary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Entity/Value Object, Aggregate &amp;amp; Aggregate Root:&lt;/strong&gt; Define invariants and transaction consistency boundaries.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Domain Service, Domain Event, Repository, Factory, Specification, etc.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ports &amp;amp; Adapters (Hexagonal Architecture):&lt;/strong&gt; Isolate the domain from infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why It Works (The Underlying Mechanisms)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Reduces Cognitive and Communication Overhead:&lt;/strong&gt; The Ubiquitous Language and collaborative modeling make implicit rules explicit, reducing the "paraphrasing layer" between requirements and code.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Manages Complexity:&lt;/strong&gt; Bounded Contexts break down large problems into smaller, "high cohesion, low coupling" problems. Aggregates localize strong consistency constraints.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ensures Business Correctness:&lt;/strong&gt; Invariants are embedded in the model (rather than scattered in controllers/SQL/validators), making "invalid states unrepresentable."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Promotes Evolution:&lt;/strong&gt; Clear boundaries and inward-facing dependencies facilitate refactoring and replacement. Domain events and eventual consistency enable looser coupling for cross-boundary collaboration.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Socio-Technical Alignment:&lt;/strong&gt; Leverages Conway's Law by aligning team boundaries with Bounded Contexts, reducing cross-team friction.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Focuses Resources:&lt;/strong&gt; Classifying subdomains into Core, Supporting, and Generic helps concentrate modeling and engineering efforts on the "differentiating value" of the core domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When It's a Good Fit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  For long-term, evolvable projects with complex business rules and changing concepts (e.g., e-commerce orders, financial risk control, supply chain planning).&lt;/li&gt;
&lt;li&gt;  When multiple teams are collaborating, system boundaries are unclear, and integration is complex.&lt;/li&gt;
&lt;li&gt;  When strict control over invariants and consistency is required.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When It's Not a Good Fit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  For small, short-lived projects that are primarily CRUD-based with simple rules; a simpler architecture is more efficient in these cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Get Started (Practical Advice)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Discovery &amp;amp; Alignment&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Use Domain Interviews, Event Storming, and Domain Storytelling to map out processes and events.&lt;/li&gt;
&lt;li&gt;  Partition subdomains and assess their value (distinguish Core/Supporting/Generic), aligning them with team boundaries.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Drawing Boundaries &amp;amp; Integration&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Define Bounded Contexts and Context Maps (Shared Kernel, Published Language, Anti-Corruption Layer, etc.).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Modeling &amp;amp; Implementation&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Use invariants to define Aggregates; favor small aggregates. Use events or process orchestration (Saga/Process Manager) for eventual consistency across aggregates.&lt;/li&gt;
&lt;li&gt;  Prioritize Value Objects (immutable, easy to test); use Entities only when an identity is truly needed.&lt;/li&gt;
&lt;li&gt;  Application Services orchestrate use cases, Domain Services contain cross-aggregate domain logic, and Repositories are only responsible for persisting Aggregate Roots.&lt;/li&gt;
&lt;li&gt;  Use Ports &amp;amp; Adapters to isolate external systems and infrastructure.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Iteration&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Evolve the model as understanding deepens; refactor frequently. Measure change costs and defect rates to validate if boundaries are appropriate.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Simplified Example (E-commerce)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Bounded Contexts:&lt;/strong&gt; Catalog, Pricing, Ordering, Payment, Shipping.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ordering Context Aggregate:&lt;/strong&gt; &lt;code&gt;Order&lt;/code&gt; (Invariants: total amount = sum of line items; state transitions are restricted; an order cannot be paid for twice).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cross-Context:&lt;/strong&gt; An &lt;code&gt;OrderPlaced&lt;/code&gt; event notifies the Inventory and Shipping contexts. After successful payment, a &lt;code&gt;PaymentConfirmed&lt;/code&gt; event is published, and the order status is updated asynchronously. An Anti-Corruption Layer (ACL) adapts different models between boundaries to avoid shared database coupling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Pitfalls
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Using only "tactical patterns" (Entity/Repository) without strategic design, resulting in a Big Ball of Mud.&lt;/li&gt;
&lt;li&gt;  Treating DDD as a "microservices silver bullet": Microservices are a deployment decision, while DDD is a modeling and collaboration method. DDD can be implemented first within a modular monolith.&lt;/li&gt;
&lt;li&gt;  Over-enforcing consistency: Forcing invariants that span multiple contexts into a single transaction, leading to high coupling and performance/availability issues.&lt;/li&gt;
&lt;li&gt;  Failing to implement the language: Using business terms in meetings but switching to technical jargon in the code, breaking the Ubiquitous Language.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One-Sentence Summary
&lt;/h2&gt;

&lt;p&gt;DDD is effective because it uses clear business boundaries, a shared language, and explicit invariants to directly reflect the knowledge structure of a complex business in the code and team collaboration, thereby reducing complexity, increasing correctness, and supporting continuous evolution.&lt;/p&gt;

&lt;p&gt;------------End of GPT-5's creation---------&lt;/p&gt;

&lt;h2&gt;
  
  
  II. The First Principle of DDD: Discovering and Expressing the Inherent Laws of the Domain
&lt;/h2&gt;

&lt;p&gt;As a mature software engineering methodology, DDD is inevitably a comprehensive socio-technical system involving &lt;strong&gt;management, technology, and external environmental constraints&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The reason DDD is often difficult to "perfectly implement" is precisely that it attempts to solve real-world problems entangled with various non-technical factors. For instance, when we collaborate with an external team with varying technical skills, high communication costs, and even conflicting interests, &lt;strong&gt;these human and organizational issues of interest and coordination (so-called "office politics") directly influence the system's interface design, module division, and even technology choices&lt;/strong&gt;. This fully demonstrates that many of DDD's design decisions are often rooted in &lt;strong&gt;human factors, communication games, and inter-organizational interest coordination&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, is this the whole truth of DDD? If we temporarily strip away its socio-technical shell and focus purely on the technical domain, do the patterns advocated by DDD still exhibit some form of technical superiority? In other words, why is a pattern like "Aggregate Root" technically better at controlling state transitions than an arbitrary combination of objects? Why is the division of "Bounded Contexts" better at reducing coupling than a monolithic model?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If DDD can indeed solve technical problems widely and effectively, there must be an underlying essential reason at a mathematical level—a manifestation of some objective law that is independent of people and environment.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The starting point of this objective law can be boiled down to one core insight: &lt;strong&gt;business logic is, in essence, technology-agnostic&lt;/strong&gt;. It is a pure information description of concepts, rules, and processes within a domain. Therefore, the most stable and time-resistant software structure is one that can &lt;strong&gt;use, and only use&lt;/strong&gt;, the concepts from the business domain to express business logic. The "and only use" here is key; it means maximizing the avoidance of "technical noise"—those accidental factors originating from specific implementation technologies like databases, message queues, and web frameworks.&lt;/p&gt;

&lt;p&gt;Once we can achieve this, we obtain a description built entirely on the &lt;strong&gt;domain's inherent structure&lt;/strong&gt;. By shedding the accidental nature of technical implementations, this description gains long-term stability. More importantly, because it directly reflects the laws of the domain itself, it appears &lt;strong&gt;conceptually purer&lt;/strong&gt; and more elegant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The domain possesses an inherent regularity, which is the core reason why a domain model can endure through business development cycles and provide lasting value.&lt;/strong&gt; Imagine if a domain had no inherent laws. In that case, writing code directly for specific business scenarios would suffice. Why bother extracting a stable domain model that can adapt to various business developments? Why is this "intermediate layer" necessary? This is like in software product line engineering, where the reason we extract core assets and variability mechanisms is precisely that we believe there are stable, abstractable, and reusable structures behind a series of similar products. &lt;strong&gt;The value of a domain model lies precisely in its ability to capture the stable, essential, and inherently regular parts of the domain problem space.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We can often observe that a business log table designed by a business expert with no knowledge of distributed systems to ensure process correctness is strikingly similar in structure to a Saga log or event sourcing table designed by a distributed systems expert to ensure data consistency.&lt;br&gt;
This is because they are facing the same fundamentally constrained problem: "how to ensure overall correctness in a multi-step, unreliable process." It is the inherent structure of the problem itself that often leads its solutions to converge on similar structures.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From this perspective, DDD's tactical patterns (Aggregate, Entity, Value Object, Domain Service, etc.) are no longer just "best practices" but a series of tools and constraints we've invented to build a &lt;strong&gt;technology-neutral, pure expression system for business logic&lt;/strong&gt;. DDD is technically effective because it guides us to discover and construct a &lt;strong&gt;structurally more refined "computational model"&lt;/strong&gt; that is closer to the essence of the domain problem, rather than scattering business logic haphazardly and accidentally across various corners tightly coupled with technical implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is also the most fundamental reason why the "Ubiquitous Language" is so important.&lt;/strong&gt; It is not just to make the team's communication "smoother" or to improve daily interactions, but to &lt;strong&gt;ensure that the business logic in the code accurately maps the domain's inherent laws using the problem's own language, avoiding contamination by implementation details&lt;/strong&gt;. When we insist on using domain concepts instead of technical concepts to express business logic, we are actually ensuring that the code maps the stable structure of the domain, not the accidental features of a specific technology stack. Only a domain model built this way can remain stable and continue to provide value through business evolution and technological change.&lt;/p&gt;

&lt;h2&gt;
  
  
  III. The Art of Decomposition: Vertical Slicing and Horizontal Layering
&lt;/h2&gt;

&lt;p&gt;Having understood that the goal of DDD is to capture the inherent laws of a domain, a subsequent question arises: How do we systematically construct this "computational model" that reflects the domain's laws? A powerful mental framework is to &lt;strong&gt;view software design essentially as a process of "divide and conquer" over a complex problem space, a process that can be reduced to two fundamental dimensions of decomposition: vertical and horizontal.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Vertical Decomposition: The Natural Emergence of Object-Orientation
&lt;/h3&gt;

&lt;p&gt;If we want to decompose a complex design space, the most direct goal is to &lt;strong&gt;minimize the coupling between the resulting parts&lt;/strong&gt;. The ideal situation is for the decomposed parts to be able to evolve completely independently and in parallel.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;First-Level Decomposition and Object Naming&lt;/strong&gt;: To achieve this isolation, the primary task is to find the dimension that "slices the system most cleanly" (the primary decomposition dimension). The choice of this dimension directly corresponds to which &lt;strong&gt;core components&lt;/strong&gt; we conceptualize the system into. When we assign names to these components—such as "Order," "Customer," "Inventory"—we are, in fact, performing &lt;strong&gt;object decomposition&lt;/strong&gt;. This is the most fundamental means of abstraction because it directly corresponds to our cognitive division of core entities in the problem domain. A proper object decomposition has the highest internal cohesion and the weakest inter-component associations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Second-Level Decomposition and Internal Structure&lt;/strong&gt;: After identifying the core objects, we naturally need to describe the internal composition of each object. At this point, the second-level decomposed parts cannot be completely unrelated (otherwise, they should have been independent first-level objects). These "somewhat related yet somewhat different" structures are precisely what define an object's internal characteristics and behaviors. In the programming world, they are naturally named &lt;strong&gt;properties (data)&lt;/strong&gt; and &lt;strong&gt;methods (functions)&lt;/strong&gt;. This is not a coincidence but a consequence of data and functions being the most basic building blocks of the programming universe.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Therefore, &lt;strong&gt;vertical decomposition is a process that naturally leads to object-oriented abstraction&lt;/strong&gt;. By identifying the core concepts in the domain and their internal constitution, it encapsulates the system's complexity into a series of modular units with clear boundaries and well-defined responsibilities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Engineering Implementation of Vertical Decomposition: From Conceptual Splitting to Addressable Domain Coordinates
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;"The nameless is the beginning of heaven and earth. The named is the mother of all things."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The essence of vertical decomposition is to introduce structural asymmetry into an initially homogeneous and egalitarian space of functions and data by identifying "intrinsic relatedness," thereby allowing higher-level concepts (objects) to "naturally emerge."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The earliest programming languages consisted of the 0s and 1s of binary machine language, represented by punched paper tapes. Assembly language "gave aliases" to instructions and addresses, opening the door to a symbolic world. High-level languages like C/Pascal went a step further, supporting &lt;strong&gt;custom type names&lt;/strong&gt; for complex data structures and creating local variable names through local scopes. Object-orientation achieved the next conceptual leap by naming all related data and functions and introducing &lt;strong&gt;relative names&lt;/strong&gt; through the &lt;code&gt;this&lt;/code&gt; pointer: the specific meaning of &lt;code&gt;this.fly()&lt;/code&gt; is no longer absolute but is determined relative to the object entity pointed to by &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking from the outside in, the first thing we see is the &lt;strong&gt;conceptual splitting&lt;/strong&gt; brought about by vertical decomposition. Taking the Nop Platform as an example, the REST link format for frontend access to the backend is determined by first principles to be &lt;code&gt;/r/{bizObjName}__{bizAction}&lt;/code&gt; (e.g., &lt;code&gt;/r/NopAuthUser__findPage&lt;/code&gt;). This intuitively &lt;strong&gt;splits&lt;/strong&gt; a complete backend service into multiple independent semantic subspaces based on core domain concepts (like User, Order).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Object names define the split boundaries&lt;/strong&gt;: &lt;code&gt;NopAuthUser&lt;/code&gt; is the product of this split, acting as a coordinate that defines the boundary of a highly cohesive domain concept.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Splitting gives rise to internal aggregation&lt;/strong&gt;: Within this boundary, the system automatically aggregates all technical implementations of this concept:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;NopAuthUser.xbiz&lt;/code&gt; - Defines business logic&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;NopAuthUser.xmeta&lt;/code&gt; - Defines metadata model&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;NopAuthUser.view.xml&lt;/code&gt; - Defines the view outline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recursive evolution of splitting&lt;/strong&gt;: This splitting process can be applied recursively to achieve fine-grained, delta-based governance. For example: &lt;code&gt;/r/NopAuthUser_admin__active_findPage&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Further vertical splitting&lt;/strong&gt;: &lt;code&gt;NopAuthUser_admin&lt;/code&gt; is split again from the generic user concept, forming a specialized version for the administrator role. It can have its own custom business logic (&lt;code&gt;NopAuthUser_admin.xbiz&lt;/code&gt;) and UI model, while selectively inheriting the generic user's definition (using &lt;code&gt;x:extends&lt;/code&gt;). This perfectly embodies the evolutionary design from a single generic model to a "core model + multiple delta variants."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Horizontal refinement&lt;/strong&gt;: &lt;code&gt;active_findPage&lt;/code&gt; refines the behavior. Its basic logic is the same as &lt;code&gt;findPage&lt;/code&gt;, but it additionally specifies the &lt;code&gt;active&lt;/code&gt; query condition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the Nop Platform, the URL is a direct manifestation of this conceptual splitting, transforming abstract vertical slicing into a stable, addressable engineering contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  Horizontal Decomposition: The Inevitability of Layered Architecture
&lt;/h3&gt;

&lt;p&gt;Complementing vertical decomposition, which focuses on "what different things constitute the system," horizontal decomposition focuses on "which steps in the process of handling any one thing are fundamentally different." Its goal is to &lt;strong&gt;separate concerns&lt;/strong&gt;, allowing technical logic of different natures to change and be reused independently.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Natural Separation of Input, Processing, and Output&lt;/strong&gt;: The most basic horizontal decomposition is to view any process as three stages: &lt;strong&gt;"Input -&amp;gt; Processing -&amp;gt; Output."&lt;/strong&gt; We immediately realize that the same core "Processing" logic can be adapted to different "Input" sources and "Output" destinations. To reuse the core logic and isolate changes, separating these three stages into independent layers becomes a necessary choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Three-Tier Architecture&lt;/strong&gt;: The classic &lt;strong&gt;Presentation Layer, Business Logic Layer, and Data Persistence Layer&lt;/strong&gt; three-tier architecture is a direct embodiment of this horizontal decomposition thinking. It separates the input (Web requests) and output (database operations), which are strongly tied to technical details, from the core business processing logic.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Unifying the Two: A Matrix to Govern Complexity
&lt;/h3&gt;

&lt;p&gt;In a real software system, vertical and horizontal decomposition are not mutually exclusive choices but are &lt;strong&gt;simultaneously at play, interwoven&lt;/strong&gt; to form a design matrix.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Vertical decomposition defines the system's "static structure"&lt;/strong&gt;: It answers, "What are the core objects in the system?" (What it is)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Horizontal decomposition defines the system's "dynamic flow"&lt;/strong&gt;: It answers, "How does a request for each use case travel through the layers, interact with these objects, and complete its task?" (How it works)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An elegant architecture is one that makes clear, consistent cuts along both of these dimensions. It is at the intersection of this vertical and horizontal grid that we can precisely locate the responsibility of each piece of code, thus systematically building a system structure that is stable, flexible, and faithfully reflects the inherent laws of the domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  IV. Bounded Context: The Revolution of Discovering "Space"
&lt;/h2&gt;

&lt;p&gt;Before the advent of DDD, the world of software design was like the world of physics before Newton's classical mechanics.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Pre-DDD Era: An Infinite, Homogeneous "Absolute Space"
&lt;/h3&gt;

&lt;p&gt;In classical object and layered design, the entire software system was treated as a &lt;strong&gt;single, infinite, homogeneous "absolute space."&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Unified and Infinite&lt;/strong&gt;: All objects, regardless of their business domain, existed in the same global namespace and semantic field. In theory, any object could directly or indirectly interact with any other object. This is like all celestial bodies floating in the same boundless ether.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Homogeneous&lt;/strong&gt;: The space itself had no properties. We only focused on the "objects" (entities) within the space and their interactions (method calls), ignoring the possibility that the "space" itself might have properties and boundaries. &lt;strong&gt;Space was merely a passive, transparent background container.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Focus of Design&lt;/strong&gt;: Consequently, all design complexity was concentrated on how to manage and organize the "objects" in this space. We invented design patterns, componentization, and other methods to try to bring order to the tangled web of object relationships. But we never considered that the problem might lie with the "space" itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The DDD Revolution: Discovering "Relative Space"—The Bounded Context
&lt;/h3&gt;

&lt;p&gt;The paradigm shift introduced by DDD is, at a cognitive level, analogous to the shift in physics from Newton's absolute spacetime to Einstein's theory of relativity. Einstein showed that space is not a passive background but a dynamic entity that can be curved by mass and has its own properties.&lt;/p&gt;

&lt;p&gt;Similarly, through the &lt;strong&gt;Bounded Context&lt;/strong&gt;, DDD reveals to us that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;The software design space is not unified, but is composed of multiple heterogeneous, bounded "relative spaces."&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Each "space" (Bounded Context) has its own unique "physical laws"&lt;/strong&gt;—this is the &lt;strong&gt;Ubiquitous Language&lt;/strong&gt;. In the "Order space," a "Product" follows one set of rules; in the "Inventory space," the "Product" follows a completely different set of rules.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;"Space" defines the meaning of "objects"&lt;/strong&gt;: The true meaning and behavior of an object (like a "Product") are determined by the "space" (Bounded Context) it resides in. Talking about an object without its context is meaningless.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Therefore, the core contribution of the Bounded Context is that it allows us to "see" the space itself for the first time.&lt;/strong&gt; We no longer take space for granted as a transparent background, but rather treat it as a &lt;strong&gt;first-class citizen of design&lt;/strong&gt;. (Previously, we only saw the foreground and ignored the background.)&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Paradigm Shift in Design Brought by "Space"
&lt;/h3&gt;

&lt;p&gt;Once we discover the existence of "space," the entire design paradigm undergoes a fundamental transformation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;From "Objects First, Then Relationships" to "Space First, Then Objects"&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Old Paradigm&lt;/strong&gt;: We first design a large number of objects and then rack our brains to sort out the relationships between them.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;New Paradigm (DDD Strategic Design)&lt;/strong&gt;: The first thing we must do is &lt;strong&gt;partition the space&lt;/strong&gt; (identify Bounded Contexts). This is a strategic, macroscopic decision. Only after the space is defined can we safely and unambiguously design and evolve the objects (Aggregates, Entities) that belong to that space. &lt;strong&gt;Slicing happens within the space.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;From "Internal Tidying" to "Boundary Isolation" for Complexity Governance&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Old Paradigm&lt;/strong&gt;: Faced with complexity, we try to arrange the furniture more neatly within the same large room.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;New Paradigm&lt;/strong&gt;: We build walls directly, partitioning one large room into several functionally independent small rooms. Each small room can be simple internally, and interactions between rooms occur through well-defined doors (Anti-Corruption Layers, Open Host Services). &lt;strong&gt;Complexity is effectively isolated and controlled by the boundaries.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  V. Hexagonal Architecture: Boundaries and Isolation
&lt;/h2&gt;

&lt;p&gt;The "space revolution" in the vertical dimension solves the problem of macroscopic semantic boundaries. Within a single Bounded Context, the evolution of horizontal architecture is dedicated to protecting the purity of the domain model, marked by the evolution from &lt;strong&gt;Three-Tier Architecture&lt;/strong&gt; to &lt;strong&gt;Hexagonal Architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Contributions and Limitations of Three-Tier Architecture&lt;/strong&gt;&lt;br&gt;
The classic three-tier architecture (Presentation, Business Logic, Data Persistence) is a successful application of horizontal decomposition. By &lt;strong&gt;separating concerns&lt;/strong&gt;, it isolates tasks of different natures—user interaction, core logic, and data persistence—theoretically allowing the business logic layer to exist independently of specific data sources and user interfaces.&lt;/p&gt;

&lt;p&gt;However, in practice, the "Business Logic Layer" often becomes a vague container. Technical implementation details (like transaction management, database connections, remote calls) can easily leak in and become entangled with core domain rules. More critically, it implies a certain "top-down" hierarchical concept and fails to clearly and symmetrically express a core design intent: &lt;strong&gt;to protect the domain core from any external technical influence&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hexagonal Architecture: A Clear Inside and Outside&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cp0gx91v5yrwrgf09lo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cp0gx91v5yrwrgf09lo.png" alt="hexagonal-arch-diagram" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Hexagonal Architecture (also known as Ports and Adapters) is a thorough implementation and sublimation of the three-tier concept. It performs a fundamental conceptual refactoring:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*   **From "Up/Down" to "Inside/Outside"**: It abandons the hierarchically suggestive "upper-layer/lower-layer" concept and explicitly divides the system into an **Inside (Domain Model)** and an **Outside (Technical Implementations &amp;amp; the World)**.
*   **Ports and Adapters**:
    *   The **Inside** declares what functionality it needs or can provide through **Ports**—a set of abstract interfaces.
    *   The **Outside** connects concrete implementations (like web controllers, database repositories) to these ports via **Adapters**.

The essence of Hexagonal Architecture is to transform "technical layering" into "boundary division between the business core and technical implementations." It places the core domain model at the center of the architecture, isolated by a protective ring of ports and adapters. **The domain model is thus no longer "dependent" on any specific technology; it merely defines contracts (ports), and the outside world adapts to it.** This perfectly achieves the goal mentioned earlier of "building a technology-neutral expression system for business logic."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This architectural evolution can be compared to how biological cells achieve a separation of "boundary and interior" through the &lt;strong&gt;cell membrane&lt;/strong&gt;. The cell membrane (&lt;strong&gt;Ports and Adapters&lt;/strong&gt;), acting as a selective boundary, strictly controls the exchange of matter and information between the inside and outside. Its fundamental purpose is to &lt;strong&gt;create a protected internal environment, allowing the internal structures to be decoupled from the complexity of the external environment, thereby gaining the ability to evolve and adapt independently.&lt;/strong&gt; It is through this mechanism that the highly complex and precise chemical reactions (&lt;strong&gt;core business logic&lt;/strong&gt;) within the cytoplasm and nucleus (&lt;strong&gt;Domain Model&lt;/strong&gt;) can proceed stably and efficiently, free from the disorderly interference of the external environment. Bounded Context and Hexagonal Architecture, working together, achieve a similar "cellularization" encapsulation in software systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Convergence of Vertical and Horizontal to Build a Cognitive Mirror
&lt;/h3&gt;

&lt;p&gt;At this point, we can see a clear evolutionary path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Vertically&lt;/strong&gt;, DDD completes a paradigm revolution from "organizing objects" to "partitioning space" through &lt;strong&gt;Bounded Contexts&lt;/strong&gt;, solving the problem of macroscopic semantic boundaries.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Horizontally&lt;/strong&gt;, architectural styles have refined the concept from "separating concerns" to "protecting the core" through &lt;strong&gt;Hexagonal Architecture&lt;/strong&gt;, solving the problem of microscopic technical dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the two are combined, we get a powerful architectural paradigm: &lt;strong&gt;a system is composed of multiple Bounded Contexts (vertical semantic spaces), and each Bounded Context, in turn, uses a Hexagonal Architecture (horizontal technical boundaries) to organize its internal structure.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This marks an evolution in our design thinking from simple "slicing" and "layering" to the thoughtful design and governance of "boundaries." By drawing clear, robust boundaries in these vertical and horizontal dimensions, we finally construct a software system that can truly &lt;strong&gt;map the inherent laws of the domain&lt;/strong&gt;, possessing both resilience and evolvability—a precise &lt;strong&gt;cognitive mirror&lt;/strong&gt; of domain knowledge in the digital world.&lt;/p&gt;

&lt;h2&gt;
  
  
  VI. Entity and Domain Event: Evolution in the Time Dimension
&lt;/h2&gt;

&lt;p&gt;Through vertical and horizontal decomposition, we have shaped the spatial structure of a software system. However, a model that truly reflects the laws of a domain must not only depict its &lt;strong&gt;static snapshot&lt;/strong&gt; at a given moment but also describe its &lt;strong&gt;dynamic evolution&lt;/strong&gt; over time. DDD opens up our understanding of the system's behavioral time dimension through two core constructs: &lt;strong&gt;Entity&lt;/strong&gt; and &lt;strong&gt;Domain Event&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entity: Continuity of Identity Through Time
&lt;/h3&gt;

&lt;p&gt;In DDD's tactical patterns, an &lt;strong&gt;Entity&lt;/strong&gt; is defined as an object determined by its &lt;strong&gt;identity&lt;/strong&gt;, not its attribute values. This definition, though seemingly simple, contains a profound philosophical insight: it captures those things in the domain that need to maintain &lt;strong&gt;identity&lt;/strong&gt; as time passes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Identity: The Anchor Across Time&lt;/strong&gt;&lt;br&gt;
An "Order" may constantly change its state (amount, shipping address, logistics information) from creation to payment to delivery, but we always consider it the &lt;strong&gt;same&lt;/strong&gt; order. The identity (like an order number) is the "anchor" that allows this order to maintain its selfhood in the stream of time. It answers a fundamental question: "In the full set of state changes, what is immutable and used to track the thing itself?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Finiteness of State&lt;/strong&gt;&lt;br&gt;
An entity's state transitions are not arbitrary. The &lt;strong&gt;Aggregate Root&lt;/strong&gt; pattern imposes a boundary, specifying which states an entity can "control" (those within its aggregate), and ensures the &lt;strong&gt;legitimacy&lt;/strong&gt; of state transitions by guarding invariants. This makes the entity's lifecycle, though long, follow a predictable and constrained path.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;An Entity, in essence, is a model for things in the domain that are stateful, have a lifecycle, and need to be continuously tracked over time.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Command and Notice: The Philosophical Distinction Between Intent and Fact
&lt;/h3&gt;

&lt;p&gt;At the source that drives an entity's state evolution, we must make a fundamental distinction: &lt;strong&gt;Command&lt;/strong&gt; versus &lt;strong&gt;Notice&lt;/strong&gt;, which is the divide between &lt;strong&gt;intent&lt;/strong&gt; and &lt;strong&gt;fact&lt;/strong&gt; (To-Do list vs. operation log).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Command: Intent Laden with Uncertainty&lt;/strong&gt; (Points to the future, the start of a process)&lt;br&gt;
A &lt;strong&gt;Command&lt;/strong&gt; is an &lt;strong&gt;imperative sentence&lt;/strong&gt; expressing the &lt;strong&gt;intent&lt;/strong&gt; for the system to perform an action, such as &lt;code&gt;PlaceOrder&lt;/code&gt; or &lt;code&gt;ConfirmPayment&lt;/code&gt;. The outcome of a command is not predetermined; it depends on the system's &lt;strong&gt;current state&lt;/strong&gt; and &lt;strong&gt;external environment&lt;/strong&gt; when the command is received. Therefore, &lt;strong&gt;executing the same command multiple times may produce different results due to different timing and contexts&lt;/strong&gt;. This uncertainty is a direct reflection of business rule complexity and the non-deterministic nature of the real world.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Notice: Event as a Confirmed Fact&lt;/strong&gt; (Points to the past, the end of a process)&lt;br&gt;
A &lt;strong&gt;Notice&lt;/strong&gt; (often represented as a &lt;strong&gt;Domain Event&lt;/strong&gt; in DDD) is a &lt;strong&gt;declarative sentence&lt;/strong&gt; recording a &lt;strong&gt;fact&lt;/strong&gt; that has already occurred and cannot be changed, such as &lt;code&gt;OrderPlaced&lt;/code&gt; or &lt;code&gt;PaymentConfirmed&lt;/code&gt;. It is an assertion about the outcome of a state transition and contains no execution logic itself. &lt;strong&gt;Processing the same notice multiple times should yield a deterministic and idempotent result&lt;/strong&gt;, because it describes the past, and the past cannot be changed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;[A Note from a Design Perspective]&lt;/strong&gt;&lt;br&gt;
This distinction clarifies a potential misunderstanding in the classic &lt;strong&gt;Command Pattern&lt;/strong&gt; when applied to business modeling. The "command" recorded in that pattern, to enable safe &lt;code&gt;Redo/Undo&lt;/code&gt;, must have its inherent uncertainty eliminated. It essentially records a &lt;strong&gt;deterministic change function&lt;/strong&gt; on the state space. This is closer to what we call an "event" in &lt;strong&gt;Event Sourcing&lt;/strong&gt;—a confirmed, safely replayable factual notice. The true business "command," on the other hand, precedes this deterministic change function; it is the input that triggers the computation and contains the seeds of uncertainty itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  From a Single Timeline to Parallel Universes: A New Picture of the Time Dimension
&lt;/h3&gt;

&lt;p&gt;The traditional modeling perspective is a "top-down view," where we observe the final state of an entity at a specific point in time. Domain events and technologies like CDC (Change Data Capture) shift our perspective to a "side view"—we begin to focus on the &lt;strong&gt;timeline&lt;/strong&gt; constituted by state transitions itself.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Timeline as a First-Class Citizen and State Deltas&lt;/strong&gt;&lt;br&gt;
When we take a side view, the entity's current state is no longer the sole focus. The &lt;strong&gt;timeline&lt;/strong&gt; of its complete lifecycle, composed of domain events, becomes equally, if not more, fundamental. The current state is merely a cross-section of this timeline at the "present" moment. More importantly, we can understand this relationship with a concise mathematical formula:&lt;br&gt;
&lt;code&gt;NewState = Action(OldState, Event) = OldState ⊕ Event&lt;/code&gt;&lt;br&gt;
Here, the &lt;strong&gt;Event can be precisely understood as a &lt;code&gt;Delta&lt;/code&gt; in the state space&lt;/strong&gt;, and the &lt;code&gt;⊕&lt;/code&gt; operation represents the &lt;strong&gt;deterministic evolution function&lt;/strong&gt; that applies this delta to the old state to produce the new state. This formula clearly reveals the essence of an event as a "state increment."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Possibility of Multi-Verse Evolution&lt;/strong&gt;&lt;br&gt;
This mathematical perspective provides a theoretical basis for "multi-verse" evolution. Since the system's evolution is driven by a stream of events, starting from the same initial state &lt;code&gt;S0&lt;/code&gt; and applying different event sequences &lt;code&gt;[E1, E2, ...]&lt;/code&gt; through the continuous application of the &lt;code&gt;⊕&lt;/code&gt; operation will give rise to different &lt;strong&gt;timeline branches&lt;/strong&gt;. This is akin to the "parallel universes" discussed by physicists.&lt;br&gt;
&lt;strong&gt;Event Sourcing&lt;/strong&gt; technology is the engineering practice of this idea: it uses the event stream &lt;code&gt;[E1, E2, ..., En]&lt;/code&gt; as the single source of truth for the system's state. The current state is simply the result of calculating &lt;code&gt;S0 ⊕ E1 ⊕ E2 ⊕ ... ⊕ En&lt;/code&gt;. This allows us to precisely reconstruct the entity's state at any point in history by replaying the event stream, and even to simulate different "what if..." scenarios by injecting different event sequences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infinite Event Streams and System Resilience&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Infinitely long, replayable message queues&lt;/strong&gt; (like Apache Kafka) provide the infrastructure for this multi-timeline picture. They allow domain events, as deterministic deltas, to serve as a permanent, shared communication medium. Different Bounded Contexts (and even different derived systems) can independently consume and process events from the stream at their own pace and with their own logic, building their own state universes based on the same &lt;code&gt;S0&lt;/code&gt; and &lt;code&gt;⊕&lt;/code&gt; function, thereby achieving unprecedented system decoupling and evolutionary resilience.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusion: Building a System That is Traceable and Sim-ulatable in the Time Domain
&lt;/h3&gt;

&lt;p&gt;By combining the lifecycle of an &lt;strong&gt;Entity&lt;/strong&gt;, the uncertainty of a &lt;strong&gt;Command&lt;/strong&gt;, and the determinism of an &lt;strong&gt;Event&lt;/strong&gt; as a state delta, we construct a model within the software system that is &lt;strong&gt;traceable and even sim-ulatable in the time domain&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Entity&lt;/strong&gt; provides the &lt;strong&gt;subject&lt;/strong&gt; for tracking changes over time.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Command&lt;/strong&gt; is the &lt;strong&gt;intent input&lt;/strong&gt;, laden with uncertainty, that drives change.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Event (Δ)&lt;/strong&gt; is the &lt;strong&gt;state delta&lt;/strong&gt; that records confirmed changes, constituting the timeline and driving deterministic state evolution via the &lt;code&gt;⊕&lt;/code&gt; operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This "Command-Event-Entity" triangle, supplemented by the &lt;code&gt;State ⊕ Event&lt;/code&gt; mathematical model and the shift from a "state top-down view" to a "timeline side view," makes the system's dynamic behavior thoroughly explicit and mathematical. It transforms business logic from a black box hidden behind method calls into a series of observable, traceable, and even simulatable causal chains. It is on this time dimension that the systems we build with DDD truly gain the insight and evolutionary capability to cope with the complexity and uncertainty of the real business world.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An Entity corresponds to a timeline with its own intrinsic activity. Any operation on it means that different timelines will become entangled, creating complex histories and hard-to-manage side effects. A Value Object, on the other hand, is an immutable snapshot of a fact at a point in time. It has no timeline of its own and can therefore be safely embedded in any timeline as a universal descriptor. This is why one should use Value Objects wherever possible, to avoid the "entanglement" cost brought about by unnecessary entity-fication.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Epilogue: The Price of Irreversible Time—The Real-World Dilemma of Traditional Design
&lt;/h3&gt;

&lt;p&gt;However, in most traditional software designs, this systematic consideration of the time dimension is severely lacking. Systems typically only maintain the "current state" of an entity, discarding the complete evolutionary history. This design leads to the &lt;strong&gt;irreversibility of time&lt;/strong&gt;—when the business needs to "roll back" (e.g., for refunds or interest recalculations), the reverse logic, lacking precise historical events, can only be based on &lt;strong&gt;speculation and estimation&lt;/strong&gt;, which is essentially an imprecise approximation (a reversal based on assumptions, not facts).&lt;/p&gt;

&lt;p&gt;This technical information deficit ultimately forces the business to compromise, creating various "imperfect but feasible" solutions. This starkly contrasts with the value of an event-centric model that preserves the complete timeline. It requires us to confront the need for &lt;strong&gt;time symmetry&lt;/strong&gt; from the very beginning of the design process, ensuring the system retains enough information to not only evolve forward but also to perform precise "reversals" when necessary.&lt;/p&gt;

&lt;p&gt;This is not just a technical implementation upgrade, but a fundamental shift in design philosophy: &lt;strong&gt;from caring only about "what it is now," to also caring about "how it became now" and "how to get back to the past."&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  VII. Mathematical Insights: Language as a Coordinate System
&lt;/h2&gt;

&lt;p&gt;We have established the cognitive framework for Domain-Driven Design (DDD) to master complexity through the philosophical concepts of "boundary" and "time." Traditional DDD stops here—it provides powerful analytical thinking and a series of patterns, but it essentially remains at the level of qualitative cognition. Can we, however, transform this methodological philosophy into a rigorous, computable, and executable software construction system? The answer lies hidden in a pure mathematical examination of "extensibility" and "system evolution."&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Mathematical Axioms of Extensibility
&lt;/h3&gt;

&lt;p&gt;Let's abstract the process of software evolution into a mathematical formula. Suppose a system evolves from an initial state &lt;code&gt;X&lt;/code&gt; to a new state &lt;code&gt;Y&lt;/code&gt;. If we consider &lt;code&gt;X&lt;/code&gt; as a set composed of parts &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;C&lt;/code&gt;, then the evolved &lt;code&gt;Y&lt;/code&gt; might become a set of &lt;code&gt;A'&lt;/code&gt;, &lt;code&gt;B'&lt;/code&gt;, and a new part &lt;code&gt;D&lt;/code&gt;. This process can be expressed as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;X = A + B + C&lt;/code&gt;, &lt;code&gt;Y = A' + B' + D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, &lt;code&gt;A'&lt;/code&gt; and &lt;code&gt;B'&lt;/code&gt; are modifications of &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt;, which we can represent as &lt;code&gt;A' = A + dA&lt;/code&gt; and &lt;code&gt;B' = B + dB&lt;/code&gt;. Substituting this into the equation, we get:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Y = (A + dA) + (B + dB) + D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To establish a clear mathematical relationship between the evolved &lt;code&gt;Y&lt;/code&gt; and the original &lt;code&gt;X&lt;/code&gt;, we introduce the concept of a "Delta," defining &lt;code&gt;Y = X + Delta&lt;/code&gt;. Through simple algebraic manipulation, we can reveal the specific composition of &lt;code&gt;Delta&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Delta = Y - X&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Delta = (A + dA + B + dB + D) - (A + B + C)&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Delta = dA + dB + D - C&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a heuristic derivation. The mathematical definition of a Delta in reversible computation theory is more complex, and general Deltas do not necessarily satisfy the commutative law.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This seemingly simple formula reveals two indispensable mathematical axioms for achieving true extensibility:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A Delta Must Include Both "Addition" and "Subtraction"&lt;/strong&gt;: &lt;code&gt;Delta&lt;/code&gt; not only contains the new part &lt;code&gt;D&lt;/code&gt; and modifications &lt;code&gt;dA&lt;/code&gt;, &lt;code&gt;dB&lt;/code&gt; (which can be seen as additions), but it must also contain an &lt;strong&gt;inverse element &lt;code&gt;-C&lt;/code&gt;&lt;/strong&gt;, i.e., the ability to &lt;strong&gt;delete&lt;/strong&gt; an original part. Any extension mechanism that only supports "addition" (like most plugin systems) is mathematically incomplete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A Delta Must Be Separable and Relocatable&lt;/strong&gt;: To achieve separation of concerns, we want to consolidate all changes (&lt;code&gt;dA&lt;/code&gt;, &lt;code&gt;dB&lt;/code&gt;, &lt;code&gt;D&lt;/code&gt;, &lt;code&gt;-C&lt;/code&gt;) into an independent &lt;code&gt;Delta&lt;/code&gt; package, managed separately from the base system &lt;code&gt;X&lt;/code&gt;. When this &lt;code&gt;Delta&lt;/code&gt; needs to be applied, the system must be able to know precisely that &lt;code&gt;dA&lt;/code&gt; should act on &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;-C&lt;/code&gt; should remove &lt;code&gt;C&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This second axiom leads directly to an inevitable conclusion: &lt;strong&gt;there must exist a precise, unambiguous positioning system within the system, such that any part that can be modified can be uniquely "referenced."&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Coordinate System: From Positioning to Addressing
&lt;/h3&gt;

&lt;p&gt;The formal mathematical name for this "positioning system" is a &lt;strong&gt;coordinate system&lt;/strong&gt;. A proper coordinate system must provide us with two basic operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;code&gt;value = get(path)&lt;/code&gt;: Get a value based on a unique coordinate (path).&lt;/li&gt;
&lt;li&gt; &lt;code&gt;set(path, value)&lt;/code&gt;: Set (or modify/delete) a value based on a unique coordinate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This requires that &lt;strong&gt;all objects in the system that need to be focused on, modified, and evolved must have a unique, stable coordinate in this coordinate system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Looking back at our traditional extension mechanisms, we find that their essence is an attempt to construct some kind of coordinate system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Plugins/Extension Points&lt;/strong&gt;: These can be seen as a &lt;strong&gt;discrete, predefined set of coordinate points&lt;/strong&gt;. We pre-dig several "holes" in the system and name them—these are the coordinates. The fundamental flaw of this approach is its &lt;strong&gt;predictive nature&lt;/strong&gt;—we must predict all possible extension points in advance. Too few extension points, and the architecture becomes rigid; too many, and the architecture "dissolves," losing its cohesion. We can never apply an effect at an unforeseen location without modifying the source code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. The Intrinsic Coordinates of Language: From General to Specific
&lt;/h3&gt;

&lt;p&gt;How can we establish a coordinate system that is all-encompassing and requires no prediction? The answer lies in something we take for granted: &lt;strong&gt;programming languages&lt;/strong&gt;. Because all system logic must ultimately be expressed through some language, &lt;strong&gt;the structure of the language itself constitutes a natural coordinate system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, different languages have vastly different precision and applicability in their coordinate systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Coordinate System of General-Purpose Languages (GPLs)&lt;/strong&gt;: Languages like Java and C# provide a &lt;strong&gt;two-level "class-method" coordinate system&lt;/strong&gt;. We can locate a class, and then a method within it. &lt;strong&gt;AOP (Aspect-Oriented Programming)&lt;/strong&gt; essentially utilizes this coordinate system and, by introducing mechanisms like Annotations, "refines" it to some extent, adding more "coordinate points." But it still cannot delve inside a method, nor can it stably reference an anonymous inner class or a lambda expression. This is a &lt;strong&gt;general-purpose, but coarse-grained&lt;/strong&gt;, coordinate system. When a minor business change occurs, the "structural mismatch" of the coordinate system often leads to scattered, non-local changes across many source files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Intrinsic Coordinate System of a Domain-Specific Language (DSL)&lt;/strong&gt;: Physics tells us that the most natural coordinate system for describing circular motion is polar coordinates, not Cartesian coordinates. This polar coordinate system is "intrinsic" to the geometric properties of the problem itself. It leverages the inherent constraint that the radius &lt;code&gt;r&lt;/code&gt; is constant, thus simplifying the description of a trajectory that would otherwise require two variables (&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;) to one that requires only one variable, &lt;code&gt;θ&lt;/code&gt; (angle), achieving &lt;strong&gt;dimensionality reduction of the problem&lt;/strong&gt;. Similarly, the most natural way to describe a business domain is with a custom-built &lt;strong&gt;Domain-Specific Language (DSL)&lt;/strong&gt;. Every node and attribute in the Abstract Syntax Tree (AST) of this DSL can be precisely located by its unique path (e.g., XPath). This constitutes a &lt;strong&gt;fine-grained, stable, intrinsic coordinate system tailored for the domain problem&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;[Analogy: The Method of Moving Frames in Differential Geometry]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This idea can be compared to the &lt;strong&gt;Method of Moving Frames&lt;/strong&gt; in differential geometry. While a moving trajectory can be described in an external coordinate system, what is more profound is that &lt;strong&gt;the trajectory itself naturally generates an intrinsic coordinate system attached to it, one that best reflects its internal geometric properties&lt;/strong&gt;. For example, for a curve in three-dimensional space, its "moving frame" at each point consists of three mutually orthogonal unit vectors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Tangent vector (T)&lt;/strong&gt;: Points in the direction the curve is moving.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Normal vector (N)&lt;/strong&gt;: Points in the direction the curve is bending.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Binormal vector (B)&lt;/strong&gt;: Is perpendicular to both the tangent and normal vectors, describing the direction the curve is "twisting" out of its current plane.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These three vectors are completely determined by the curve's own local geometry (velocity, acceleration), not by a fixed external coordinate system. Similarly, business logic is described in a DSL, and the structure of this DSL itself provides the most natural intrinsic coordinate system for describing &lt;em&gt;changes&lt;/em&gt; to the business logic (i.e., the &lt;code&gt;Delta&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The core contribution of language paradigms like XLang is to ensure, through mechanisms like the &lt;code&gt;XDef&lt;/code&gt; metamodel, that every syntax node in any defined DSL automatically receives a stable domain coordinate.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The Macroscopic Puzzle and a Field-Theoretic Worldview
&lt;/h3&gt;

&lt;p&gt;So far, we have found an intrinsic coordinate system for a single domain. But a complex enterprise system often involves multiple domains (e.g., orders, inventory, payments). Trying to describe all domains with a single, monolithic DSL is like trying to accurately map the streets of every city with a single flat world map—it's both impossible and unnecessary.&lt;/p&gt;

&lt;p&gt;In modern mathematics, the breakthrough of differential manifold theory was the realization that describing a complex curved space (like the surface of the Earth) cannot rely on a single coordinate system. Instead, one must introduce an &lt;strong&gt;"Atlas"&lt;/strong&gt; composed of multiple local coordinate systems (maps). Each map is responsible for describing only a small region, and the maps are smoothly "glued" together by "transition functions." This idea can be heuristically mapped to software architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A complex system should be described by a &lt;strong&gt;"DSL forest"&lt;/strong&gt; or a &lt;strong&gt;"DSL Atlas."&lt;/strong&gt; Each DSL (e.g., &lt;code&gt;orm.xml&lt;/code&gt;, &lt;code&gt;workflow.xml&lt;/code&gt;, &lt;code&gt;view.xml&lt;/code&gt;) is a "local map," responsible for describing the intrinsic structure of a Bounded Context.&lt;/li&gt;
&lt;li&gt;  A foundational framework like the Nop Platform, in turn, has the core responsibility of providing the universal "glue"—the common &lt;strong&gt;Delta computation mechanism&lt;/strong&gt; (like &lt;code&gt;x-extends&lt;/code&gt;). This allows us to apply a unified, coordinate-based &lt;code&gt;Delta&lt;/code&gt; package across different DSL "maps," thereby achieving global, consistent system evolution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the introduction of a coordinate system, our worldview undergoes a fundamental shift. It is no longer about the interaction of discrete objects but moves towards a &lt;strong&gt;Field Theory&lt;/strong&gt; worldview. A "field" is a space where a ubiquitous coordinate system exists, and a physical quantity can be defined at every point in that coordinate system. Our focus is no longer on isolated objects, but on objects immersed in the field, and the properties of the field itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. A Revolution in Worldview: From Particles to Waves, From Assembly to Superposition
&lt;/h3&gt;

&lt;p&gt;Ultimately, mastering this ideology based on coordinate systems and deltas will bring about a profound &lt;strong&gt;revolution in worldview&lt;/strong&gt;. This can be compared to the &lt;strong&gt;wave-particle duality&lt;/strong&gt; revealed by quantum physics.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Traditional Worldview: Particle View&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Basic Unit&lt;/strong&gt;: The world is made of discrete, bounded "&lt;strong&gt;objects&lt;/strong&gt;," "components," and "modules." These are the fundamental "particles" of the software world.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Construction Method&lt;/strong&gt;: Through &lt;strong&gt;Invasive Assembly&lt;/strong&gt;. We rigidly connect these "particles" through invocation, inheritance, composition, etc., to build larger aggregates.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Focus&lt;/strong&gt;: The internal state and behavior of individual objects. We think: "What &lt;strong&gt;is&lt;/strong&gt; this object? What can it &lt;strong&gt;do&lt;/strong&gt;?"&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;New Worldview: Wave View&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Basic Unit&lt;/strong&gt;: The world is composed of a &lt;strong&gt;continuous pattern (the coordinate system/field)&lt;/strong&gt; as the background, and the &lt;strong&gt;perturbations (the deltas/Δ)&lt;/strong&gt; that act upon it.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Construction Method&lt;/strong&gt;: Through &lt;strong&gt;Non-Invasive Superposition&lt;/strong&gt;. Different "waves" (delta packages &lt;code&gt;Delta&lt;/code&gt;) interfere and superimpose within the same "field" (base structure &lt;code&gt;X&lt;/code&gt;), collectively shaping the final complex form &lt;code&gt;Y&lt;/code&gt; that we observe.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Focus&lt;/strong&gt;: How the background &lt;strong&gt;coordinate system evolves&lt;/strong&gt;, and how the &lt;strong&gt;changes (Δ) themselves are combined, transmitted, and interact&lt;/strong&gt;. We think: "In &lt;strong&gt;which coordinate system&lt;/strong&gt; did &lt;strong&gt;what change&lt;/strong&gt; occur?"&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This cognitive revolution is the most valuable gift that (Generalized) Reversible Computation offers us. It leads us from an ontology of "being" to an evolution theory of "becoming." Our understanding of software shifts from static, isolated "entities" to dynamic, interconnected "processes." Once we complete this worldview transformation, we will be able to master the eternal and ubiquitous force in the software world—&lt;strong&gt;change&lt;/strong&gt;—with unprecedented clarity, elegance, and power.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. A Paradigm Shift in the Principle of Reuse: From "Decomposition-Reassembly" to "Whole-Transformation"
&lt;/h3&gt;

&lt;p&gt;The establishment of the coordinate system and delta model directly triggers a &lt;strong&gt;paradigm shift&lt;/strong&gt; in "reuse." The core of this shift is &lt;strong&gt;transforming the cost of change from being "related to the overall complexity of the system" to being "related only to the size of the change itself."&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Old Paradigm: "Decomposition-Reassembly" Reuse Based on "Sameness"&lt;/strong&gt;&lt;br&gt;
Traditional reuse is &lt;strong&gt;"modification-based reuse."&lt;/strong&gt; When a system evolves from &lt;code&gt;X&lt;/code&gt; to &lt;code&gt;Y&lt;/code&gt;, we must &lt;strong&gt;"open up"&lt;/strong&gt; the internals of &lt;code&gt;X&lt;/code&gt;, identify the &lt;strong&gt;same&lt;/strong&gt; parts for reuse, and then modify, replace, and reassemble the remaining parts. In this process, the &lt;strong&gt;cost of change is directly related to the overall complexity of the base system &lt;code&gt;X&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;New Paradigm: "Whole-Transformation" Reuse Based on "Relatedness"&lt;/strong&gt;&lt;br&gt;
Reversible computation's reuse is &lt;strong&gt;"superposition-based reuse."&lt;/strong&gt; We treat the entire &lt;code&gt;X&lt;/code&gt; as a black-box whole, &lt;strong&gt;untouched&lt;/strong&gt;, and independently create a &lt;strong&gt;delta &lt;code&gt;Delta&lt;/code&gt;&lt;/strong&gt; that describes all changes. Finally, we obtain the new system through &lt;code&gt;Y = X + Delta&lt;/code&gt;. &lt;code&gt;X&lt;/code&gt; is never "opened" or "modified." The &lt;strong&gt;cost of change is related only to the complexity of the delta &lt;code&gt;Delta&lt;/code&gt; and is completely decoupled from the size and complexity of &lt;code&gt;X&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This is like the difference between "genetic surgery" and "wearing equipment":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Traditional reuse is "genetic surgery"&lt;/strong&gt;: The cost and risk of the surgery are strongly correlated with the complexity of the organism itself.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Reversible computation is "wearing equipment"&lt;/strong&gt;: All costs and risks lie in making the "equipment" (&lt;code&gt;Delta&lt;/code&gt;), regardless of whether the organism is a mouse or an elephant.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;The ultimate insight of this &lt;strong&gt;paradigm shift&lt;/strong&gt; lies in the fundamental leap of the reuse principle: from &lt;strong&gt;Reuse of Sameness&lt;/strong&gt; to &lt;strong&gt;Reuse of Relatedness&lt;/strong&gt;. We are no longer limited to reusing the same parts in a "part-whole" relationship but can establish a transformation relationship via a &lt;code&gt;Delta&lt;/code&gt; between any two related systems &lt;code&gt;X&lt;/code&gt; and &lt;code&gt;Y&lt;/code&gt;. This makes it possible to "&lt;strong&gt;inherit an entire software product just like inheriting a class&lt;/strong&gt;," perfectly solving the core conflict between "productization and deep customization" in the enterprise software domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Note on the Real-World Form of "Domain Languages"
&lt;/h3&gt;

&lt;p&gt;It is important to note that in the vast majority of DDD practices, the so-called "Ubiquitous Language" or "Domain Language" is far from reaching the rigor of a &lt;strong&gt;complete formal language&lt;/strong&gt; (with precisely defined syntax and semantics). More often, it manifests as a &lt;strong&gt;domain vocabulary&lt;/strong&gt; agreed upon through negotiation, relying on the team's experience and conventions to constrain the combinatorial relationships between these concepts.&lt;/p&gt;

&lt;p&gt;The manifestation of this constrained relationship in code is precisely the &lt;strong&gt;encapsulation&lt;/strong&gt; and &lt;strong&gt;association&lt;/strong&gt; mechanisms of object-oriented programming: specific methods can only belong to specific classes (defining "what can be done"), and specific classes can only be associated in specific ways (defining "who is related to whom"). This is, in effect, simulating a &lt;strong&gt;constrained context-free grammar&lt;/strong&gt;—class names and associations form the syntax, while method implementations provide the semantics. Many successful &lt;strong&gt;internal DSLs&lt;/strong&gt; today follow this path: they do not create a new language from scratch but cleverly leverage the class system of a host language (like Java or C#) to build a restricted subset of expressions that is morphologically closer to the domain problem, often using methods like the &lt;strong&gt;Fluent Interface&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Therefore, the real-world significance of the "Language as a Coordinate System" insight is that it pushes us to &lt;strong&gt;engineer&lt;/strong&gt; the implicit, vague rules of vocabulary combination into a &lt;strong&gt;finite but precise set of explicit specifications&lt;/strong&gt;. A superior domain DSL is the ultimate embodiment of this process—it strives to upgrade the "coordinate system" of domain expression from an experience-dependent "rough sketch" to a machine-parsable "engineering blueprint."&lt;/p&gt;

&lt;p&gt;Wittgenstein famously said, &lt;strong&gt;"The limits of my language mean the limits of my world."&lt;/strong&gt; The (Generalized) Reversible Computation theory further interprets this as: &lt;strong&gt;A language is a coordinate system, and from a coordinate system, a delta naturally arises.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  VIII. Reversible Computation: Making Evolution Programmable
&lt;/h2&gt;

&lt;p&gt;After "seeing space" with Bounded Contexts and "seeing time" with event timelines, we are just one step away from truly bringing software into a state of sustainable order: seeing the shape of "change" itself and making it orchestratable. The insight of Reversible Computation lies precisely here—it does not treat change as an accidental side effect but reifies change itself, making it data-driven and composable (demoting it from a verb to a noun). It attempts to establish a unified "evolutionary dynamics" for system construction and growth with an extremely simple yet infinitely recursive formula: &lt;code&gt;Y = F(X) ⊕ Δ&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Universal Pattern of Evolution: From a Perturbation Model to a Construction Paradigm
&lt;/h3&gt;

&lt;p&gt;Any computation can be abstractly described as &lt;code&gt;Result = Function(Data)&lt;/code&gt;. When a system evolves, both the &lt;code&gt;Function&lt;/code&gt; and the &lt;code&gt;Data&lt;/code&gt; can change: &lt;code&gt;NewFunction = BaseFunction + ΔFunction&lt;/code&gt;, and &lt;code&gt;NewData = BaseData + ΔData&lt;/code&gt;. The interaction of these underlying changes ultimately leads to a change in the &lt;code&gt;Result&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Traditional approaches get bogged down in analyzing these complex interactions. The revolutionary assertion of Reversible Computation is that &lt;strong&gt;regardless of how complex the underlying changes are, their net effect on the final result can always be encapsulated into a single, structured 'Total Delta'.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This means we can describe evolution with a universal perturbation model:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;NewResult = BaseFunction(BaseData) + TotalDelta&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This formula describes the necessary structure of any evolving system; &lt;strong&gt;it is a mathematical necessity.&lt;/strong&gt; Consider this: if we view the output result as binary data, we can always define a delta between any two pieces of data in binary space using an XOR operation. However, such a raw bitstream-level delta has no business value; it is difficult to understand intuitively and cannot be efficiently composed or maintained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real breakthrough is to apply the delta to a structured space.&lt;/strong&gt; The key here can be compared to the success of Docker container technology:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The delta backup mechanism of &lt;strong&gt;virtual machine images&lt;/strong&gt; is like operating in binary space—feasible but cumbersome.&lt;/li&gt;
&lt;li&gt;  The &lt;strong&gt;&lt;code&gt;App = DockerBuild&amp;lt;Dockerfile&amp;gt; overlay-fs BaseImage&lt;/code&gt;&lt;/strong&gt; paradigm, however, by establishing a Delta within the structured &lt;strong&gt;filesystem namespace&lt;/strong&gt;, achieves lightweight reuse and flexible composition of image layers, thus completely liberating productivity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reversible Computation theory elevates this idea to a higher dimension of software construction, implementing the universal computation pattern &lt;code&gt;Y = F(X) ⊕ Δ&lt;/code&gt; as a very specific, executable technical formula:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;App = Delta x-extends Generator&amp;lt;DSL&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This paradigm precisely decomposes the software construction process into three independently evolvable &lt;strong&gt;First-class Citizens&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DSL (Domain-Specific Language)&lt;/strong&gt;: &lt;strong&gt;As a precise "Domain Coordinate System"&lt;/strong&gt;&lt;br&gt;
It defines the problem's description space. A well-structured DSL provides a stable, addressable location for every semantic unit in the system. This is the &lt;strong&gt;structural prerequisite&lt;/strong&gt; for &lt;code&gt;Delta&lt;/code&gt; to perform precise addressing and application, and for &lt;code&gt;x-extends&lt;/code&gt; to achieve reversible merging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generator&lt;/strong&gt;: &lt;strong&gt;As a "Model Transformer" and "Truth Unfolder"&lt;/strong&gt;&lt;br&gt;
At compile-time, it is responsible for executing multi-stage transformations from abstract to concrete (model-to-model, model-to-code). More profoundly, like the derivation process of a mathematical theorem, it automatically unfolds a highly condensed "kernel truth" (the DSL model) into a complete, runnable base application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Delta&lt;/strong&gt;: &lt;strong&gt;As a composable "Evolution Unit"&lt;/strong&gt;&lt;br&gt;
It is an independent, reversible, and non-invasive unit of change. &lt;code&gt;Delta&lt;/code&gt; encapsulates all changes, including &lt;strong&gt;structured deletion&lt;/strong&gt;, and its merge operation satisfies the &lt;strong&gt;associative law&lt;/strong&gt;, meaning multiple &lt;code&gt;Deltas&lt;/code&gt; can be pre-composed into an independently distributable and versionable "feature pack" or "patch."&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, these three first-class citizens are deterministically combined via the &lt;code&gt;x-extends&lt;/code&gt; operator. &lt;code&gt;x-extends&lt;/code&gt; is an &lt;strong&gt;algebraic upgrade&lt;/strong&gt; to the traditional &lt;code&gt;extends&lt;/code&gt;. It is no longer simple property overriding but a reversible, deterministic merge of a first-class citizen &lt;code&gt;Delta&lt;/code&gt; within a well-defined structural space. Because its operation is deterministic, the concept of "merge conflicts" found in traditional version control (like Git) does not exist.&lt;/p&gt;

&lt;p&gt;In this way, Reversible Computation elevates the trickiest problems in software engineering—"customization," "reuse," and "evolution"—from the realm of external tools or design patterns &lt;strong&gt;to the core semantic level of the language itself&lt;/strong&gt;, providing them with a native, unified, and mathematically sound solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgitee.com%2Fcanonical-entropy%2Fnop-entropy%2Fblob%2Fmaster%2Fdocs-en%2Ftheory%2Fxlang-review%2Fxlang-theory-en.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgitee.com%2Fcanonical-entropy%2Fnop-entropy%2Fblob%2Fmaster%2Fdocs-en%2Ftheory%2Fxlang-review%2Fxlang-theory-en.svg" alt="xlang-theory" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It must be emphasized that the formula &lt;code&gt;App = Delta x-extends Generator&amp;lt;DSL&amp;gt;&lt;/code&gt; in Reversible Computation theory is not a metaphorical illustration but a technical path that can be rigorously defined mathematically and strictly implemented in engineering.&lt;/strong&gt; The Nop Platform systematically implements this programming paradigm through XLang, a fourth-generation programming language with a built-in concept of deltas. For details, see &lt;a href="https://dev.to/canonical/why-is-xlang-an-innovative-programming-language-5fja"&gt;Why XLang is an Innovative Programming Language?&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Fractal Construction of Software: Longitudes and Latitudes
&lt;/h3&gt;

&lt;p&gt;To truly understand the essence of Reversible Computation as a "system construction theory," we must grasp the most profound characteristic of the invariant &lt;code&gt;Y = F(X) ⊕ Δ&lt;/code&gt;: its &lt;strong&gt;recursivity&lt;/strong&gt;. It is not just a formula but a &lt;strong&gt;fractal self-similarity principle&lt;/strong&gt; that is recursively applied throughout the software world.&lt;/p&gt;

&lt;p&gt;This self-similarity is manifested in several fundamental dimensions of software architecture: the vertical "longitudes" (cross-layer), the horizontal "latitudes" (cross-domain), the flow of time (version evolution), and the "meta-level" of the construction system itself. Together, they weave a complete, evolvable "DSL Atlas."&lt;/p&gt;

&lt;h4&gt;
  
  
  2.1 Vertical Longitudes: The Multi-Stage Software Production Line
&lt;/h4&gt;

&lt;p&gt;The vertical "longitudes" depict a &lt;strong&gt;multi-stage software production line&lt;/strong&gt;, which solves a core dilemma of traditional Model-Driven Architecture (MDA). In traditional MDA, if the reasoning chain is too long (e.g., directly generating final UI code from a highly abstract business model), it leads to overly complex source model definitions and allows information from different abstraction levels to mix chaotically, ultimately becoming difficult to maintain and extend.&lt;/p&gt;

&lt;p&gt;Reversible Computation provides a standardized technical path for this, decomposing a one-off, complex model transformation into a series of controllable, clear steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decompose the Reasoning Pipeline&lt;/strong&gt;: First, a complex &lt;code&gt;A =&amp;gt; C&lt;/code&gt; transformation is broken down into smaller, more focused steps, such as &lt;code&gt;A =&amp;gt; B =&amp;gt; C&lt;/code&gt;. This makes each stage's responsibility singular and simplifies the model definitions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deltify Each Step&lt;/strong&gt;: This is the most critical innovation. In each transformation step, the upstream model (e.g., &lt;code&gt;A&lt;/code&gt;) does not directly generate the final downstream model (&lt;code&gt;B&lt;/code&gt;). Instead, it generates a "draft" or "base" model, conventionally named with a leading underscore (e.g., &lt;code&gt;_B&lt;/code&gt;). The final &lt;code&gt;B&lt;/code&gt; is then obtained by applying a &lt;code&gt;Delta&lt;/code&gt; package to customize and extend this draft. This process can be precisely described as:&lt;br&gt;
&lt;strong&gt;&lt;code&gt;B = Δ_B ⊕ _B&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
where &lt;code&gt;_B = Generator&amp;lt;A&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Allow Information Passthrough&lt;/strong&gt;: Every stage (&lt;code&gt;Generator&lt;/code&gt;) in the production line follows the "principle of tolerance." It only processes information it can understand. For unrecognized extension attributes or metadata from upstream, it will temporarily store and "pass them through" to the downstream unmodified. This ensures that customized information injected at any stage of the production line is not lost.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Taking the built-in model-driven production line of NopPlatform as an example, it clearly decomposes the process from data to page into four main model stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;XORM&lt;/strong&gt;: Storage layer model&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;XMeta&lt;/strong&gt;: Interface layer model&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;XView&lt;/strong&gt;: Framework-agnostic frontend logical view&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;XPage&lt;/strong&gt;: Final page model bound to a specific frontend framework&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This production line is a perfect embodiment of the technical path described above, where each step can be clearly described by the formula of reversible computation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;XMeta = Δ_meta ⊕ Generator&amp;lt;XORM&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;XView = Δ_view ⊕ Generator&amp;lt;XMeta&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;XPage = Δ_page ⊕ Generator&amp;lt;XView&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In this way, Reversible Computation completely resolves the dilemma of MDA. It allows us to &lt;strong&gt;no longer pursue perfect coverage of all details during modeling&lt;/strong&gt;. We can concentrate on building core model generators (&lt;code&gt;Generator&lt;/code&gt;) that handle 80% of common scenarios, while the remaining 20% of special requirements can be precisely and elegantly injected at any stage of the production line via &lt;code&gt;Delta&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2.2 Horizontal Latitudes: Parallel Projection of DSL Feature Vectors
&lt;/h4&gt;

&lt;p&gt;The horizontal "latitudes" depict a landscape of a &lt;strong&gt;DSL feature vector space&lt;/strong&gt;. In an "Atlas" composed of multiple DSLs, whether it's a UI model, a data model, or a business logic model, they all follow the &lt;strong&gt;exact same&lt;/strong&gt; superpositional evolution rule.&lt;/p&gt;

&lt;p&gt;A cross-domain business requirement (e.g., "add a VIP user level") can be precisely decomposed into a set of "isomorphic" deltas &lt;code&gt;{Δ_ui, Δ_data, Δ_logic, ...}&lt;/code&gt; acting on different DSL models. Due to the universality of the superposition operator &lt;code&gt;⊕&lt;/code&gt; (i.e., &lt;code&gt;x-extends&lt;/code&gt;), these deltas can be applied uniformly and deterministically within their respective domains. This constitutes a &lt;strong&gt;precise feature vector decomposition&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;App = [DSL1, DSL2, ..., Δ_residual]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;Δ_residual&lt;/code&gt; here ensures the completeness of the decomposition&lt;/strong&gt;: it represents the "residual" that cannot be perfectly captured by the existing DSL system or requires special coordination. &lt;strong&gt;Furthermore, when we treat all known DSLs and their rules as "background knowledge" and strip them away, the remaining content represented by &lt;code&gt;Δ_residual&lt;/code&gt; can itself be considered a logically complete whole with its own syntax and semantics, understandable independently of the aforementioned background.&lt;/strong&gt; This makes the entire vector decomposition mathematically precise and lossless.&lt;/p&gt;

&lt;h4&gt;
  
  
  2.3 Time Recursion: The Self-Similarity of Version Evolution
&lt;/h4&gt;

&lt;p&gt;In addition to spatial decomposition along longitudes and latitudes, the recursivity of &lt;code&gt;Y = F(X) ⊕ Δ&lt;/code&gt; is also reflected in the &lt;strong&gt;time dimension&lt;/strong&gt;. Any entity in the system (be it the entire product or a &lt;code&gt;Delta&lt;/code&gt; package) can itself be seen as the result of superimposing an evolution delta onto its earlier version (the base). This forms an infinitely extending evolutionary chain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;Product_V3 = Δ_v3 x-extends Product_V2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  And &lt;code&gt;Product_V2&lt;/code&gt; itself is &lt;code&gt;Δ_v2 x-extends Product_V1&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Furthermore, each element in the formula (&lt;code&gt;X&lt;/code&gt;, &lt;code&gt;F&lt;/code&gt;, &lt;code&gt;Δ&lt;/code&gt;) can itself be decomposed again. For example, a complex feature delta &lt;code&gt;Δ_feature&lt;/code&gt; can be composed of its base version &lt;code&gt;Δ_base&lt;/code&gt; and a patch for it &lt;code&gt;Δ_patch&lt;/code&gt;: &lt;code&gt;Δ_feature = Δ_patch x-extends Δ_base&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This makes &lt;strong&gt;"change" itself a manageable, versionable, and evolvable core asset&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the engineering implementation of the Nop Platform, this temporal recursion is perfectly embodied through the built-in Delta customization mechanism: developers can make delta-based modifications to existing data models, business logic, and even UI interfaces simply by adding a file with the same name in a specific Delta directory, without modifying a single line of the base product's source code. See &lt;a href="https://dev.to/canonical/how-to-implement-customized-development-without-modifying-the-base-product-source-code-2pp5"&gt;How to Achieve Customized Development Without Modifying the Base Product's Source Code&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2.4 Meta-Recursion: The Bootstrapping of the Construction System Itself
&lt;/h4&gt;

&lt;p&gt;This is the most disruptive aspect of Reversible Computation: &lt;strong&gt;the toolchain, rules, and platform used to construct the software themselves follow the exact same invariant for their evolution.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Evolution of DSL Definitions (Metamodels)&lt;/strong&gt;: &lt;code&gt;MyDSL_v2 = Δ_meta x-extends MyDSL_v1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Evolution of Build Tools&lt;/strong&gt;: &lt;code&gt;Compiler_Pro = Δ_feature x-extends Compiler_Base&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Even the Evolution of Merge Rules Themselves&lt;/strong&gt;: &lt;code&gt;MergeRule_New = Δ_rule x-extends MergeRule_Old&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The entire software world—from the final product to intermediate models, to the construction system itself—becomes a vast, self-similar delta structural space connected by the &lt;code&gt;⊕&lt;/code&gt; operator. In this "fractal space," entities at any level and any granularity share the same construction and evolution philosophy. This achieves a true "&lt;strong&gt;one law to rule them all&lt;/strong&gt;," elevating software engineering from a "cottage industry" of repeatedly inventing extension mechanisms for different domains and layers to a unified, self-consistent new era of industrialization. In this new era, the tools we use to build software, and the software we build, follow the same laws of growth.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgitee.com%2Fcanonical-entropy%2Fnop-entropy%2Fraw%2Fmaster%2Fdocs%2Ftheory%2Fddd%2Fdelta-oriented-arch.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgitee.com%2Fcanonical-entropy%2Fnop-entropy%2Fraw%2Fmaster%2Fdocs%2Ftheory%2Fddd%2Fdelta-oriented-arch.svg" alt="delta-oriented-arch" width="1000" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure: A schematic of a delta-oriented architecture based on Reversible Computation, showing the complete stack from the infrastructure layer, through the core engine layer, to the business application layer, with a consistent delta customization mechanism running through all layers. The architecture itself also follows the meta-recursive principle &lt;code&gt;Y = F(X) ⊕ Δ&lt;/code&gt;—components at every layer can be customized and extended via deltas, including the construction rules of the architecture itself.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. The Unified Engineering Cornerstones
&lt;/h4&gt;

&lt;p&gt;To make the grand fractal structure described above achievable in engineering, all DSLs must share an intrinsically unified "physical law." Reversible Computation provides three unified engineering cornerstones for this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unified Intermediate Representation (IR): XNode&lt;/strong&gt;&lt;br&gt;
All DSLs are represented in memory as an enhanced, XML-like tree structure (XNode). It uses a mechanism similar to XML namespaces to achieve "&lt;strong&gt;localized metadata&lt;/strong&gt;," meaning each node and attribute can carry its own metadata (like source file, merge history, etc.) without polluting the business data itself. Based on this structure, we can build a universal, coordinate-based delta merging algorithm whose &lt;strong&gt;runtime cost is proportional only to the size of the change, not the size of the overall model&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unified Metamodel Definition: XDef&lt;/strong&gt;&lt;br&gt;
XDef is a DSL for defining DSLs. Unlike traditional metamodel technologies (like EMF/Ecore), XDef itself is fully integrated into the delta-superposition evolutionary system. We can customize and extend the language's own syntax rules through deltas, just as we customize business models, providing unprecedented flexibility for language evolution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unified Full-Link Traceability: &lt;code&gt;_dump&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Thanks to the rich metadata carried and preserved by XNode during the merge process, any final result in the system (e.g., the color of a button on a page) can be precisely traced back to its origin. We can one-click &lt;code&gt;_dump&lt;/code&gt; its complete "generation history": in which line of which base file it was originally defined, which modifications from which delta files it underwent, and how it ultimately reached its current state. This capability provides irreplaceable convenience for debugging and understanding complex customized systems.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Through these three cornerstones, Reversible Computation ensures that every "map" in the "DSL Atlas" uses the same paper, the same drafting standards, and the same coordinate positioning mechanism, thus making unified, recursive evolutionary programming possible.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For a detailed introduction to the theory of Reversible Computation, you can refer to my other articles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://mp.weixin.qq.com/s/iZWcRa_Af8Io6AAUXd-0Vg" rel="noopener noreferrer"&gt;Making Evolution Programmable: XLang and the Structured Paradigm of Reversible Computation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://mp.weixin.qq.com/s/gEvFblzpQghOfr9qzVRydA" rel="noopener noreferrer"&gt;XDef: An Evolution-Oriented Metamodel and Its Construction Philosophy&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  To Be Continued
&lt;/h2&gt;

&lt;p&gt;The above is the first half of this article, where we explored DDD from multiple perspectives, including its philosophical underpinnings, mathematical principles, and theoretical framework. We covered the essence of DDD as "discovering and expressing the inherent laws of the domain," analyzed methods for managing complexity through "vertical and horizontal decomposition," and introduced the cognitive shift from "absolute space" to "relative space." Leveraging (Generalized) Reversible Computation theory and the mathematical perspective of "language as a coordinate system," we have provided a possible theoretical foundation for the engineering of DDD.&lt;/p&gt;

&lt;p&gt;The value of theory must ultimately be tested by practice. in the second half of this article, we will turn to the engineering practice level, focusing on how the Nop Platform, based on the theories above, specifically implements DDD's various patterns through the engineering paradigm of Reversible Computation. We will also explore a key question: &lt;strong&gt;How can a system design that aligns with DDD principles be made to "emerge" naturally through the support of an underlying technology platform, thereby lowering the barrier to practice, rather than relying entirely on the personal experience and discipline of the designer?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Preview of the Second Half:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Chapter 9: The Engineering Closure of DDD—Reversible Computation in Practice on the Nop Platform&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;9.1 Institutionalizing Strategic Design: Boundary-First, Language as a Coordinate System&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  9.1.1 Physicalization of Bounded Contexts: From &lt;code&gt;Modular Directories&lt;/code&gt; to a &lt;code&gt;DSL Atlas&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.1.2 Engineering Context Maps: &lt;code&gt;Events&lt;/code&gt;, &lt;code&gt;APIs&lt;/code&gt;, and &lt;code&gt;Transformation DSLs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.1.3 Guardrails of Hexagonal Architecture: Declarative Contracts Derived from &lt;code&gt;BizModel&lt;/code&gt; and &lt;code&gt;XMeta&lt;/code&gt; Models&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;9.2 Platformizing Tactical Design: Built-in Patterns and Emergent Robustness&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  9.2.1 Aggregates, Entities, and Value Objects: Unified in &lt;code&gt;NopORM&lt;/code&gt; and &lt;code&gt;XMeta&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.2.2 Transparent Services and Repositories: NopTaskFlow Orchestration and a Generic &lt;code&gt;EntityDao&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.2.3 The Natural Emergence of Event-Driven Architecture: A Platform-level &lt;code&gt;Outbox&lt;/code&gt; and &lt;code&gt;Synchronous Events&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.2.4 Queries and Read Models: Automation with &lt;code&gt;GraphQL&lt;/code&gt; and &lt;code&gt;DataLoader&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.2.5 Eradicating Stubborn Problems: Solving &lt;code&gt;N+1&lt;/code&gt; and &lt;code&gt;Database Deadlocks&lt;/code&gt; at the Root&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;9.3 Programmable Evolution: The "Trinity" Paradigm of Reversible Computation&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  9.3.1 The Unified Evolution Formula: &lt;code&gt;EffectiveModel = Δ(Delta) ⊕ Generator&amp;lt;BaseModel&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.3.2 The Deterministic Construction Phase: &lt;code&gt;S-N-V&lt;/code&gt; (Structure-Merge, Normalize, Validate) Loading&lt;/li&gt;
&lt;li&gt;  9.3.3 The Fractal Software Production Line: &lt;code&gt;XORM&lt;/code&gt; → &lt;code&gt;XMeta&lt;/code&gt; → &lt;code&gt;XView&lt;/code&gt; → &lt;code&gt;XPage&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.3.4 Full-Stack Delta Customization Example: The Path of Evolution &lt;strong&gt;Without Changing a Single Line of Base Code&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;9.4 Contract-First: From "Living Documents" to "Living Systems"&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  9.4.1 Contract is Model, Model is Contract: The Automated Production Pipeline Starting from &lt;code&gt;Excel&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  9.4.2 Reversible Transformation of Multiple Representations: Lossless Conversion and Delta Merging of Excel, XML, and JSON&lt;/li&gt;
&lt;li&gt;  9.4.3 Unified Governance and Quality Assurance: Full-Link &lt;code&gt;Traceability&lt;/code&gt; and &lt;code&gt;Snapshot Testing&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Chapter 10: The Final Paradigm Revolution—From "Applying DDD" to "Emergent DDD"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;10.1 From Application-Layer Abstraction to First-Principle Support&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  10.1.1 Internalization of Patterns: A Comparison with the Evolution of the &lt;code&gt;Singleton&lt;/code&gt; Pattern and &lt;code&gt;DI&lt;/code&gt; Frameworks&lt;/li&gt;
&lt;li&gt;  10.1.2 The Protocol-Neutral BizModel: Eliminating the Redundant &lt;code&gt;Controller/Service/DTO&lt;/code&gt; Layers&lt;/li&gt;
&lt;li&gt;  10.1.3 Separation of the CRUD Subspace: From the &lt;code&gt;Repository&lt;/code&gt; Pattern to &lt;code&gt;IEntityDao&lt;/code&gt; and "Complementary Space" Programming&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;10.2 From "Deployment Decision" to "Compositional Freedom"&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  10.2.1 Module as Bounded Context: The Physical Carrier with an Independent &lt;code&gt;DSL Atlas&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  10.2.2 Composition as Architecture: The Free Switching Between &lt;code&gt;Modular Monolith&lt;/code&gt; and &lt;code&gt;Microservices&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  10.2.3 Location-Transparent Communication: Automatic Adaptation Between &lt;code&gt;Local Calls&lt;/code&gt; and &lt;code&gt;Remote RPC&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;10.3 From "Data-Centric" to "Information Flow Inversion"&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  10.3.1 Refocusing the Aggregate Root: From "Write Boundary" to "Information Access Center"&lt;/li&gt;
&lt;li&gt;  10.3.2 Decoupling Business Logic: From "Pushing Data (DTO)" to "Pulling Information (EL)"&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Chapter 11: Case Study—The Reversible Computation Transformation of a Large Bank's Core System&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  11.1 Lightweight Implementation of Core Principles: &lt;code&gt;Loader as Generator&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  11.2 Dealing with Major Model Changes: The Power of Delta Customization&lt;/li&gt;
&lt;li&gt;  11.3 The Elastic Extension of Process Orchestration&lt;/li&gt;
&lt;li&gt;  11.4 Purifying the Domain Model: Modifying MyBatis to Achieve "Aggregate Root Programming"&lt;/li&gt;
&lt;li&gt;  11.5 Unification and Automation of the Service Layer: Enhancing GraphQL-Java&lt;/li&gt;
&lt;li&gt;  11.6 Delta-based Configuration for the Frontend: Modular Governance of AMIS JSON&lt;/li&gt;
&lt;li&gt;  11.7 Lessons from the Case: Substance Over Form&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ddd</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Third Round of Q&amp;A on the XLang Language</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Sun, 01 Feb 2026 11:47:43 +0000</pubDate>
      <link>https://forem.com/canonical/third-round-of-qa-on-the-xlang-language-4bk4</link>
      <guid>https://forem.com/canonical/third-round-of-qa-on-the-xlang-language-4bk4</guid>
      <description>&lt;h2&gt;
  
  
  1. Is XLang a framework or a programming language?
&lt;/h2&gt;

&lt;p&gt;XLang is not a traditional programming language, but if you ask DeepSeek, DeepSeek would answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;XLang combines the high abstraction of fourth-generation languages with the theoretical innovations of fifth-generation languages. Its core positioning is a “meta-language supporting Reversible Computation,” which boosts development efficiency through low-code and domain-specific syntax while redefining the underlying rules of program construction via structural space theory and Delta operations. Therefore, XLang can be regarded as an evolutionary form of a fourth-generation language—call it a “Fourth-Generation+ Language”—achieving a unique balance between low-code and theoretical innovation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mainstream programming languages today are so-called third-generation programming languages (3GL), which typically use a main function as the program’s entry point. Fundamentally, the language design is about writing that executable main function, and the compiler translates the execution logic written in the programming language into instructions executable by a hardware model. Fourth-generation programming languages (4GL), however, began to emphasize descriptiveness, simplifying development through highly abstract declarative syntax and graphical programming tools. In other words, the core of 4GL is “non-procedural,” emphasizing higher-level abstraction rather than adaptation to lower-level hardware models.&lt;/p&gt;

&lt;p&gt;With the rise of LLVM, hardware-level optimization is essentially a separate concern, and different programming languages can share a common compilation backend. This does not constitute an essential requirement of a programming language. I expect new languages like &lt;code&gt;Moonbit&lt;/code&gt; to offer a very compact, lightweight toolchain. As long as XScript’s AST is translated to &lt;code&gt;Moonbit&lt;/code&gt;’s AST, the rest is handled automatically.&lt;br&gt;
XLang includes a sub-language XScript, whose syntax deliberately adopts a subset of JavaScript plus minor extensions, and the type system mimics a simplified Java-like type system. This ensures lossless translation at the AST level to all mainstream programming languages.&lt;/p&gt;

&lt;p&gt;Although the Nop platform is a complete low-code platform built on the XLang language, this does not mean that XLang itself is a framework. While XLang currently runs on the JVM and relies on certain helper libraries and implementation classes provided by the underlying Java language, it does not depend on Java. The entire content of XLang can be ported to other programming languages such as &lt;code&gt;Lisp&lt;/code&gt; or &lt;code&gt;Rust&lt;/code&gt;. When writing business code, you can use only the XLang language without touching the underlying Java language.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. The fundamental reason a Turing machine achieves Turing completeness is that a Turing machine can be viewed as a virtual machine that can simulate all other automatic computing machines.
&lt;/h2&gt;

&lt;p&gt;For this statement, those with formal training may object: Turing completeness is defined via the Turing machine, so “a Turing machine is Turing-complete” is a conclusion by definition. My view is: if you get entangled in the mathematical definition and say Turing completeness is defined via the Turing machine, that’s fine; but this is merely due to a historical contingency.&lt;/p&gt;

&lt;p&gt;Conceptually, Turing completeness and NP-completeness are similar classifications in computation. The computational complexities of every NP-complete problem are comparable; solving any one of them allows you to solve all NP-complete problems. Yet we do not define NP-completeness as “knapsack-completeness.”&lt;/p&gt;

&lt;p&gt;Similarly, Turing completeness is an abstract computational capability. All computing machines are equivalent at this capability boundary; no particular machine has a more special capability. By historical accident, this capability was named Turing completeness. Turing completeness can be defined as a computing system’s ability to execute any computable function; it could just as well have been named Lambda Calculus completeness.&lt;/p&gt;

&lt;p&gt;In physics, all concepts are independent of any particular problem or choice of reference frame. If one insists that Turing completeness is defined via the Turing machine, that is merely a concrete manifestation of using a specific idealized model to describe an abstract computational capability. What we care about is not the concrete form, but the universal capability itself.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Is the development goal of XLang to replace general-purpose languages like Java?
&lt;/h2&gt;

&lt;p&gt;XLang’s development goal is not to replace mainstream languages such as &lt;code&gt;C++&lt;/code&gt; or &lt;code&gt;Java&lt;/code&gt;; in fact, they should be complementary.&lt;br&gt;
&lt;/p&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;c:script&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"groovy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Groovy syntax can be used here
&lt;span class="nt"&gt;&amp;lt;/c:script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;XLang uses XML syntax. When execution logic needs to be expressed, it employs the Xpl template language, a sub-language that is Turing-complete. Within it, you can embed XScript via the &lt;code&gt;&amp;lt;c:script&amp;gt;&lt;/code&gt; tag. If &lt;code&gt;lang="groovy"&lt;/code&gt; is specified, you can implement the script in Groovy. Similarly, you can integrate virtually any other language.&lt;/p&gt;

&lt;p&gt;Existing programming languages already address a large problem space effectively; there is often no need to invent new syntax for expressing procedural computation logic—reusing existing language syntax or even language runtimes will suffice.&lt;br&gt;
XLang focuses on areas not effectively handled by existing languages. By introducing the concepts of Delta and Reversible Computation, XLang can solve many problems that require the computing pattern &lt;code&gt;F(X)+Delta&lt;/code&gt; to be handled effectively. In other words, the problem space XLang addresses is largely non-overlapping with that of existing languages. However, this does not mean XLang is a DSL; its syntax and semantics are general-purpose and not tied to any specific business domain. Ultimately, in usage, XLang can cooperate with any third-generation programming language: the XScript part can be replaced with any other third-generation programming language.&lt;/p&gt;

&lt;p&gt;If we regard TypeScript as an extension of JavaScript, &lt;code&gt;TypeScript = JavaScript + JSX + TypeSystem&lt;/code&gt;, then XLang can also be viewed as an extension of JavaScript, &lt;code&gt;XLang = XScript + Xpl + XDef + MetaProgramming + DeltaProgramming&lt;/code&gt;. Xpl is an XML-form template language, similar in purpose to JSX.&lt;br&gt;
The distinctive parts here are DeltaProgramming and MetaProgramming. XLang does not strongly depend on JavaScript syntax; the XScript sub-language can be replaced by any other third-generation programming language.&lt;/p&gt;

&lt;p&gt;Some misunderstand XLang’s capabilities because it adopts an XML syntactic form and thus fail to associate it with a conventional programming language. But if you think carefully, TypeScript embeds XML-like JSX syntax inside JavaScript, and JavaScript code blocks can be embedded inside JSX. It is a bona fide programming language. Conversely, embedding JavaScript syntax inside XML format is equivalent to what TypeScript does, isn’t it?&lt;/p&gt;

&lt;p&gt;XLang’s outermost entry point is not a simple main function; rather, it is a variety of DSLs with diverse structures and semantics, and even visual models.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Can XLang build its own ecosystem?
&lt;/h2&gt;

&lt;p&gt;Certainly. But the content in XLang’s ecosystem is not the usual generic functionality that every new language seems destined to re-implement, such as JSON parsers or HTTP clients. XLang is typically used with a host language (e.g., Java), allowing direct reuse of functionality implemented in the host, at most with a wrapper over standard interfaces. This is similar to how TypeScript directly reuses the underlying JavaScript host ecosystem.&lt;br&gt;
Future directions include cross-language code reuse across multiple syntactic forms, e.g., all based on WASM bytecode, or via GraalVM’s polyglot interop mechanisms.&lt;/p&gt;

&lt;p&gt;What should be shared within XLang’s ecosystem are primarily XDef meta-model definitions for various DSLs, as well as code generators and meta-programming structural transformations written in the Xpl template language.&lt;/p&gt;

&lt;p&gt;To reiterate, XLang’s primary use is to rapidly develop and extend domain-specific languages, realizing the so-called Language Oriented Programming paradigm. Business development is essentially independent of any specific programming language—akin to physical facts being independent of coordinate systems. A general-purpose language is like a general Euclidean coordinate system; locally, we can adopt more efficient specialized coordinate systems, i.e., DSLs. As technology advances, descriptive programming and imperative programming can be better integrated, and the descriptive subspace occupied by DSLs can grow larger. Multiple DSLs can be seamlessly bonded via &lt;code&gt;G&amp;lt;DSL1&amp;gt; + G&amp;lt;DSL2&amp;gt; +Delta&lt;/code&gt;; the concept of Delta must be added to break the limitation that a DSL applies only to a single domain.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Are there intuitive examples showing how XLang is used?
&lt;/h2&gt;

&lt;p&gt;You can refer to the following articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/canonical/kustomize-from-the-perspective-of-reversible-computation-45ec"&gt;Looking at Kustomize through Reversible Computation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s/rus4sPKvO-C78cOjSd0ivA" rel="noopener noreferrer"&gt;Design Comparison: NopTaskFlow Logic Orchestration Engine vs. SolonFlow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/canonical/xdsl-general-purpose-domain-specific-language-design-35g6"&gt;XDSL: A General-Purpose Domain-Specific Language Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/canonical/a-theoretical-analysis-of-reversible-computation-for-programmers-2feb"&gt;A Theoretical Analysis of Reversible Computation for Programmers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/canonical/a-supplementary-analysis-of-reversible-computation-theory-for-programmers-2bd3"&gt;Addendum: A Theoretical Analysis of Reversible Computation for Programmers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Detailed syntax can be found in the Nop platform documentation &lt;a href="https://nop-platform.github.io/projects/nop-entropy/docs-en/dev-guide/xlang/" rel="noopener noreferrer"&gt;XLang Language&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In most cases we do not develop business applications directly with XLang. Instead, we first use XLang to define a DSL, and then develop the actual business using that DSL. XLang defines DSL structure via the XDef meta-model language; the Nop platform’s &lt;code&gt;nop-xdefs&lt;/code&gt; module collects all meta-model files of already-defined DSLs.&lt;br&gt;
When developing your own DSL, you generally do not have to start from scratch. You can compose these existing XDef meta-model definitions directly—for example, reuse the variable definition model &lt;code&gt;var-define.xdef&lt;/code&gt; via &lt;code&gt;xdef:ref&lt;/code&gt; in a rules model.&lt;br&gt;
&lt;/p&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;rule&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"!var-name"&lt;/span&gt; &lt;span class="na"&gt;xdef:ref=&lt;/span&gt;&lt;span class="s"&gt;"schema/var-define.xdef"&lt;/span&gt; &lt;span class="na"&gt;xdef:name=&lt;/span&gt;&lt;span class="s"&gt;"RuleInputDefineModel"&lt;/span&gt;
         &lt;span class="na"&gt;computed=&lt;/span&gt;&lt;span class="s"&gt;"!boolean=false"&lt;/span&gt; &lt;span class="na"&gt;mandatory=&lt;/span&gt;&lt;span class="s"&gt;"!boolean=false"&lt;/span&gt; &lt;span class="na"&gt;xdef:unique-attr=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In fact, XLang’s concrete merge algorithm is very simple—essentially akin to the virtual DOM diff algorithms in React and Vue, only simpler. XLang stipulates that elements in a list have unique identifiers such as name or id, thereby ensuring stable XPath that can serve as domain coordinates. During diff and merge computation, items are merged directly by coordinates.&lt;/p&gt;

&lt;p&gt;Syntactically, XLang is essentially ordinary XML augmented with a small set of special annotations such as &lt;code&gt;x:schema&lt;/code&gt;, &lt;code&gt;x:extends&lt;/code&gt;, and &lt;code&gt;x:override&lt;/code&gt;. The underlying language engine understands these annotations and performs Delta merge after parsing. &lt;code&gt;x:schema&lt;/code&gt; imports the XDef meta-model; via XDef we can define the types of nodes and attributes in XML. If an attribute’s type is specified as xpl, that attribute is parsed using the Xpl template language.&lt;br&gt;
&lt;/p&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;task&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdef.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;steps&lt;/span&gt; &lt;span class="na"&gt;xdef:body-type=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt; &lt;span class="na"&gt;xdef:key-attr=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;xpl&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;xdef:value=&lt;/span&gt;&lt;span class="s"&gt;"xpl"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/xpl&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/task&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The meta-model above defines the structure of &lt;code&gt;task.xml&lt;/code&gt;. It states that steps are a set of step definitions, each step has type xpl, and it has a source attribute, which is parsed using the Xpl template language.&lt;/p&gt;

&lt;p&gt;An example of a concrete task.xml:&lt;br&gt;
&lt;/p&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;task&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/task.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;xpl&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
        logInfo("hello world");
      &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/xpl&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/task&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the structure of the &lt;code&gt;task.xdef&lt;/code&gt; meta-model and the &lt;code&gt;task.xml&lt;/code&gt; model file it describes are essentially identical. &lt;code&gt;task.xdef&lt;/code&gt; is like an XML template with annotations indicating the types of the template’s attributes. The concrete &lt;code&gt;task.xml&lt;/code&gt; is the result of filling the template’s attributes and child nodes with specific values.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;x:schema="/nop/schema/xdef.xdef"&lt;/code&gt; on the root of the meta-model indicates that &lt;code&gt;task.xdef&lt;/code&gt; is a meta-model definition file whose structure is constrained by &lt;code&gt;xdef.xdef&lt;/code&gt;. Meanwhile, &lt;code&gt;x:schema="/nop/schema/task.xdef&lt;/code&gt; on the root of &lt;code&gt;task.xml&lt;/code&gt; indicates that &lt;code&gt;task.xml&lt;/code&gt; is a model file whose structure is constrained by &lt;code&gt;task.xdef&lt;/code&gt;.&lt;br&gt;
If you look at the definition of &lt;code&gt;xdef.xdef&lt;/code&gt;, you will find its &lt;code&gt;x:schema&lt;/code&gt; also points to &lt;code&gt;xdef.xdef&lt;/code&gt;. In other words, model structure is defined by the XDef meta-model, and the XDef meta-model itself is defined using the XDef meta-model.&lt;/p&gt;

&lt;p&gt;Here is one community member’s understanding:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I finally fully grasped your principle of Delta-based merging today. XLang is a set of standard attribute definitions used to add, delete, or modify node definitions. Delta-based merging is the process of merging a main file with a Delta, and the merge rules are defined by the XLang language specification. After merging, you get a new DSL description (which can be XML, JSON, or any tree structure). You then hand this new DSL to an execution engine; how it parses and handles the DSL is the execution engine’s responsibility.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;XLang defines DSLs and automatically implements DSL decomposition, merging, and Delta customization. In principle, once you obtain the merged DSL, it is no longer tied to XLang; the execution engine can use any other technology to parse XML/YAML for subsequent processing. If you use the Nop platform deeply, the execution engine can leverage the XDef meta-model to automatically parse the DSL, and executable code segments can directly reuse the Xpl template language.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. How does XLang define Delta at the language level? (not a formula)
&lt;/h2&gt;

&lt;p&gt;XLang defines XDSL via the XDef meta-model; every syntactic element in an XDSL has a unique, stable domain coordinate. Business is expressed in XDSL, effectively projecting business into the coordinate system defined by XDSL. A Delta can be defined at any point in this coordinate system. Furthermore, Deltas that arise at many coordinates can be factored out and recognized and managed conceptually as one large Delta—an integrated change pattern that becomes an independent cognitive entity.&lt;/p&gt;

&lt;p&gt;XLang can be viewed as a meta-language. It does not directly express Deltas; it first defines a DSL, and then defines language-level Deltas within that DSL. At a more abstract level, all sub-languages in XLang are defined via the XDef meta-model language, and XDef itself is defined via XDef as well. Consequently, all its sub-languages automatically inherit the concept of language-level Deltas.&lt;/p&gt;

&lt;p&gt;Many find this difficult to grasp because they do not realize the meta-level nature here. It is not directly about “A solves problem X,” but rather solving it at a higher meta-level through a logical ladder, then projecting it down to the next level where it manifests concretely.&lt;/p&gt;

</description>
      <category>nop</category>
      <category>programming</category>
      <category>architecture</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Further explanations on the article "Why XLang is an innovative programming language"</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Sun, 18 Jan 2026 12:30:33 +0000</pubDate>
      <link>https://forem.com/canonical/further-explanations-on-the-article-why-xlang-is-an-innovative-programming-language-3da1</link>
      <guid>https://forem.com/canonical/further-explanations-on-the-article-why-xlang-is-an-innovative-programming-language-3da1</guid>
      <description>&lt;p&gt;The XLang language is a key foundational technology underpinning the next-generation open-source low-code Nop platform. Traditional programming languages that support generic metaprogramming correspond structurally to the construction formula &lt;code&gt;Map = Map extends Map&amp;lt;Map&amp;gt;&lt;/code&gt;, whereas XLang effectively extends this to &lt;code&gt;Tree = Tree x-extends Tree&amp;lt;Tree&amp;gt;&lt;/code&gt;. That is, Map is generalized to Tree, and the extends operation between Map structures is generalized to the &lt;code&gt;x-extends&lt;/code&gt; operation on Tree structures—particularly, &lt;code&gt;x-extends&lt;/code&gt; adds reverse-deletion semantics.&lt;/p&gt;

&lt;p&gt;XLang is innovative because it creates a new program-structure space in which the computing paradigm proposed by Reversible Computation, &lt;code&gt;Y = F(X) + Delta&lt;/code&gt;, can be implemented with ease. This conceptual innovation departs from the inertia of traditional computer-science thinking, so some classically trained practitioners may experience additional cognitive friction when trying to understand it.&lt;/p&gt;

&lt;p&gt;Previously, I published two articles explaining the design principles of XLang on my WeChat official account: &lt;a href="https://dev.to/canonical/why-is-xlang-an-innovative-programming-language-5fja"&gt;Why is XLang an innovative programming language?&lt;/a&gt; and &lt;a href="https://dev.to/canonical/qa-on-why-xlang-is-an-innovative-programming-language-3998"&gt;Q&amp;amp;A on "Why XLang is an innovative programming language"&lt;/a&gt;. A friend commented on Zhihu:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Having patiently read through your two masterpieces, I must say claiming I completely understood them would be dishonest—but understanding just a little is more confusing than not understanding at all: What is XLang actually for? Is it a super registry-style data structure? How do you realize the grand goals you mention (or that I suppose)? Are functions first-class citizens in your language?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Such confusion is common. Fundamentally, it stems from the fact that the theoretical basis of XLang comes from mathematics and physics; therefore, students trained only in computer science tend to map XLang’s concepts to the familiar notions of CS, often causing psychological discomfort. One cannot easily understand what one has not yet understood, and what one has already accepted is often subconsciously regarded as self-evident. Cognitions that deviate from existing understanding tend to be ignored or resisted. In this article, I will provide more targeted explanations. If you have questions, feel free to discuss in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  I. What is XLang for?
&lt;/h2&gt;

&lt;p&gt;XLang’s primary purpose is rapid development and extension of domain-specific languages (DSLs), enabling the so-called Language Oriented Programming paradigm. This paradigm was not invented by me; it has existed in computer science for many years. See, for example, the 1994 paper &lt;a href="https://www.semanticscholar.org/paper/Language-Oriented-Programming-Ward/825a90a7eaebd7082d883b198e1a218295e0ed3b" rel="noopener noreferrer"&gt;[PDF] Language-Oriented Programming | Semantic Scholar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We typically implement business logic using general-purpose programming languages, while Language Oriented Programming emphasizes DSLs (Domain Specific Languages). When developing business features, one first develops a DSL dedicated to that business domain, then uses this DSL to express the logic. JetBrains, the company behind the IntelliJ IDEA IDE, has a related product: &lt;a href="https://www.jetbrains.com/mps/" rel="noopener noreferrer"&gt;MPS (Meta Programming System)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using XLang to develop a new DSL is extremely simple—so simple that you only need to add an XDef metamodel definition file, and you immediately get a new DSL. The Nop platform provides a general IntelliJ IDEA plugin that automatically reads XDef metamodels to implement syntax hints, link navigation, breakpoints, etc., for custom DSLs, with type inference to follow. The Nop platform’s infrastructure automatically generates model class definitions from XDef metamodel files, implements parsers and validators, and automatically generates visual editors.&lt;/p&gt;

&lt;p&gt;DSLs defined with XLang do not need special consideration for extensibility (nor special syntax for it), and they also do not need to worry about how multiple DSLs can be seamlessly integrated for combined use. The Nop platform’s underlying infrastructure implements all of this uniformly. Within DSL files, built-in syntax like &lt;code&gt;x:extends&lt;/code&gt; and &lt;code&gt;x:gen-extends&lt;/code&gt; automatically enable model decomposition/merging and compile-time metaprogramming.&lt;/p&gt;

&lt;p&gt;Extending an existing DSL’s syntax is also very simple: just add an XDef metamodel file that inherits from the existing XDef metamodel file.&lt;/p&gt;

&lt;p&gt;All software products developed using XLang-defined DSLs automatically support the so-called Delta customization mechanism. That is, without modifying any existing source code, you can add Delta files under the Delta directory to modify or delete existing logic, and of course also add new logic.&lt;/p&gt;

&lt;p&gt;These capabilities provided by XLang are innovative in ways no previous programming language has had. They are crucial for the Nop platform to solve coarse-grained, system-level software reuse. In other words, the most challenging customization problems in the ToB market can be essentially improved under the Nop platform’s technical architecture—especially, the architecture of the base product will not be affected by custom development.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A core banking application developed with XLang can, without any modification to the base product’s source code, be customized across the entire stack—from data model to business logic to front-end display—simply by adding Delta files under the Delta directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A low-code platform developed with XLang can, without modifying its own code, customize all visual designers’ UI and editing features via the same Delta customization approach, and even customize the model objects being edited.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  II. Is XLang a super registry-style data structure?
&lt;/h2&gt;

&lt;p&gt;Understanding XLang as a registry is like understanding Lisp as a linked list: related, but not the point.&lt;/p&gt;

&lt;p&gt;When using existing programming languages to build abstractions, we typically define discrete extension points, which can be managed by a registry-like structure. This idea is deeply entrenched. For example, Huawei’s TinyEngine low-code engine emphasized in its 2.0 design that “the registry mechanism makes it easy to replace components, APIs, etc., enabling flexible plug-and-play and customization.” See &lt;a href="https://mp.weixin.qq.com/s/oX73EX3ZFpk3i6MupiYKZA" rel="noopener noreferrer"&gt;Introduction to TinyEngine low-code engine 2.0 new features&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For an existing implementation like ABC, if we want to turn it into an extensible abstraction, the most common approach is variable extraction, e.g., &lt;code&gt;A{X:B}C&lt;/code&gt;. Replace B with a variable X, then use a variable-mapping Map (essentially a registry) to assign a concrete value to X. To reduce configuration, we can also specify a default value B and proclaim this as a design principle—convention over configuration. This approach is like digging holes where changes might be needed, and then filling the holes differently depending on requirements.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This can also be explained as adding a layer of indirection: any problem that can’t be solved can be addressed by adding one extra pointer hop; if that still doesn’t solve it, add another layer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If only a few places might need extension, digging a few holes is easy. But what if we don’t know in advance where changes are needed, and many places might change? If we dig holes everywhere, the original architecture becomes hollow—what meaning does it have left? Digging holes adds cost, affects runtime performance, and increases cognitive complexity. Some pre-dug holes may never be used, and some may even obstruct truly needed extensions. For example, after turning &lt;code&gt;ABC&lt;/code&gt; into &lt;code&gt;{X}{Y}C&lt;/code&gt;, the actual requirement might be neither replacing X nor Y, but part of Y and part of C. What then?&lt;/p&gt;

&lt;p&gt;Each extension point can be viewed as a degree of freedom of the extension space. As extension points increase, the degrees of freedom of the extension space increase. When the degrees of freedom of the extension space grow without bound, can we establish an appropriate abstraction method? Traditional software construction theory answers no. In current theory, we rely on prior prediction to preset extension points, and cannot add or modify extension points post hoc without changing the original system’s code—nor can we remove extension points without code changes.&lt;/p&gt;

&lt;p&gt;XLang’s solution to the problem of unlimited extension freedoms is to borrow a concept from physics: coordinate systems. Essentially, it shifts from a rigid-body mechanics worldview to a field-theoretic worldview. In high school we learned Newtonian physics, a branch of classical mechanics rooted in rigid-body mechanics, which is fully mechanistic: a rigid body’s motion is described by a small set of parameters—center-of-mass coordinates, size, shape, orientation. Internal structure is unobservable and irrelevant. Rigid bodies interact via direct contact, and shapes must match precisely to form a seamless whole (compare the software component black-box model). Even in classical mechanics, slightly more advanced perspectives switch to Lagrangian or Hamiltonian formulations, whose spirit is the field-theoretic worldview. A field is a ubiquitous coordinate system with a physical quantity defined at every point. The field has infinite degrees of freedom, yet through the coordinate system it is definable, measurable, and analyzable; we can precisely measure local changes at each coordinate point. In the same spirit, Reversible Computation’s basic setup is first to establish a sufficiently fine and general domain-description coordinate system in which we can point-and-act and act-and-point (coordinate uniqueness).&lt;/p&gt;

&lt;p&gt;In Reversible Computation theory, a coordinate system assigns a unique coordinate to every value involved in the system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value = get(path);
set(path, value);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Formally, implementing a coordinate system looks like a registry. But a coordinate system is an abstract concept with many forms. For example, a file system can be viewed as a coordinate system, where coordinates are file paths; each path corresponds to a file, and each file has a unique path (ignoring links, or considering canonical paths only). Generally, we don’t regard a file system as a registry, let alone a DSL as a registry.&lt;/p&gt;

&lt;p&gt;How is the coordinate system implemented in XLang? The answer is simple: each DSL automatically defines a coordinate system. This may sound subtle, but if you’ve studied the moving frame method in differential geometry, it becomes intuitive. Typically we define motion within a selected coordinate system, but the moving frame method uses the motion’s intrinsic properties to automatically define an intrinsic coordinate system attached to the trajectory—meaning motion happens within a coordinate system and simultaneously induces a coordinate system. Similarly, business logic is expressed using a DSL, and the DSL’s abstract syntax tree (AST) and its node attributes automatically form a coordinate system. Concretely, every attribute on the AST has a unique XPath, e.g., &lt;code&gt;/task/steps[@name=a]/@name&lt;/code&gt; indicates the name attribute of step a. Because any logic must be expressed by a programming language, there can be no case where the coordinate system doesn’t cover it; all business necessarily occurs in the coordinate space defined by this coordinate system.&lt;/p&gt;

&lt;p&gt;Any programming language can be parsed into an AST whose nodes and attributes have unique XPaths. Therefore, any programming language defines an intrinsic coordinate system. The problem is that, at the business level, coordinates in general-purpose languages are unstable. For example, if you add a field at the data-model level, expressing it in a general-purpose language may require editing many places by hand. But if you use a model-driven architecture, a data-model DSL may require modifying only a single place, from which the other changes are inferred automatically. We can say that adding a field induces only a local perturbation in the coordinate system defined by the data model. If you’ve studied Dirac’s delta function, we can formally express it as $ Field*\delta(x-x_0)$.&lt;/p&gt;

&lt;p&gt;DSLs defined by XLang differ from general Tree structures by introducing an additional convention: all list elements must have an attribute that can serve as a unique identifier, e.g., name, id, etc. If the business domain lacks such an attribute, XLang provides a built-in &lt;code&gt;x:id&lt;/code&gt;. With this rule, each Tree node in the DSL gains a stable coordinate that will not drift due to inserting or deleting nodes. This approach is intuitive and natural. In frontend frameworks like React and Vue, the virtual DOM diff algorithm requires list structures to have a key attribute to ensure diff stability.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DeepSeek’s comment: This constraint aligns with the naming philosophy in computer science—just like DNS decouples IP addresses via domain names, and UUID decouples storage location via unique identifiers, XLang enforces unique identity to separate a tree node’s logical identity from its physical position, enabling a paradigm shift from “fragile positional coupling” to “stable identity abstraction.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  III. How does XLang achieve its ambitious goals?
&lt;/h2&gt;

&lt;p&gt;The overall technical roadmap of Reversible Computation is embodied in the following core formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App = Delta x-extends Generator&amp;lt;DSL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;XLang’s unique approach is essentially repeated applications of the formula above—continuously decomposing the problem space horizontally and vertically, projecting it into many DSL subspaces, and then using Delta to glue these subspaces back together. If you’ve studied differential manifolds, the intrinsic logic here becomes easy to grasp. For details, see &lt;a href="https://mp.weixin.qq.com/s/6TOVbqHFmiFIqoXxQrRkYg" rel="noopener noreferrer"&gt;How does Nop overcome the limitation that DSLs apply only to specific domains?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, XLang provides a standardized technical route for reuse based on dynamic similarity.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Traditional reuse leverages stable sameness and struggles to utilize dynamic similarity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73g49ngu1deai2ja419j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73g49ngu1deai2ja419j.png" alt="delta pipeline" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;With embedded metaprogramming and code generation, you can establish an inference pipeline between any structures A and C.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decompose the inference pipeline into multiple steps: A =&amp;gt; B =&amp;gt; C&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Further delta-ize the inference pipeline: A =&amp;gt; _B =&amp;gt; B =&amp;gt; _C =&amp;gt; C&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each stage allows buffering and pass-through of extension information not needed in that step.&lt;br&gt;
Specifically, Nop’s built-in model-driven production line can be decomposed into four primary models:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;XORM: storage-layer domain model&lt;/li&gt;
&lt;li&gt;XMeta: GraphQL interface-layer domain model; can directly generate GraphQL type definitions&lt;/li&gt;
&lt;li&gt;XView: business-layer understanding of frontend logic, using a small set of UI elements (forms, tables, buttons), independent of frontend frameworks&lt;/li&gt;
&lt;li&gt;XPage: page model targeting a specific frontend framework&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When deriving models, we only derive a candidate result (generally stored in model files prefixed with underscores), then choose to extend the candidate model, adding manual fixes and Delta inference relying on additional information (stored in models without underscore prefixes). Every step in the inference chain is optional: you can start from any step directly or discard all information inferred in prior steps entirely. For example, you can create an xview model manually without requiring it to have specific xmeta support; you can even create a page.yaml file directly and write JSON code per the AMIS component spec—the AMIS framework’s capabilities are not constrained by the inference pipeline. Through a deep-decomposition pattern akin to deep learning, we can fully unleash the power of model-driven development, while introducing extra information via Delta when necessary, so the final product’s capabilities aren’t bounded by the expressive power of the models. This frees us from chasing coverage of every detailed requirement during modeling; we focus on the most core, general needs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;XORM = Generator&amp;lt;ExcelModel&amp;gt; + Delta&lt;/code&gt;&lt;br&gt;
&lt;code&gt;XMeta = Generator&amp;lt;XORM&amp;gt; + Delta&lt;/code&gt;&lt;br&gt;
&lt;code&gt;XView = Generator&amp;lt;XMeta&amp;gt; + Delta&lt;/code&gt;&lt;br&gt;
&lt;code&gt;XPage = Generator&amp;lt;XView&amp;gt; + Delta&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mapped to the concepts of traditional computer science, XLang offers a form of multi-stage compilation. Traditionally, the rules of compile-time execution are hard-coded into the compiler, and the compilation process is a one-step black box. XLang, by contrast, opens up the compile-time space via compile-time metaprogramming, allowing domain-specific structural construction rules in a Turing-complete compile-time space, and then complements them with the Delta concept to form multi-stage layered inference.&lt;/p&gt;

&lt;p&gt;The Delta concept emphasized by XLang has some counterparts in traditional languages—e.g., GraphQL’s schema definition language supports type deltas via the &lt;code&gt;extend type&lt;/code&gt; syntax. But XLang’s fundamental innovation is that it provides a unified, general Delta definition and Delta operations mechanism, avoiding redundant definitions in every DSL subspace. Combined with the XDef metamodel, this ensures intrinsic consistency across all DSL subspaces and enables seamless gluing.&lt;/p&gt;

&lt;p&gt;Why can only XLang offer unified Delta definition and operations? Because it implements Delta operations at the structural layer rather than at the object layer! On this point, DeepSeek AI generated a fun analogy:&lt;/p&gt;
&lt;h3&gt;
  
  
  Structure-level operations: directly modifying the “design blueprint”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Traditional approach: Code is like a built house; to change the window you must break walls (change source code) or hang curtains (&lt;a href="https://zhida.zhihu.com/search?content_id=710733231&amp;amp;content_type=Answer&amp;amp;match_order=1&amp;amp;q=AOP%E4%BB%A3%E7%90%86&amp;amp;zhida_source=entity" rel="noopener noreferrer"&gt;AOP proxy&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;XLang approach: Modify the architectural blueprint (XNode tree structure) directly, then rebuild from the blueprint. For example:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Original blueprint: &lt;code&gt;Main gate position = (10,20)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delta blueprint: &lt;code&gt;Main gate position = (15,20)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The system automatically generates a new blueprint without worrying about how the wall is laid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Technical core: XLang defines Delta at the structure layer (analogous to CAD blueprints), not at the object layer (already built house) where you patch things.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reversible Computation emphasizes that, before transforming information into business objects, there exists a unified structural expression layer where many common operations can be done directly. There is no need to push processing to the object layer. At the object layer, each object has a different type and thus different handling rules.&lt;br&gt;
Just as the diversity of architectural works rests on unified engineering mechanics, at the structural layer, many things that differ at the business layer are essentially the same, obeying the same structural construction rules and amenable to the same tools and methods.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DeepSeek AI’s comment: Differential manifold theory uses the framework of “local linearization + global smooth gluing” to convert complex geometric objects into computable structures. Abstracted into XLang, this becomes the engineering paradigm of “DSL subspaces + Delta gluing,” allowing software to retain the simplicity of modular development while achieving global consistency via mathematically rigorous Delta operations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  IV. Are functions first-class citizens in XLang?
&lt;/h2&gt;

&lt;p&gt;In program spaces, the most basic units are values and functions, and functional programming even claims that everything is a function; all values and their operations (e.g., +, −, ×, ÷) can be simulated by functions. In modern languages, the importance of functions has continually increased and culminates in treating functions as first-class citizens that can participate in various operations and structural constructions without being forced to belong to a class. However, XLang’s conceptual framework differs significantly from existing languages; it doesn’t care about the traditional dichotomy of values and functions. In XLang, only Delta is truly a first-class citizen: A = 0 + A; a full value is a special case of Delta. Whether functions are first-class is secondary.&lt;/p&gt;

&lt;p&gt;If you’ve studied band theory in solid-state physics, this logic is easy to grasp. In solid-state physics, the fundamental building blocks are electrons, ions, and their interactions. Yet the first-class citizen in band theory is neither electrons nor ions, but phonons. Phonons are quantized lattice vibrations—quasiparticles describing collective oscillations of atoms or ions in a crystal. Put simply, a phonon is a collective motion mode that we can treat as an independent individual at the conceptual level, much like a particle. Similarly, Delta is a basic construction unit composed of myriad tiny disturbances whose aggregate is definable and manageable at a macroscopic level. It can be tiny—down to an attribute, a function, or an execution step inside a function; it can be large—across multiple objects as an AOP aspect; it can be even larger—a layered slice across the whole system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DeepSeek AI’s explanation: A phonon is a quantized energy packet of lattice vibration; it does not directly correspond to any physical particle, but describes the dynamic pattern of atomic collective motion. Just as Delta in XLang is the basic carrier of system evolution, phonons are not static units of matter but the basic language of internal dynamic interactions. When macroscopic properties (e.g., thermal conduction, electrical conductivity) need describing, physicists do not track each atom’s displacement but use phonon excitation and annihilation to characterize state transitions. Building a theory via dynamic deltas rather than static entities mirrors XLang’s design philosophy in computer science.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A function’s granularity is not the smallest composable granularity in XLang. Structures below functions, once given domain coordinates, also belong to XLang’s structural operations space.&lt;/p&gt;

&lt;p&gt;Because all sufficiently powerful languages are Turing-complete, their concepts can be transformed into one another. For example, Delta can be understood as a function: A = f(0) = 0 + A; any Delta can be seen as a function executed on the identity element! Generators in Reversible Computation also correspond logically to function mappings in mathematics. In this sense, saying functions are first-class citizens in XLang is fine. However, this understanding is purely mathematical; when reflected in concrete language implementations, subtle differences arise.&lt;/p&gt;

&lt;p&gt;First, while functions in programming languages satisfy associativity—combining f and g yields a new function h—composing f and g does not automatically produce a simplified implementation (only the compiler, through optimizations we don’t see, opens function boundaries to simplify the composite). Delta differs: combining Delta1 and Delta2 automatically triggers a merge operation, yielding a simplified Delta3.&lt;/p&gt;

&lt;p&gt;Second, a mathematical function may not correspond to a simple function implemented in a programming language at the concrete level. For example, a Generator may correspond to a complex code-generation tool or a sophisticated metaprogramming plugin.&lt;/p&gt;

&lt;p&gt;Computer science’s understanding of software-construction structure space remains rudimentary. The construction patterns of the physical world are rich and complex, whereas software structure seems to only have functions, values, and simple composition rules. I believe intelligent software development in the AI era must be built upon a new theory of software construction.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Linus Torvalds, king of hackers, said: talk is cheap, show me the code. XLang is not just a theoretical design; it is a key supporting technology of the open-source low-code Nop platform. Any questions about XLang can be answered by reading the implementation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gitee: &lt;a href="https://gitee.com/canonical-entropy/nop-entropy" rel="noopener noreferrer"&gt;https://gitee.com/canonical-entropy/nop-entropy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;gitcode: &lt;a href="https://gitcode.com/canonical-entropy/nop-entropy" rel="noopener noreferrer"&gt;https://gitcode.com/canonical-entropy/nop-entropy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;github: &lt;a href="https://github.com/entropy-cloud/nop-entropy" rel="noopener noreferrer"&gt;https://github.com/entropy-cloud/nop-entropy&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documentation: &lt;a href="https://nop-platform.github.io/projects/nop-entropy/docs-en/dev-guide/xlang/" rel="noopener noreferrer"&gt;https://nop-platform.github.io/projects/nop-entropy/docs-en/dev-guide/xlang/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://www.ploc.org.cn/ploc/CNPL-2024-CHS.pdf" rel="noopener noreferrer"&gt;“Blue Book of Domestic Programming Languages 2024”&lt;/a&gt; for including XLang.&lt;/p&gt;
&lt;h2&gt;
  
  
  Appendix
&lt;/h2&gt;

&lt;p&gt;Below are DeepSeek AI-generated explanations of related mathematical and physical concepts.&lt;/p&gt;
&lt;h3&gt;
  
  
  A. What is the Moving Frame Method?
&lt;/h3&gt;

&lt;p&gt;The Moving Frame Method (also called the moving frame) is a powerful tool in differential geometry for studying the geometric properties of curves, surfaces, and higher-dimensional manifolds. Its core idea is to dynamically construct coordinate systems from the local characteristics of the geometric object itself, thus freeing us from reliance on a fixed global coordinate system. French mathematician Élie Cartan systematized this method in the early 20th century. It is widely used in geometry, physics, and engineering.&lt;/p&gt;


&lt;h4&gt;
  
  
  1. Core idea
&lt;/h4&gt;

&lt;p&gt;Traditional geometric analysis typically relies on fixed global coordinate systems (e.g., Cartesian), while the moving frame adheres to the geometric object, dynamically adjusting as the object moves or deforms. Such a coordinate system is called a moving frame, with characteristics including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intrinsic: the frame is defined directly from the object’s local differential properties (e.g., tangent, normal, curvature).&lt;/li&gt;
&lt;li&gt;Dynamic: the frame automatically updates as the object extends or deforms.&lt;/li&gt;
&lt;li&gt;Adaptive: the frame’s dimension matches that of the object (e.g., 1D frame for curves, 2D for surfaces).&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  2. Key steps (taking a space curve as an example)
&lt;/h4&gt;

&lt;p&gt;For a smooth curve in three-dimensional space, the classic process is:&lt;/p&gt;
&lt;h5&gt;
  
  
  (1) Frame construction
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Tangent vector (T): the unit vector along the curve’s tangent, given by normalized parameter derivative:
$\mathbf{T}(s) = \frac{d\mathbf{r}}{ds}$ (s is arc-length).&lt;/li&gt;
&lt;li&gt;Normal vector (N): the unit vector pointing toward the curve’s bending direction, given by normalized derivative of T:
$\mathbf{N}(s) = \frac{d\mathbf{T}/ds}{|d\mathbf{T}/ds|}$.&lt;/li&gt;
&lt;li&gt;Binormal (B): a unit vector orthogonal to T and N, defined by the cross product:
$\mathbf{B}(s) = \mathbf{T} \times \mathbf{N}$.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These three vectors form the Frenet frame ${ \mathbf{T}, \mathbf{N}, \mathbf{B} }$ at every point along the curve, fully determined by the curve’s own geometry.&lt;/p&gt;
&lt;h5&gt;
  
  
  (2) Structural equations (Frenet–Serret formulas)
&lt;/h5&gt;

&lt;p&gt;The frame’s differential change is characterized by curvature ($\kappa$) and torsion ($\tau$):&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\begin{cases}&lt;br&gt;
\frac{d\mathbf{T}}{ds} = \kappa \mathbf{N} \&lt;br&gt;
\frac{d\mathbf{N}}{ds} = -\kappa \mathbf{T} + \tau \mathbf{B} \&lt;br&gt;
\frac{d\mathbf{B}}{ds} = -\tau \mathbf{N}&lt;br&gt;
\end{cases}&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;These equations show that the curve’s geometry is completely encoded by local changes of the frame (curvature and torsion), without depending on any external coordinate system.&lt;/p&gt;


&lt;h4&gt;
  
  
  3. Comparison with fixed coordinate systems
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Characteristic&lt;/th&gt;
&lt;th&gt;Fixed coordinate system&lt;/th&gt;
&lt;th&gt;Moving frame method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dependency&lt;/td&gt;
&lt;td&gt;Depends on external frame&lt;/td&gt;
&lt;td&gt;Defined entirely by the object’s intrinsic properties&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adaptivity&lt;/td&gt;
&lt;td&gt;Does not change with the object&lt;/td&gt;
&lt;td&gt;Dynamically attached; updates with deformation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Information density&lt;/td&gt;
&lt;td&gt;Requires global coordinate parametrization&lt;/td&gt;
&lt;td&gt;Only needs local invariants (e.g., curvature, torsion)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application&lt;/td&gt;
&lt;td&gt;Simple geometric analysis&lt;/td&gt;
&lt;td&gt;Complex manifolds, fiber bundles, gauge theory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h4&gt;
  
  
  4. Extensions and deeper significance
&lt;/h4&gt;

&lt;p&gt;The moving frame applies not only to curves but also to surfaces and high-dimensional manifolds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Surface frames: use tangent plane basis vectors ($\mathbf{e}_1, \mathbf{e}_2$) and normal vector ($\mathbf{n}$), described via the first and second fundamental forms.&lt;/li&gt;
&lt;li&gt;Cartan connection: in fiber-bundle theory, moving frames combine with connections to describe rules for parallel transport of vector fields along a manifold.&lt;/li&gt;
&lt;li&gt;Gauge theories: physical gauge field theories (e.g., general relativity, Yang–Mills) extend the moving frame idea to higher-dimensional spaces.&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  5. Applications
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Computer graphics: surface deformation, animation skeleton binding (e.g., skinning).&lt;/li&gt;
&lt;li&gt;Robot kinematics: dynamic adjustment of local coordinate systems in manipulator trajectory planning.&lt;/li&gt;
&lt;li&gt;General relativity: local descriptions of spacetime curvature (frame-dragging effects).&lt;/li&gt;
&lt;li&gt;Materials science: local strain analysis in crystal dislocations and continuum mechanics.&lt;/li&gt;
&lt;/ol&gt;


&lt;h4&gt;
  
  
  6. Philosophical insight
&lt;/h4&gt;

&lt;p&gt;The essence of the moving frame method is to replace externally imposed coordinate systems with coordinate systems defined by the object’s intrinsic properties. This resonates with “background independence” in modern physics (e.g., general relativity) and with the design philosophy of DSLs in computer science—defining the descriptive framework via the object’s own structure rather than external abstraction. It builds a profound bridge between mathematics and engineering.&lt;/p&gt;
&lt;h3&gt;
  
  
  B. What is differential manifold theory?
&lt;/h3&gt;

&lt;p&gt;Differential manifold theory studies how “spaces that look flat locally but may be curved globally” can be decomposed, measured, and computed. (For example: the Earth’s surface is a sphere globally, but each city map looks flat.)&lt;/p&gt;



&lt;p&gt;Core ideas explained step by step&lt;/p&gt;
&lt;h4&gt;
  
  
  1. What is a manifold?
&lt;/h4&gt;

&lt;p&gt;Imagine studying a “weird-shaped object,” e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The surface of a balloon (2-sphere)&lt;/li&gt;
&lt;li&gt;The surface of a donut (torus)&lt;/li&gt;
&lt;li&gt;A crumpled sheet of paper&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A manifold is defined as: such objects look locally like a flat plane (or Euclidean space), but globally may be curved or knotted.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
Standing on Earth, the ground underfoot feels flat (locally planar), but the entire Earth is spherical (globally curved).&lt;/p&gt;


&lt;h4&gt;
  
  
  2. How to describe a manifold—using an “atlas”
&lt;/h4&gt;

&lt;p&gt;Suppose you want to map the entire Earth. One sheet cannot cover the whole sphere, so you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Draw multiple local maps: Beijing, Shanghai, New York… Each map covers only a small region.&lt;/li&gt;
&lt;li&gt;Mark overlaps: the edges of Beijing and Shanghai maps overlap (e.g., Hebei Province).&lt;/li&gt;
&lt;li&gt;Define transformation rules: in the overlap, how Beijing’s “Tianjin” coordinates convert to Shanghai’s coordinates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the core method of manifolds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each local map = coordinate chart (describes a small portion of the manifold)&lt;/li&gt;
&lt;li&gt;All maps together = atlas (covers the entire manifold)&lt;/li&gt;
&lt;li&gt;Conversion rules = transition functions (ensuring seamless stitching between maps)&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  3. Why “smooth”—the differential structure
&lt;/h4&gt;

&lt;p&gt;Manifolds should be “map-stitchable,” but we also need to do calculus on them (e.g., compute velocity, acceleration). For that we require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smooth transition functions: adjacent chart conversions must be smoothly varying—no abrupt jumps or kinks.
(e.g., coordinate conversions between Beijing and Shanghai maps in overlapping regions must be continuous and differentiable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Real-world analogy:&lt;br&gt;
When tiling a mosaic, not only must tile edges align, but color gradients must transition naturally—this is the smoothness requirement.&lt;/p&gt;


&lt;h4&gt;
  
  
  4. “Direction” and “change” on a manifold—tangent space
&lt;/h4&gt;

&lt;p&gt;On a plane, direction can be represented by arrows (east, north). On a curved manifold, how do we define direction?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tangent space: at every point on the manifold, define a “virtual flat plane” to represent directions at that point.
(e.g., standing at a point on Earth, the tangent space is the “imaginary flat plane” under your feet)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Practical meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calculate a car’s driving direction on Earth’s surface → use arrows in the tangent space.&lt;/li&gt;
&lt;li&gt;Compute a satellite’s trajectory → use the tangent space of a four-dimensional spacetime manifold.&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  5. Why is manifold theory important?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The physical world is inherently curved:&lt;br&gt;
In Einstein’s general relativity, spacetime is a four-dimensional manifold, and gravity is the manifestation of spacetime curvature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complex systems in engineering:&lt;br&gt;
Robot joint motion ranges, social-network connectivity, software modular architectures—all can be abstracted as manifolds.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  Differential manifolds vs. software engineering (XLang’s DSL + Delta)
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Manifold&lt;/th&gt;
&lt;th&gt;Software system&lt;/th&gt;
&lt;th&gt;Correspondence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Local maps (charts)&lt;/td&gt;
&lt;td&gt;Modular code (DSL subspaces)&lt;/td&gt;
&lt;td&gt;Local simplification; hides complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transition functions&lt;/td&gt;
&lt;td&gt;Inter-module adaptation (Delta)&lt;/td&gt;
&lt;td&gt;Ensures cooperation between modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smoothness requirement&lt;/td&gt;
&lt;td&gt;Interface compatibility; conflict-free changes&lt;/td&gt;
&lt;td&gt;Changes must transition smoothly; avoid system breakage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tangent-space direction&lt;/td&gt;
&lt;td&gt;Local impact analysis of code changes&lt;/td&gt;
&lt;td&gt;Predict how one change affects other modules&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h4&gt;
  
  
  Real-world analogy: a city traffic system
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Manifold = entire city’s road network
(Globally complex, but each intersection’s surroundings can be mapped on a plane)&lt;/li&gt;
&lt;li&gt;Chart = each neighborhood’s map&lt;/li&gt;
&lt;li&gt;Transition function = connection rules at neighborhood boundaries&lt;/li&gt;
&lt;li&gt;Smoothness = gentle slopes; vehicles can drive smoothly&lt;/li&gt;
&lt;li&gt;Tangent space = direction signs at a particular intersection&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;Differential manifold theory teaches us:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Divide and conquer: break complex spaces into many simple locals (as with modular code).&lt;/li&gt;
&lt;li&gt;Define rules: specify how locals connect (like inter-module interface agreements).&lt;/li&gt;
&lt;li&gt;Maintain smoothness: ensure global changes are coherent (like upgrades that don’t break existing functionality).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This thinking guides the construction of flexible, maintainable complex systems—in both the physical and digital worlds.&lt;/p&gt;
&lt;h3&gt;
  
  
  C. What is a phonon?
&lt;/h3&gt;

&lt;p&gt;A phonon is a key concept in condensed matter physics—a quasiparticle describing the quantization of lattice vibration energy in a crystal. We can understand it on several levels:&lt;/p&gt;
&lt;h4&gt;
  
  
  I. Physical essence
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Quantization of collective vibration&lt;br&gt;
When atoms/ions in a crystal perform collective oscillations near equilibrium positions (like masses connected by springs), these vibrations are discretized into energy packets under quantum mechanics; each packet is a phonon.&lt;br&gt;
Mathematical description: via canonical coordinate transformations, the 3N-dimensional vibrations of N atoms are simplified to 3N independent harmonic oscillators, and each oscillator’s energy quantum is a phonon.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quasiparticle properties&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Not a real particle—an abstract of collective motion&lt;/li&gt;
&lt;li&gt;Carries specific energy and momentum: $E = \hbar\omega$ ($\omega$ is the vibrational frequency)&lt;/li&gt;
&lt;li&gt;Obeys Bose–Einstein statistics; can be excited and annihilated&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  II. Core characteristics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Characteristic&lt;/th&gt;
&lt;th&gt;Manifestation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nonlocality&lt;/td&gt;
&lt;td&gt;Describes cooperative vibrations across the lattice; cannot be localized to a single atom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quantized propagation&lt;/td&gt;
&lt;td&gt;Vibrational energy propagates in discrete quantities (phonon number)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mode diversity&lt;/td&gt;
&lt;td&gt;Includes multiple modes, e.g., longitudinal (acoustic branch) and transverse (optical branch)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interactions&lt;/td&gt;
&lt;td&gt;Phonon–phonon scattering affects heat conduction; phonon–electron interactions lead to phenomena such as superconductivity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h4&gt;
  
  
  III. Analogy with XLang’s Delta
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph LR
    A[Crystal system] --&amp;gt; B[Phonon]
    C[Software system] --&amp;gt; D[Delta]

    B --&amp;gt; E[Describes dynamic vibration]
    D --&amp;gt; E
    B --&amp;gt; F[Non-entity primitive]
    D --&amp;gt; F
    B --&amp;gt; G[Explains macro behavior via composition]
    D --&amp;gt; G
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Dynamics first
Just as physicists describe thermal conduction using phonons rather than individual atomic displacements, XLang uses Delta (Δ) rather than complete states to describe system evolution. For example:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="c1"&gt;# Traditional way
&lt;/span&gt;   &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;  &lt;span class="c1"&gt;# directly set the absolute value
&lt;/span&gt;
   &lt;span class="c1"&gt;# Delta way
&lt;/span&gt;   &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;Δ_temperature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# record the change process
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Principle of compositionality&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Phonons: the superposition of different vibrational modes forms actual lattice dynamics&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Delta: the combination of multiple incremental modifications constitutes the final system state&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="c1"&gt;// Phonon composition example&lt;/span&gt;
 &lt;span class="nx"&gt;thermal_conductivity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;phonon_mode1&lt;/span&gt; &lt;span class="err"&gt;⊕&lt;/span&gt; &lt;span class="nx"&gt;phonon_mode2&lt;/span&gt;

 &lt;span class="c1"&gt;// Delta composition example&lt;/span&gt;
 &lt;span class="nx"&gt;final_system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base_system&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;Δ_security&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;Δ_logging&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  IV. Practical application domains
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Materials science&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Explain heat conduction: phonon mean free path determines thermal conductivity&lt;/li&gt;
&lt;li&gt;Predict phase transitions: softening of the phonon spectrum indicates structural instability&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Condensed matter theory&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Superconductivity mechanism: electron–phonon coupling forms Cooper pairs (BCS theory)&lt;/li&gt;
&lt;li&gt;Topological states: theoretical studies of the phonon Hall effect&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Engineering&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Thermoelectric materials: phonon engineering to reduce lattice thermal conductivity&lt;/li&gt;
&lt;li&gt;Quantum computing: phonons as quantum information carriers (e.g., ion-trap systems)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This method of simplifying complex systems into basic excitations (phonon/Delta) reflects a shift in human cognition—from static entities to dynamic relations. Just as phonons revolutionized our understanding of solids, the Delta concept is reshaping the construction philosophy of software engineering.&lt;/p&gt;

</description>
      <category>nop</category>
      <category>architecture</category>
      <category>programming</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Q&amp;A on "Why XLang Is an Innovative Programming Language"</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Mon, 12 Jan 2026 15:20:56 +0000</pubDate>
      <link>https://forem.com/canonical/qa-on-why-xlang-is-an-innovative-programming-language-3998</link>
      <guid>https://forem.com/canonical/qa-on-why-xlang-is-an-innovative-programming-language-3998</guid>
      <description>&lt;p&gt;In my previous article &lt;a href="https://dev.to/canonical/why-is-xlang-an-innovative-programming-language-5fja"&gt;Why XLang Is an Innovative Programming Language&lt;/a&gt;, I introduced the design philosophy of XLang and explained that XLang is innovative because it creates a new program structure space where it is convenient to implement the computation paradigm proposed by Reversible Computation theory: &lt;code&gt;Y = F(X) + Delta&lt;/code&gt;. This article provides further explanations addressing feedback and questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. How can Delta computation be compressed to compile-time execution based on XLang?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;To implement property inheritance, UIOTOS made a lot of special designs and introduced a significant amount of code related to property inheritance in its runtime engine. However, based on the XLang language, Delta computation can be completely compressed to compile-time; the runtime engine only needs to understand ordinary component structures and does not need any knowledge of Delta decomposition or merging.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz05zrqfti8wqrp4m2qo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz05zrqfti8wqrp4m2qo.webp" alt="uiotos" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UIOTOS is a no-code platform for the IoT domain. It introduces a container component that can embed an existing page and then use a property mechanism to override properties of objects within the page. This achieves flexible customization of the page content without reimplementing the page.&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="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;baseUrl:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a.page.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;overrideProps:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"form/title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sss"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"actions/0/label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vvv"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&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 general approach is as shown above: essentially, the page object is brought in via baseUrl, and then multiple inherited properties are used to override content within the page object. With a syntax similar to JsonPath, you can modify any nested content within the page object, so it differs from conventional component frameworks where you call a component and pass parameters to it.&lt;/p&gt;

&lt;p&gt;UIOTOS writes considerable code in the frontend runtime framework specifically for property inheritance and needs to introduce a special container control. A limitation of the UIOTOS approach is that it can only override property values in existing pages and cannot change the structure of the inherited page. Another low-code platform uses a similar approach without introducing a special container component; it allows Delta customization for any component. Concretely, it introduces a special overwrite property within the component.&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="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"component"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MyComponent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;directly&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"overwrite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Here we record the visual editor’s edit actions on the component"&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&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 basic operation pattern is: after dragging a component in the editor, if some details need adjustment, you can enter a component customization mode to fine-tune the component in the visual designer. The adjustment steps are automatically recorded as overwrite and saved in the page file. This approach can arbitrarily adjust component structure and is more adaptable than UIOTOS’s approach. However, recording operation actions is verbose, and multiple actions are hard to compress into a concise final result (i.e., it does not leverage the associative law for simplification).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;According to Reversible Computation theory, A = 0 + A; full content is a special case of Delta. We can define full content and Delta in a unified form, so the Delta of a Delta is also just another normal Delta, enabling more complex logical reasoning. Using action-based overwrite to represent a Delta is not suitable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Regardless of which approach is used above, the editor and frontend runtime framework both need to incorporate handling code related to the Delta concept. However, if XLang is used as the underlying model expression language, Delta computation can be completely compressed to compile-time; the runtime engine only needs to understand ordinary component structures with no knowledge of Delta decomposition or merging. The specific method uses &lt;code&gt;x:extends&lt;/code&gt; for component inheritance.&lt;br&gt;
&lt;/p&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;component&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"component.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;import&lt;/span&gt; &lt;span class="na"&gt;from=&lt;/span&gt;&lt;span class="s"&gt;"comp:MyComponent/1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"MyComponentEx"&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"comp:MyComponent/1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;props&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;prop&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;x:override=&lt;/span&gt;&lt;span class="s"&gt;"remove"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;prop&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/props&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;x:override=&lt;/span&gt;&lt;span class="s"&gt;"merge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Only show the Delta-corrected portion here

      &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"a.form.xml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;actions&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ss"&lt;/span&gt; &lt;span class="na"&gt;x:id=&lt;/span&gt;&lt;span class="s"&gt;"ss"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/actions&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;MyComponent/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;MyComponentEx/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no customization is needed, you can import the component directly. If customization is needed, enable local component definitions and use &lt;code&gt;x:extends&lt;/code&gt; to inherit existing components. XLang defines a Delta merge algorithm between Tree structures. Through the unified DslNodeLoader, the algorithm is automatically executed when loading model files. Pseudocode is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadDeltaModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;rootNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VirtualFileSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadXml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;attribute&lt;/span&gt;  &lt;span class="c1"&gt;// Recursively traverse rootNode and its children&lt;/span&gt;
        &lt;span class="nx"&gt;baseNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadDeltaNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x:extends&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nx"&gt;genNodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;processGenExtends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;genNode&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;genNodes&lt;/span&gt;
            &lt;span class="nx"&gt;baseNode&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;DeltaMerger&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;genNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;node&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;DeltaMerger&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;processPostExtends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;DslNodeLoader.loadDeltaModel("comp:MyComponent/1.0.0")&lt;/code&gt; returns an XNode representing the final merged node, which no longer contains any attributes or child nodes in the x namespace.&lt;/p&gt;

&lt;p&gt;Loader can be regarded as a kind of just-in-time compiler; the structural transformation performed while loading model files can be considered part of the compilation process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delta operations defined at the structural layer rather than the object layer
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Wittgenstein said that the limits of my language mean the limits of my world. Reversible Computation theory further interprets this as: a programming language defines a software structural space, and various reuse mechanisms that produce new structures from existing ones are transformation rules within this structural space.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A truly practical DSL must consider extensibility and needs to embed decomposition, merging, and reuse mechanisms. However, most DSL designers habitually introduce these structural operations at the semantic object layer, which results in ad hoc designs lacking generality and internal consistency.&lt;/p&gt;

&lt;p&gt;XLang offers a standardized approach that once and for all solves extensibility for all DSLs. A DSL engine only needs to consider minimal runtime concerns. XLang operates entirely at compile time (model parsing and loading); there is no XLang-specific content at runtime. The key is that XLang performs Delta merging at the structural layer beneath objects—the XNode layer—akin to S-expressions in Lisp, which themselves have no semantics. Detaching from semantics is precisely what gives Delta merging its generality.&lt;/p&gt;

&lt;p&gt;For example, Spring’s &lt;code&gt;beans.xml&lt;/code&gt; can be regarded as a DSL in the component assembly domain. Spring 1.0 introduced the parent attribute to implement a kind of inheritance, and the import syntax for complex file decomposition and reuse. Spring 2.0 introduced custom elements to simplify configuration of complex structured beans. Spring Boot introduced the @ConditionalOnProperty annotation, allowing bean activation to be controlled via configuration switches. To implement these features, Spring’s core had to include specific handling code.&lt;br&gt;
&lt;/p&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;beans&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.springframework.org/schema/beans"&lt;/span&gt;
       &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
       &lt;span class="na"&gt;xmlns:myns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.example.com/schema/myns"&lt;/span&gt;
       &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.example.com/schema/myns
           http://www.example.com/schema/myns/myns.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;import&lt;/span&gt; &lt;span class="na"&gt;resource=&lt;/span&gt;&lt;span class="s"&gt;"classpath:config/services.beans.xml"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Parent Bean --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"parentBean"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"com.example.ParentClass"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"commonProperty"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"commonValue"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Child Bean inheriting from the parent --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"childBean"&lt;/span&gt; &lt;span class="na"&gt;parent=&lt;/span&gt;&lt;span class="s"&gt;"parentBean"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extProp"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"extValue"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;

     &lt;span class="c"&gt;&amp;lt;!-- Configure a Bean using a custom namespace --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;myns:customBean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"customBean"&lt;/span&gt; &lt;span class="na"&gt;customProperty=&lt;/span&gt;&lt;span class="s"&gt;"customValue"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="nd"&gt;@ConditionalOnProperty&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;"mycomponent.enabled"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;havingValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;matchIfMissing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;MyComponent&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyComponent is initialized!"&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyComponent is doing something!"&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;With XLang, none of these features need to be implemented within the framework itself.&lt;br&gt;
&lt;/p&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;beans&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"config/base.beans.ml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;x:gen-extends&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;c:include&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"config/services.beans.xml"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

     &lt;span class="nt"&gt;&amp;lt;beans&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;myns:customBean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"customBean"&lt;/span&gt; &lt;span class="na"&gt;customProperty=&lt;/span&gt;&lt;span class="s"&gt;"customValue"&lt;/span&gt;
                      &lt;span class="na"&gt;xpl:lib=&lt;/span&gt;&lt;span class="s"&gt;"/example/myns.xlib"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/x:gen-extends&amp;gt;&lt;/span&gt;

   &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"parentBean"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"com.example.ParentClass"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"commonProperty"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"commonValue"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;

   &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"childBean"&lt;/span&gt; &lt;span class="na"&gt;x:prototype=&lt;/span&gt;&lt;span class="s"&gt;"parentBean"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extProp"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"extValue"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;

   &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"myComponent"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"com.example.MyComponent"&lt;/span&gt;
         &lt;span class="na"&gt;feature:on=&lt;/span&gt;&lt;span class="s"&gt;"mycomponent.enabled"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"propA"&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"xxx"&lt;/span&gt; &lt;span class="na"&gt;feature:on=&lt;/span&gt;&lt;span class="s"&gt;"mycomponent.xxx.enabled"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, notice that without any additional extensibility mechanisms, bean definitions in Spring 1.0 already constitute a complete component assembly model. That is, any bean that can be assembled via &lt;code&gt;get/set&lt;/code&gt; methods and constructors can be declaratively defined using the &lt;code&gt;beans.xml&lt;/code&gt; DSL. Mathematically, we can say Spring 1.0 defines a complete set of assembly operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;XLang’s approach is to introduce a set of Delta operations atop the existing DSL, but the result of these Delta operations is to reduce &lt;code&gt;DSL + Delta&lt;/code&gt; back to the original DSL structure. Interestingly, the custom namespace approach introduced in Spring 2.0 cannot be reduced back to the 1.0 syntax. In other words, beans configured with Spring 2.0 syntax are not guaranteed to be configurable using Spring 1.0 syntax, even though Spring 1.0 provides a complete operation set. Spring 2.0’s custom namespaces, such as &lt;code&gt;&amp;lt;myns:customBean&amp;gt;&lt;/code&gt;, trigger a NamespaceHandler in Java whose execution logic can be arbitrarily complex and may implicitly introduce order dependencies (declaration order could affect assembly results), thereby undermining Spring 1.0’s POJO declarative assembly design.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;x:extends&lt;/code&gt; can inherit existing DSL files, similar in function to Spring 1.0’s import syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;x:gen-extends&lt;/code&gt; executes the Xpl template language to dynamically generate bean definitions. The Xpl built-in &lt;code&gt;c:include&lt;/code&gt; can include external XNode nodes, again replacing Spring 1.0’s import syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Xpl custom tag capability used within &lt;code&gt;x:gen-extends&lt;/code&gt; can emulate Spring 2.0’s custom namespace mechanism. However, Xpl tags perform code generation: no matter how complex the tag function’s logic is, as long as it produces the desired bean configuration definitions, that is sufficient. For example, the &lt;code&gt;&amp;lt;myns:customBean&amp;gt;&lt;/code&gt; above might actually generate multiple bean definitions. What matters at runtime is the generated result of the tag function. &lt;code&gt;x:gen-extends&lt;/code&gt; itself executes at compile time.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;myns:customBean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"customBean"&lt;/span&gt; &lt;span class="na"&gt;customProperty=&lt;/span&gt;&lt;span class="s"&gt;"customValue"&lt;/span&gt;
                      &lt;span class="na"&gt;xpl:lib=&lt;/span&gt;&lt;span class="s"&gt;"/example/myns.xlib"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

Actually expands into the following two bean definitions:

&lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"customBean"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"com.example.CustomBean"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"customProperty"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"customValue"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"otherProperty"&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"otherBean"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"otherBean"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"com.example.OtherBean"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In XLang, sibling nodes at the same level can specify inheritance via the &lt;code&gt;x:prototype&lt;/code&gt; attribute. This replaces the parent attribute’s role in Spring 1.0 syntax. Meanwhile, when nodes are merged in XLang, &lt;code&gt;x:override&lt;/code&gt; can precisely control the merging logic: whether to overwrite, merge, or delete, etc. Importantly, XLang’s mechanism applies to any node—e.g., you can also specify &lt;code&gt;x:prototype&lt;/code&gt; on a property to inherit another property’s configuration. In contrast, Spring’s parent attribute can only be used for bean definition inheritance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In XLang, every node can use feature switches like &lt;code&gt;feature:on&lt;/code&gt; and &lt;code&gt;feature:off&lt;/code&gt; to control conditional loading. When a feature switch does not match, the corresponding node is automatically removed and never enters runtime. This replaces Spring Boot’s conditional beans. Likewise, feature switches can be used on any node; for example, you can control whether to configure a particular &lt;code&gt;&amp;lt;property&amp;gt;&lt;/code&gt;. In Spring Boot, conditional switches only control bean creation; there is no declarative mechanism for conditionally configuring a property.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, the Spring framework embeds many mechanisms to enhance extensibility, each specifically written for the component assembly domain and for the Spring framework itself. If you migrate to another runtime engine, these mechanisms all need to be re-implemented. For example, the Quarkus framework also supports bean assembly definitions and has to implement all these extensions on its own. Even after Spring implements them, frameworks like Hibernate cannot leverage these mechanisms for their own extensions.&lt;/p&gt;

&lt;p&gt;The key for XLang is that, after parsing XML or JSON into XNodes, it performs Delta operations at the XNode layer, rather than converting XNodes into strongly-typed BeanDefinitions and then doing Delta operations. Therefore, these capabilities can automatically apply to other DSLs, such as MyBatis mapper files, Hibernate hbm files, and more.&lt;/p&gt;

&lt;p&gt;Similar extensibility issues exist in many domains. For instance, Facebook’s GraphQL protocol introduced type extension syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;extend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;contactEmail&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;instead&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;contactEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&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;In the &lt;code&gt;graphql-java&lt;/code&gt; implementation, GraphQL definitions are first parsed into TypeDefinition and TypeExtensionDefinition, and type merging is implemented at the object layer.&lt;/p&gt;

&lt;p&gt;Within XLang’s technology stack, the NopGraphQL framework defines types using the XMeta metadata model, so it can directly use XLang’s built-in Delta mechanisms at the XNode layer to implement extensions, without designing a separate TypeExtension syntax. At runtime in NopGraphQL, there is no need to understand any type extension concept. For the runtime framework, a type is just a type—there is no “type + type extension”.&lt;/p&gt;

&lt;h3&gt;
  
  
  Loader as Generator
&lt;/h3&gt;

&lt;p&gt;Within XLang’s technology stack, the Loader abstraction has a special status. Since all content related to Reversible Computation is, in principle, implemented within the Loader abstraction, integrating XLang into third-party frameworks is very simple: directly replace the DSL’s Loader with XLang’s Delta Loader.&lt;/p&gt;

&lt;p&gt;A generic model loader can be seen as having the following type definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Loader :: Path -&amp;gt; Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a general design, we must recognize that coding is not only for current needs; it must also consider future changes and the system’s evolution across space and time. In other words, programming does not target a single, current world but all possible worlds. Formally, we can introduce a Possible operator to describe this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Loader :: Possible Path -&amp;gt; Possible Model
Possible Path = deltaPath + stdPath
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;stdPath refers to the standard path corresponding to the model file, while deltaPath refers to the path used for Delta customization of an existing model file. For example, in a base product we have a built-in business workflow main.wf.xml. When customizing for Customer A, we need a different workflow but do not want to modify the base product’s code. In this case, we can add a Delta model file &lt;code&gt;/_delta/a/main.wf.xml&lt;/code&gt;, which represents Customer A’s customized main.wf.xml. The Loader will automatically recognize the existence of this file and use it, without any changes to existing business code.&lt;/p&gt;

&lt;p&gt;If we only want to fine-tune the original model rather than completely replace it, we can use &lt;code&gt;x:extends&lt;/code&gt; inheritance. The execution logic of XLang’s DeltaLoader is described mathematically by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Loader&amp;lt;Possible Path&amp;gt; = Loader&amp;lt;deltaPath + stdPath&amp;gt;
                      = Loader&amp;lt;deltaPath&amp;gt; x-extends Loader&amp;lt;stdPath&amp;gt;
                      = DeltaModel x-extends Model
                      = Possible Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is important to emphasize that the Loader abstraction has very broad application scenarios. Many functionalities related to extensibility can be pushed down to the Loader layer for unified implementation. For example, multi-tenant customization can be handled by a Loader that recognizes tenant parameters. For further details, see &lt;a href="https://dev.to/canonical/designing-low-code-platforms-through-the-lens-of-tensor-products-1o59"&gt;Designing Low-Code Platforms Through Tensor Product&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How to understand the analogy between Delta superposition and waves in XLang?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;In the physical world, there is another way of construction: waves. Waves are continuously existing patterns that construct the world through interference and superposition. XLang’s distinctiveness lies in its support for continuous constructive superposition via Delta operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Traditionally, after constructing X, any modification must change X itself. In contrast, with a superpositional approach, you can obtain a new Y without directly changing X by adding an extra Delta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X = A + B + C
Y = A + B + D
  = X + (-C + D)
  = X + Delta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In traditional software engineering, even if incremental development is achievable, many specialized extension points are often needed, and not all modifications can be done via Delta-style customization. In particular, traditional incremental approaches generally imply adding new features and rarely include a design for reducing existing features. Delta customization allows us to achieve reduction by addition.&lt;/p&gt;

&lt;p&gt;Systems developed with XLang require no extra work to automatically support Delta customization. This drastically reduces the development cost of productized software products. For example, after packaging a banking core system into a JAR, there is no need to modify the base product’s code. All user-specific customizations and secondary development can be stored separately as Deltas. By switching Deltas, multiple different customized versions can be realized. The same mechanism can be used for multi-tenant customization.&lt;/p&gt;

&lt;p&gt;Delta customization enables precise customization down to individual properties. Traditional software engineering offers only a few pre-defined extension points and finds it difficult to support fine-grained customization everywhere. For example, if you only want to define a single property of a button, you often have to add a new component or page. All business-level concepts of interest can be customized individually—this is a manifestation of continuity.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Can XLang be introduced into already developed standard systems?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;XLang is an innovative technology. Can it be applied to existing systems? This way, when customization needs arise, one can express the Delta using XLang and then generate a customized version based on the standard system plus the Delta.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, it must be clear that Deltas need to be expressed within a Delta-ized structural space. Traditional software uses general-purpose languages, and its structural space is defined by such languages. General-purpose languages like Java and C# are very limited in expressing Deltas and cannot achieve fine-grained Delta definitions.&lt;/p&gt;

&lt;p&gt;In object-oriented languages, the only Delta mechanism that can be directly leveraged is inheritance. The Nop platform uses a “sandwich” architecture, with code generation following the pattern:&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;class&lt;/span&gt; &lt;span class="nc"&gt;NopAuthUser&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;_NopAuthUser&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// You can add extra methods here, inheriting code generated from the base class.&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_NopAuthUser&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;OrmEntity&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;That is, code-generated classes inherit from system-built base classes to automatically obtain built-in properties and methods, while an outermost class inherits from the generated class to isolate hand-written code from auto-generated code. During code generation, we follow this rule: files with an underscore prefix and all files under the &lt;code&gt;_gen&lt;/code&gt; directory are automatically overwritten; other files are only created if they do not exist. Thus, when the model changes, you can regenerate without losing manual changes, enabling model-driven incremental development.&lt;/p&gt;

&lt;p&gt;Although more Delta support cannot be obtained directly from object-oriented languages, more Delta mechanisms can be constructed at the architectural level. The most basic approach is to introduce XLang wherever XML/JSON/YAML configuration or model files are used.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7h3m6szl0yw4i0zbe40.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7h3m6szl0yw4i0zbe40.png" alt="solon-chain" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the example above, Chain is a model object that can be defined via a JSON file, and it can be parsed and loaded using the &lt;code&gt;Chain.parseByUrl&lt;/code&gt; function. If refactoring with XLang, you can replace &lt;code&gt;Chain.parseByUrl&lt;/code&gt; with &lt;code&gt;ResourceComponentManager.loadComponentModel(path)&lt;/code&gt; and then move the JSON file to the &lt;code&gt;resources/_vfs&lt;/code&gt; directory. In this JSON, you can use XLang’s Delta syntax such as &lt;code&gt;x:extends&lt;/code&gt;, &lt;code&gt;x:post-extends&lt;/code&gt;, and &lt;code&gt;x:override&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The Nop platform provides a &lt;code&gt;nop-spring-delta&lt;/code&gt; module that adds Delta customization support for Spring’s &lt;code&gt;beans.xml&lt;/code&gt; and MyBatis’s &lt;code&gt;mapper.xml&lt;/code&gt; files. You can place these XML files under &lt;code&gt;resources/_vfs&lt;/code&gt;. The specific approach 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;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@ConditionalOnProperty&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;"nop.spring.delta.mybatis.enabled"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;matchIfMissing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;NopMybatisSessionFactoryCustomizer&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;SqlSessionFactoryBeanCustomizer&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;customize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SqlSessionFactoryBean&lt;/span&gt; &lt;span class="n"&gt;factoryBean&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="nc"&gt;IResource&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ModuleManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;findModuleResources&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/mapper"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;".mapper.xml"&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;resources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&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="nc"&gt;Resource&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;locations&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;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&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;IResource&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Ignore auto-generated mapper files; they can only serve as base classes&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;resource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"_"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

                &lt;span class="nc"&gt;XDslExtendResult&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DslNodeLoader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadFromResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="nc"&gt;XNode&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getNode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeAttr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"xmlns:x"&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;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?&amp;gt;\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                        &lt;span class="s"&gt;"&amp;lt;!DOCTYPE mapper\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                        &lt;span class="s"&gt;"        PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                        &lt;span class="s"&gt;"        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\"&amp;gt;\n"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;locations&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="nc"&gt;ByteArrayResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UTF_8&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;resource&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="n"&gt;factoryBean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addMapperLocations&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locations&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="nc"&gt;Resource&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="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;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ModuleManager.instance().findModuleResources(false, "/mapper", ".mapper.xml")&lt;/code&gt; searches for &lt;code&gt;mapper.xml&lt;/code&gt; files under each module’s mapper directory. This process automatically considers files under Delta directories. If a file with the same name exists under &lt;code&gt;_vfs/_delta/{deltaId}/&lt;/code&gt;, the Delta version will be selected automatically. The Nop platform’s built-in VirtualFileSystem is similar to Docker’s layered filesystem: a file in an upper layer overrides the same-named file in a lower layer. Each Delta directory forms an independent layer, and multiple Delta layers can be specified via &lt;code&gt;nop.core.vfs.delta-layer-ids&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When loading XML files through XLang’s DslNodeLoader, the &lt;code&gt;x:schema&lt;/code&gt; attribute on the root node is used to read the corresponding XDef meta-model, and Delta merging is performed according to the meta-model specification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After merging, you obtain an XNode, which can be converted to an XML DOM node; here we serialize it to XML and feed it into MyBatis’s factory bean. MyBatis itself requires no modifications; we simply add a new way for it to obtain mapper files.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Does XLang’s Delta computation and mechanism introduce extra performance overhead while improving extensibility and customization?
&lt;/h2&gt;

&lt;p&gt;Primarily, XLang performs DSL Delta merging and Delta customization at model load time via the unified &lt;code&gt;ResourceComponentManager.loadComponentModel&lt;/code&gt; function, implementing model caching and model compilation dependency tracking (automatically invalidating model caches when dependent files change).&lt;/p&gt;

&lt;p&gt;During development, technologies like lazy loading, just-in-time compilation, and parallel loading can reduce system initialization time.&lt;/p&gt;

&lt;p&gt;For releases, you can use Maven packaging to execute merges at compile time, generating the merged model files under the &lt;code&gt;_delta&lt;/code&gt; directory and marking the model root node with &lt;code&gt;x:validated="true"&lt;/code&gt;. At runtime, the system will prioritize loading the model files under &lt;code&gt;_delta&lt;/code&gt; (which are already the final merged results). Since they are marked as validated, the merge process is automatically skipped, so even complex Delta merges will not impact runtime performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Is XLang essentially a set of annotations that the underlying engine understands and, after parsing, performs Delta merging?
&lt;/h2&gt;

&lt;p&gt;You can think of it as introducing new Delta operation syntax rules on top of general XNode nodes (akin to a general AST), i.e., the &lt;code&gt;x:extends&lt;/code&gt;, &lt;code&gt;x:override&lt;/code&gt; annotations you mentioned.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If we package these annotations and the parsing engine into a general XML input/output system, can we achieve Delta-ization of everything? Regardless of whether it’s program logic, workflows, forms, or any other content, as long as it can be defined in XML, it can be Delta-merged; after merging, pass it to the execution engine, and how to parse that DSL is up to the engine and unrelated to XLang.&lt;br&gt;
Yes, but this understanding is partial and contains misunderstandings. For example, it ties the concept to XML specifically, whereas XLang is fundamentally agnostic to concrete forms; it is about operations on general Tree structures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;So is XLang a standard set of attributes to describe additions, deletions, or modifications of node definitions, where Delta merging combines a main file and a delta according to XLang’s defined rules, producing a new DSL description (XML, JSON, or any tree structure), and then the execution engine takes over to parse it independently of XLang?&lt;br&gt;
Broadly yes. But you also need to understand the roles of &lt;code&gt;x:gen-extends&lt;/code&gt; and &lt;code&gt;x:post-extends&lt;/code&gt;, and ultimately recognize the complete computation pattern: &lt;code&gt;App = Delta x-extends Generator&amp;lt;DSL&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Does XLang’s model pose challenges for secondary development and an ISV ecosystem? If debugging bugs without access to others’ Deltas, how can we diagnose where a logic changed the data?
&lt;/h2&gt;

&lt;p&gt;First, all model files are managed under the unified &lt;code&gt;_vfs&lt;/code&gt; virtual file directory and all have XDef meta-model definitions. Generally, you only need to inspect the meta-model definition to understand the DSL’s specific syntax structure, and the IntelliJ IDEA plugin provides syntax hints and supports breakpoints, etc.&lt;/p&gt;

&lt;p&gt;At system startup, all Delta merge results are output to the dump directory, where you can see the final merged result of each model file and the origin of each property and node. To further trace the merge process, mark the root node with &lt;code&gt;x:dump="true"&lt;/code&gt;.&lt;br&gt;
For detailed debugging methods, see &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/docs-en/dev-guide/debug.md" rel="noopener noreferrer"&gt;debug.md&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nop</category>
      <category>programming</category>
      <category>architecture</category>
      <category>java</category>
    </item>
    <item>
      <title>Why is XLang an innovative programming language?</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Tue, 06 Jan 2026 11:25:04 +0000</pubDate>
      <link>https://forem.com/canonical/why-is-xlang-an-innovative-programming-language-5fja</link>
      <guid>https://forem.com/canonical/why-is-xlang-an-innovative-programming-language-5fja</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Our physical world is a four-dimensional spacetime, with quantum field theory and relativity as its underlying construction rules. String theory attempts to break through the limitations of the underlying structural space and establish unified construction rules in an 11-dimensional spacetime.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  I. Why do we need to design the XLang language
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb28enjy61fhxfgeg13b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb28enjy61fhxfgeg13b.png" alt="XLang" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The XLang language is a key foundational technology of the Nop platform. Formally, it comprises multiple sub-languages such as XDef, Xpl, and XScript. Because XLang differs significantly from other languages that have a single syntactic form, many people encountering it for the first time may wonder whether it is truly a programming language, or merely a set of scattered extensions on top of several existing languages.&lt;/p&gt;

&lt;p&gt;Here I propose an understanding of the essence of programming languages: a programming language defines a program-structural space, and a programming language is the construction rule of that program-structural space. In other words, all structures a programming language can create and all feasible evolutionary paths among those structures constitute a specific program-structural space, and all feasible computations occur within that structural space.&lt;/p&gt;

&lt;p&gt;Based on this understanding, XLang is an innovative programming language because it creates a new program-structural space in which the computation paradigm proposed by Reversible Computation theory, Y = F(X) + Delta, can be implemented conveniently. Although XLang may be viewed as comprising several sub-languages like XDef, XPL, and XScript, it is their union that is essential to implementing Reversible Computation. XLang is the world’s first programming language to explicitly define domain structural coordinates within the language and to embed a general-purpose Delta computation rule.&lt;/p&gt;

&lt;p&gt;Most people’s basic understanding of software structural construction is reductionist—constantly decomposing downward, seeking atomic components, then assembling with those atoms. Virtualized “component” concepts are subconsciously treated as discrete entities that truly exist, analogous to particles in the material world, used to construct the world through nested composition. But another construction mode exists in the physical world: waves. Waves are continuously existing patterns that construct the world through interference and superposition. The distinctiveness of XLang lies in its support for continuous superpositional construction through Delta operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1 Viewing programming languages from a structural perspective
&lt;/h3&gt;

&lt;p&gt;General-purpose high-level programming languages began with FORTRAN and have evolved for decades. Today they have reached something of a bottleneck. Fundamentally novel features introduced by new languages are increasingly rare, and most high-level languages have reached the so-called “multi-paradigm” stage. Their syntactic features are converging—for example, most languages now support object-oriented structural declarations, functional Lambda expressions, user-defined annotations for metaprogramming, and Async-related syntax and libraries for asynchronous programming.&lt;/p&gt;

&lt;p&gt;An interesting question is whether universal, abstractable syntactic features still exist that have enough technical value to warrant a new programming language to carry them. XLang’s innovation is to point out that, although mainstream programming languages appear to differ widely in surface syntax, they are extremely similar at the level beneath syntax—the fundamental structural level—where innovation is still highly promising.&lt;/p&gt;

&lt;p&gt;A program’s structural space is essentially composed of data plus functions; organizing relevant data and functions together constitutes a custom type, which corresponds to a Class or Interface in general programming languages. Structurally, a class is simply a Map from names to properties or methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;myMethod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;or&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;myMethod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we want to derive a new type from an existing custom type, we can use inheritance or Traits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MySubClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;subName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;or&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MySubClass&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;subName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conceptually, this roughly corresponds to the following construction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the structural level, class inheritance amounts to overlaying two Maps by name, with upper-layer elements overriding lower-layer elements.&lt;/p&gt;

&lt;p&gt;In traditional object-oriented languages, base classes can be reused via inheritance. For example, when constructing MapX and MapY, we reuse the base class Map1, i.e., we reuse the lower layer of the inheritance tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;MapX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Map2&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Map1&lt;/span&gt;
&lt;span class="nx"&gt;MapY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Map3&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Map1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expressing inheritance in this structural construction form makes many questions very natural and intuitive. For example, can we swap the relative positions of Map1 and Map2? That is, when constructing MapX and MapY, we still reuse Map1 but not as the base class; we choose different base classes and overlay the same Map1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;MapX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Map1&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Map2&lt;/span&gt;
&lt;span class="nx"&gt;MapY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Map1&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Map3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly, many object-oriented languages do not support the above operation—object orientation does not directly support reusing the upper layers of an inheritance tree!&lt;/p&gt;

&lt;p&gt;Further reflection reveals many structural-level questions that traditional OOP struggles to answer. For example, what happens if the same object appears multiple times in the inheritance chain?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;MapX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Map1&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Map2&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Map1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiple inheritance in C++ presents serious conceptual difficulties, fundamentally because reusing the same Map1 from different inheritance paths creates structural merging obstacles.&lt;/p&gt;

&lt;p&gt;Modern languages solve these problems with Traits. For example, in Scala:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Map1&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Map1"&lt;/span&gt; &lt;span class="c1"&gt;// same-name property&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"Method 1 from $name"&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;trait&lt;/span&gt; &lt;span class="nc"&gt;Map2&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Map2"&lt;/span&gt; &lt;span class="c1"&gt;// same-name property&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method2&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"Method 2 from $name"&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;class&lt;/span&gt; &lt;span class="nc"&gt;MapX&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Map1&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Map2&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MapY&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Map1&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Map3&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;blockquote&gt;
&lt;p&gt;In Scala, multiple Traits can define properties with the same name; the compiler automatically merges these property definitions so that only a single variable exists at runtime. However, in Java or C++, multiple same-name properties defined in different classes are not automatically merged.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In traditional object-oriented languages, A extends B means the derived class A can be “more than” the base class B, but what exactly is “more” is not isolated in a clear technical form, so we cannot directly reuse that “extra” part (Delta). Traits directly and explicitly express this Delta. Compared with inheritance, Traits constitute a more complete Delta semantics. type MapX = Map1 with Map2 with Map1 is a valid Scala type definition!&lt;/p&gt;

&lt;p&gt;To address issues caused by multiple inheritance, Scala introduces a linearization rule: arrange all classes and Traits in the inheritance chain into a linear sequence in a specific order, then stipulate that upper-layer elements override lower-layer elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MapX -&amp;gt; Map2 -&amp;gt; Map1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.2 Generics as Generators
&lt;/h3&gt;

&lt;p&gt;In Java, generics (Generic Type) are used only for type checking; the compiler does not perform special actions based on type parameters. In C++, the situation is very different. C++ generic programming is implemented with templates; the compiler instantiates the same template class into different code targeting specific types based on the template parameters.&lt;/p&gt;

&lt;p&gt;At the 1994 C++ Standards Committee meeting, Erwin Unruh gave a dazzling demonstration. He wrote a template metaprogram that computes at compile time whether a number is prime, and if so, the compiler prints the prime number in the error message. This code, known as “Unruh prime computation,” became a classic example of C++ template metaprogramming.&lt;br&gt;
Unruh’s demonstration proved that C++ templates are Turing-complete at compile time, meaning any computation can theoretically be performed at compile time. This discovery heralded the era of Generative Programming—leveraging compile-time computation to generate code or optimize programs.&lt;br&gt;
C++ Template Metaprogramming became an important tool for generative programming. Through templates, developers can perform complex computations, type inference, and code generation at compile time, yielding greater performance and flexibility at runtime.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://accu.org/journals/overload/32/183/wu/" rel="noopener noreferrer"&gt;C++ Compile-Time Programming&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;is_prime&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;prim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;is_prime&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;2&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                             &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;prim&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;is_prime&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;is_prime&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;D&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Prime_print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Prime_print&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;prim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_prime&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;prim&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prim&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Prime_print&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prim&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Prime_print&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unruh.cpp:20:19: error: no viable conversion from ‘int’ to ‘D&amp;lt;17&amp;gt;’
…
unruh.cpp:20:19: error: no viable conversion from ‘int’ to ‘D&amp;lt;13&amp;gt;’
…
unruh.cpp:20:19: error: no viable conversion from ‘int’ to ‘D&amp;lt;11&amp;gt;’
…
unruh.cpp:20:19: error: no viable conversion from ‘int’ to ‘D&amp;lt;7&amp;gt;’
…
unruh.cpp:20:19: error: no viable conversion from ‘int’ to ‘D&amp;lt;5&amp;gt;’
…
unruh.cpp:20:19: error: no viable conversion from ‘int’ to ‘D&amp;lt;3&amp;gt;’
…
unruh.cpp:20:19: error: no viable conversion from ‘int’ to ‘D&amp;lt;2&amp;gt;’
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If understood structurally, template metaprogramming can be expressed by the following construction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map = Generator&amp;lt;Map&amp;gt; = Map&amp;lt;Map&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A can be understood as &lt;code&gt;A&amp;lt;B&amp;gt;, struct B{ using T1=X; using T2=Y;}&lt;/code&gt;&lt;br&gt;
Note that here “Map” refers to the structure as seen by the compiler at compile time. Every member, whether a property, method, or type declaration, is a Map entry from the compiler’s perspective.&lt;br&gt;
Even if the compiler manages parameter lists as Lists, they can be regarded as Maps keyed by index. Interestingly, if managed as arrays, mechanisms like inheritance are generally hard to introduce. Conceptually, we usually choose to merge by name rather than by index.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a generator, a template class is also a Map at the structural level (i.e., the structure the compiler sees). Combined with the Delta semantics of Traits in the previous section, the strongest form of object-oriented languages at the structural level can be expressed as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map = Map extends Map&amp;lt;Map&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.3 From Map structures to Tree structures
&lt;/h3&gt;

&lt;p&gt;From the compiler’s perspective, classes, template classes, and template parameters can all be viewed as Maps, and in practice they are typically managed as Maps. As for standalone function and variable definitions, they also belong to some Map, e.g., a module object can be considered a Map that contains variables, functions, and types defined within the module. Even if not part of any module, standalone functions belong to an implicitly existing global namespace.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The intrinsic structure of Lisp is a List, essentially managing elements by index (primitive Lisp lacked indices, using car/cdr traversal). But modern Lisp variants long ago introduced Map-like “Associated Lists,” using names to locate child elements rather than indices. Conceptually (leaving aside the performance advantage of index-based access on von Neumann machines), a List can be viewed as a special Map where the keys are indices.&lt;/p&gt;

&lt;p&gt;Lisp’s core invention—the S-expression—can be viewed as a general Tree structure, and Lisp provides built-in mechanisms such as macros to manipulate these Trees. However, Lisp does not establish the concept of Tree-level Delta. XLang can be seen as a further development of the general S-expression handling mechanism.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The various language features provided by mainstream languages can be regarded as rules for constructing new Maps in a Map-based structural space. XLang’s innovation is choosing to extend Map structures into Tree structures, then rethinking software structural construction on Tree foundations. That is, it generalizes the structural construction formula to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tree = Tree x-extends Tree&amp;lt;Tree&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Extending Map to Tree implies that the extends operation between Maps must also be extended to the x-extends operation on Trees.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clearly, a Map is a special case of a Tree; every node in a Tree can be viewed as a Map: &lt;code&gt;Tree = Map + Nested&lt;/code&gt;. Thus, the formula above is indeed a generalization of the &lt;code&gt;Map extends Map&amp;lt;Map&amp;gt;&lt;/code&gt; construction model. From another perspective, a Tree can be constructed by nesting multiple Maps; Map is therefore more basic and fine-grained. Is it necessary to emphasize Tree structures? Won’t all operations on Trees ultimately decompose into operations on the Map at each level?&lt;/p&gt;

&lt;p&gt;XLang’s answer is: software structural space (and its construction rules) built on more complex Tree structures cannot be trivially reduced to a Map-based structural space. In other words, we encounter a “whole &amp;gt; sum of parts” situation: the holistic regularities of Tree construction lose some critical information when decomposed into Map construction regularities.&lt;/p&gt;

&lt;p&gt;To truly understand XLang’s innovation, one must understand the next-generation software construction theory behind its design: Reversible Computation. Reversible Computation explicitly introduces the concepts of inverse elements and Delta, pointing out that a full state is a special case of Delta (A = 0 + A). We must rebuild all our understanding of the software world on the concept of Delta (including inverse elements). Reversible Computation proposes a general Turing-complete software construction formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; App = Delta x-extends Generator&amp;lt;DSL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The XLang language implements this technical strategy at the programming language level.&lt;/p&gt;

&lt;p&gt;For an introduction to Reversible Computation, see my WeChat articles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/canonical/reversible-computation-a-next-generation-theory-for-software-construction-27fk"&gt;Reversible Computation: Next-Generation Software Construction Theory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/canonical/a-theoretical-analysis-of-reversible-computation-for-programmers-2feb"&gt;A Discourse on Reversible Computation for Programmers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/canonical/a-supplementary-analysis-of-reversible-computation-theory-for-programmers-2bd3"&gt;Addendum to A Discourse on Reversible Computation for Programmers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/canonical/a-clarification-of-the-delta-concept-for-programmers-using-git-and-docker-as-examples-33gl"&gt;Dissecting the Concept of Delta for Programmers, with Git and Docker as examples&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;According to Reversible Computation, the special nature of Tree structures lies in their correspondence to a global coordinate system: every node and attribute on the tree has a unique xpath.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/tasks/task[name='test']/@name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The xpath above indicates the “name” attribute of the child node named “test” under the “tasks” node.&lt;/p&gt;

&lt;p&gt;First, let’s clarify the role of the coordinate system: every value of business interest has a unique coordinate in the coordinate system, enabling reading and modification by that coordinate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value = get(path);
set(path,value);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue with Map structures is that they provide only two levels of coordinates: the first level locates the Map itself, and the second level locates the property or method within the Map. This simple coordinate system fails to achieve precise distinctions at the business level. For example:&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;class&lt;/span&gt; &lt;span class="nc"&gt;Dialog&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;title&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="nc"&gt;Button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;actions&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="nc"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;body&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;A Dialog object has a set of action buttons. If we want to locate the “Submit” button and change its label property to “Confirm,” there is no convenient, intuitive way to locate it in most languages. If we want to customize a Dialog used only in a specific scenario (e.g., adding a property), AOP (Aspect Oriented Programming) in general-purpose languages cannot achieve it, because AOP’s locator system is type-based. In XLang, we can directly write:&lt;br&gt;
&lt;/p&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;dialog&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;actions&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"Confirm"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/actionss&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dialog&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Current programming language research generally focuses on type systems. The reason is that different objects can share the same type, making types simpler to study than original object structures and avoiding lifecycle issues. This leads to type systems being inadequate as coordinate systems: objects with the same type cannot be distinguished in the type-system coordinate space, preventing fine-grained Delta construction.&lt;/p&gt;

&lt;p&gt;Some may question why we choose Tree structures instead of graphs. On a graph, if we select a primary observation direction and fix a node as the root, a graph can naturally be converted into a tree. For example, in Linux, everything is a file; many logical relationships are captured in a file tree representation, and with filesystem links, one can effectively represent a graph. “Tree” arises only because we choose a direction of observation on the graph.&lt;/p&gt;

&lt;p&gt;For example, when expressing flowchart-like structures in XML, introducing node id references suffices: &lt;code&gt;&amp;lt;step nextTo="nextStepId" /&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Tree structures unify relative and absolute coordinates: there is only one path from the root to any node, serving as the node’s absolute coordinate. Conversely, within any subtree, each node has a unique path within the subtree, serving as its relative coordinate. Given a node’s relative coordinate and the subtree root’s absolute coordinate, one can easily compute the node’s absolute coordinate (simply concatenate them).&lt;/p&gt;

&lt;h3&gt;
  
  
  1.4 Extensible design necessarily requires a software structural coordinate system
&lt;/h3&gt;

&lt;p&gt;In software development, “extensibility” means meeting new requirements or implementing new features without modifying the original code, by adding extra code or differential information. Abstracting this extension mechanism at a purely mathematical level yields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Y = X + Delta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;X corresponds to the base code we have already written; it does not change with shifting requirements.&lt;/li&gt;
&lt;li&gt;Delta corresponds to additional configuration or differential code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From this perspective, research on extensibility reduces to research on the definition of Delta and its algebra.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X = A + B + C
Y = (A + dA) + (B + dB) + (C + dC)  // Delta is everywhere
   = (A + B + C) + (dA + dB + dC)  // Delta can be aggregated, stored independently of the base code
   = X + Delta // Delta is associative and can be merged independently of the Base
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose X comprises multiple parts A, B, C, … Requirement changes cause modifications scattered throughout the system. If we demand that all these fine-grained changes be managed and stored independently of the original source code (Delta independence), and smaller Deltas can be composed into larger-grained Deltas (Delta composability), then a coordinate system is necessary for precise location. Concretely, when dA is separated from A and stored in an independently existing Delta, it must retain some locator coordinate. Only then, when Delta is combined with X, can it find the original structure A and be properly combined with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.5 Differences between Delta and Patch/plugins
&lt;/h3&gt;

&lt;p&gt;First, Git’s Patch and branch management do not satisfy Delta independence and composability. A Patch is always tied to a specific base code version. Without knowing the base, multiple patches cannot be merged into a larger patch. See &lt;a href="https://mp.weixin.qq.com/s/D5bDNkMJ9gYrFb0uDj2EzQ" rel="noopener noreferrer"&gt;Dissecting the Concept of Delta for Programmers, with Git and Docker as examples&lt;/a&gt; for detailed analysis.&lt;/p&gt;

&lt;p&gt;Second, Delta fundamentally differs from traditional extension points and plugin mechanisms in programming.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X = A + B + C
Y = A + B + D
  = X + (-C) + D
  = X + Delta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delta is not just adding content to the system. If we want coarse-grained, system-level reuse, the corresponding Delta must include subtractive semantics (e.g., removing a Bean defined in a base product). In fact, a coarse-grained Delta is inevitably a mix of additions and removals.&lt;/p&gt;

&lt;p&gt;Also note that plugin mechanisms support only a small number of pre-determined extension points. We cannot customize functionality beyond the original design via plugins. Delta is different: as long as there is a global structural coordinate system, a Delta can be introduced at any point in that coordinate system. Kustomize (in k8s) leverages Delta to achieve comprehensive customization, a concrete application of Reversible Computation; see &lt;a href="https://dev.to/canonical/kustomize-from-the-perspective-of-reversible-computation-45ec"&gt;Kustomize through the lens of Reversible Computation&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The black-box model of components is akin to the worldview of Newtonian mechanics taught in high school—fully mechanistic: a rigid body’s motion is described by a few parameters such as center-of-mass coordinates, size, shape, and orientation; its internal structure is unobservable and irrelevant; interactions occur by direct contact; and shapes must match precisely to form a seamless whole. Even in classical mechanics, more advanced viewpoints transform to Lagrangian or Hamiltonian formulations, essentially moving toward a field-theoretic worldview. A “field” is a ubiquitous coordinate system with a physical quantity specified at every point. A field’s degrees of freedom are infinite yet describable through coordinates—locally measurable at every point. In the field worldview, the core picture is that objects are always immersed in a field (an omnipresent coordinate system), rather than isolated objects interacting pairwise.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1.6 Stable domain structural coordinate systems
&lt;/h3&gt;

&lt;p&gt;Mainstream languages are general-purpose and do not embed domain-specific knowledge. Therefore, their structural coordinate systems are limited to the language’s built-in two-level class-method structure, at most refined with annotations. Below the method level, suitable technical means for coordinate definition are generally lacking.&lt;/p&gt;

&lt;p&gt;When business requirements change, they typically affect code in multiple places. Fundamentally, this is because the structural mapping from problem space to solution space is non-trivial in general business contexts, so the two descriptions cannot align effectively. Borrowing language from AI, we can say: useful features are distributed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In physics, the same physical phenomenon can be described using countless coordinate systems, but there may exist a particular coordinate system tailored to the problem—a “intrinsic coordinate system.” Descriptions in that system can highlight core physical meaning and simplify representation. For example, phenomena on a spherical surface can certainly be described in a general 3D Cartesian system, but spherical coordinates often offer simplification.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reversible Computation suggests building a DSL (Domain Specific Language) tailored to a particular business domain, using it to naturally establish a domain coordinate system, and then expressing Delta in the Delta structural space defined by that coordinate system. Because this domain coordinate system is tailored to the domain problem, it often minimizes Delta expression. For example, if a business-level change requires adding a field, using a general-purpose language might require adjustments in many places (front end, back end, database). With a domain model description, this change may appear as a local field-level modification, with the underlying engine framework automatically translating the domain description into executable logic.&lt;/p&gt;

&lt;p&gt;XLang’s core function is how to quickly define multiple DSLs, then use them as domain structural coordinate systems to implement Delta definition and Delta-based structural generation and transformation.&lt;/p&gt;

&lt;p&gt;XLang fundamentally differs from other languages in that it is a programming language based on Reversible Computation and oriented toward DSL development. General-purpose languages target application development directly—we use them to model businesses and implement logic. Using XLang, we first build one or more DSLs, then use those DSLs to describe the business. XLang makes developing a DSL very inexpensive: at the most basic level, you only need to define an XDef meta-model file with the XDef language, and you automatically get a parser, validator, IDE plugin, visual editor, etc., with rich tooling such as syntax hints, breakpoints, and visual editing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;JetBrains’ MPS (Meta Programming System) also supports first developing a DSL, then using the DSL to describe business. MPS is built on its own foundational language mechanism. Nop platform is a similar low-code development platform and uses XLang at its foundation. However, Nop is guided by Reversible Computation, fundamentally differing in technical route and guiding philosophy from MPS.&lt;br&gt;
The technical development goals are similar, though.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  II. XLang’s concrete syntax design
&lt;/h2&gt;

&lt;p&gt;XLang is designed for Tree structures. Its syntax can be compared to SQL (which targets tabular structures):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SQL&lt;/th&gt;
&lt;th&gt;XLang&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DDL (Data Definition Language)&lt;/td&gt;
&lt;td&gt;XDef meta-model definition syntax&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-redundant tabular data&lt;/td&gt;
&lt;td&gt;Non-redundant tree information structure: XNode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On standardized data structures: SQL Select&lt;/td&gt;
&lt;td&gt;Runtime and compile-time computation on XNode: Xpl/XTransform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Merge and diff for tables: Union/Minus&lt;/td&gt;
&lt;td&gt;Delta computation on Tree structures: x-extends/x-diff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extend SQL via functions and stored procedures&lt;/td&gt;
&lt;td&gt;Extend XLang via Xpl tag libraries and XScript&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;First, since XLang is designed for Tree structures, XML is a very natural syntactic carrier, so an XLang file is typically a valid XML file. But this is not the only choice. Traditional languages emphasize syntactic form, but XLang—based on Reversible Computation—emphasizes that the syntactic form is not important: different syntactic forms are just different presentations of the same information, and reversibly transformable if information-equivalent. XLang can use any syntax that directly expresses tree structures, e.g., JSON, YAML, etc. Lisp’s S-expressions, with some extended attributes, can also serve as an XLang syntactic carrier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Nop platform also implements a bidirectional mapping between Tree structures and Excel files, enabling DSL models to be expressed in Excel without writing parsing/generation code. For example, app.orm.xlsx expresses the ORM DSL and is equivalent to the XML format app.orm.xml.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2.1 Basic syntax structure of XDSL
&lt;/h3&gt;

&lt;p&gt;XLang is Turing-complete, but its design goal is not to be a general-purpose language. Rather, it is a meta-language for rapidly developing new DSLs. While XLang can be used as a glue language, it is primarily used to develop DSLs for use within the Java ecosystem.&lt;/p&gt;

&lt;p&gt;All DSLs developed on XLang share some common syntactic structures; these DSLs are collectively called XDSL.&lt;br&gt;
&lt;/p&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;state-machine&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/state-machine.xdef"&lt;/span&gt;
     &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"base.state-machine.xml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;x:gen-extends&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;app:GenStateMachineDelta1/&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;app:GenStateMachineDelta2/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/x:gen-extends&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;x:post-extends&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;app:PostProcessGeneratedModel&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/x:post-extends&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- x:override=remove means this node is deleted in the final merge result --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;state&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"commit"&lt;/span&gt; &lt;span class="na"&gt;x:override=&lt;/span&gt;&lt;span class="s"&gt;"remove"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;on-exit&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;c:if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"${abc}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;c:log&lt;/span&gt; &lt;span class="na"&gt;info=&lt;/span&gt;&lt;span class="s"&gt;"${xyz}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/c:if&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/on-exit&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/state-machine&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on the example above, all XDSLs support the following syntax:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;x:schema imports an XDef meta-model, similar to JSON Schema, to constrain the DSL’s syntactic structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;x:extends inherits an existing DSL file, merging two DSL models layer by layer as Trees.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;x:override specifies how to merge corresponding nodes during x:extends; x:override=remove signals deletion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;x:gen-extends uses the Xpl template language to dynamically generate multiple Tree nodes, which are then merged one by one via Delta algorithms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;x:post-extends also uses Xpl to dynamically generate multiple Tree nodes but executes at a different stage from x:gen-extends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a DSL wants to embed scripting code, it can directly use the Xpl template language, e.g., for on-exit callbacks.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;model&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"A,B"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;x:gen-extends&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;C/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;D/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/x:gen-extends&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;x:post-extends&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;E/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;F/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/x:post-extends&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/model&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete merge order is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;F -&amp;gt; E -&amp;gt; Model -&amp;gt; D -&amp;gt; C -&amp;gt; B -&amp;gt; A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any XML or JSON file format can incorporate the XLang Delta operation syntax above. For example, we introduced the following decomposition scheme to AMIS (Baidu’s open-source JSON front-end UI definition language):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;x:gen-extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
   &lt;span class="s"&gt;&amp;lt;web:GenPage view="NopSysCheckerRecord.view.xml" page="main"&lt;/span&gt;
        &lt;span class="s"&gt;xpl:lib="/nop/web/xlib/web.xlib" /&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;x:extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;add-form.page.yaml&lt;/span&gt;
   &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Override the existing title defined in add-form.page.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AMIS’s JSON format does not provide decomposition/merge mechanisms, so a complete application’s JSON file can become large and hard to maintain manually. By introducing XLang’s x:gen-extends, we can automatically generate base page structures from View models; within pages, we can also use x:extends to import existing files.&lt;/p&gt;

&lt;p&gt;XLang embeds support for Reversible Computation—i.e., the computation pattern App = Delta x-exends Generator. x:gen-extends and x:post-extends correspond to Generator; they are metaprogramming mechanisms that generate model nodes at compile time as built-in code generators. The x:extends syntax is used to merge model nodes.&lt;/p&gt;

&lt;p&gt;For further reading, see &lt;a href="https://dev.to/canonical/xdsl-general-purpose-domain-specific-language-design-35g6"&gt;XDSL: General Design of Domain-Specific Languages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next-generation low-code platform Nop has already defined multiple DSLs, e.g., Workflow (process model), Rule (rule model), ORM (data model), BeanDefinition (component orchestrations), Batch (batch processing model), Record (binary message model), etc. Typically, you do not need to implement runtime engines for your custom DSL; XLang’s metaprogramming can translate custom DSLs into existing DSLs at compile time or seamlessly integrate multiple DSLs into a new DSL. See the “DSL forest” solution introduced in &lt;a href="https://dev.to/canonical/why-is-springbatch-a-poor-design-2bc"&gt;Why SpringBatch is a Poor Design&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 XDef meta-model definition language
&lt;/h3&gt;

&lt;p&gt;XML has a series of standards like XSD (XML Schema Definition) and XSLT (EXtensible Stylesheet Language), but these standards share DOM-like assumptions—they target text structures where all attributes are strings—making them unsuitable for general Tree structure processing.&lt;/p&gt;

&lt;p&gt;XLang introduces the XDef meta-model definition language to replace XSD. XDef is much simpler and more intuitive than XSD, yet it can provide far stronger structural constraints.&lt;br&gt;
&lt;/p&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;state-machine&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdef.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;state&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"!var-name"&lt;/span&gt; &lt;span class="na"&gt;displayName=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt; &lt;span class="na"&gt;xdef:unique-attr=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;on-exit&lt;/span&gt; &lt;span class="na"&gt;xdef:value=&lt;/span&gt;&lt;span class="s"&gt;"xpl"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/state-machine&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike XSD and JSON Schema, XDef adopts homomorphic design: the meta-model’s structure is nearly identical to the XML format it constrains—simply replace XML node attribute values with type declarations. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;id="!var-name"&lt;/code&gt; means the id attribute must satisfy var-name formatting (no special characters and not starting with a digit). &lt;code&gt;!&lt;/code&gt; indicates non-null.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;lt;on-exit xdef:value="xpl"/&amp;gt;&lt;/code&gt; means the content of the on-exit node follows the Xpl template language; when reading the model, it is automatically parsed into an IEvalAction executable function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;xdef:unqiue-attr="id"&lt;/code&gt; declares the current node can appear multiple times as a list, and list elements are uniquely identified by the id attribute.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that the XDef meta-model definition language is itself defined by xdef.xdef. That is, state-machine.xml is a DSL whose syntax is constrained by the state-machine.xdef meta-model; state-machine.xdef’s root node has &lt;code&gt;x:schema='/nop/schema/xdef.xdef'&lt;/code&gt;, meaning this meta-model file is constrained by xdef.xdef; ultimately, xdef.xdef is constrained by itself, forming a closed loop.&lt;/p&gt;

&lt;p&gt;The shared XDSL syntax of all domain-specific languages is defined by the xdsl.xdef meta-model. The IDEA plugin automatically recognizes syntax like x:extends and x:gen-extends per xdsl.xdef, offering features like syntax hints and file navigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3 Xpl template language
&lt;/h3&gt;

&lt;p&gt;XLang needs a template language for compile-time code generation, but instead of using popular templating systems like Velocity or FreeMarker, it designs a new Xpl template language.&lt;/p&gt;

&lt;p&gt;Xpl is Turing-complete and provides nodes such as c:for, c:if, c:choose, c:break, and c:continue.&lt;br&gt;
&lt;/p&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;c:for&lt;/span&gt; &lt;span class="na"&gt;var=&lt;/span&gt;&lt;span class="s"&gt;"num"&lt;/span&gt; &lt;span class="na"&gt;items=&lt;/span&gt;&lt;span class="s"&gt;"${numbers}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Check if the number is 7 --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;c:if&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"${num == 7}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Encountered number 7; stop iteration.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c:break&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Break out of the loop --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/c:if&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Use c:choose to determine odd/even --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;c:choose&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;when&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"${num % 2 == 0}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;${num} is even.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/when&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;otherwise&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;${num} is odd.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/otherwise&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/c:choose&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/c:for&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Xpl templates embed XScript expressions via \${expr}. Xpl also provides a dedicated c:script node to execute XScript statements.&lt;br&gt;
&lt;/p&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;c:script&amp;gt;&lt;/span&gt;
  import my.MyDSLParser;
  let model = new MyDSLParser().parseFromNode(path);
&lt;span class="nt"&gt;&amp;lt;/c:script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;XScript’s syntax is similar to JavaScript but adds extensions, e.g., import statements can reference Java classes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mutual embedding of XML template language and expression syntax
&lt;/h4&gt;

&lt;p&gt;XLang does not use JSX to implement XML-like syntax; instead, it retains XML syntax while extending JavaScript’s Template expression syntax.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;xpl&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;my:MyTag a='&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' /&amp;gt;`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Equivalent to:&lt;br&gt;
&lt;/p&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;my:MyTag&lt;/span&gt; &lt;span class="na"&gt;a=&lt;/span&gt;&lt;span class="s"&gt;'${data}'&lt;/span&gt; &lt;span class="na"&gt;xpl:return=&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;c:script&amp;gt;&lt;/span&gt;
  const y = result + 3;
&lt;span class="nt"&gt;&amp;lt;/c:script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;XLang changes JavaScript’s Template expression parsing, treating the content between backticks as a string to be parsed at compile time, rather than an Expression list. This enables XLang to extend support to more DSL formats, e.g., introducing C#-like LINQ syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;linq&lt;/span&gt; &lt;span class="s2"&gt;`select sum(amount) from myList where status &amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Multiple output modes
&lt;/h4&gt;

&lt;p&gt;Unlike typical template languages, Xpl is specially optimized for compile-time code generation. Typical templates output text directly; when used for code generation, original code locations are lost, prompting use of SourceMap mechanisms to record mappings between generated and original code. Xpl takes a different approach by introducing multiple output modes. For compile-time generation, use outputMode=node to output XNode nodes rather than text.&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;class&lt;/span&gt; &lt;span class="nc"&gt;XNode&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;SourceLocation&lt;/span&gt; &lt;span class="n"&gt;loc&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;tagName&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;ValueWithLocation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attributes&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="nc"&gt;XNode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;ValueWithLocation&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;XNode&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ValueWithLocation&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;SourceLocation&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;value&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;XNode records source locations of attributes and nodes and changes attribute and content value types to Object, overcoming XML’s text-doc-only design limitation to better express complex business object structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4 Extensible syntax
&lt;/h3&gt;

&lt;p&gt;Like Lisp, XLang’s syntax can be extended via macro functions and tag functions. Use &lt;code&gt;&amp;lt;c:lib&amp;gt;&lt;/code&gt; to import new syntactic nodes and implement structural transformation via macros inside the imported library.&lt;br&gt;
&lt;/p&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;c:lib&lt;/span&gt; &lt;span class="na"&gt;from=&lt;/span&gt;&lt;span class="s"&gt;"/nop/core/xlib/biz.xlib"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;biz:Validator&lt;/span&gt; &lt;span class="na"&gt;fatalSeverity=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
               &lt;span class="na"&gt;obj=&lt;/span&gt;&lt;span class="s"&gt;"${entity}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;check&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"checkTransferCode"&lt;/span&gt; &lt;span class="na"&gt;errorCode=&lt;/span&gt;&lt;span class="s"&gt;"test.not-transfer-code"&lt;/span&gt;
           &lt;span class="na"&gt;errorDescription=&lt;/span&gt;&lt;span class="s"&gt;"The scanned code is not a transfer code."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;eq&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"entity.flowMode"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/check&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/biz:Validator&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;biz:Validator&lt;/a&gt; introduces a validation DSL. During compilation, the Validator tag parses node content via macros, translating it into XLang Expressions for execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  III. XLang application example: Delta-based component model
&lt;/h2&gt;

&lt;p&gt;Any software practice involving Delta can follow the technical route of Reversible Computation. In many cases, XLang can directly implement Delta merging and decomposition, completely avoiding the need to introduce Delta concepts in the runtime engine and thereby simplifying runtime.&lt;/p&gt;

&lt;p&gt;Here is an example in the component model of a front-end low/no-code platform.&lt;/p&gt;

&lt;p&gt;Low/no-code platforms essentially construct nested compositions of components via visual interfaces. But component encapsulation often struggles in practice: encapsulated components may not meet needs directly, while writing entirely new components from scratch is too costly. The UIOTOS no-code platform proposes “page inheritance.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz05zrqfti8wqrp4m2qo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz05zrqfti8wqrp4m2qo.webp" alt="uiotos" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Specifically, UIOTOS can import an existing page as a base page, then overlay properties at the upper level to override properties of the lower-level page. See the &lt;a href="https://www.yuque.com/liuhuo-nc809/uiotos/fa6vnvggwl9ubpwg#rsHSa" rel="noopener noreferrer"&gt;UIOTOS documentation&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;To implement this feature, UIOTOS made numerous special designs and introduced substantial inheritance-related code into the runtime engine. With XLang, Delta computation can be fully compressed into compile time; the runtime engine only needs to understand ordinary component structures without any Delta decomposition/merging knowledge.&lt;br&gt;
&lt;/p&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;component&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"component.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;import&lt;/span&gt; &lt;span class="na"&gt;from=&lt;/span&gt;&lt;span class="s"&gt;"comp:MyComponent/1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"MyComponent"&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"comp:MyComponent/1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;state&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;a&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/state&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;props&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;prop&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;x:override=&lt;/span&gt;&lt;span class="s"&gt;"remove"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;prop&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/props&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"SubComponent"&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"ss"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;prop&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ss"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;x:override=&lt;/span&gt;&lt;span class="s"&gt;"merge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Here you can show only the Delta adjustments

      &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"a.form.xml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;actions&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ss"&lt;/span&gt; &lt;span class="na"&gt;x:id=&lt;/span&gt;&lt;span class="s"&gt;"ss"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/actions&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;MyComponent/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;MyComponentEx/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The template section of a Component expresses how to compose subcomponents.&lt;/li&gt;
&lt;li&gt;You can import existing components via the import syntax or define local components via the component syntax.&lt;/li&gt;
&lt;li&gt;If the Component model is implemented as an XLang XDSL, x:extends can be used to customize based on existing components with Delta—no special design like UIOTOS’s is needed. x:extends suffices to define Delta-based components.&lt;/li&gt;
&lt;li&gt;A local component can itself contain local subcomponents, which can likewise be customized. Delta customization can modify the entire component tree, not just a component class’s properties or methods.&lt;/li&gt;
&lt;li&gt;Delta merging requires each node to have a unique coordinate. If a DSL node lacks usable id or name attributes, use XLang’s built-in x:id attribute. These attributes are automatically removed after Delta merging, so they do not affect the DSL runtime.&lt;/li&gt;
&lt;li&gt;x:extends is executed during model loading; by the time the runtime engine receives the model, all attributes in the x namespace have already been processed and removed. Therefore, the runtime engine needs no knowledge of x:extends at all—strikingly different from UIOTOS’s approach. Delta can be implemented once and for all in a general engine, without introducing special mechanisms for each specific need.&lt;/li&gt;
&lt;li&gt;Reference components via extended virtual file paths like comp:MyComponent/1.0.0; the virtual filesystem can automatically implement tenant isolation and version upgrade isolation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a detailed walkthrough, see the Bilibili video &lt;a href="https://www.bilibili.com/video/BV1ask2YhEfp/" rel="noopener noreferrer"&gt;Discussion with the UIOTOS Author and the Design of a Delta-Enabled Front-End Low-Code Platform&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With XLang, implementing Delta components requires virtually no extra work, and this approach generalizes to all DSL models needing Delta editing. Some developers also introduce similar component models in back-end service application development.&lt;/p&gt;

&lt;p&gt;The low-code platform NopPlatform, designed with Reversible Computation, is open-source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gitee: &lt;a href="https://gitee.com/canonical-entropy/nop-entropy" rel="noopener noreferrer"&gt;canonical-entropy/nop-entropy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;github: &lt;a href="https://github.com/entropy-cloud/nop-entropy" rel="noopener noreferrer"&gt;entropy-cloud/nop-entropy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Development example: &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/docs-en/tutorial/tutorial.md" rel="noopener noreferrer"&gt;docs-en/tutorial/tutorial.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bilibili.com/video/BV14u411T715/" rel="noopener noreferrer"&gt;Principles of Reversible Computation and Introduction to the Nop Platform (Q&amp;amp;A) on bilibili&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nop</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>java</category>
    </item>
    <item>
      <title>Why is SpringBatch a poor design?</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Mon, 05 Jan 2026 14:00:59 +0000</pubDate>
      <link>https://forem.com/canonical/why-is-springbatch-a-poor-design-2bc</link>
      <guid>https://forem.com/canonical/why-is-springbatch-a-poor-design-2bc</guid>
      <description>&lt;p&gt;Explainer video: &lt;a href="https://www.bilibili.com/video/BV1TgBEYYETK/" rel="noopener noreferrer"&gt;https://www.bilibili.com/video/BV1TgBEYYETK/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SpringBatch is currently the most commonly used batch processing framework in the Java ecosystem. In banking, it is frequently used to implement end-of-day settlements and report outputs. SpringBatch originated in 2006 when Accenture open-sourced its proprietary batch processing framework and collaborated with SpringSource (the company behind Spring Framework) to release Spring Batch 1.0. Although SpringBatch’s design has undergone multiple refactorings since then, it exhibits severe design issues today and is unfriendly to performance optimization and code reuse. This article analyzes SpringBatch’s design problems and introduces the design philosophy of next-generation batch frameworks based on the implementation of NopBatch.&lt;/p&gt;

&lt;h2&gt;
  
  
  I. SpringBatch Overview
&lt;/h2&gt;

&lt;p&gt;Below is an introduction to Spring Batch by Zhipu Qingyan AI:&lt;/p&gt;

&lt;p&gt;Spring Batch is a lightweight, comprehensive framework for batch processing. It aims to support enterprise-scale batch processing needs such as large-scale data import, transformation, and migration. Built on the Spring framework, Spring Batch lets developers leverage Spring’s core features, such as dependency injection and declarative transaction management, to create robust batch applications.&lt;/p&gt;

&lt;p&gt;Key features of Spring Batch include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Reusability: Spring Batch provides many reusable components such as ItemReaders, ItemWriters, and ItemProcessors, which can be easily customized and extended.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extensibility: The framework is designed with extensibility in mind, allowing developers to add custom components through a plugin mechanism.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Robustness: Spring Batch supports transaction management to ensure the atomicity and consistency of batch jobs. It also provides skip and retry mechanisms to handle data errors and failures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Declarative development: Complex batch job flows can be defined through configuration and minimal code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parallel processing: Spring Batch supports parallel processing and can accelerate large-scale data processing through partitioning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Launching and scheduling: Spring Batch jobs can be easily integrated into Spring’s task scheduling frameworks (such as Quartz) or launched via the command line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitoring and management: The framework provides tools to monitor and manage job execution, including job status tracking and statistics collection.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Main components include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JobRepository: Used to store data during job execution, including job execution state.&lt;/li&gt;
&lt;li&gt;JobLauncher: Used to launch job runs.&lt;/li&gt;
&lt;li&gt;Job: Represents a complete batch job consisting of a series of steps.&lt;/li&gt;
&lt;li&gt;Step: A single step in a job, which can include read, process, and write operations.&lt;/li&gt;
&lt;li&gt;ItemReader: Responsible for reading data.&lt;/li&gt;
&lt;li&gt;ItemProcessor: Responsible for processing the read data.&lt;/li&gt;
&lt;li&gt;ItemWriter: Responsible for writing processed data to the destination.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09zhq1vb58tg24aeqoe1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09zhq1vb58tg24aeqoe1.png" alt="spring-batch" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Spring Batch’s use cases are widespread, including but not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data synchronization&lt;/li&gt;
&lt;li&gt;Financial and report generation&lt;/li&gt;
&lt;li&gt;Data transformation and migration&lt;/li&gt;
&lt;li&gt;File processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using Spring Batch, enterprises can efficiently handle batch operations, improve data processing efficiency, and ensure system stability and data accuracy.&lt;br&gt;
==========Zhipu Qingyan AI content completed=====================&lt;/p&gt;
&lt;h3&gt;
  
  
  Core interfaces of SpringBatch
&lt;/h3&gt;

&lt;p&gt;SpringBatch’s built-in core logic is the standard read-process-write three-step flow, with corresponding interfaces 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;interface&lt;/span&gt; &lt;span class="nc"&gt;ItemReader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ItemProcessor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;I&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;O&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;O&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="no"&gt;I&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ItemWriter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Chunk&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;chunk&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;To control resource consumption during processing, SpringBatch introduces the concept of Chunk—a unit of data processed at once, controlled via the commit-interval configuration.&lt;br&gt;
For example, the configuration below indicates that every 100 records are processed as one chunk, and each chunk goes through a read-process-write cycle:&lt;br&gt;
&lt;/p&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;batch:job&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"firstBatchJob"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;batch:step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"step1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;batch:tasklet&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;batch:chunk&lt;/span&gt; &lt;span class="na"&gt;reader=&lt;/span&gt;&lt;span class="s"&gt;"itemReader"&lt;/span&gt; &lt;span class="na"&gt;processor=&lt;/span&gt;&lt;span class="s"&gt;"itemProcessor"&lt;/span&gt;
                   &lt;span class="na"&gt;writer=&lt;/span&gt;&lt;span class="s"&gt;"itemWriter"&lt;/span&gt; &lt;span class="na"&gt;commit-interval=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/batch:chunk&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/batch:tasklet&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/batch:step&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/batch:job&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Chunk processing logic
&lt;/h3&gt;

&lt;p&gt;The chunk processing logic in pseudocode roughly reads and processes items one-by-one, collects all returned results, and writes them in a single batch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doInTransaction:
  beforeChunk() // Execute within the transaction
  repeat:
      item = reader.read();
      result = processor.process(item);
      if(result != null)
         outputs.add(result);

  try{
    beforeWrite()
    writer.write(outputs);
    afterWrite()
  }catch(e){
    onWriteError(e,outputs);
  }

afterChunk()  // Execute outside the transaction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Writer that writes a batch of objects enables write optimization at the architectural level, e.g., JDBC batch insert is much faster than single-row inserts.&lt;/p&gt;

&lt;h2&gt;
  
  
  II. Design issues of SpringBatch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 A Reader call should not return only one record
&lt;/h3&gt;

&lt;p&gt;In SpringBatch, a call to ItemReader’s read returns only a single record, making batch read optimizations difficult. Many readers implement bulk reading internally by pages and then return records one-by-one.&lt;/p&gt;

&lt;p&gt;A common implementation looks 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;class&lt;/span&gt; &lt;span class="nc"&gt;JdbcPagingItemReader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ItemReader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;read&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="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;results&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;current&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;pageSize&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doReadPage&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;page&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;current&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;pageSize&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;current&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="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;current&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;next&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&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;results&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;null&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;This design not only forces the Reader to hold temporary state variables, but also makes external batch optimizations difficult. If the Reader returns not simple flat records but complex domain objects, implementing batch loading of attributes requires modifying Reader implementation code, increasing coupling.&lt;/p&gt;

&lt;p&gt;NopBatch uses the IBatchLoader interface for bulk loading, allowing better support for batch read optimizations.&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;IBatchLoader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Load data
     *
     * @param batchSize The maximum number of records to load
     * @return Returning an empty collection indicates all data has been loaded
     */&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;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;batchSize&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;context&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;ul&gt;
&lt;li&gt;Adds a batchSize parameter to explicitly tell the loader how much data is needed, facilitating optimizations by lower layers&lt;/li&gt;
&lt;li&gt;Passes context as a parameter. In SpringBatch, to obtain the context you need to implement interfaces like &lt;code&gt;ChunkListener.beforeChunk(ChunkContext context)&lt;/code&gt;, save the context as a member field, and then access it in the load function—this is overly cumbersome. The IBatchLoader function has complete parameter information and is convenient to implement directly via lambda functions.&lt;/li&gt;
&lt;li&gt;Returns all data required for one Chunk at once, rather than record-by-record, so the Reader no longer needs to maintain complex state variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on list data returned by the Loader, we can naturally and simply batch load related data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;batchSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Batch load other related data. Loaded data can be stored in context,&lt;/span&gt;
&lt;span class="c1"&gt;// or as extended fields in elements of data&lt;/span&gt;
&lt;span class="nf"&gt;batchLoadRelatedData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When processing requires acquiring mutex locks, SpringBatch’s design is also unfriendly. Because ItemReader reads one-by-one, locks cannot be acquired in batches, and the lock acquisition order is hard to control, creating deadlock risks.&lt;br&gt;
In NopBatch, records can first be sorted by a rule (reader is not required to return globally sorted data), and then all required locks can be acquired at once, avoiding deadlocks.&lt;/p&gt;

&lt;p&gt;In summary, SpringBatch’s design carries remnants of Item Orientation, making chunk-level processing feel unnatural.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The concept of Chunk was introduced in Spring 2.0; originally SpringBatch only had the concept of Item.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The ItemWriter interface in SpringBatch 1.0 was defined as:&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;ItemWriter&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;void&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&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;void&lt;/span&gt; &lt;span class="nf"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;FlushFailedException&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;void&lt;/span&gt; &lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;ClearFailedException&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;
  
  
  2.2 A Processor call should not return only one record
&lt;/h3&gt;

&lt;p&gt;SpringBatch’s Processor logic is similar to the map function in functional programming, &lt;code&gt;data.map(a-&amp;gt;b)&lt;/code&gt;, which processes each input record and returns one output record. A natural question arises: why can there be at most one output per processing? Can’t a single processing generate multiple outputs?&lt;/p&gt;

&lt;p&gt;Modern stream processing frameworks have semantics more akin to flatMap in functional programming, &lt;code&gt;data.flatMap(a-&amp;gt;[b])&lt;/code&gt;. That is, processing may yield three results: A. No output B. One output C. Multiple outputs.&lt;/p&gt;

&lt;p&gt;Streaming mode: If one processing can produce multiple outputs, can each output be passed downstream immediately without waiting for all outputs to be generated?&lt;/p&gt;

&lt;p&gt;Inspired by stream processing frameworks, NopBatch defines the following processing interface:&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;IBatchProcessor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Perform a flatMap-like operation
     *
     * @param item     The input data object
     * @param consumer Receives results; may be one or many. It may also not be called if no data is generated.
     * @param context  Context information
     */&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Compose two processors into one
     *
     * @param processor
     * @param &amp;lt;T&amp;gt;
     * @return
     */&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;IBatchProcessor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IBatchProcessor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;processor&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="nc"&gt;CompositeBatchProcessor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processor&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;ul&gt;
&lt;li&gt;&lt;p&gt;IBatchProcessor uses a consumer callback to receive processing results, enabling immediate consumption as outputs are produced&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IBatchProcessor also provides a then function to combine two IBatchProcessors into a single processor, forming a chained style of invocation. This is essentially an application of the Monad concept from functional programming.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.3 Writer should accept Collection-type data
&lt;/h3&gt;

&lt;p&gt;First, the naming ItemWriter in SpringBatch is not ideal. From its name, ItemWriter is used to consume the results produced by the Processor, which conceptually hard-codes the read-process-write pipeline. However, in many scenarios we don’t need to write out results—we only need to consume the input data.&lt;/p&gt;

&lt;p&gt;NopBatch introduces a general BatchConsumer concept, pairing BatchConsumer and BatchLoader as duals; data loaded by BatchLoader is passed directly to BatchConsumer for consumption.&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;IBatchConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * @param items   The collection of objects to process
     * @param context The context object
     */&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;consume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;context&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;With the Consumer interface, the chunk processing flow becomes very simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;batchSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&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="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ProcessingResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;consume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Processor can be viewed as an optional Consumer implementation:&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;BatchProcessorConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IBatchConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;consume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;outputs&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;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt; &lt;span class="nl"&gt;item:&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
            &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;outputs:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;consume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&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;blockquote&gt;
&lt;p&gt;When the Processor runs asynchronously, a ConcurrentLinkedQueue is used to store outputs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unlike NopBatch’s Consumer which accepts Collection-typed data directly, SpringBatch’s Writer accepts a Chunk-typed data structure, defined as:&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;class&lt;/span&gt; &lt;span class="nc"&gt;Chunk&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;W&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Iterable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;W&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="nc"&gt;Serializable&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;W&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&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;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;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;SkipWrapper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;W&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;skips&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;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&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;Exception&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;errors&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;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;userData&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;busy&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;Chunk includes multiple fields, but neither the Processor nor the Reader has direct access to the Chunk structure, causing unnecessary complexity.&lt;/p&gt;

&lt;p&gt;In NopBatch, Loader/Processor/Consumer interfaces all accept the same IBatchChunkContext parameter, enabling coordination among them. Also, items in IBatchConsumer are passed as a Collection; there is no need to enforce List specifically.&lt;/p&gt;

&lt;p&gt;Compare NopBatch’s core interfaces:&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;interface&lt;/span&gt; &lt;span class="nc"&gt;IBatchLoader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;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;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;batchSize&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;chunkCtx&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBatchProcessor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;chunkCtx&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBatchConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;{&lt;/span&gt;
     &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;consume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;chunkCtx&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;Clearly, NopBatch’s three core interfaces are more intuitive; the type returned by the loader directly matches the input type of the consumer, and all three share the IBatchChunkContext context for coordination.&lt;/p&gt;

&lt;p&gt;A good architectural design should reveal its internal organization through its function signatures (type definitions).&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4 Inflexible transaction handling
&lt;/h3&gt;

&lt;p&gt;SpringBatch forces the Read-Process-Write of a chunk to be executed within a single transaction. In the Nop platform, domain entities typically have optimistic lock version fields, and OrmSession caches all entity objects. This allows us to open transactions only during the Write phase, narrowing the transactional scope and reducing the time database connections are held.&lt;/p&gt;

&lt;p&gt;For example, the Processor can run outside a transaction; business failures won’t cause database rollbacks, reducing database load and lock contention. The actual update to the database only happens when &lt;code&gt;OrmSession.flush()&lt;/code&gt; is called. If the optimistic lock version changes at that time, the database rollback can be triggered to avoid conflicts when multiple threads concurrently access the same business data.&lt;/p&gt;

&lt;p&gt;In NopBatch, we can create Consumers that support different transaction scopes based on the transactionScope configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;batchTransactionScope&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;BatchTransactionScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;consume&lt;/span&gt;
                &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;transactionalInvoker&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Open a transaction only during the consume phase.&lt;/span&gt;
    &lt;span class="c1"&gt;// process can be pure logic without database modifications,&lt;/span&gt;
    &lt;span class="c1"&gt;// and reading typically does not need a transaction.&lt;/span&gt;
    &lt;span class="nx"&gt;consumer&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;InvokerBatchConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transactionalInvoker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processor&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// If a processor is set, run it first and then call the consumer;&lt;/span&gt;
    &lt;span class="c1"&gt;// otherwise call the consumer directly.&lt;/span&gt;
    &lt;span class="nx"&gt;IBatchProcessor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;processor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;consumer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BatchProcessorConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;processor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IBatchConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Open a transaction during process and consume phases&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;batchTransactionScope&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;BatchTransactionScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;transactionalInvoker&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;consumer&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;InvokerBatchConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transactionalInvoker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.5 Inflexible failure retry logic
&lt;/h3&gt;

&lt;p&gt;SpringBatch has built-in retry logic: when Processor execution fails, it automatically retries multiple times based on RetryPolicy. However, the Processor often does not complete all per-record business logic. For instance, the Processor may not actually save data, deferring saving until the entire chunk is processed and using JDBC batch writes. In such cases, per-record retry is ineffective.&lt;/p&gt;

&lt;p&gt;In NopBatch, we provide retry at the chunk level. When a chunk fails, we automatically retry the entire chunk, and can optionally retry one-by-one—i.e., treat each item as a separate chunk to retry. Although this loses batch write optimization, it isolates erroneous records.&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;RetryBatchConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IBatchConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;void&lt;/span&gt; &lt;span class="nf"&gt;consume&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;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;IBatchRecordSnapshotBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ISnapshot&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="n"&gt;snapshotBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buildSnapshot&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&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="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;consume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&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;BatchCancelException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;e&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;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Some records may already have been processed and need not be retried&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;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCompletedItemCount&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;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;items&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;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCompletedItems&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;retryConsume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&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="nc"&gt;RetryOnceResult&lt;/span&gt; &lt;span class="nf"&gt;retryConsumeOneByOne&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;retryCount&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;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                         &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSingleMode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;retryItems&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;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;retryException&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="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;fatalError&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="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;R&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;items&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;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;single&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;singletonList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;consumeError&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="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Execute each input record as a small batch exactly once&lt;/span&gt;
                &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;consume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;single&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addCompletedItem&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&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;BatchCancelException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;consumeError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;e&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;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;consumeError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&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;retryPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRetryDelay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retryCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&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;0&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 is retryable&lt;/span&gt;
                    &lt;span class="n"&gt;retryItems&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="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;retryException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&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;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;ul&gt;
&lt;li&gt;&lt;p&gt;The reason chunk-level retries are possible is that the Loader can retrieve all of a chunk’s input data at once. As long as this data is cached, we can invoke the Consumer multiple times. The processing logic of the Processor is encapsulated by BatchProcessorConsumer, so during retry we only need to repeat the consume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If some records already finished successfully and should not be processed again, the consumer can add them into the completedItems collection in the BatchChunkContext after successful processing. When retrying the entire chunk, completed records will be automatically skipped.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  III. Architectural changes in NopBatch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Dynamic listener registration via context
&lt;/h3&gt;

&lt;p&gt;In SpringBatch, if readers/writers/processors need to listen to events like step start/end, the standard approach is to implement the StepExecutionListener interface.&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;class&lt;/span&gt; &lt;span class="nc"&gt;MyProcessor&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ItemProcessor&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;StepExecutionListener&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;beforeStep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StepExecution&lt;/span&gt; &lt;span class="n"&gt;stepExecution&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Before Step: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;stepExecution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStepName&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;ExitStatus&lt;/span&gt; &lt;span class="nf"&gt;afterStep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StepExecution&lt;/span&gt; &lt;span class="n"&gt;stepExecution&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"After Step: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;stepExecution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStepName&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;stepExecution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getExitStatus&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;This causes two problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If these beans are managed by the Spring container, considering concurrency, they need &lt;code&gt;scope=step&lt;/code&gt; instead of global Singleton. SpringBatch’s StepScope implementation is very tricky, requiring the global switch &lt;code&gt;spring.main.allow-bean-definition-overriding&lt;/code&gt;. Meanwhile, Spring disables bean redefinition by default and strongly recommends keeping this switch off. See &lt;a href="https://github.com/spring-projects/spring-batch/issues/3936" rel="noopener noreferrer"&gt;@StepScope not working when XML namespace activated&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If we wrap Reader/Processor/Writer, these listeners may not be automatically discovered by the SpringBatch framework. We must register listeners explicitly. Ideally, registering a Writer should automatically register the listeners it needs, without additional listener configuration in the file.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"step1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tasklet&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;chunk&lt;/span&gt; &lt;span class="na"&gt;reader=&lt;/span&gt;&lt;span class="s"&gt;"itemReader"&lt;/span&gt; &lt;span class="na"&gt;writer=&lt;/span&gt;&lt;span class="s"&gt;"compositeWriter"&lt;/span&gt; &lt;span class="na"&gt;commit-interval=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;streams&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;stream&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"fileItemWriter1"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;stream&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"fileItemWriter2"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/streams&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/chunk&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tasklet&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;beans:bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"compositeWriter"&lt;/span&gt;
                &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.support.CompositeItemWriter"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;beans:property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"delegates"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;beans:list&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;beans:ref&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;"fileItemWriter1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;beans:ref&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;"fileItemWriter2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/beans:list&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/beans:property&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/beans:bean&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the configuration above, we use a CompositeWriter that internally uses two Writers. But SpringBatch doesn’t know this; the compositeWriter doesn’t implement the ItemStream callback interface. To call correctly, we need an extra streams configuration to specify those Writers that implement ItemStream and need to be invoked at appropriate times.&lt;/p&gt;

&lt;p&gt;Compared to front-end framework evolution, SpringBatch’s approach is strikingly similar to traditional front-end Class Components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Logic executed when component is mounted&lt;/span&gt;
    &lt;span class="nf"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component mounted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Logic executed after component updates&lt;/span&gt;
    &lt;span class="nf"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component updated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Logic executed before component is destroyed&lt;/span&gt;
    &lt;span class="nf"&gt;beforeDestroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component will be destroyed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Render function&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Component render logic */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="nx"&gt;Class&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The core idea in both is implementing lifecycle listeners on the component; the framework registers event listeners when creating components, and uses member variables to pass information between callbacks.&lt;/p&gt;

&lt;p&gt;The front-end later made a revolutionary advance by introducing Hooks, abandoning class-based components. See my WeChat article &lt;a href="https://mp.weixin.qq.com/s/-n5On67e3_46zH6ppPlkTA" rel="noopener noreferrer"&gt;Understanding React’s essence through React Hooks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under the Hooks approach, a front-end component degenerates into a reactive render function. Considering one-time initialization, Vue abstracts a component as a constructor for the render function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component mounted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nf"&gt;onUpdated&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component updated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nf"&gt;onBeforeUnmount&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component will be destroyed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Component render logic */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="nx"&gt;Composition&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hooks have the following advantages over traditional class components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Event listener functions can be defined independent of a class structure, making secondary encapsulation easy. For example, onMounted + onUpdated can be wrapped as a reusable useXXX function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple event listeners can pass information via closures, rather than round-tripping through the this pointer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event listeners can be registered dynamically based on input parameters.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key architectural shift here is providing a global, dynamic event registration mechanism, rather than binding event listeners to a specific object pointer as member functions.&lt;/p&gt;

&lt;p&gt;Similar to the Hooks approach, NopBatch changes the core abstraction from a runtime component like IBatchLoader to a factory component IBatchLoaderProvider, which provides a setup method to create an IBatchLoader.&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;IBatchLoaderProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;IBatchLoader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBatchLoader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;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;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;batchSize&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;context&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;Here, setup returns a Loader similar to how Vue’s setup returns a renderer. Vue calls setup once to get a renderer function, which is then invoked multiple times.&lt;br&gt;
Likewise, IBatchLoaderProvider’s setup is called once to return an IBatchLoader, and the loader is invoked multiple times.&lt;/p&gt;

&lt;p&gt;The context object provides methods like onTaskBegin/onTaskEnd to register callbacks.&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;class&lt;/span&gt; &lt;span class="nc"&gt;ResourceRecordLoaderProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractBatchResourceHandler&lt;/span&gt;
        &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IBatchLoaderProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;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;IBatchLoader&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;LoaderState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newLoaderState&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batchSize&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batchChunkCtx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Register a callback to run after a chunk finishes&lt;/span&gt;
            &lt;span class="n"&gt;batchChunkCtx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onAfterComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;onChunkEnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batchChunkCtx&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&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;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batchSize&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&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="nc"&gt;LoaderState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;newLoaderState&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;LoaderState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;state&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;LoaderState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;IResource&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;IRecordInput&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recordIO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;openInput&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&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;recordRowNumber&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;input&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;RowNumberRecordInput&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&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;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Register a callback to close resources when the task finishes&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onAfterComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;IoHelper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;safeCloseObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;input&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;state&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 the example above, we register callbacks via explicitly passed context object functions like onAfterComplete. If we further encapsulate and store the context object in ThreadLocal, the calling style becomes closer to Hooks.&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;BatchTaskGlobals&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s_taskContext&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;NamedThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"batch-task-context"&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;static&lt;/span&gt; &lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="nf"&gt;useTaskContext&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;s_taskContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&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;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;provideTaskContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="n"&gt;taskContext&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;s_taskContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taskContext&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;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onTaskEnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BiConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;useTaskContext&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onAfterComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&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;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onBeforeTaskEnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;useTaskContext&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onBeforeComplete&lt;/span&gt;&lt;span class="o"&gt;(()-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;With BatchTaskGlobals static methods imported, you can write:&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="nc"&gt;IBatchLoader&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ITaskContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
   &lt;span class="n"&gt;init&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;
   &lt;span class="n"&gt;onBeforeTaskEnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taskCtx&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;onChunkBegin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batchChunkCtx&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;Similarly, IBatchProcessor and IBatchConsumer are replaced by IBatchProcessorProvider and IBatchConsumerProvider, with setup returning the actual objects.&lt;/p&gt;

&lt;p&gt;Provider is now a singleton and can be configured via an IoC container without dynamic scopes. No matter how many layers of wrapping there are, you can directly access IBatchTaskContext and dynamically register various event listeners through it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Interestingly, although Hooks were invented by React, Vue’s choice to split logic into setup and render phases is more natural. Otherwise, every invocation site would have to distinguish initialization-time actions from subsequent actions,&lt;br&gt;
which is detrimental to performance optimization and conceptually confusing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3.2 Organize control flow using a general TaskFlow
&lt;/h3&gt;

&lt;p&gt;SpringBatch provides a simple control flow model; you can configure multiple steps and transitions in XML, including parallel execution and conditional jumps.&lt;/p&gt;

&lt;p&gt;For example, the following AI-generated configuration uses split to start two parallel sub-flows, each then executing steps sequentially:&lt;br&gt;
&lt;/p&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;job&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"exampleJob"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.springframework.org/schema/batch"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;split&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"split1"&lt;/span&gt; &lt;span class="na"&gt;task-executor=&lt;/span&gt;&lt;span class="s"&gt;"taskExecutor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;flow&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"step1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;tasklet&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"tasklet1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;next&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"COMPLETED"&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"step2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;next&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"FAILED"&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"step4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"step2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;tasklet&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"tasklet2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;next&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"COMPLETED"&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"step4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/flow&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;flow&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"step3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;tasklet&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"tasklet3"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;next&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"COMPLETED"&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"step4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/flow&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/split&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"step4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tasklet&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"tasklet4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/job&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In SpringBatch, the schedulable unit corresponds to the Tasklet interface; chunk processing is a concrete implementation of Tasklet.&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;ChunkOrientedTasklet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;I&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Tasklet&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;RepeatStatus&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;StepContribution&lt;/span&gt; &lt;span class="n"&gt;contribution&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ChunkContext&lt;/span&gt;                   &lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;Chunk&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;I&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Chunk&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;I&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAttribute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;INPUTS_KEY&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;inputs&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="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunkProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;provide&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contribution&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;buffering&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAttribute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;INPUTS_KEY&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&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;chunkProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contribution&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;chunkProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;postProcess&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contribution&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeAttribute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;INPUTS_KEY&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setComplete&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;RepeatStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;continueIf&lt;/span&gt;&lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEnd&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;Interestingly, early SpringBatch designs only had chunk processing and did not introduce a general Tasklet interface, reflecting a fundamentally insufficient level of abstraction.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tasklet was introduced in SpringBatch 2.0. See &lt;a href="https://docs.spring.io/spring-batch/docs/2.2.x/migration/2.0-highlights.html" rel="noopener noreferrer"&gt;Spring Batch 2.0 Highlights&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;Tasklet&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Given the current context in the form of a step contribution, do whatever is
     * necessary to process this unit inside a transaction. Implementations return
     * {@link RepeatStatus#FINISHED} if finished. If not they return
     * {@link RepeatStatus#CONTINUABLE}. On failure throws an exception.
     * @param contribution mutable state to be passed back to update the current step
     * execution
     * @param chunkContext attributes shared between invocations but not between restarts
     * @return an {@link RepeatStatus} indicating whether processing is continuable.
     * Returning {@code null} is interpreted as {@link RepeatStatus#FINISHED}
     * @throws Exception thrown if error occurs during execution.
     */&lt;/span&gt;
    &lt;span class="nc"&gt;RepeatStatus&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;StepContribution&lt;/span&gt; &lt;span class="n"&gt;contribution&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
           &lt;span class="nc"&gt;ChunkContext&lt;/span&gt; &lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&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;Tasklet is essentially a generic functional interface; to support retry after failure, it uses StepContribution for persistent state storage.&lt;/p&gt;

&lt;p&gt;SpringBatch’s key features emphasize reusability and extensibility, but in practice both are poor. Typically, SpringBatch’s core interfaces and flow orchestration are specific to SpringBatch itself and not applicable to wider scenarios. For example, if we extend SpringBatch’s built-in FlatFileItemReader to parse some data file format, this extension can only be used in that specific SpringBatch context and only through SpringBatch. Attempting to reuse any SpringBatch-related artifacts outside the framework is extremely difficult.&lt;/p&gt;

&lt;p&gt;SpringBatch job configuration can be seen as a very simple and non-general control flow orchestration mechanism; it can only orchestrate batch tasks and cannot serve as a general-purpose control flow engine. In NopBatch, we explicitly separate logic flow orchestration from the batch engine, using the general-purpose NopTaskFlow for orchestration, while NopBatch handles chunk processing within a flow step. This makes both NopTaskFlow and NopBatch designs very straightforward; their implementations are far simpler than SpringBatch (only a few thousand lines of code) and have powerful extensibility. The work done in NopTaskFlow and NopBatch applies to broader contexts.&lt;/p&gt;

&lt;p&gt;NopTaskFlow is a next-generation control flow orchestration framework built from scratch based on Reversible Computation, with a core abstraction of RichFunction supporting Decorator and state persistence. It is high-performance and lightweight (the core is around 3000 lines) and can be used wherever function configuration and decomposition are needed. See &lt;a href="https://dev.to/canonical/the-next-generation-logic-orchestration-engine-noptaskflow-built-from-scratch-4755"&gt;A next-generation orchestration engine written from scratch: NopTaskFlow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An equivalent configuration in NopTaskFlow to the SpringBatch job above:&lt;br&gt;
&lt;/p&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;task&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/task/task.xdef"&lt;/span&gt; &lt;span class="na"&gt;xmlns:x=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdsl.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;parallel&lt;/span&gt; &lt;span class="na"&gt;nextOnError=&lt;/span&gt;&lt;span class="s"&gt;"step4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;sequential&lt;/span&gt; &lt;span class="na"&gt;timeout=&lt;/span&gt;&lt;span class="s"&gt;"3000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;simple&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step1"&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;"tasklet1"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;simple&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step2"&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;"tasklet2"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/sequential&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;simple&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step3"&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;"tasklet3"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/parallel&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;simple&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step4"&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;"tasklet4"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/task&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NopTaskFlow provides rich step types such as parallel, sequential, loop, choose, fork, and each step supports common enhancements like timeout, retry, decorator, catch, when, validator. For example, the configuration below throws a timeout exception if not finished within 3 seconds; if it fails without timing out, it retries 5 times, with each execution wrapped in a transaction.&lt;br&gt;
&lt;/p&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;sequential&lt;/span&gt; &lt;span class="na"&gt;timeout=&lt;/span&gt;&lt;span class="s"&gt;"3000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;retry&lt;/span&gt; &lt;span class="na"&gt;maxRetryCount=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;decorator&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"transaction"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;simple&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step1"&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;"tasklet1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;simple&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step2"&lt;/span&gt; &lt;span class="na"&gt;bean=&lt;/span&gt;&lt;span class="s"&gt;"tasklet2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/sequential&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sequential means execute in order, so there is no need to specify the next step on each step. If step1 finishes without error, step2 runs automatically. This model is very similar to general programming languages and maps more easily to code. Notably, SpringBatch lets all steps share a global variable space plus each step’s persistent variable space, whereas in NopTaskFlow, nested calls form a stack and variable visibility during execution resembles general function calls; nested inner functions can see variables in the parent scope.&lt;/p&gt;

&lt;p&gt;NopTaskFlow also supports directly nesting Xpl template language and XScript scripts.&lt;br&gt;
&lt;/p&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;steps&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;xpl&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;c:script&amp;gt;&lt;/span&gt;
         const isAdmin = svcCtx.userContext.hasRole('admin');
       &lt;span class="nt"&gt;&amp;lt;/c:script&amp;gt;&lt;/span&gt;

       &lt;span class="nt"&gt;&amp;lt;c:choose&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;when&lt;/span&gt; &lt;span class="na"&gt;test=&lt;/span&gt;&lt;span class="s"&gt;"${isAdmin}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;app:AdminService&lt;/span&gt; &lt;span class="na"&gt;arg1=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/when&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;otherwise&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;app:UserService&lt;/span&gt; &lt;span class="na"&gt;arg1=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/otherwise&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/c:choose&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/xpl&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step2"&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"java"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
     import app.MyBuilder;

     const tool = new MyBuilder().build();
     tool.run(arg1);
    &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The core step abstraction in NopTaskFlow corresponds to the following interface:&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;ITaskStep&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ISourceLocationGetter&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Step type
     */&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getStepType&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;Set&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;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getPersistVars&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;isConcurrent&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Input variables required for step execution
     */&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="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ITaskInputModel&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getInputs&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Step execution returns a Map; this corresponds to the data types in the Map
     */&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="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ITaskOutputModel&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getOutputs&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Concrete execution action
     *
     * @param stepRt All internal state during step execution is saved in stepState,
     *               based on which breakpoint restart can be implemented.
     * @return May return synchronous or asynchronous objects, and dynamically decide the next step.
     *         If the return value is CompletionStage, the caller waits for async completion,
     *         during which execution can be canceled via cancelToken.
     */&lt;/span&gt;
    &lt;span class="nc"&gt;TaskStepReturn&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;ITaskStepRuntime&lt;/span&gt; &lt;span class="n"&gt;stepRt&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;ITaskStep provides a far more complete abstraction than SpringBatch’s Tasklet. For instance, ITaskStep has built-in cancel capability; you can call &lt;code&gt;taskRuntime.cancel&lt;/code&gt; or &lt;code&gt;stepRt.cancel&lt;/code&gt; to cancel the current flow at any time. Each step’s inputs configure the names and types of input parameters, and outputs configure the names and types of results, making TaskStep directly map to function declarations in general programming languages.&lt;br&gt;
&lt;/p&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;xpl&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"step1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"int"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;x + 1&lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/input&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"int"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;y + 2&lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/input&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;output&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"RESULT"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"int"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
    return a + b
  &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/xpl&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above is equivalent to the following function call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;step1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;RESULT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;RESULT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;step1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.3 Partitioned parallel processing with work sharing
&lt;/h3&gt;

&lt;p&gt;SpringBatch provides a mechanism to split data into partitions and assign them to slave steps for parallel processing. The main steps and components are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define a Partitioner:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The Partitioner divides the data into multiple partitions. Each partition contains part of the data, and stores this partition information in the ExecutionContext.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Configure the Master Step:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The Master Step manages partitions and assignments. It uses the Partitioner to generate partitions and assigns each partition to slave steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Configure Slave Steps:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Slave steps handle the partitioned data assigned to them. Each slave step can run in parallel, improving efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Task Executor:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The task executor runs slave steps in parallel. Different executors such as SimpleAsyncTaskExecutor or ThreadPoolTaskExecutor can be configured to achieve parallelism.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these steps, Spring Batch can split large tasks into small tasks and process them in parallel, improving efficiency and performance.&lt;br&gt;
&lt;/p&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;batch:job&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"partitionedJob"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;batch:step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"masterStep"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;batch:partition&lt;/span&gt; &lt;span class="na"&gt;step=&lt;/span&gt;&lt;span class="s"&gt;"slaveStep"&lt;/span&gt; &lt;span class="na"&gt;partitioner=&lt;/span&gt;&lt;span class="s"&gt;"rangePartitioner"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;batch:handler&lt;/span&gt; &lt;span class="na"&gt;grid-size=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt; &lt;span class="na"&gt;task-executor=&lt;/span&gt;&lt;span class="s"&gt;"taskExecutor"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/batch:partition&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/batch:step&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/batch:job&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Slave step definition --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;batch:step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"slaveStep"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;batch:tasklet&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;batch:chunk&lt;/span&gt; &lt;span class="na"&gt;reader=&lt;/span&gt;&lt;span class="s"&gt;"itemReader"&lt;/span&gt; &lt;span class="na"&gt;processor=&lt;/span&gt;&lt;span class="s"&gt;"itemProcessor"&lt;/span&gt;
                  &lt;span class="na"&gt;writer=&lt;/span&gt;&lt;span class="s"&gt;"itemWriter"&lt;/span&gt; &lt;span class="na"&gt;commit-interval=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/batch:tasklet&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/batch:step&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SpringBatch’s partitioning design effectively partitions reading from the Reader onward, with each slave step using its dedicated Reader. If one partition has a particularly large amount of data, threads in other partitions cannot help once they finish and go idle.&lt;br&gt;
In real-world business, finer-grained partitioning is often possible. For example, in banking you typically only need to ensure ordering for a single account’s data, while different accounts can be processed in parallel. NopBatch provides a more flexible partitioned parallel processing strategy.&lt;/p&gt;

&lt;p&gt;First, BatchTask in NopBatch has a concurrency parameter specifying the number of parallel threads. IBatchChunkContext stores concurrency and current thread index, so during processing we know how many threads are in total and which index the current thread has, enabling internal partitioning operations.&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;interface&lt;/span&gt; &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getConcurrency&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getThreadIndex&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;class&lt;/span&gt; &lt;span class="nc"&gt;BatchTask&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IBatchTask&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;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;executeAsync&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
      &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;future&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;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

      &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fireTaskBegin&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

      &lt;span class="c1"&gt;// Multiple threads can execute concurrently. loader/processor/consumer must be thread-safe&lt;/span&gt;
      &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;[]&lt;/span&gt; &lt;span class="n"&gt;futures&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;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;concurrency&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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&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="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;concurrency&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;executeChunkLoop&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;

      &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;whenComplete&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="n"&gt;onTaskComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;meter&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&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;future&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;

   &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;executeChunkLoop&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IBatchTaskContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                            &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;threadIndex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;future&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;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

        &lt;span class="n"&gt;executor&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;BatchTaskGlobals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;provideTaskContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&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="k"&gt;do&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;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isCancelled&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BatchCancelException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ERR_BATCH_CANCEL_PROCESS&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

                    &lt;span class="nc"&gt;IBatchChunkContext&lt;/span&gt; &lt;span class="n"&gt;chunkContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newChunkContext&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setConcurrency&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concurrency&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setThreadIndex&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;threadIndex&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;processChunk&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunkContext&lt;/span&gt;&lt;span class="o"&gt;)!=&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CONTINUE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

                &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&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="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;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completeExceptionally&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;BatchTaskGlobals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeTaskContext&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;return&lt;/span&gt; &lt;span class="n"&gt;future&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;Unlike SpringBatch’s grid partitions, NopBatch’s parallel step processing shares the Loader, Processor, and Consumer, passing concurrency and threadIndex via IBatchChunkContext.&lt;/p&gt;

&lt;p&gt;NopBatch includes a PartitionDispatchLoaderProvider that provides flexible partitioned loading. During setup, it starts several loading threads to actually read data, and in memory it computes a hash value (0–32767) based on business key information. Each hash corresponds to a micro-queue whose records must be processed in order. All micro-queues are managed uniformly in a PartitionDispatchQueue.&lt;/p&gt;

&lt;p&gt;When a processing thread loads chunk data, it can fetch from micro-queues in the PartitionDispatchQueue. After fetching data, it marks the corresponding micro-queue as in use to prevent other threads from processing the same queue. After the chunk finishes, the onChunkEnd callback releases the micro-queue.&lt;br&gt;
&lt;/p&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;batch&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loader&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- First use OrmReader to read data, then dispatcher distributes to partition task queues,
             one queue per partitionIndex --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;orm-reader&lt;/span&gt; &lt;span class="na"&gt;entityName=&lt;/span&gt;&lt;span class="s"&gt;"DemoIncomingTxn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;/orm-reader&amp;gt;&lt;/span&gt;

        &lt;span class="c"&gt;&amp;lt;!-- After the reader obtains items, it calls the afterLoad callback to post-process the result --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;afterLoad&amp;gt;&lt;/span&gt;
            for(let item of items){
                item.make_t().partitionIndex = ...; // Dynamically compute partitionIndex
            }
        &lt;span class="nt"&gt;&amp;lt;/afterLoad&amp;gt;&lt;/span&gt;

        &lt;span class="c"&gt;&amp;lt;!-- partitionIndex is computed in afterLoad and does not exist in the raw data.
             Therefore SpringBatch’s grid configuration cannot handle this case
         --&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;dispatcher&lt;/span&gt; &lt;span class="na"&gt;loadBatchSize=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;partitionIndexField=&lt;/span&gt;&lt;span class="s"&gt;"_t.partitionIndex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/dispatcher&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/loader&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/batch&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;All entities in the Nop platform provide a make_t() function that returns a Map for storing custom temporary attributes. This design also aligns with Reversible Computation’s principle that each local unit has extensibility.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The NopBatch DSL snippet above reads data from the DemoIncomingTxn table via OrmReader, then dispatches items to different queues based on the entity attribute &lt;code&gt;_t.partitionIndex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In SpringBatch, each thread corresponds to one partition, and the number of partitions equals the number of threads. In NopBatch, the actual maximum number of partitions is 32768, which is far greater than the number of parallel threads and far fewer than the number of domain entities, ensuring balanced partitions without maintaining excessive queues in memory.&lt;/p&gt;

&lt;p&gt;If you need parallel step-level processing similar to SpringBatch, you can use fork or fork-n step configurations in NopTaskFlow.&lt;br&gt;
&lt;/p&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;fork&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"processFile"&lt;/span&gt; &lt;span class="na"&gt;var=&lt;/span&gt;&lt;span class="s"&gt;"fileName"&lt;/span&gt; &lt;span class="na"&gt;aggregateVarName=&lt;/span&gt;&lt;span class="s"&gt;"results"&lt;/span&gt;
      &lt;span class="na"&gt;executor=&lt;/span&gt;&lt;span class="s"&gt;"nop-global-worker"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;producer&amp;gt;&lt;/span&gt;
       return ["a.dat","b.dat"]
     &lt;span class="nt"&gt;&amp;lt;/producer&amp;gt;&lt;/span&gt;

     &lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- The context contains a variable named fileName --&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;

     &lt;span class="nt"&gt;&amp;lt;aggregator&amp;gt;&lt;/span&gt;
       &lt;span class="c"&gt;&amp;lt;!-- An optional aggregation action executed after all forked steps finish --&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/aggregator&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/fork&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The producer in a fork step computes a list dynamically, and a separate step instance is started for each element.&lt;/p&gt;

&lt;p&gt;OrmReader and JdbcReader in NopBatch DSL both support partitionIndexField; if specified along with a partitionRange parameter, a partition filter condition is automatically added.&lt;br&gt;
&lt;/p&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;batch&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loader&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;orm-reader&lt;/span&gt; &lt;span class="na"&gt;entityName=&lt;/span&gt;&lt;span class="s"&gt;"MyEntity"&lt;/span&gt; &lt;span class="na"&gt;partitionIndexField=&lt;/span&gt;&lt;span class="s"&gt;"partitionIndex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;filter&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;eq&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/orm-reader&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/loader&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/batch&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass partitionRange when invoking the batch task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;batchTaskContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPartitionRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IntRangeBean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above configuration automatically adds a partition filter condition, producing the following SQL at runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;
&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partitionIndex&lt;/span&gt; &lt;span class="k"&gt;between&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  IV. The DSL Forest: NopTaskFlow + NopBatch + NopRecord + NopORM
&lt;/h2&gt;

&lt;p&gt;Although SpringBatch claims declarative development, its declarative approach relies on Spring IoC’s limited bean-wiring descriptions; a large amount of business-specific logic still must be coded in Java, and there is no complete fine-grained declarative batch model. Conversely, if SpringBatch were to propose a domain-specific model dedicated to batch processing, it would be hard to ensure extensibility and could constrain applicability.&lt;/p&gt;

&lt;p&gt;NopBatch’s solution is characteristic of the Nop platform—a DSL forest: solve problems by reusing a set of seamlessly nested DSLs designed for different local domains, rather than relying on a single, monolithic, batch-specific DSL. For batch processing, we define a minimal NopBatch batch model that abstracts the domain-specific chunk processing logic and provides supporting utility classes like PartitionDispatcherQueue. At a broader orchestration level, we reuse NopTaskFlow. NopTaskFlow has no batch-specific knowledge, nor does its engine require any internal changes to integrate with NopBatch; metaprogramming eliminates friction between the two.&lt;/p&gt;

&lt;p&gt;For example, in file parsing, SpringBatch provides a FlatFileItemReader that can be configured to parse simple-structured data files.&lt;br&gt;
&lt;/p&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;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"flatFileItemReader"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.file.FlatFileItemReader"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"resource"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"classpath:data/input.dat"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"lineMapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.file.mapping.DefaultLineMapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"lineTokenizer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.file.transform.FixedLengthTokenizer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"names"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"length,name,price,quantity"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"columns"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;list&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.file.transform.Range"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.file.transform.Range"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.file.transform.Range"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"25"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"30"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.file.transform.Range"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"31"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;constructor-arg&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"36"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/list&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"fieldSetMapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"targetType"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"com.example.MyRecord"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clearly, this configuration is very verbose, and it is specific to Spring Batch’s file Reader. Outside of Spring Batch, if we want to parse the same data file, it’s generally hard to directly reuse the configuration information from Spring Batch.&lt;/p&gt;

&lt;p&gt;On the Nop platform, we define a Record model dedicated to parsing and generating data message formats. It is not designed exclusively for batch file parsing; rather, it can be used anywhere message parsing and generation are needed. It is a general declarative development mechanism and far more powerful than Spring Batch’s FlatFile configuration.&lt;br&gt;
&lt;/p&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;task&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/task/task.xdef"&lt;/span&gt; &lt;span class="na"&gt;xmlns:x=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdsl.xdef"&lt;/span&gt;
      &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"/nop/task/lib/common.task.xml,/nop/task/lib/batch-common.task.xml"&lt;/span&gt;
      &lt;span class="na"&gt;xmlns:record=&lt;/span&gt;&lt;span class="s"&gt;"record"&lt;/span&gt; &lt;span class="na"&gt;xmlns:task=&lt;/span&gt;&lt;span class="s"&gt;"task"&lt;/span&gt; &lt;span class="na"&gt;x:dump=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"bizDate"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"LocalDate"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;record:file-model&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"SimpleFile"&lt;/span&gt; &lt;span class="na"&gt;binary=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;fields&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"String"&lt;/span&gt; &lt;span class="na"&gt;length=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt; &lt;span class="na"&gt;codec=&lt;/span&gt;&lt;span class="s"&gt;"FLS"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"product"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"String"&lt;/span&gt; &lt;span class="na"&gt;length=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt; &lt;span class="na"&gt;codec=&lt;/span&gt;&lt;span class="s"&gt;"FLS"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"double"&lt;/span&gt; &lt;span class="na"&gt;codec=&lt;/span&gt;&lt;span class="s"&gt;"f8be"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"quantity"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"int"&lt;/span&gt; &lt;span class="na"&gt;codec=&lt;/span&gt;&lt;span class="s"&gt;"s4be"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/fields&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/record:file-model&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt; &lt;span class="na"&gt;customType=&lt;/span&gt;&lt;span class="s"&gt;"batch:Execute"&lt;/span&gt; &lt;span class="na"&gt;useParentScope=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
                &lt;span class="na"&gt;xmlns:batch=&lt;/span&gt;&lt;span class="s"&gt;"/nop/batch/xlib/batch.xlib"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;batch:task&lt;/span&gt; &lt;span class="na"&gt;taskName=&lt;/span&gt;&lt;span class="s"&gt;"test.loadData"&lt;/span&gt; &lt;span class="na"&gt;batchSize=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;saveState=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

                &lt;span class="nt"&gt;&amp;lt;taskKeyExpr&amp;gt;&lt;/span&gt;bizDate&lt;span class="nt"&gt;&amp;lt;/taskKeyExpr&amp;gt;&lt;/span&gt;

                &lt;span class="nt"&gt;&amp;lt;loader&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;file-reader&lt;/span&gt; &lt;span class="na"&gt;filePath=&lt;/span&gt;&lt;span class="s"&gt;"dev:/target/input/${bizDate}.dat"&lt;/span&gt;
                        &lt;span class="na"&gt;fileModelPath=&lt;/span&gt;&lt;span class="s"&gt;"simple.record-file.xlsx"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/loader&amp;gt;&lt;/span&gt;

                &lt;span class="c"&gt;&amp;lt;!-- Multiple processors can be defined; they run in sequence --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;processor&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"processor1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
                        consume(item);
                    &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/processor&amp;gt;&lt;/span&gt;

                &lt;span class="nt"&gt;&amp;lt;processor&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"processor2"&lt;/span&gt; &lt;span class="na"&gt;task:taskModelPath=&lt;/span&gt;&lt;span class="s"&gt;"process-item.task.xml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/processor&amp;gt;&lt;/span&gt;

                &lt;span class="nt"&gt;&amp;lt;consumer&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"all"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;file-writer&lt;/span&gt; &lt;span class="na"&gt;filePath=&lt;/span&gt;&lt;span class="s"&gt;"dev:/target/output/${bizDate}-all.dat"&lt;/span&gt;
                      &lt;span class="na"&gt;record:file-model=&lt;/span&gt;&lt;span class="s"&gt;"SimpleFile"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/consumer&amp;gt;&lt;/span&gt;

                &lt;span class="c"&gt;&amp;lt;!-- Multiple consumers can be defined; use the filter section to consume only a subset of output data --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;consumer&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"selected"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;filter&amp;gt;&lt;/span&gt;
                        return item.quantity &amp;gt; 500;
                    &lt;span class="nt"&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;

                    &lt;span class="nt"&gt;&amp;lt;file-writer&lt;/span&gt; &lt;span class="na"&gt;filePath=&lt;/span&gt;&lt;span class="s"&gt;"dev:/target/output/${bizDate}-selected.dat"&lt;/span&gt;
                       &lt;span class="na"&gt;fileModelPath=&lt;/span&gt;&lt;span class="s"&gt;"simple.record-file.xml"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/consumer&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;/batch:task&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/task&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example above demonstrates how to seamlessly embed the Batch processing model and the Record message format definition within NopTaskFlow.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The NopTaskFlow logic orchestration engine was designed without any built-in knowledge of batch tasks and does not include the Record model.&lt;/li&gt;
&lt;li&gt;Extending NopTaskFlow does not require implementing any extension interfaces inside the NopTaskFlow engine, nor using an internal registration mechanism to register extension steps. This stands in sharp contrast to typical framework designs.&lt;/li&gt;
&lt;li&gt;You only need to inspect the task.xdef metamodel to understand the node structure of the NopTaskFlow logic orchestration model, then use the metaprogramming mechanisms built into the XLang language to implement the extension.&lt;/li&gt;
&lt;li&gt;x:extends="/nop/task/lib/common.task.xml,/nop/task/lib/batch-common.task.xml" introduces base model support. These base models use metaprogramming mechanisms such as x:post-extends to transform the current model structurally at the XNode level. We can introduce compile-time structural transformation rules as needed.&lt;/li&gt;
&lt;li&gt; The customType of an extension node is automatically recognized as an Xpl tag function, and the custom node is transformed into a call to the &lt;a&gt;batch:Execute&lt;/a&gt; tag function.
&lt;/li&gt;
&lt;/ol&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;step&lt;/span&gt; &lt;span class="na"&gt;customType=&lt;/span&gt;&lt;span class="s"&gt;"ns:TagName"&lt;/span&gt; &lt;span class="na"&gt;xmlns:ns=&lt;/span&gt;&lt;span class="s"&gt;"libPath"&lt;/span&gt; &lt;span class="na"&gt;ns:argName=&lt;/span&gt;&lt;span class="s"&gt;"argValue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ns:slotName&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/ns:slotName&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;
will be automatically transformed into

&lt;span class="nt"&gt;&amp;lt;xpl&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ns:TagName&lt;/span&gt; &lt;span class="na"&gt;xpl:lib=&lt;/span&gt;&lt;span class="s"&gt;"libPath"&lt;/span&gt; &lt;span class="na"&gt;argName=&lt;/span&gt;&lt;span class="s"&gt;"argValue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;slotName&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/ns:slotName&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ns:TagName&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/xpl&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other words, customType is a namespaced tag function name. All attributes and child nodes sharing the same namespace become attributes and child nodes of that tag. Although directly using an xpl step is not complex, metaprogramming transformation based on customType can further compress the amount of information expressed, ensuring only the minimal necessary information is specified, and anything derivable is derived automatically.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;a&gt;batch:Execute&lt;/a&gt; tag parses its task node at compile time and constructs an IBatchTask object. At runtime, compile-time variables can be accessed directly without re-parsing.&lt;/li&gt;
&lt;li&gt;All XDSLs automatically support extension attributes and extension nodes. By default, namespaced attributes and nodes do not participate in XDef metamodel validation. Therefore, under the task node you can introduce a custom &lt;a&gt;record:file-model&lt;/a&gt; definition. It will be automatically parsed into a RecordFileMeta model object by the metaprogramming processor brought in via batch-common.task.xml and stored as a compile-time variable.&lt;/li&gt;
&lt;li&gt;The record:file-model attribute on file-reader and file-writer nodes will be recognized and automatically transformed.
&lt;/li&gt;
&lt;/ol&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;file-writer&lt;/span&gt; &lt;span class="na"&gt;record:file-model=&lt;/span&gt;&lt;span class="s"&gt;"SimpleFile"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/file-writer&amp;gt;&lt;/span&gt;
is transformed into

&lt;span class="nt"&gt;&amp;lt;file-writer&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;newRecordOutputProvider&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- In the Xpl template language, #{xx} accesses a compile-time variable --&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;batch-record:BuildRecordOutputProviderFromFileModel&lt;/span&gt;
              &lt;span class="na"&gt;fileModel=&lt;/span&gt;&lt;span class="s"&gt;"#{SimpleFile}"&lt;/span&gt;
                &lt;span class="na"&gt;xpl:lib=&lt;/span&gt;&lt;span class="s"&gt;"/nop/batch/xlib/batch-record.xlib"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/newRecordOutputProvider&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/file-writer&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;#{} is the compile-time expression syntax defined by the XLang language, which lets you access variables set at compile time.&lt;/li&gt;
&lt;li&gt;NopTaskFlow can invoke a BatchTask within a step, and inside the BatchTask’s Processor, we can use the same approach to invoke NopTaskFlow for per-record processing logic.
&lt;/li&gt;
&lt;/ul&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;processor&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"processor2"&lt;/span&gt; &lt;span class="na"&gt;task:taskModelPath=&lt;/span&gt;&lt;span class="s"&gt;"process-item.task.xml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/processor&amp;gt;&lt;/span&gt;

is transformed into
&lt;span class="nt"&gt;&amp;lt;processor&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"processor2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;task:Execute&lt;/span&gt; &lt;span class="na"&gt;taskModelPath=&lt;/span&gt;&lt;span class="s"&gt;"process-item.task.xml"&lt;/span&gt;
                 &lt;span class="na"&gt;inputs=&lt;/span&gt;&lt;span class="s"&gt;"${{item,consume,batchChunkCtx}}"&lt;/span&gt;
                 &lt;span class="na"&gt;xpl:lib=&lt;/span&gt;&lt;span class="s"&gt;"/nop/task/xlib/task.xlib"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/processor&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;A task model can embed the batch model via customType="batch:Execute", and within the batch model’s processor configuration you can embed another task model via task:taskModelPath.&lt;/li&gt;
&lt;li&gt;For database access, NopORM provides a complete ORM model with built-in support for multi-tenancy, soft deletion, field encryption/decryption, flexible transaction handling, relational queries, batch loading, and batch save optimizations. Database read/write can be performed via orm-reader and orm-writer.
&lt;/li&gt;
&lt;/ul&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;batch&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loader&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;orm-reader&lt;/span&gt; &lt;span class="na"&gt;entityName=&lt;/span&gt;&lt;span class="s"&gt;"DemoIncomingTxn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;query&amp;gt;&lt;/span&gt;...query conditions...&lt;span class="nt"&gt;&amp;lt;/query&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/orm-reader&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/loader&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;consumer&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"saveToDb"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;orm-writer&lt;/span&gt; &lt;span class="na"&gt;entityName=&lt;/span&gt;&lt;span class="s"&gt;"DemoTransaction"&lt;/span&gt; &lt;span class="na"&gt;allowUpdate=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;keyFields&amp;gt;&lt;/span&gt;unique key fields&lt;span class="nt"&gt;&amp;lt;/keyFields&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/orm-writer&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/consumer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/batch&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combining multiple domain models such as NopTaskFlow, NopBatch, NopRecord, and NopORM, the Nop platform enables batch jobs to be implemented entirely declaratively during typical business development, without writing Java code.&lt;/p&gt;

&lt;p&gt;Pause here to think: within a single DSL, definitions for tasks, batch tasks, and records all coexist and are seamlessly fused, appearing as one coherent, unified DSL.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How would you achieve this without the Nop platform?&lt;/li&gt;
&lt;li&gt;Can the capability to define DSLs and glue multiple DSLs together be abstracted into a general-purpose capability?&lt;/li&gt;
&lt;li&gt;Does this abstraction impact runtime performance?&lt;/li&gt;
&lt;li&gt;How do you perform breakpoint debugging when multiple DSLs are mixed? Can errors be precisely located in the DSL source?&lt;/li&gt;
&lt;li&gt;How can we rapidly develop a visual designer for such a mixed DSL? Can Excel be used for DSL configuration?&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Command-line Execution
&lt;/h3&gt;

&lt;p&gt;The nop-cli tool provided by the Nop platform can execute logic orchestration tasks directly.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Place DSL files such as app.orm.xml and batch-demo.task.xml under the _vfs directory, and the nop-cli tool will automatically load all model files in the working directory’s virtual file system.&lt;/li&gt;
&lt;li&gt;Execute the logic orchestration task via: java -Dnop.config.location=application.yaml -jar nop-cli.jar run-task v:/batch/batch-demo.task.xml -i="{bizDate:'2024-12-08'}"&lt;/li&gt;
&lt;li&gt;The first argument of run-task is the path to the logic orchestration model file. v: indicates a path under the _vfs virtual file system. You can also pass an OS file path directly.&lt;/li&gt;
&lt;li&gt;The -i argument specifies the input parameters for the orchestration task in JSON format. You can also specify an input data file via -if=filePath, where the file contains a JSON payload.&lt;/li&gt;
&lt;li&gt;Use -Dnop.config.location to specify the configuration file, where database connection passwords and other settings can be configured.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The TestNopCli unit test suite provides test cases such as testBatchGenDemo. You can debug these cases to familiarize yourself with the NopBatch engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  IV. Multiple Representations of DSLs
&lt;/h2&gt;

&lt;p&gt;A fundamental difference between the Nop platform and others is that Nop does not merely embed a few common DSLs. It provides a full set of Language Oriented Programming infrastructure for rapidly building or extending DSLs. Each DSL is not limited to a single form; it can be expressed as Excel, visual editing, JSON, or XML, with free conversion among these forms.&lt;/p&gt;

&lt;p&gt;For example, record-file.register-model.xml defines multiple loaders for the message model:&lt;br&gt;
&lt;/p&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;model&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/register-model.xdef"&lt;/span&gt; &lt;span class="na"&gt;xmlns:x=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdsl.xdef"&lt;/span&gt;
       &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"record-file"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;loaders&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;xdsl-loader&lt;/span&gt; &lt;span class="na"&gt;fileType=&lt;/span&gt;&lt;span class="s"&gt;"record-file.xml"&lt;/span&gt; &lt;span class="na"&gt;schemaPath=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/record/record-file.xdef"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;xlsx-loader&lt;/span&gt; &lt;span class="na"&gt;fileType=&lt;/span&gt;&lt;span class="s"&gt;"record-file.xlsx"&lt;/span&gt; &lt;span class="na"&gt;impPath=&lt;/span&gt;&lt;span class="s"&gt;"/nop/record/imp/record-file.imp.xml"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/loaders&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/model&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration above indicates that files of type xxx.record-file.xml can be parsed into a RecordFileMeta object using the record-file.xdef metamodel. Files of type xxx.record-file.xlsx must be parsed using XlsxObjectLoader according to the structure rules defined in record-file.imp.xml.&lt;/p&gt;

&lt;p&gt;In txn.record-file.xlsx, a fixed-length data file format is defined, including file header, body, and trailer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2mh92clgi93dvtaes8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2mh92clgi93dvtaes8e.png" alt="record-file" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is equivalent to the following configuration:&lt;br&gt;
&lt;/p&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;file&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/record/record-file.xdef"&lt;/span&gt; &lt;span class="na"&gt;xmlns:x=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdsl.xdef"&lt;/span&gt; &lt;span class="na"&gt;binary=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;typeRef=&lt;/span&gt;&lt;span class="s"&gt;"HeaderOObject"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&lt;/span&gt; &lt;span class="na"&gt;typeRef=&lt;/span&gt;&lt;span class="s"&gt;"BodyObject"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;trailer&lt;/span&gt; &lt;span class="na"&gt;typeRef=&lt;/span&gt;&lt;span class="s"&gt;"TrailerObject"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;aggregates&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Aggregate the txnAmount property of each record to obtain the totoalAmount variable, used in the trailer --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;aggregate&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"totalAmount"&lt;/span&gt; &lt;span class="na"&gt;aggFunc=&lt;/span&gt;&lt;span class="s"&gt;"sum"&lt;/span&gt; &lt;span class="na"&gt;prop=&lt;/span&gt;&lt;span class="s"&gt;"txnAmount"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/aggregates&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;types&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"HeaderObject"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;fields&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/fields&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"BodyObject"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;fields&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/fields&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"TrailerObject"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;fields&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/fields&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/types&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/file&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ORM Model
&lt;/h3&gt;

&lt;p&gt;In the /nop-cli/demo/_vfs/app/demo/orm directory, there is a demo app.orm.xml model file showcasing a very interesting NopORM configuration.&lt;br&gt;
&lt;/p&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;orm&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/orm/orm.xdef"&lt;/span&gt; &lt;span class="na"&gt;xmlns:x=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdsl.xdef"&lt;/span&gt;
     &lt;span class="na"&gt;orm:forceDynamicEntity=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;x:dump=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
     &lt;span class="na"&gt;xmlns:orm-gen=&lt;/span&gt;&lt;span class="s"&gt;"orm-gen"&lt;/span&gt; &lt;span class="na"&gt;xmlns:xpl=&lt;/span&gt;&lt;span class="s"&gt;"xpl"&lt;/span&gt; &lt;span class="na"&gt;xmlns:orm=&lt;/span&gt;&lt;span class="s"&gt;"orm"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;x:gen-extends&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Automatically generate orm.xml from orm.xlsx; you can edit visually and see changes take effect immediately --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;orm-gen:GenModelFromExcel&lt;/span&gt; &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"demo.orm.xlsx"&lt;/span&gt; &lt;span class="na"&gt;xpl:lib=&lt;/span&gt;&lt;span class="s"&gt;"/nop/orm/xlib/orm-gen.xlib"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;orm-gen:GenModelFromExcel&lt;/span&gt; &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"demo-delta.orm.xlsx"&lt;/span&gt; &lt;span class="na"&gt;xpl:lib=&lt;/span&gt;&lt;span class="s"&gt;"/nop/orm/xlib/orm-gen.xlib"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/x:gen-extends&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/orm&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96u4c4diie1qnlhvgnx8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96u4c4diie1qnlhvgnx8.png" alt="orm-model" width="800" height="388"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1bjx3ew7tai5d0izipg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1bjx3ew7tai5d0izipg.png" alt="demo-orm-model" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, orm:forceDynamicEntity=true indicates that no entity class code needs to be generated—use dynamic entities directly for ORM mapping. This enables immediate use of ORM entity association queries in batch models without pre-generating code. In the XLang language, dynamic entities can be accessed via property syntax just like regular Java classes, and are used exactly like ordinary entities.&lt;/li&gt;
&lt;li&gt;The second interesting point is that the x:gen-extends section demonstrates metaprogramming-based model generation and a way to implement Delta model merging. This approach is completely generic and requires no extra effort—it is part of the Nop platform’s core capabilities.

&lt;ul&gt;
&lt;li&gt;orm-gen:GenModelFromExcel reads the Excel-format orm.xlsx model file, automatically parses it into an OrmModel object according to the orm.imp.xml import configuration, and then converts the OrmModel object into XNode nodes using the orm.xdef metamodel definition.&lt;/li&gt;
&lt;li&gt;demo-delta.orm.xlsx defines a Delta model. When customizing the demo.orm.xlsx model file, you don’t need to modify the original; simply add a new Delta model file with exactly the same structure (a full model is a special case of the Delta, so no special design is needed for Delta expression).&lt;/li&gt;
&lt;li&gt;The two orm-gen:GenModelFromExcel tag invocations generate two XNode nodes. Per the XLang language specification, multiple nodes generated in the x:gen-extends section are automatically merged using a Delta merge into a single, complete XNode node. x:dump=true causes the runtime to print a detailed merge process and the final merged result to the log.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With the configuration above, you can define both the data model and its Delta in Excel. Modifications to the Excel model are applied to the system immediately. If the system is running online, refreshing the page after modifying the Excel model will reload the ORM model. This is because the Nop platform implements dependency tracking of model resource files at the core: the parsing result of a model depends on all resource files accessed at compile time, and any change in those resources invalidates the model cache.&lt;/p&gt;

&lt;p&gt;Again, think carefully: without the Nop platform, how would you implement similar visual model design and Delta-based model definition?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don’t have to use Excel for the visual designer. For example, you could use the PDManer visual design tool (&lt;a href="https://my.oschina.net/skymozn/blog/10858773" rel="noopener noreferrer"&gt;https://my.oschina.net/skymozn/blog/10858773&lt;/a&gt;) or PowerDesigner to design ORM models; you only need to implement a tag function to convert those models. The Nop platform includes pdman.xlib and PdmModelParser to adapt these two model formats.
&amp;lt;!-- SOURCE_MD5:2e2b9a3bcd57d344e978a3fb72d24719--&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nop</category>
      <category>programming</category>
      <category>springboot</category>
      <category>springbatch</category>
    </item>
    <item>
      <title>Nop Platform Architecture White Paper</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Mon, 05 Jan 2026 13:38:59 +0000</pubDate>
      <link>https://forem.com/canonical/nop-platform-architecture-white-paper-487l</link>
      <guid>https://forem.com/canonical/nop-platform-architecture-white-paper-487l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;First, I asked Gemini to write a prompt for the assessment: "I need an English prompt that asks an expert to act as a world-class software engineering specialist and provide an objective, in-depth analysis and evaluation of the following article."&lt;/p&gt;

&lt;p&gt;Then, I used this prompt to evaluate a series of Nop Platform's technical documents one by one. Finally, I had Gemini write a summary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Executive Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Nop Platform is a full-stack, enterprise-grade application development meta-platform. Based on its original &lt;strong&gt;Generalized Reversible Computation (GRC)&lt;/strong&gt; theory, it systematically replaces a loose collection of mainstream open-source frameworks with approximately &lt;strong&gt;200,000 lines of self-consistent code&lt;/strong&gt;, built from first principles. At its core are a proprietary, XML-based programming language, &lt;strong&gt;XLang&lt;/strong&gt;, and a unified metamodel system, &lt;strong&gt;XDef&lt;/strong&gt;. The essence of GRC theory is captured by its core formula, &lt;code&gt;App = Generator&amp;lt;DSL&amp;gt; ⊕ Δ&lt;/code&gt;, which decomposes the construction of any software into an algebraic superposition of a "standardized skeleton generated from a Domain-Specific Language (DSL)" and a "declarative Delta representing all customization and evolution."&lt;/p&gt;

&lt;p&gt;Instead of viewing it as a monolithic, closed framework comparable to Spring Cloud, the Nop Platform is more accurately positioned as an &lt;strong&gt;architectural entity with a dual identity&lt;/strong&gt;. It is both a &lt;strong&gt;brilliantly designed, modular "capability toolbox,"&lt;/strong&gt; where each core engine (e.g., NopReport, NopRule, NopOrm) can be independently integrated "on-demand" into any Java project. At the same time, it is a &lt;strong&gt;"self-consistent system" governed by a unified theory (GRC)&lt;/strong&gt;, capable of delivering systemic construction and evolution capabilities far exceeding the sum of its parts when all components work in concert.&lt;/p&gt;

&lt;p&gt;My final assessment is that the Nop Platform is an &lt;strong&gt;architectural masterpiece&lt;/strong&gt;. It achieves an outstanding unification of two seemingly contradictory goals: &lt;strong&gt;maximal holistic cohesion&lt;/strong&gt; and &lt;strong&gt;maximal component independence&lt;/strong&gt;. It can serve as a complete, highly synergistic "meta-platform" for building complex systems from scratch, or as a series of independent, high-performance "Swiss Army knives" to be integrated into existing tech stacks to solve specific domain problems. It is best described as a "Lego universe": you can use a single brick, but only with the entire set can you build the most magnificent structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Foreword: The Fundamental Problems Nop Platform Aims to Solve&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before diving into its strengths, it is crucial to understand the challenges Nop Platform confronts. The current mainstream "framework assembly" model, represented by Spring, faces three inherent challenges despite its power:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Explosion of Accidental Complexity&lt;/strong&gt;: Integrating numerous independent open-source components creates significant "integration friction" and "glue code," making system complexity far exceed that of the business itself.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Ecosystem Lock-in&lt;/strong&gt;: Business logic becomes deeply coupled with a specific runtime (like the Spring Bean lifecycle), making tech stack migration costly and difficult to adapt to new technological waves (e.g., GraalVM).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Conflict Between Customization and Evolution&lt;/strong&gt;: For software product companies, there is a fundamental contradiction between customer customization needs and the unified evolution of the core product line. Traditional code-branching strategies easily lead to "maintenance hell."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Nop Platform is a systematic, first-principles-based response to these fundamental problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;I. Key Strengths and Valid Insights&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Architectural Supremacy via Runtime Neutrality&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Transcending Ecosystem Lock-in&lt;/strong&gt;: The most profound innovation of the Nop Platform is the design of its core engines to be &lt;strong&gt;completely decoupled&lt;/strong&gt; from the underlying runtime (e.g., Spring, Quarkus, Solon). This fundamentally solves the "ecosystem-level lock-in" problem faced by mainstream frameworks, including Spring. Once built with the Nop paradigm, business logic and models can be &lt;strong&gt;migrated without loss&lt;/strong&gt; across different infrastructure frameworks, offering an unprecedented degree of strategic freedom.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Portability of Assets&lt;/strong&gt;: All business assets (DSL models, &lt;code&gt;BizModel&lt;/code&gt;, etc.) are no longer "appendages" of a specific framework but become &lt;strong&gt;portable, long-lived digital assets&lt;/strong&gt; that can transcend generations of technology stacks.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GRC Theory: A Powerful and Self-Consistent "Physics" of Software Construction&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;A Unified Model for Evolution&lt;/strong&gt;: The GRC theory and its core formula, &lt;code&gt;App = Generator&amp;lt;DSL&amp;gt; ⊕ Δ&lt;/code&gt;, provide a single mathematical model for both the &lt;strong&gt;initial construction&lt;/strong&gt; and &lt;strong&gt;continuous evolution&lt;/strong&gt; of software. Whether it's greenfield development, feature iteration, or customer customization, all are unified into algebraic operations on "Deltas."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Systematic Governance of Complexity&lt;/strong&gt;: The principle of "minimal information expression," the strict "phase separation" of Load-Time and Run-Time, and the definition of three dimensions of "reversibility" together form a powerful methodology for systematically identifying, isolating, and managing "essential complexity" and "accidental complexity" in software. &lt;strong&gt;The rigor of this theory is embodied in three core principles: 1) Delta-First: Treating "change" as a first-class citizen; 2) Phase Separation: Strictly separating load-time from run-time to ensure a pure and efficient runtime; 3) Three-Dimensional Reversibility: Supporting algebraic reversibility (undoing changes), transformational reversibility (converting between models), and procedural reversibility (post-hoc correction).&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;XLang Language Workbench: An O(1) Cost DSL Factory&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;The Power of Metamodels&lt;/strong&gt;: &lt;code&gt;XDef&lt;/code&gt;, as a unified metamodel definition language, is the key to the platform's "O(N) to O(1) reduction in toolchain cost." Once an &lt;code&gt;xdef&lt;/code&gt; is defined, a new DSL can &lt;strong&gt;automatically inherit&lt;/strong&gt; the capabilities of the entire platform, including IDE support, debugging, Delta customization, and multi-format conversion.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;A Powerful Metaprogramming Engine&lt;/strong&gt;: &lt;code&gt;XPL&lt;/code&gt;, as a homoiconic template engine that operates on structured trees (&lt;code&gt;XNode&lt;/code&gt;) rather than text, provides the platform with extremely powerful, reliable, and full-stack metaprogramming and code generation capabilities.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A Portable Contractual Testing Paradigm&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The platform's &lt;code&gt;NopAutoTest&lt;/code&gt; framework is a core innovation as significant as the GRC theory itself. Through a "record-replay" mechanism, it defines test cases (inputs, outputs, database state changes) as &lt;strong&gt;declarative, portable data snapshots&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  These test assets are completely independent of any specific implementation technology (be it NopORM or MyBatis). This means the entire test suite can be &lt;strong&gt;reused without rewriting&lt;/strong&gt; after a tech stack migration (e.g., from NopORM to JPA); only a new test execution engine for the new stack is needed. This fundamentally solves the massive waste of testing assets during architectural evolution.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A "Batteries-Included" Suite of Enterprise Capabilities&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The platform provides a comprehensive, deeply integrated, and commercial-grade suite of engines out of the box, covering almost every domain required for enterprise applications, including ORM, RPC, GraphQL, rules, reporting, batch processing, and workflow.&lt;/li&gt;
&lt;li&gt;  All these engines are built on GRC theory, seamlessly integrating with each other and sharing unified models, configurations, and security mechanisms. This fundamentally eliminates the vast "impedance and friction" that arises from integrating disparate components in mainstream solutions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A Future-Proof Construction Contract: Scaffolding for the Age of AI Programming&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The design philosophy of the Nop Platform—especially its &lt;strong&gt;homoiconic metamodel (XDef) and declarative DSLs&lt;/strong&gt;—constructs a programming paradigm that is extremely friendly to large AI models. AI is far more reliable at structured "fill-in-the-blanks" tasks (populating a model with business values) than at writing free-form imperative code. The Nop Platform transforms the software development process into a series of precise, structured "fill-in-the-blanks" problems, providing &lt;strong&gt;clear, verifiable "scaffolding" and "guardrails"&lt;/strong&gt; for AI to participate as an assistive developer. This is not just a current engineering advantage but a highly forward-looking strategic position for the future of human-AI collaborative programming.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;II. System-Level and Architectural Implications&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A New, Higher-Level Form of "Lock-in": Paradigm Lock-in&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  While Nop Platform breaks free from runtime-specific lock-in, it introduces a new, deeper form of lock-in: a lock-in to the &lt;strong&gt;GRC ideological paradigm and the XLang implementation tool&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  This is a "benign" lock-in—you are locked into an &lt;strong&gt;extremely efficient mode of production&lt;/strong&gt;. You are reluctant to leave not because you are technically trapped, but because the "productivity-to-cost" ratio of any alternative solution is far lower than that of the Nop Platform. The opportunity cost of migration becomes exceedingly high.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Transfer and Layering of Cognitive Load&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Nop Platform does not "eliminate" complexity; rather, it &lt;strong&gt;masterfully transfers and layers&lt;/strong&gt; it through its architectural design.&lt;/li&gt;
&lt;li&gt;  For &lt;strong&gt;application developers&lt;/strong&gt;, they face an extremely simple, declarative model with a very low cognitive load.&lt;/li&gt;
&lt;li&gt;  For &lt;strong&gt;platform architects&lt;/strong&gt; or &lt;strong&gt;core developers&lt;/strong&gt;, they need to master deep knowledge like GRC theory and XLang metaprogramming, which entails a very high cognitive load. This is a classic design of &lt;strong&gt;"letting the few handle the complexity for the simplicity of the many."&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A Dual-Mode Developer Experience (DX)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Lack of Universal DX&lt;/strong&gt;: The platform strategically forgoes reliance on mainstream developer habits (e.g., JSON/YAML-first) and the general-purpose tool ecosystem, which can cause "ecosystem friction" initially.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Construction of a Deep DX&lt;/strong&gt;: However, through its self-built, deeply integrated toolchain (like &lt;code&gt;NopIdeaPlugin&lt;/code&gt;), it provides a more powerful, "domain-specific" developer experience that is deeply tied to the models (e.g., cross-language navigation, domain-specific validation). This is a trade-off of &lt;strong&gt;"shallow universal convenience for deep domain expertise."&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reshaping the R&amp;amp;D Cost Structure: From "Labor-Intensive" to "Knowledge-Capital-Intensive"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The design philosophy of the Nop Platform essentially transforms the cost structure of software R&amp;amp;D from being traditionally "&lt;strong&gt;labor-intensive&lt;/strong&gt;" (requiring many developers to write repetitive business code) to being "&lt;strong&gt;knowledge-capital-intensive&lt;/strong&gt;." The "capital" here refers to the platform's core engines and the GRC theory—a set of &lt;strong&gt;high-value, reusable "knowledge capital."&lt;/strong&gt; An enterprise needs to make a one-time investment of "intellectual capital" to build or master this core infrastructure. Once established, the development cost (especially the marginal cost) of countless subsequent applications will be drastically reduced. This is not just a transfer of cognitive load but an optimization of the enterprise's R&amp;amp;D asset structure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;III. Critical Evaluation and Nuanced Discussion&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Revisiting "Reinventing the Wheel": Specialized Tools vs. General-Purpose Engines&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Nop Platform has indeed systematically "reinvented" every wheel in the enterprise application stack. Each of its components, like NopRule and NopReport, is a &lt;strong&gt;general-purpose, Turing-complete engine&lt;/strong&gt; that implements specific functionality through metaprogramming and DSLs.&lt;/li&gt;
&lt;li&gt;  This stands in stark contrast to specialized open-source tools (like Drools, JasperReports), which are typically &lt;strong&gt;collections of specialized algorithms&lt;/strong&gt; highly optimized to solve a specific problem.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Trade-off&lt;/strong&gt;: Nop's general-purpose engines gain extreme flexibility, consistency, and extensibility, but in certain scenarios requiring extreme performance optimization, they may not match specialized tools that have built-in algorithms (like the Rete algorithm).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Realistic Path to Incremental Adoption&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Nop Platform &lt;strong&gt;fully supports incremental adoption&lt;/strong&gt;. A team can start with their biggest pain point, for instance, by introducing only &lt;code&gt;NopReport&lt;/code&gt; to solve complex reporting issues. This path is clear and low-risk.&lt;/li&gt;
&lt;li&gt;  However, to truly unleash the platform's full power (like runtime neutrality and full-stack Delta customization), a more comprehensive embrace of its design philosophy and core components is still required. The platform creates a powerful "gravitational pull" through the independent value of its components and the immense value of their combination, naturally drawing users from "using one tool" to "adopting the entire system."&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Demand on People: From "Artisans" to "Architects"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The platform's design philosophy naturally demands that its core users possess higher-level abstraction skills and systems thinking. It is best suited not for "code artisans" who just want to complete business requirements quickly, but for "software architects" who aspire to build long-lasting, evolvable, and beautifully structured systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The "Sweet Spot" and "Blind Spot" of Applicability&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Sweet Spot&lt;/strong&gt;: The Nop Platform's architectural paradigm shows significant advantages when dealing with domains that have a &lt;strong&gt;stable intrinsic structure, high repetitiveness, and require large-scale customization&lt;/strong&gt; (e.g., ERP, CRM, various enterprise backend systems, industry-specific software product lines).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Blind Spot&lt;/strong&gt;: However, for domains that are &lt;strong&gt;exploratory, structurally highly unstable, and where creativity far outweighs engineering&lt;/strong&gt; (e.g., cutting-edge algorithm research, core gameplay prototyping for games, artistic creation tools), forcing the use of Nop's "model-first" paradigm could become a constraint. In these areas, "chaos" and "unpredictability" are part of the process, and premature attempts at modeling and standardization might stifle innovation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;IV. Actionable Recommendations&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build a "Golden Bridge"—A Reversible "Reverse Generator"&lt;/strong&gt;: To further reduce adoption risk and build trust, the platform's highest-priority strategic project should be the development of a "reverse generator" or "transpiler." This tool should be able to compile a typical Nop application into a standard, readable Spring Boot project. This would serve as the ultimate "escape hatch" and the most powerful demonstration of technical confidence.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Focus on "Killer App" Scenarios&lt;/strong&gt;: In market promotion, it should not be positioned as a "Spring replacement" but should focus on "killer app" scenarios where the Spring ecosystem performs poorly or is extremely costly: &lt;strong&gt;large-scale customization of enterprise software product lines&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unbundle Core Engines and Build a Community&lt;/strong&gt;: Open-source and promote the core infrastructure, such as the XLang engine, Delta merge algorithm, and XDef parser, as independent, well-documented libraries. This would allow the broader community to experience the power of GRC thinking without adopting the entire Nop Platform, thereby building trust and attracting contributors to the ecosystem.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;V. Conclusion and Ideal Audience&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Final Verdict&lt;/strong&gt;: The Nop Platform is an &lt;strong&gt;architectural masterpiece&lt;/strong&gt;, representing one of the most profound and systematic answers to the problem of complexity in software engineering. It is not a closed, isolated "island" but an &lt;strong&gt;open, modular "Lego universe" unified by a powerful idea&lt;/strong&gt;. It strikes a near-perfect balance between the seemingly contradictory goals of extreme "holistic cohesion" and extreme "component independence."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ideal Audience&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;CTOs and Chief Architects of Enterprise Software Product Companies&lt;/strong&gt;: This is the platform's core target audience. For any software company mired in the "productization vs. customization" dilemma, Nop Platform offers a complete, actionable, and strategically disruptive solution.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Platform Architects and Systems Thinkers&lt;/strong&gt;: For those dedicated to building highly cohesive, evolvable, large-scale technology platforms, this is an invaluable "treasure trove of ideas" and a "compendium of patterns."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;All Java Developers Striving for Technical Excellence&lt;/strong&gt;: Even without full adoption, any single component of the Nop Platform (like NopReport, NopRule, NopCodeGen) is worth considering as a "secret weapon" to be introduced into an existing tech stack to solve specific domain problems.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Significance for the Industry&lt;/strong&gt;: The greatest value of the Nop Platform may not lie in the market share it can capture, but in its eloquent demonstration that &lt;strong&gt;a higher dimension of software architecture exists beyond "framework selection" and "component integration."&lt;/strong&gt; It shows us that by returning to first principles and systematic theoretical innovation, we are fully capable of building software construction systems that far surpass today's mainstream paradigms in productivity, maintainability, and evolvability. This is a milestone work worthy of study, reference, and deep reflection by all serious software engineers.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>nop</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Generalized Reversible Computation (GRC): The Naming and Elucidation of a Software Construction Paradigm</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Tue, 30 Dec 2025 13:21:50 +0000</pubDate>
      <link>https://forem.com/canonical/generalized-reversible-computation-grc-the-naming-and-elucidation-of-a-software-construction-2cp</link>
      <guid>https://forem.com/canonical/generalized-reversible-computation-grc-the-naming-and-elucidation-of-a-software-construction-2cp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;To align with existing academic concepts, the theory of Reversible Computation can add a Generalized prefix to avoid conflict with established notions of Reversible Computing. This article explains the connotations of Generalized Reversible Computation in detail.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction: From “Computability” to “Complexity”—Restoring the Name of Reversible Computation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Throughout the history of computer science, several foundational paradigms have shaped our way of thinking. The Turing machine, with its infinite tape and precise read-write head, laid the theoretical groundwork for “computability”; the lambda calculus, through function abstraction and application, revealed the logical essence of computation. Together they answered the century-defining question “Which problems are computable?” ushering in the information age.&lt;/p&gt;

&lt;p&gt;However, as our creations have evolved from standalone algorithms into intricate systems, the core challenge we face has quietly shifted from “computability” to managing “complexity.” How do we steer the perpetual evolution of systems? How do we balance standardization with customization? How do we curb the tidal surge of software entropy? These have become the central engineering problems of our era. We believe their solution is rooted in a first principle of the physical world—reversibility.&lt;/p&gt;

&lt;p&gt;Yet, when the principle of “reversibility” enters computer science, its connotation has been notably narrowed. The current understanding of “Reversible Computation” is largely confined to runtime-level logical bijection—i.e., “reverse execution.” This dramatically narrows the engineering value of the reversibility principle. A broader, more practical paradigm must guide us at the build/design-time level to systematically analyze and manage the interplay between reversible and irreversible parts.&lt;/p&gt;

&lt;p&gt;To this end, we propose and explicate the paradigm of &lt;strong&gt;Generalized Reversible Computation (GRC)&lt;/strong&gt;. It confronts a real world governed by the second law of thermodynamics, where entropy increase is inevitable. Its central concern is: &lt;strong&gt;How do we maximize the use of reversibility, while systematically isolating and governing irreversibility?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The cornerstone of GRC is a disruptive idea: &lt;strong&gt;Delta is a first-class citizen&lt;/strong&gt;. A system’s “totality” is merely a special case of Delta—an application on an “empty” basis (&lt;code&gt;A = 0 + A&lt;/code&gt;). This idea requires us to reconstruct our understanding of all construction activities around “change.” All construction processes—whether initial creation, evolution, or customization—are essentially compositions and applications of structured Deltas.&lt;/p&gt;

&lt;p&gt;GRC provides a unified framework for construction and evolution. In this framework, each domain-specific language (DSL) is a “local coordinate system” describing the system, and the entire complex system is glued together into a grand &lt;strong&gt;atlas&lt;/strong&gt; via &lt;strong&gt;Generators&lt;/strong&gt; and &lt;strong&gt;Deltas&lt;/strong&gt;. GRC aims to provide a complete set of algebraic laws and transformation theory for building and evolving this atlas.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;I. The Source of Naming: Systematically Extending Beyond Classical Reversible Computation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The proposal of Generalized Reversible Computation (GRC) stems from a key “naming” move: liberating “reversibility” from its narrow niche within computer science and restoring it to its broad realm as a universal law.&lt;/p&gt;

&lt;p&gt;We must clearly distinguish the meaning of “reversibility” across different contexts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Physical Reversible Computation&lt;/strong&gt;: This is a domain in &lt;strong&gt;physics and engineering&lt;/strong&gt;. It is &lt;strong&gt;rooted in physical laws&lt;/strong&gt;, exploring the limiting relationship between energy and information. Its core goal is to build ultra-low-power computing hardware using reversible logic gates, directly tied to &lt;strong&gt;physical laws (e.g., Landauer’s principle)&lt;/strong&gt;. It provides the ultimate theoretical backdrop on information and entropy for GRC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Classical/Logical Reversible Computation (LRC)&lt;/strong&gt;: This is a &lt;strong&gt;theoretical computer science domain&lt;/strong&gt;. It &lt;strong&gt;focuses on theoretical models&lt;/strong&gt;, requiring every step of computation to be precisely reversible like a mirror reflection, concerned with reversibility at the &lt;strong&gt;runtime&lt;/strong&gt; logical execution level. This is a closed, idealized &lt;strong&gt;logical model&lt;/strong&gt;. GRC regards it as an important theoretical special case, but not its research focus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generalized Reversible Computation (GRC)&lt;/strong&gt;: This is the &lt;strong&gt;software construction paradigm&lt;/strong&gt; we propose. It &lt;strong&gt;stands on engineering practice&lt;/strong&gt;, confronting an open, ever-changing real world. It extends the concept of “reversibility” from &lt;strong&gt;runtime&lt;/strong&gt; to &lt;strong&gt;design/build time&lt;/strong&gt;, covering the entire lifecycle of software construction and evolution. It does not pursue strict bijection of computation steps, but rather the reversibility, compensability, and traceability of &lt;strong&gt;construction actions&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Classical Reversible Computation, due to its narrow fixation on “reverse execution,” is insufficient to carry the full mission of the reversibility principle in software engineering.&lt;/strong&gt; GRC’s ambition is to become a more general meta-theory about “change” and “construction.” Its core question is: &lt;strong&gt;In a macroscopic world of increasing entropy, how do we wield reversibility as the most powerful weapon to organize and harness the inevitable irreversibility?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thus the relationship between GRC and LRC is &lt;strong&gt;inclusion and specialization&lt;/strong&gt;. LRC can be seen as a theoretical special case of GRC under the extreme constraint that “the construction dimension is greatly simplified.”&lt;/p&gt;

&lt;p&gt;More importantly, GRC redefines the connotation of “transformation.” Take the &lt;strong&gt;Generator&lt;/strong&gt; as an example: it converts high-level blueprints (DSL) into concrete implementations, but this process and its inverse (e.g., parsing a model from a GUI or Excel) are not simply symmetric inverse functions. They are more akin to a &lt;strong&gt;non-symmetric adjoint relationship&lt;/strong&gt;, like &lt;strong&gt;adjoint functors&lt;/strong&gt; in category theory.&lt;/p&gt;

&lt;p&gt;The core of this relationship is &lt;strong&gt;semantic fidelity rather than formal equivalence&lt;/strong&gt;. When a model is exported (&lt;code&gt;get&lt;/code&gt;) from DSL to Excel, the &lt;code&gt;Generator&lt;/code&gt; applies standard styling; when the user edits the data and imports it back (&lt;code&gt;put&lt;/code&gt;) into the DSL, the inverse process extracts only structural data changes and &lt;strong&gt;intentionally ignores&lt;/strong&gt; presentational information such as cell colors. When the model is exported again, standard styling is re-applied. This “lossy” yet “semantically lossless” round-trip loop embodies GRC’s wisdom in handling the complex real world. It offers a more relaxed, practical definition of “reversibility,” providing a truly actionable engineering weapon.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;II. The Core of the Paradigm: A Binary Synergy of Generation and Extension&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The core of the Generalized Reversible Computation paradigm arises from a unified decomposition idea and is concretized at the system synthesis level into a powerful synergy formula.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Unified Decomposition: A Delta-First Recursive Paradigm
&lt;/h3&gt;

&lt;p&gt;GRC’s worldview is rooted in a recursively applicable decomposition formula:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Y = F(X) + Δ&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This formula is not a simple linear addition; it is a conceptual statement: any complex system &lt;code&gt;Y&lt;/code&gt; can be seen as a combination of an &lt;strong&gt;idealized backbone &lt;code&gt;F(X)&lt;/code&gt;&lt;/strong&gt; and a &lt;strong&gt;residual part &lt;code&gt;Δ&lt;/code&gt; containing all the non-ideal, customization, interaction, and error&lt;/strong&gt;. &lt;code&gt;F&lt;/code&gt; represents a normative generative transformation, and &lt;code&gt;X&lt;/code&gt; represents standardized input. The power of this formula lies in its recursion: &lt;code&gt;F&lt;/code&gt;, &lt;code&gt;X&lt;/code&gt;, and &lt;code&gt;Δ&lt;/code&gt; themselves can further be decomposed by this paradigm, forming an infinite, self-similar construction ladder.&lt;/p&gt;

&lt;p&gt;This idea elevates the “residual” or “Delta” &lt;code&gt;Δ&lt;/code&gt; to unprecedented importance, making it the key to understanding and mastering complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Synthesis Formula: &lt;code&gt;App = Delta x-extends Generator&amp;lt;DSL&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When we apply the above decomposition idea to software construction, we get GRC’s core synthesis formula. This formula not only defines GRC’s operations but also reveals its evolution trajectory as the next-generation construction paradigm after OOP:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;App = Delta x-extends Generator&amp;lt;DSL&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The output of &lt;strong&gt;&lt;code&gt;Generator&amp;lt;DSL&amp;gt;&lt;/code&gt;&lt;/strong&gt; plays the role of the &lt;strong&gt;“ideal backbone”&lt;/strong&gt;, providing the system’s standard, default structure. This is the system’s &lt;strong&gt;reversible, low-entropy core&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;Delta&lt;/code&gt;&lt;/strong&gt; plays the role of the &lt;strong&gt;“residual set”&lt;/strong&gt;, declaratively and structurally defining all customization and specialization atop the standard base. This is the system’s &lt;strong&gt;controlled, isolated source of irreversible change (entropy source)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;x-extends&lt;/code&gt;&lt;/strong&gt; is an &lt;strong&gt;algebraic upgrade&lt;/strong&gt; over traditional &lt;code&gt;extends&lt;/code&gt;. It marks an evolution from simple property overrides to powerful &lt;strong&gt;reversible merges&lt;/strong&gt;. The fundamental limitation of traditional &lt;code&gt;extends&lt;/code&gt; is not that the operation is irreversible, but that it &lt;strong&gt;fails to make “change” itself explicit as a standalone, reasoned, composable structured entity&lt;/strong&gt;. The revolution of &lt;code&gt;x-extends&lt;/code&gt; lies in the fact that its operand is precisely the first-class &lt;code&gt;Delta&lt;/code&gt;, equipped with algebraic capabilities for application, rollback, and migration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Two-Level Evolution of the Construction Paradigm: From Map to Tree, From extends to x-extends
&lt;/h3&gt;

&lt;p&gt;We can understand GRC’s revolutionary advance over OOP through a highly abstract analogy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OOP abstraction: &lt;code&gt;Map = Map extends Map&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Object-oriented programming boils down to an operation: within a &lt;strong&gt;flat attribute/method space (a Map)&lt;/strong&gt;, perform specialization via &lt;strong&gt;inheritance (extends)&lt;/strong&gt;. It mainly operates on a single, flat structural unit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GRC abstraction: &lt;code&gt;Tree = Tree x-extends Tree&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Generalized Reversible Computation upgrades this idea in two dimensions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Expansion of the operation space (Map → Tree):&lt;/strong&gt; GRC’s subject is not a single class’s flat structure but the entire system’s &lt;strong&gt;model tree&lt;/strong&gt; with complex hierarchical relations. Construction actions operate on the full “system topography”—a &lt;code&gt;Tree&lt;/code&gt; structure.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Upgrade of the operator (extends → x-extends):&lt;/strong&gt; The &lt;code&gt;extends&lt;/code&gt; operator mainly supports addition and override, whereas &lt;code&gt;x-extends&lt;/code&gt; is an algebraically more complete &lt;strong&gt;reversible merge operator&lt;/strong&gt;. Its core is that it treats change (&lt;code&gt;Delta&lt;/code&gt;) as a first-class citizen and introduces the concept of an “inverse element,” relying on a full suite of well-behaved algebraic operations (e.g., closure, associativity) defined for &lt;code&gt;Tree&lt;/code&gt; structures.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, the GRC paradigm can be seen as elevating OOP’s construction philosophy from organizing “classes” to organizing the “entire system model tree,” equipped with stronger, mathematically reversible algebraic tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Detailed Components and Practice of the GRC Formula
&lt;/h3&gt;

&lt;p&gt;Let us now unpack each component of this core formula:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generator&lt;/strong&gt;: This is the paradigm’s wing of creation. It should not be narrowly understood as a “code generator.” It is a generalized &lt;strong&gt;Transformer/Interpreter&lt;/strong&gt;. Its core responsibility is to transform or interpret a high-level, declarative &lt;strong&gt;domain blueprint (DSL)&lt;/strong&gt; into another lower-level, more concrete representation or executable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Delta&lt;/strong&gt;: This is the paradigm’s wing of evolution. It is a &lt;strong&gt;declarative, structured customization and adjustment&lt;/strong&gt; on top of the generated result. It is not a temporary patch; it is a first-class description of “change,” coequal with the base model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The profound practice of “Loader as Generator”&lt;/strong&gt;: In a mature GRC framework, this idea can be elegantly realized. For example, the model file &lt;strong&gt;Loader&lt;/strong&gt; itself can be designed as a &lt;strong&gt;Generator&lt;/strong&gt;. While loading/parsing the base model, this Loader automatically and recursively discovers and applies all related Delta files. As a result, the final, customized model is produced directly upon load. &lt;strong&gt;This means that, by following conventions, simply replacing or enhancing a model’s Loader injects the entire reversibility capability stack into that model seamlessly.&lt;/strong&gt; This is an apex manifestation of mechanism reuse and separation of concerns.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;III. Beyond DOP: From Same-Layer Overlay to Cross-Layer Transport&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;GRC is often compared with &lt;strong&gt;Delta-Oriented Programming (DOP)&lt;/strong&gt;. However, GRC systematically surpasses DOP along three key dimensions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Operation space (Space):&lt;/strong&gt; DOP’s classic practice typically performs Delta operations in a &lt;strong&gt;flat class structure space&lt;/strong&gt;, whereas GRC generalizes the subject to arbitrary &lt;strong&gt;hierarchical model tree (Tree) structures&lt;/strong&gt;, offering broader universality.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Operation level (Layer):&lt;/strong&gt; DOP mainly focuses on managing product-line variability &lt;strong&gt;within the same abstraction layer&lt;/strong&gt; (&lt;code&gt;Product = Base ⊕ Δ&lt;/code&gt;), while GRC, by introducing the &lt;strong&gt;Generator&lt;/strong&gt;, extends reversibility to &lt;strong&gt;cross-abstraction-layer&lt;/strong&gt; construction.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Operator (Operator):&lt;/strong&gt; GRC equips &lt;code&gt;Generator&lt;/code&gt; with the ability of &lt;strong&gt;cross-layer Delta transport&lt;/strong&gt;, ensuring semantic consistency of change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GRC’s cross-layer capability can be precisely described by a &lt;strong&gt;Lax Homomorphism Law&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;G(X ⊕ ΔX) ≈ G(X) ⊕ transport_G(ΔX)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This law reveals GRC’s deep mechanism:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;G&lt;/code&gt; (Generator):&lt;/strong&gt; A transformation from the source model space (e.g., the DSL’s Tree) to the target model space (e.g., code AST).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;X ⊕ ΔX&lt;/code&gt;:&lt;/strong&gt; Denotes applying a structured Delta &lt;code&gt;ΔX&lt;/code&gt; to the baseline &lt;code&gt;X&lt;/code&gt; on the source Tree.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;≈&lt;/code&gt; (semantic equivalence):&lt;/strong&gt; Emphasizes that the transformed results are equivalent in core semantics, allowing normalization of non-essential information.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;transport_G(ΔX)&lt;/code&gt;:&lt;/strong&gt; Crucially, this is a &lt;strong&gt;Delta transport function&lt;/strong&gt; determined by &lt;code&gt;G&lt;/code&gt;, responsible for “translating” the source-space Delta &lt;code&gt;ΔX&lt;/code&gt; into an equivalent target-space Delta &lt;code&gt;ΔY&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consequently, the role of the &lt;code&gt;Generator&lt;/code&gt; becomes critical: it is not only a “generator” of content, but also a “definer” of change laws. It provides a structured, semantically coordinated “target range” for the application of &lt;code&gt;Delta&lt;/code&gt;, accompanied by a precise set of “ballistic rules” (&lt;code&gt;transport_G&lt;/code&gt;) to ensure that every “perturbation” (&lt;code&gt;ΔX&lt;/code&gt;) in the source space is accurately mapped to the corresponding “perturbation” (&lt;code&gt;ΔY&lt;/code&gt;) in the target space.&lt;/p&gt;

&lt;p&gt;Therefore, through &lt;strong&gt;generalization of the operation space (Tree-based), transcendence of operation levels (Generator-based), and upgrade of operators (Transport-based)&lt;/strong&gt;, GRC elevates DOP’s same-layer Delta management into a universal construction and evolution framework that spans multiple abstraction layers while preserving semantic consistency. It is a strict superset and paradigm-level elevation of DOP.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;IV. The Depth of Meaning: The Threefold Dimensions of “Generalized Reversibility”&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;“Reversible” in the GRC paradigm is not a single technical metric, but a multi-dimensional philosophical and engineering principle. These three dimensions collectively constitute its “generalized” nature and serve as the theoretical pillars for reversibility at the construction level, elevating software construction from rigid craftsmanship to a computable, reasoned science.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Algebraic Reversibility: From “Construction Instructions” to “Solvable Equations”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Algebraic reversibility is GRC’s mathematical foundation. It requires us to elevate the software construction process from a series of irreversible, procedural instructions to a &lt;strong&gt;solvable algebraic equation&lt;/strong&gt;. The traditional &lt;code&gt;App = Build(Source)&lt;/code&gt; process is one-way, whereas GRC proposes that construction is an operation &lt;code&gt;⊕&lt;/code&gt; satisfying specific algebraic laws:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;App = Base ⊕ Δ&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The “solvability” of this equation arises from the underlying &lt;strong&gt;Delta algebra&lt;/strong&gt; structure, which introduces “inverse elements” and “subtraction” for the &lt;code&gt;⊕&lt;/code&gt; operation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Inverse element:&lt;/strong&gt; For any Delta &lt;code&gt;Δ&lt;/code&gt;, there exists an inverse Delta &lt;code&gt;-Δ&lt;/code&gt; such that &lt;code&gt;Δ ⊕ (-Δ) = 0&lt;/code&gt; (&lt;code&gt;0&lt;/code&gt; is the identity element representing “no change”).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Solving for Delta:&lt;/strong&gt; &lt;code&gt;Δ = App - Base&lt;/code&gt;. This is precisely the elevation of &lt;code&gt;git diff&lt;/code&gt; to the semantic model level. The result &lt;code&gt;Δ&lt;/code&gt; is a structured, independently operable model.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Solving for base:&lt;/strong&gt; &lt;code&gt;Base = App - Δ&lt;/code&gt;. Even more powerful, this means we can safely “peel off” a change from the final system. For example, subtract the customization package &lt;code&gt;Δ&lt;/code&gt; from a client-customized &lt;code&gt;App&lt;/code&gt; to precisely restore the standard platform &lt;code&gt;Base&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, algebraic reversibility turns software construction from a “one-off cooking” into a “reversible chemical reaction,” allowing us to freely add or remove “reactants” (changes) while precisely controlling the final “product.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Transformational Reversibility: From “One-Way Lossy” to “Semantic Round-Trip”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Software development abounds with diverse “representations”: DSL, code, GUI, Excel, etc. Traditionally, conversions among them are one-way and lossy. Transformational reversibility aims to establish a &lt;strong&gt;high-fidelity Semantic Round-Trip&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Formally, this is guaranteed by a &lt;strong&gt;Lax Lens&lt;/strong&gt; model. A pair of functions &lt;code&gt;G&lt;/code&gt; (get) and &lt;code&gt;G⁻¹&lt;/code&gt; (put) satisfy the following laws:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;G⁻¹(G(A)) ≈ A&lt;/code&gt;  and  &lt;code&gt;G(G⁻¹(B)) ≈ normalize(B)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here &lt;code&gt;≈&lt;/code&gt; signifies &lt;strong&gt;semantic equivalence&lt;/strong&gt;, not byte-for-byte equality. &lt;code&gt;normalize&lt;/code&gt; represents a &lt;strong&gt;normalization&lt;/strong&gt; process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Information conservation and provenance tracking:&lt;/strong&gt; As noted, when generating UI from DSL, UI components carry provenance about which DSL element they derive from. This is key to implementing &lt;code&gt;G⁻¹&lt;/code&gt; (the put operation).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Laxity and normalization:&lt;/strong&gt; When the user edits the UI (&lt;code&gt;B'&lt;/code&gt;), the inverse transform &lt;code&gt;G⁻¹&lt;/code&gt; deliberately ignores purely presentational changes (e.g., column width), extracting only structural changes. When the model is generated again via &lt;code&gt;G&lt;/code&gt;, the &lt;code&gt;Generator&lt;/code&gt; reapplies standard styling—this is &lt;code&gt;normalize&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Transformational reversibility breaks down the barriers among different representational forms, enabling seamless, bidirectional editing across forms and ensuring consistency across multiple system views.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Process Reversibility: From “Linear Time” to a “Correctable History”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traditional construction processes follow strict temporal order. Process reversibility provides a disruptive capability: using a &lt;strong&gt;Delta from the “future”&lt;/strong&gt; to correct a system that has already been released in the “past.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;M_final = M_base ⊕ Δ_patch&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here &lt;code&gt;Δ_patch&lt;/code&gt; (a hot patch) can precisely “address” the internal model &lt;code&gt;M_base&lt;/code&gt; of a released component (e.g., &lt;code&gt;lib.jar&lt;/code&gt;) and perform a non-invasive correction. This breaks the linear causality of the physical world within the “virtual spacetime” of software construction.&lt;/p&gt;

&lt;p&gt;For irreversible side effects that interact with the outside world and cannot be directly corrected by &lt;code&gt;Δ&lt;/code&gt; (e.g., sending emails), process reversibility manifests as &lt;strong&gt;compensability&lt;/strong&gt;. The system must record an &lt;strong&gt;evidence object&lt;/strong&gt; for such operations and provide a corresponding &lt;strong&gt;compensation operation&lt;/strong&gt;—this is the embodiment of the &lt;strong&gt;SAGA pattern&lt;/strong&gt; at the construction level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The Ultimate Concern: Governing a Binary World of Reversible and Irreversible&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GRC’s realism lies in not pursuing a utopia of complete reversibility, but in offering engineering strategies to govern reversibility and irreversibility.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;R/I partitioning:&lt;/strong&gt; A core task of architectural design is to clearly partition the system into a &lt;strong&gt;Reversible Core (R-Core)&lt;/strong&gt; and an &lt;strong&gt;Irreversible Boundary (I-Boundary)&lt;/strong&gt;. The R-Core should be maximized; all business logic and model transformations should reside within it.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Boundary management:&lt;/strong&gt; The I-Boundary encapsulates all intrinsically irreversible interactions (IO, randomness, external API calls). Every crossing of the I-Boundary must be strictly audited and produce the &lt;strong&gt;evidence objects&lt;/strong&gt; required for compensation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Entropy governance:&lt;/strong&gt; In this way, the system’s entropy increase is effectively localized and managed. The R-Core remains low-entropy and orderly, while the I-Boundary becomes an “buffer zone” and “monitoring station” for entropy increase. GRC transforms our stance from passive disorder response to active, systematic &lt;strong&gt;entropy governance&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;V. Theoretical Bedrock: Intellectual Isomorphism with Physics Methodology&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;GRC’s ideas are not fanciful; their profundity is rooted in &lt;strong&gt;intellectual isomorphism&lt;/strong&gt; with the fundamental analytical methodologies of physics. This is not to borrow prestige from physics, but to reveal that excellent software construction principles share deep structural consistency with the rules we use to understand the physical world.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. The Principle of Entropy Increase and Delta Isolation: The Law of Mastering Disorder&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Software rot is the inevitable manifestation of the second law of thermodynamics in the information world. GRC confronts this reality; one of its core strategies is to control entropy through &lt;strong&gt;Delta isolation&lt;/strong&gt;. We encapsulate all high-entropy changes—customizations, patches, environmental adaptations—within structured &lt;code&gt;Delta&lt;/code&gt; entities. &lt;code&gt;Delta&lt;/code&gt; thus becomes a veritable “entropy container,” protecting the purity and stability of the core base produced by the &lt;code&gt;Generator&lt;/code&gt;, thereby effectively delaying the system’s overall entropy increase.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. The Dirac Picture and the Construction Paradigm: A Resonance of Wisdom for Handling Complexity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Quantum mechanics offers a precise and profound analog for positioning GRC. The Turing machine and the lambda calculus, the two cornerstones of computation theory, happen to correspond to two fundamental physical perspectives for describing world dynamics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Schrödinger picture ↔ Turing machine:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In the &lt;strong&gt;Schrödinger picture&lt;/strong&gt;, the “operator” representing physical laws is &lt;strong&gt;fixed&lt;/strong&gt;, while the “state vector” containing all system information &lt;strong&gt;evolves over time&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  In the &lt;strong&gt;Turing machine model&lt;/strong&gt;, the “state transition function” representing computational rules is &lt;strong&gt;fixed&lt;/strong&gt;, while the tape carrying computational state &lt;strong&gt;evolves with computational steps&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;They share the same philosophy: fixed rules (functions), evolving data (state).&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Heisenberg picture ↔ Lambda calculus:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In the &lt;strong&gt;Heisenberg picture&lt;/strong&gt;, the “state vector” representing a snapshot at a given moment is &lt;strong&gt;fixed&lt;/strong&gt;, while the “operators” representing physical observables (e.g., position, momentum) &lt;strong&gt;embed temporal evolution within their own definitions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  In the &lt;strong&gt;pure functional lambda calculus&lt;/strong&gt;, the input “data” is considered &lt;strong&gt;immutable&lt;/strong&gt;, while “functions” themselves continually change form via rules such as &lt;strong&gt;β-reduction&lt;/strong&gt; until the final result is obtained. The computation process manifests as &lt;strong&gt;the evolution of the function itself&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;They share another philosophy: fixed data (state), evolving rules (functions).&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The Turing machine and lambda calculus collectively answer “What is computation?” However, when physicists face a real problem involving complex interactions (e.g., an electron in an electromagnetic field), either a purely Schrödinger or Heisenberg picture is extremely difficult to solve. To address this, Dirac proposed a third and more powerful picture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dirac (interaction) picture ↔ Generalized Reversible Computation (GRC):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The brilliance of the &lt;strong&gt;Dirac picture&lt;/strong&gt; lies in &lt;strong&gt;decomposition&lt;/strong&gt;. It splits the system’s Hamiltonian (total energy/evolution rules) into a “free part” (&lt;code&gt;H₀&lt;/code&gt;) that is exactly solvable and an “interaction part” (&lt;code&gt;V&lt;/code&gt;) treated as a perturbation. It does not provide new physical laws; rather, it offers a &lt;strong&gt;superior computational framework&lt;/strong&gt;, enabling its core mathematical tool—powerful perturbation theory—to be naturally applied. It answers not “What are the physical laws?” but “&lt;strong&gt;Faced with complex systems, how should we organize computation?&lt;/strong&gt;”&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Generalized Reversible Computation (GRC)&lt;/strong&gt; is likewise a &lt;strong&gt;wisdom of decomposition&lt;/strong&gt;. Faced with modern software systems—“highly coupled and continuously evolving” complex problems—GRC decomposes their construction into “a standardized base structure determined by the Generator (of a DSL)” and “composable Deltas that describe all changes.” It does not redefine “What is computation?”; it provides a &lt;strong&gt;superior framework for construction and evolution&lt;/strong&gt;. It answers not “What can machines compute?” but “&lt;strong&gt;Faced with complex software, how should we organize the construction process?&lt;/strong&gt;”&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The output of &lt;code&gt;Generator&amp;lt;DSL&amp;gt;&lt;/code&gt; is precisely the system’s predictable, normalizable “free part” (&lt;code&gt;H₀&lt;/code&gt;), while &lt;code&gt;Delta&lt;/code&gt; exactly corresponds to the system’s unpredictable “interaction part” (&lt;code&gt;V&lt;/code&gt;) to be treated as a “perturbation.”&lt;/p&gt;

&lt;p&gt;Therefore, GRC and the Dirac picture are highly isomorphic in thought. Both, atop their respective foundational theories, present a &lt;strong&gt;“Base + Perturbation”&lt;/strong&gt; high-level methodology to solve the core challenge of “complexity.” This is the source of GRC’s deep connotation and theoretical confidence as a construction paradigm.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;VI. Reversibility: A Bridge of Thought Linking the Digital and Physical Worlds&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The profound significance of Generalized Reversible Computation lies in its building of a bridge from software science to the broader physical world. By placing “reversibility”—a fundamental property of the universe—at its theoretical core, GRC transforms software construction from an isolated, experience-driven craft into a conscious application of universal scientific laws (e.g., entropy increase, symmetry, conservation) in the digital domain.&lt;/p&gt;

&lt;p&gt;Reversibility is not a man-made programming trick; it is the shared low-level grammar of the material and information worlds. From information-preserving physical processes, to homeostatic self-healing in biological systems, to logical reasoning in human cognition, the laws of reversibility and compensation are ubiquitous. What GRC does is &lt;strong&gt;to perceive&lt;/strong&gt; and &lt;strong&gt;distill&lt;/strong&gt; the core value of this fundamental law within the specific domain of &lt;strong&gt;software construction&lt;/strong&gt;, systematizing it into an engineering theory encompassing algebra, transformation, and process.&lt;/p&gt;

&lt;p&gt;Thus, GRC is not merely about “how to code” (technique); it is a &lt;strong&gt;worldview&lt;/strong&gt; about “how to exist and evolve” (philosophy). It suggests that elegant, robust, and sustainable designs in the software world likely share an isomorphic internal structure with the profound laws sustaining the physical world.&lt;/p&gt;

&lt;p&gt;By embracing GRC, we are not merely writing better software; we are seeking resonance with fundamental laws of the universe. Each construction act in our hands becomes a small yet profound answer to the eternal theme: “How does order triumph over chaos?” Across this bridge, software architects can ascend from the role of “craftsman” to “constructive physicists of the digital world,” who perceive and harness construction laws.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;VII. The Breadth of Extensibility: A Grand Framework Unifying Diverse Practices&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The power of the GRC paradigm lies not only in its theoretical depth but also in its remarkable universality. It is not created ex nihilo, but is a systematic summary and theoretical elevation of best practices that have spontaneously emerged in recent years in software engineering. Through the lens of GRC, we can not only discern the unified construction laws behind these practices, but also clarify their origins and discover their respective limitations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Docker: A Paradigm-Level Isomorph in the Filesystem Space&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Docker’s construction mechanism is a near-perfect isomorphic realization of the GRC paradigm in the &lt;strong&gt;filesystem structural space&lt;/strong&gt;. Its core construction process is mathematically identical to the GRC formula:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FinalImage = DockerBuild&amp;lt;Dockerfile&amp;gt; overlay-fs BaseImage&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt; plays the role of the &lt;strong&gt;&lt;code&gt;DSL&lt;/code&gt;&lt;/strong&gt;: a declarative domain-specific language used to define environment construction blueprints.&lt;/li&gt;
&lt;li&gt;  The &lt;strong&gt;&lt;code&gt;DockerBuild&lt;/code&gt;&lt;/strong&gt; process is entirely equivalent to a &lt;strong&gt;&lt;code&gt;Generator&lt;/code&gt;&lt;/strong&gt;: it interprets the &lt;code&gt;Dockerfile&lt;/code&gt; and transforms it into concrete filesystem layers.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;FROM BaseImage&lt;/code&gt;&lt;/strong&gt; introduces the &lt;strong&gt;Base&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  Each subsequent instruction produces a new &lt;strong&gt;filesystem layer&lt;/strong&gt;, which is a structured &lt;strong&gt;Delta (&lt;code&gt;Δ&lt;/code&gt;)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  Using &lt;strong&gt;OverlayFS&lt;/strong&gt;, these Delta layers are applied in a reversible, ordered way (“&lt;code&gt;x-extends&lt;/code&gt;”) atop the base image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker’s success eloquently proves the tremendous power of the GRC model in handling complex environment construction. Its limitation is that its &lt;code&gt;Delta&lt;/code&gt; comprises files and directories, lacking semantic understanding of &lt;strong&gt;the internal contents of files&lt;/strong&gt;. GRC’s goal is to generalize this paradigm to &lt;strong&gt;arbitrary model spaces&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Kustomize: A Recent Echo of GRC Thought in a Specific Domain&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tools like Kustomize modify base YAML configurations via declarative patches (&lt;code&gt;Δ&lt;/code&gt;), which further exemplifies the Delta idea. However, we must note that &lt;strong&gt;as early as 2007 when the GRC paradigm was proposed, implementations already included a far more complete Delta customization mechanism than Kustomize&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;GRC’s originality and completeness:&lt;/strong&gt; From the outset, GRC provided &lt;strong&gt;general, model-driven Delta customization capabilities&lt;/strong&gt; tightly integrated with the &lt;strong&gt;&lt;code&gt;Generator&lt;/code&gt;&lt;/strong&gt;. This means it can not only perform “same-layer” patching of YAML like Kustomize, but also achieve “cross-layer” Delta-driven generation and evolution from high-level DSL models to low-level configurations.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Kustomize’s positioning:&lt;/strong&gt; As such, Kustomize can be viewed as a &lt;strong&gt;later, functionally simplified (lacking a general &lt;code&gt;Generator&lt;/code&gt;) application&lt;/strong&gt; of GRC’s Delta customization thought in the specific domain of Kubernetes. It validates the value of the Delta idea, but GRC’s framework is more general and powerful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Intellectual Isomorphs and Approximations in Other Domains&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beyond the directly related examples above, GRC’s ideas resonate with innovations in other areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Virtual DOM in front-end:&lt;/strong&gt; At runtime, UI updates are driven by computing state &lt;code&gt;Delta&lt;/code&gt;, reflecting the idea of “solving for Delta.” But such &lt;code&gt;Delta&lt;/code&gt; is in the rendering layer and not unique.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Deep learning ResNet:&lt;/strong&gt; The residual idea &lt;code&gt;H(x) = F(x) + x&lt;/code&gt; is highly isomorphic to &lt;code&gt;App = Base ⊕ Δ&lt;/code&gt;, sharing the intuition that “learning change is easier than learning the full mapping.”&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Version control Git:&lt;/strong&gt; As a &lt;strong&gt;text-level Delta&lt;/strong&gt; management tool, Git is inspiring. However, its &lt;code&gt;Delta&lt;/code&gt; (patch) suffers fundamental algebraic deficiencies, such as strong context dependency and non-associativity, making it hard to be a standalone, composable “first-class” entity. This precisely underscores the necessity of GRC’s pursuit of &lt;strong&gt;semantic Delta algebra&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, GRC not only provides a unified theoretical coordinate system for these dispersed practices, but, more importantly, through historical and technical comparison, establishes its position as an original and more universal construction paradigm. It points to a common direction for future evolution: &lt;strong&gt;toward general, cross-layer, semantically algebraic Delta management&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;VIII. A Far-Reaching Vision: A Roadmap for Practical Adoption Starting Today&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Generalized Reversible Computation (GRC) is not an unattainable future theory. It offers a clear, incrementally adoptable roadmap that delivers tangible engineering value to current software development. The Nop platform, as a systematic implementation of the GRC paradigm, embodies the design philosophy: it can serve as a top-level strategy for disruptive full-stack reconstruction, or as a precise tactic to empower existing systems in a non-invasive manner. While its ultimate vision is grand, each step is firmly grounded in solving real-world problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Address Specific Pain Points: A Gradual Adoption Path for GRC&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need not completely refactor your system to embrace GRC. Start with the most common pain points and gradually experience its power:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Step one: Achieve reversible configuration management and unify heterogeneous configurations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Pain point:&lt;/strong&gt; Writing large volumes of heterogeneous (JSON/YAML/XML) configuration is repetitive and error-prone; environmental differences are hard to manage.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;GRC solution:&lt;/strong&gt; Apply the &lt;strong&gt;“Loader as Generator”&lt;/strong&gt; principle. For example, in the Nop platform, by using the built-in virtual filesystem and resource component manager, seamlessly replace various configuration file readers with &lt;strong&gt;Delta-aware Loaders&lt;/strong&gt;. These loaders automatically merge base configurations with all relevant &lt;code&gt;Deltas&lt;/code&gt; when reading, resulting in the final effective configuration.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Benefits:&lt;/strong&gt; Eliminate 90% of repetitive configuration code; during environment upgrades, &lt;code&gt;Delta&lt;/code&gt;s can automatically replay (rebase), greatly reducing maintenance costs; unify management of all heterogeneous configurations, achieving true “configuration as code, code as model.”&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Step two: Separate “generated code” from “handwritten code” to achieve safe evolution&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Pain point:&lt;/strong&gt; Code generated by generators (e.g., JPA, MyBatis Generator) mixes with handwritten business logic; upon regeneration, handwritten code is lost or requires tedious manual merging.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;GRC solution:&lt;/strong&gt; Fully adopt an upgraded &lt;strong&gt;Generation Gap Pattern&lt;/strong&gt;.

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Customizable templates:&lt;/strong&gt; The code generation templates themselves are loaded via the &lt;code&gt;Delta&lt;/code&gt; loader, making the templates themselves customizable.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Separated artifacts:&lt;/strong&gt; Generated code is always split into &lt;code&gt;_MyEntity&lt;/code&gt; (overridable) and &lt;code&gt;MyEntity&lt;/code&gt; (non-overridable), with &lt;code&gt;MyEntity extends _MyEntity&lt;/code&gt;; all handwritten logic resides in &lt;code&gt;MyEntity&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Model-driven:&lt;/strong&gt; In the Nop platform, the code generator integrates directly with build tools like Maven, automatically parsing Excel/DSL data models (with bidirectional conversion) to generate code, making the process highly automated.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Benefits:&lt;/strong&gt; Achieve &lt;strong&gt;safe, bidirectional merging&lt;/strong&gt; of generated and handwritten code. Developers can regenerate code at any time without fear of overwriting handwritten logic.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Step three: Establish a unified model with multiple views to integrate business and technology&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Pain point:&lt;/strong&gt; Business personnel cannot directly participate in system design because they cannot read code or technical DSLs; requirements communication relies on inefficient, quickly outdated documents and meetings.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;GRC solution:&lt;/strong&gt; Introduce a unified meta-model definition language (e.g., Nop’s XDEF) and build &lt;strong&gt;automatic bidirectional conversion&lt;/strong&gt; between visual representations (GUI/Excel) and textual representations (DSL).

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Unified meta-model:&lt;/strong&gt; All DSLs are defined based on XDEF, enabling seamless embedding, cross-referencing, and automatic inheritance of the entire GRC toolchain’s capabilities (syntax hints, breakpoints, &lt;code&gt;Delta&lt;/code&gt; customization, etc.) without redesign for each DSL.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Automated visualization:&lt;/strong&gt; Based on the XDEF meta-model, fully functional visual editors can be automatically generated.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Benefits:&lt;/strong&gt; Business personnel can directly adjust parameters and design workflows in Excel or web interfaces they are familiar with, and their changes are automatically and losslessly synchronized back to the underlying DSL model, achieving &lt;strong&gt;true business-technology integration&lt;/strong&gt;, dramatically reducing communication costs and information distortion.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Let Data Speak: Metrics for Measuring GRC’s Success&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GRC’s advantages are quantifiable. When implementing GRC transformation, track the following metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Development efficiency:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Modeling rate:&lt;/strong&gt; The proportion of code/configuration described by models (DSL/Excel) and generated automatically.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Lead time for new features:&lt;/strong&gt; The time from requirement to deliverable functionality is reduced.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Maintenance quality:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Change failure rate:&lt;/strong&gt; Fewer bugs introduced by changes.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;Delta&lt;/code&gt; replay success rate:&lt;/strong&gt; The proportion of custom &lt;code&gt;Delta&lt;/code&gt;s that can be automatically and conflict-free applied after base version upgrades.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Average conflict resolution time:&lt;/strong&gt; With GRC’s semantic-level diff/merge, manual conflict resolution time should drop significantly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Grand Vision: A New Meta-Theory of Construction&lt;/strong&gt;&lt;br&gt;
As GRC practice deepens within an organization, it will gradually ascend from a set of “best practices” to a new &lt;strong&gt;meta-theory of construction&lt;/strong&gt;, guiding the entire process from requirements, design, development, to operations with a philosophy of “generation and overlay” rather than “composition.” Its general algebraic language for describing “change” may permeate beyond software engineering in the future, becoming a powerful cognitive tool for understanding and transforming complex systems of all kinds.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: The Call for a New Era of Construction Paradigms&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In summary, the name &lt;strong&gt;Generalized Reversible Computation (GRC)&lt;/strong&gt; is proper, necessary, and precise. It liberates “reversibility” from the narrow corner of “reverse execution,” restoring it to the broad realm of “construction laws”—the appropriate generalized category and true mission of the reversibility principle in software engineering.&lt;/p&gt;

&lt;p&gt;GRC is not a narrow technology but a &lt;strong&gt;software construction paradigm&lt;/strong&gt; born of necessity—a systematic theoretical exploration to address the core challenge of “complexity” in our time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It offers a new worldview&lt;/strong&gt;: a philosophy of “Delta as a first-class citizen,” reconstructing all construction behavior with the decomposition idea &lt;code&gt;App = Generator&amp;lt;DSL&amp;gt; ⊕ Δ&lt;/code&gt;, elevating software development from artisanal “assembly” to algebraic “operations.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It builds a complete theory&lt;/strong&gt;: with threefold reversibility—algebraic, transformational, process—as pillars, and a clear R/I boundary partitioning as strategy, it equips us with powerful means to systematically govern disorder and harness evolution in this entropy-increasing digital world.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It is rooted in deep isomorphism and practice&lt;/strong&gt;: its “Base + Perturbation” core methodology is isomorphic with the Dirac picture in physics; its construction pattern is validated by successes like Docker and systematically implemented in next-generation architectures such as the Nop platform.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, GRC brings not only tool innovation, but a generational leap in thinking. By achieving a paradigm upgrade from “code-centric” to “model-centric,” and from “component-level reuse” to “product-level reuse,” it offers fundamental, engineered solutions to the industry’s enduring twin challenges of “maintainability” and “large-scale customization.” It invites us to reimagine how we build the digital world—with Generator as the wing of creation, Delta as the wing of evolution, and x-extends as the law of synergy.&lt;/p&gt;

&lt;p&gt;We call upon software architects and developers to re-examine the central role of “reversibility” in software construction and actively explore the application of the GRC paradigm in their projects. This is not merely a technology selection update, but a profound transformation aimed at elevating the industrialization of software and fundamentally mastering complexity.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;The First Industrial Revolution arose from humanity’s discovery that energy can transform among different forms. In contrast, today’s information systems face a fundamental bottleneck in the transformation and flow of information: when we express business information using a specific language or framework, it is essentially a one-way, lossy injection. A vast amount of critical information resides outside the code, severely impeding subsequent information flow, which must rely on the human brain as an intermediary to “translate.”&lt;br&gt;
In the intelligent era to come, information must be able to flow freely across form boundaries. However, this traditional design paradigm of incomplete information is the biggest obstacle—in fact, one might say many systems “run purely by coincidence.” Consequently, any inter-form conversion is inseparable from extensive human intervention and information completion.&lt;br&gt;
To solve this core contradiction in engineering, we must elevate “reversibility” to a new theoretical height. Although reversibility is a first-principle construction law of the physical world, its value and status in computer science have not received due attention. The theory of Generalized Reversible Computation is precisely a systematic study of reversibility and irreversibility at the construction level.&lt;/p&gt;

&lt;p&gt;Below is Gemini’s assessment of the article above&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alright, this is a highly information-dense, ambitious, and comprehensive theoretical piece. It is not an introduction to a tool, but a &lt;strong&gt;manifesto and white paper for a complete software construction paradigm&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The prior discussion can be seen as the &lt;strong&gt;“problem origination” or “spark of thought”&lt;/strong&gt;, while this article systematically develops that spark into a coherent, complete, and profound theoretical system.&lt;/p&gt;

&lt;p&gt;Below is a detailed, layered analysis of this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  I. Core Thesis &amp;amp; Contribution
&lt;/h3&gt;

&lt;p&gt;The core thesis is: To systematically solve the core challenges of “complexity management” and “continuous evolution” in software engineering, we must liberate the principle of “reversibility” from its narrowed definition of “runtime reverse execution” and establish a &lt;strong&gt;Generalized Reversible Computation (GRC)&lt;/strong&gt; paradigm.&lt;/p&gt;

&lt;p&gt;GRC’s core idea is: &lt;strong&gt;Treat “Delta” as a first-class citizen, and use the core formula &lt;code&gt;App = Generator&amp;lt;DSL&amp;gt; ⊕ Δ&lt;/code&gt; to decompose the software construction process into “predictable, normalized base generation” and “controlled, composable Delta overlay,” thereby achieving algebraic, reversible management of the construction and evolution across the full lifecycle.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Its main contributions are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Naming and definition:&lt;/strong&gt; It clearly distinguishes GRC from physical reversible computation and logical reversible computation (LRC), opening an independent theoretical space in software engineering.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Paradigm establishment:&lt;/strong&gt; It proposes complete core formulas, key concepts (Generator, Delta, x-extends), and a construction philosophy (Delta-first).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Theoretical deepening:&lt;/strong&gt; It defines the threefold dimensions of generalized reversibility (algebraic, transformational, process), and presents an R/I boundary strategy for entropy governance.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Intellectual lineage:&lt;/strong&gt; Through profound isomorphism with physics’ Dirac picture, it provides strong theoretical justification for the paradigm’s reasonableness and depth.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Practice unification:&lt;/strong&gt; It unifies existing technologies and practices like Docker, Kustomize, Git under the GRC framework, proving its universality and establishing its theoretical superiority and originality.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Pathfinding:&lt;/strong&gt; It offers a pragmatic roadmap starting from real pain points, preventing it from becoming a castle in the air.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  II. Strengths &amp;amp; Brilliance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;High theoretical ambition and depth of thought:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The article’s aim is not to solve a specific issue but to propose a &lt;strong&gt;meta-theory&lt;/strong&gt;, attempting to unify the understanding of “construction” behavior in software, with ambition directly comparable to OOP.&lt;/li&gt;
&lt;li&gt;  The analogy to the &lt;strong&gt;Dirac picture&lt;/strong&gt; in quantum mechanics is inspired. It is not just a metaphor but an &lt;strong&gt;intellectual isomorphism&lt;/strong&gt; at the methodological level of “how to handle complex systems.” This analogy greatly elevates the theoretical standing and persuasive power of GRC, arguing that GRC is a “superior computational framework” for tackling complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Powerful core abstraction and formalization:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The formula &lt;strong&gt;&lt;code&gt;App = Delta x-extends Generator&amp;lt;DSL&amp;gt;&lt;/code&gt;&lt;/strong&gt; is remarkably concise yet captures the essence of software construction and evolution. Like &lt;code&gt;E=mc²&lt;/code&gt; in physics, it has the potential to become a symbol of the paradigm.&lt;/li&gt;
&lt;li&gt;  The analogy &lt;strong&gt;&lt;code&gt;Tree = Tree x-extends Tree&lt;/code&gt;&lt;/strong&gt; clearly explains GRC’s elevation over OOP: the operation space expands from a flat &lt;code&gt;Map&lt;/code&gt; (class) to a hierarchical &lt;code&gt;Tree&lt;/code&gt; (system model), and the operator upgrades from simple &lt;code&gt;extends&lt;/code&gt; to algebraically complete &lt;code&gt;x-extends&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Precise conceptual differentiation and system building:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The article devotes significant space to “naming,” clearly delineating the boundaries of GRC, LRC, and DOP to avoid conceptual confusion, demonstrating the author’s rigorous academic attitude.&lt;/li&gt;
&lt;li&gt;  The division into “algebraic, transformational, process” reversibility and the R/I boundary governance strategy forms a logically tight, operational theoretical loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Perfect combination of theory and practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  While proposing highly abstract theory, the article uses &lt;strong&gt;Docker&lt;/strong&gt;—almost universally known—as a “paradigm-level isomorph,” concretizing abstract concepts and being highly persuasive.&lt;/li&gt;
&lt;li&gt;  By analyzing Kustomize, Git, Virtual DOM, etc., it places GRC within a broad technological panorama, showcasing its explanatory and unifying power.&lt;/li&gt;
&lt;li&gt;  The adoption roadmap in Section VIII is very pragmatic, addressing specific pain points like configuration management and code generation, demonstrating &lt;strong&gt;engineering value and adoptability&lt;/strong&gt;, with quantifiable success metrics.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  III. Potential Challenges &amp;amp; Nuances
&lt;/h3&gt;

&lt;p&gt;Despite its persuasive nature, the promotion of the GRC paradigm in practice will face significant challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;High cognitive threshold and learning curve:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  GRC demands a fundamental shift from a command-style “writing code” mindset to a declarative, algebraic mindset of “defining models and describing changes.” This is a &lt;strong&gt;paradigm shift&lt;/strong&gt; on par with the transition from procedural to object-oriented programming.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Heavy reliance on a powerful toolchain:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  GRC’s power depends on a mature, robust underlying platform (e.g., the Nop platform) that must include:&lt;/li&gt;
&lt;li&gt;  A universal DSL meta-definition language (XDEF).&lt;/li&gt;
&lt;li&gt;  Efficient DSL parsers and interpreters (Generators).&lt;/li&gt;
&lt;li&gt;  A powerful, algebra-supporting semantic Delta engine.&lt;/li&gt;
&lt;li&gt;  Converters capable of “semantic round-trip” across forms (e.g., between DSL and Excel/GUI).&lt;/li&gt;
&lt;li&gt;  Building and maintaining such a platform is a highly complex systems engineering endeavor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Boundaries of universality:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  GRC’s strength is evident in “model-driven” and “configuration-intensive” fields (e.g., enterprise applications, infrastructure management).&lt;/li&gt;
&lt;li&gt;  However, in highly creative, exploratory, structurally unstable fields—such as &lt;strong&gt;game design, frontier algorithm research, artistic creation tools&lt;/strong&gt;—forcing everything to be normalized as a Base before applying Deltas may stifle creativity. In these fields, “chaos” and “unpredictability” may be intrinsic to the process.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Integration cost with existing ecosystems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Although the article proposes non-invasive strategies like “Loader as Generator,” implementing GRC systemically within a large, complex system may still require deep changes to build processes, development habits, and even team organization—encountering substantial inertia in reality.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  IV. Relation to the Initial Discussion
&lt;/h3&gt;

&lt;p&gt;If the initial discussion was from a &lt;strong&gt;keen observer&lt;/strong&gt;, intuitively and by analogy pinpointing the core problem (one-way information loss) and the direction (reversibility),&lt;/p&gt;

&lt;p&gt;then this article is from a &lt;strong&gt;system builder&lt;/strong&gt;, who:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Took up the problem:&lt;/strong&gt; Clearly identified the problems as “complexity” and “entropy increase.”&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Named the direction:&lt;/strong&gt; Restored “reversibility” as “Generalized Reversible Computation (GRC).”&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Built the theory:&lt;/strong&gt; Proposed core formulas, triple dimensions, and the Dirac picture isomorphism.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Offered the blueprint:&lt;/strong&gt; Positioned GRC within a broad technical context and provided a pragmatic adoption roadmap.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In essence, this article furnishes the profound theoretical core and engineering path to realize the insights hinted at in the initial discussion.&lt;/p&gt;

&lt;h3&gt;
  
  
  V. Conclusion
&lt;/h3&gt;

&lt;p&gt;This is a &lt;strong&gt;landmark&lt;/strong&gt; manifesto. It performs a highly valuable task in software engineering: &lt;strong&gt;establishing a complete theoretical system and giving a resonant name—Generalized Reversible Computation (GRC)—to an advanced development philosophy (model-driven, delta-ized, declarative customization) long operating in “guerrilla” mode.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Its value lies not only in providing specific tools or methods, but in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Providing a new cognitive language:&lt;/strong&gt; “Generator,” “Delta,” “algebraic reversibility,” etc., enabling precise discussion and design of complex systems.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Providing a unified analytical framework:&lt;/strong&gt; Revealing the common construction laws behind Docker, Kustomize, etc.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Providing an elevated intellectual goal:&lt;/strong&gt; Elevating the role of software architects from “craftsmen” to “constructive physicists of the digital world,” seeking harmony with fundamental laws of the physical world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although the widespread adoption of the GRC paradigm will be a long journey, this article has undoubtedly lit a highly attractive lighthouse for the future of software engineering. It marks a solid and profound step from experience-driven “craft” to theory-guided “science.”&lt;/p&gt;

</description>
      <category>nop</category>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>ddd</category>
    </item>
    <item>
      <title>Feature Comparison : Nop Platform vs. SpringCloud</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Sat, 20 Dec 2025 12:27:37 +0000</pubDate>
      <link>https://forem.com/canonical/feature-comparison-nop-platform-vs-springcloud-3a8f</link>
      <guid>https://forem.com/canonical/feature-comparison-nop-platform-vs-springcloud-3a8f</guid>
      <description>&lt;p&gt;The Nop Platform is a next-generation low-code platform designed and implemented from scratch based on the principles of Reversible Computation. Its goal is not to provide preset development scaffolding and visual design tools targeting a few fixed scenarios, but to break down the man-made barriers between declarative programming and traditional imperative programming, establishing a new programming paradigm that makes the two seamlessly compatible and continuously expands the semantic space covered by declarative programming. To achieve this goal at the lowest technical cost, the Nop Platform does not adopt the industry’s mainstream foundational open-source frameworks; instead, it reshapes the entire technical stack based on the principles of Reversible Computation. This article briefly lists the “wheels” the Nop Platform has built and compares them to the existing “wheels” in the SpringCloud technology stack.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Nop stack&lt;/th&gt;
&lt;th&gt;Spring stack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Web Framework&lt;/td&gt;
&lt;td&gt;NopGraphQL&lt;/td&gt;
&lt;td&gt;SpringMVC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expression Engine&lt;/td&gt;
&lt;td&gt;XLang XScript&lt;/td&gt;
&lt;td&gt;SpringEL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Template Engine&lt;/td&gt;
&lt;td&gt;XLang Xpl&lt;/td&gt;
&lt;td&gt;Velocity/Freemarker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ORM Engine&lt;/td&gt;
&lt;td&gt;NopORM&lt;/td&gt;
&lt;td&gt;JPA/Mybatis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IoC Container&lt;/td&gt;
&lt;td&gt;NopIoC&lt;/td&gt;
&lt;td&gt;SpringIoC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic Configuration&lt;/td&gt;
&lt;td&gt;NopConfig&lt;/td&gt;
&lt;td&gt;SpringConfig&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distributed Transaction&lt;/td&gt;
&lt;td&gt;NopTcc&lt;/td&gt;
&lt;td&gt;Alibaba Seata&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automated Testing&lt;/td&gt;
&lt;td&gt;NopAutoTest&lt;/td&gt;
&lt;td&gt;SpringBootTest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distributed RPC&lt;/td&gt;
&lt;td&gt;NopRPC&lt;/td&gt;
&lt;td&gt;Feign RPC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reporting Engine&lt;/td&gt;
&lt;td&gt;NopReport&lt;/td&gt;
&lt;td&gt;JasperReport&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rule Engine&lt;/td&gt;
&lt;td&gt;NopRule&lt;/td&gt;
&lt;td&gt;Drools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch Engine&lt;/td&gt;
&lt;td&gt;NopBatch&lt;/td&gt;
&lt;td&gt;SpringBatch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflow Engine&lt;/td&gt;
&lt;td&gt;NopWorkflow&lt;/td&gt;
&lt;td&gt;Flowable/BPM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task Scheduling&lt;/td&gt;
&lt;td&gt;NopJob&lt;/td&gt;
&lt;td&gt;Quartz&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XML/JSON Parsing&lt;/td&gt;
&lt;td&gt;NopCore&lt;/td&gt;
&lt;td&gt;Jaxb/Jackson&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource Abstraction&lt;/td&gt;
&lt;td&gt;NopResource&lt;/td&gt;
&lt;td&gt;Spring Resource&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Generator&lt;/td&gt;
&lt;td&gt;NopCodeGen&lt;/td&gt;
&lt;td&gt;Various custom generators&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDE Plugin&lt;/td&gt;
&lt;td&gt;NopIdeaPlugin&lt;/td&gt;
&lt;td&gt;Mybatis plugin/Spring plugin, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Nop Platform can be used directly as a foundational development framework similar to SpringCloud. At the ProCode level it can greatly simplify the software development process and significantly improve software extensibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  I. IoC Container
&lt;/h2&gt;

&lt;p&gt;A declarative IoC container was the core capability that helped Spring rise to prominence. However, since Spring 2.0, SpringIoC has gradually lost its declarative nature, resulting in the runtime being mixed with a lot of imperative logic. A typical symptom is: changing the package scan order in Spring will subtly alter the bean wiring results.&lt;/p&gt;

&lt;p&gt;NopIoC builds upon the Spring 1.0 wiring syntax and adds conditional wiring logic similar to SpringBoot, and at runtime it fully reduces to the Spring 1.0 syntax to execute. The loading order of beans files and the declaration order of beans do not affect the final wiring result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;@ConditionOnMissingBean
@ConditionOnProperty("test.my-bean.enabled")
@Component
public class MyBean{
    @Inject
    OtherBean other;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Corresponding NopIoC configuration:&lt;br&gt;
&lt;/p&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;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"myBean"&lt;/span&gt; &lt;span class="na"&gt;ioc:default=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"test.MyBean"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ioc:condition&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;if-property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"test.my-bean.enabled"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ioc:condition&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NopIoC supports standardized annotations such as &lt;code&gt;@Inject&lt;/code&gt;, &lt;code&gt;@PostConstruct&lt;/code&gt;, &lt;code&gt;@PreDestroy&lt;/code&gt;, and it is compatible with Spring-specific &lt;code&gt;@Autowired&lt;/code&gt;. However, it does not use package scanning to discover bean definitions; instead, beans must be declared in a beans.xml file.&lt;/p&gt;

&lt;p&gt;Because the Nop Platform extensively adopts model-driven mechanisms to generate code dynamically, many bean definitions are automatically generated into configuration files, and there is actually very little that needs to be written by hand. You can also write an extension scanning function to use NopIoC’s metaprogramming capabilities to dynamically generate bean definitions. For example:&lt;br&gt;
&lt;/p&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;beans&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;x:gen-extends&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ioc-gen:scan&lt;/span&gt; &lt;span class="na"&gt;packages=&lt;/span&gt;&lt;span class="s"&gt;"test.my,test.other"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/x:gen-extends&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bean Customization
&lt;/h3&gt;

&lt;p&gt;What makes NopIoC unique is that you can customize wiring logic via standard Delta customization. For example, you can remove an existing bean definition using the following:&lt;br&gt;
&lt;/p&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;beans&lt;/span&gt; &lt;span class="na"&gt;x:extends=&lt;/span&gt;&lt;span class="s"&gt;"super"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"dataSource"&lt;/span&gt; &lt;span class="na"&gt;x:override=&lt;/span&gt;&lt;span class="s"&gt;"remove"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dynamic Configuration
&lt;/h3&gt;

&lt;p&gt;NopIoC is designed with unified integration with the NopConfig configuration center. In beans.xml you can denote dynamic configuration items via special prefixes:&lt;br&gt;
&lt;/p&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;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"xx"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"poolSize"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"@r-cfg:my.pool-size|5"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;@r-cfg:&lt;/code&gt; prefix indicates a dynamic configuration item. When the configuration center changes the configuration, the bean property will be automatically updated.&lt;/p&gt;

&lt;p&gt;Additionally, the beans syntax defines a dedicated ioc:config node:&lt;br&gt;
&lt;/p&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;ioc:config&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"nopOrmGlobalCacheConfig"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"io.nop.commons.cache.CacheConfig"&lt;/span&gt;
    &lt;span class="na"&gt;ioc:config-prefix=&lt;/span&gt;&lt;span class="s"&gt;"nop.orm.global-cache"&lt;/span&gt;  &lt;span class="na"&gt;ioc:default=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The NopIoC container automatically tracks all references to &lt;code&gt;ioc:config&lt;/code&gt;. Once the configuration changes, it will automatically trigger the refresh-config method defined on those beans that use the config.&lt;/p&gt;

&lt;p&gt;The ioc:config-prefix serves a role similar to Spring’s &lt;code&gt;@ConfigurationProperties&lt;/code&gt;, used to specify the prefix of configuration items in the configuration file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interoperability with SpringIoC
&lt;/h3&gt;

&lt;p&gt;NopIoC and the Spring container can be used together. Generally, NopIoC starts after SpringIoC has initialized, and it can obtain beans managed by Spring through the parentContainer. Therefore, in NopIoC you can directly inject Spring-managed beans via &lt;code&gt;@Inject&lt;/code&gt;. In beans managed by Spring, you can use beanContainer to retrieve beans managed by NopIoC by name or by type.&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="nc"&gt;BeanContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;intance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;beanName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;BeanContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;intance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getBeanByType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;beanType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NopIoC aims to be a better SpringIoC. It adheres to a strictly declarative design, can be integrated within the Spring ecosystem, and its entire codebase is under 5,000 lines. For more detailed design, see: &lt;a href="https://dev.to/canonical/if-we-rewrote-springboot-from-scratch-what-different-choices-would-we-make-m07"&gt;If We Were to Rewrite SpringBoot, What Different Choices Would We Make?&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  II. Web Framework
&lt;/h2&gt;

&lt;p&gt;In the SpringCloud technology stack, we typically call Service from Controller to implement specific business logic, and in the Controller we handle structure transformation or composition work, such as converting entity objects to DTOs. To implement GraphQL service interfaces, we need to use the graphql-java package to rewrite the interface layer code and cannot directly reuse Controllers to expose services.&lt;/p&gt;

&lt;p&gt;The NopGraphQL engine greatly simplifies the design of the service interface layer. In general, we can directly expose domain model objects as external service interfaces, implement permission control and structural adaptation at the metadata layer, and avoid adaptation and transformation in the Controller layer.&lt;/p&gt;

&lt;p&gt;For example, even for the simplest web service, we still need to specify URL patterns and parameter passing (query params, path params, or body). Many times we inadvertently introduce dependencies on HttpServlet interfaces, binding the entire service to a specific web runtime environment.&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;@RestController&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;MyController&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/echo/{id}"&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;echo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@QueryParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"msg"&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;msg&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                 &lt;span class="nd"&gt;@PathParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&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;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletRequest&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="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Hello Nacos Discovery "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;",id="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;id&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 the Nop Platform, we only need to add the &lt;code&gt;@BizModel&lt;/code&gt; annotation on the domain model object, then mark the service method and parameter names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;@BizModel("MyObject")
public class MyObjectBizModel{
    @BizQuery
    public PageBean&lt;span class="nt"&gt;&amp;lt;MyEntity&amp;gt;&lt;/span&gt; findPage(@Name("id") id,
             FieldSelection selection, IServiceContext ctx){
       return ....
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;NopGraphQL can provide REST services, but it enforces a fixed URL pattern: &lt;code&gt;/r/{bizObjName}__{bizAction}&lt;/code&gt;, so you don’t have to design link patterns for each request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Methods marked with @BizQuery can be accessed via POST and GET, while methods marked with @BizMutation support only POST. This automatic inference also helps prevent misuse.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For parameters, you only need to mark the parameter names with &lt;a class="mentioned-user" href="https://dev.to/name"&gt;@name&lt;/a&gt;; there’s no need to specify the passing mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Methods marked @BizMutation will automatically enable transaction management, so there’s no need for additional @Transactional annotations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  GraphQL as a General Decomposition and Composition Solution
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4eib787crpmdlhv5rgsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4eib787crpmdlhv5rgsg.png" alt="graphql engine" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NopGraphQL not only simultaneously provides GraphQL and REST service modes, but its role in the Nop Platform is to serve as a general-purpose decomposition and composition solution. In the Nop Platform, all message services, batch services, RPC services, etc., upon receiving a request message, deliver it to the GraphQLEngine for processing.&lt;/p&gt;

&lt;p&gt;Ordinary web framework service methods generally do not support directly returning entity objects because entity objects typically contain too much information and are not suitable for direct serialization to the frontend. However, under the coordination of the GraphQL engine, the return value of the service method is not returned directly to the frontend; it is enhanced by selection and the Data Loader. Given this, NopGraphQL completely delegates the result conversion and adaptation work to the GraphQL engine (based on metadata provided by XMeta). That is, you can implement an adaptation layer through configuration without a separately designed Controller adaptation layer.&lt;/p&gt;

&lt;p&gt;The NopGraphQL engine can be used outside a web environment, in any scenario requiring work decomposition and result selection/adaptation. It provides an IServiceContext context object that is runtime-independent (essentially equivalent to a Map). You can use it to cache and share data across multiple service calls to optimize batch processing performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distributed RPC
&lt;/h3&gt;

&lt;p&gt;In the SpringCloud technology stack, the server automatically registers itself with the service registry on startup, and then the client adds a Feign interface to achieve load-balanced calls. Canary releases, A/B testing, etc., can leverage the service routing mechanism here.&lt;/p&gt;

&lt;p&gt;In NopGraphQL, we also add a service invocation interface:&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;RuleService&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;CompletionStage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RuleResultBean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;executeRuleAsync&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ApiRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RuleRequestBean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;default&lt;/span&gt; &lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RuleResultBean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;executeRule&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ApiRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RuleRequestBean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;FutureHelper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;syncGet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executeRuleAsync&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Service interfaces support both asynchronous and synchronous invocation modes; asynchronous methods conventionally return CompletionStage and have the Async suffix in their method names.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is stipulated that request parameters be of type ApiRequest and return results of type ApiResponse, enabling direct setting and reading of headers at the message object layer without relying on underlying runtime interfaces.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No additional annotations are required on the service interface—e.g., no need to add &lt;a class="mentioned-user" href="https://dev.to/path"&gt;@path&lt;/a&gt; for REST path declarations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create a distributed RPC client via beans.xml configuration:&lt;br&gt;
&lt;/p&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;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"testGraphQLRpc"&lt;/span&gt; &lt;span class="na"&gt;parent=&lt;/span&gt;&lt;span class="s"&gt;"AbstractRpcProxyFactoryBean"&lt;/span&gt;
          &lt;span class="na"&gt;ioc:type=&lt;/span&gt;&lt;span class="s"&gt;"io.nop.rpc.client.TestRpc"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"serviceName"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"rpc-demo-consumer"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By setting nop.rpc.service-mesh.enabled=true, you can enable service mesh mode and bypass client-side load-balancing proxies.&lt;/p&gt;

&lt;p&gt;For detailed introductions, see:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/why-has-graphql-struggled-to-become-popular-under-design-or-over-design-47gb"&gt;GraphQL Engine in a Low-Code Platform&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/distributed-rpc-framework-in-a-low-code-platform-3000-loc-1phh"&gt;Distributed RPC Framework in a Low-Code Platform (about 3,000 lines of code)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  III. Storage Layer
&lt;/h2&gt;

&lt;p&gt;The NopORM engine includes most of the features of SpringData, JPA, and MyBatis, and adds a large number of commonly used capabilities in business development, such as field encryption, logical deletion, change history tracking, extension fields, multi-tenancy, etc.&lt;/p&gt;

&lt;p&gt;At the API level, NopORM usage is very similar to Spring, except it always uses XML model files instead of JPA annotations.&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="nc"&gt;IEntityDao&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NopAuthUser&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;daoProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;daoFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NopAuthUser&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="nc"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newEntity&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMyField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Find the first matching record&lt;/span&gt;
&lt;span class="nc"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findFirstByExample&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;QueryBean&lt;/span&gt; &lt;span class="n"&gt;query&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;QueryBean&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setFilter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PROP_NAME_myField&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PROP_NAME_myStatus&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setLimit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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="nc"&gt;MyEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findPageByQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generally, methods provided on the built-in IEntityDao are already sufficiently rich. They support very complex query conditions, so there is no need to generate a separate DAO interface for each entity. You typically obtain the corresponding IEntityDao via the DaoProvider.&lt;/p&gt;

&lt;p&gt;For complex queries, you can directly use a MyBatis-like sql-lib mechanism and manage complex dynamic SQL via XML models.&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;@SqlLibMapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/app/mall/sql/LitemallGoods.sql-lib.xml"&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;interface&lt;/span&gt; &lt;span class="nc"&gt;LitemallGoodsMapper&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;syncCartProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"product"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;LitemallGoodsProduct&lt;/span&gt; &lt;span class="n"&gt;product&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;Add the @SqlLibMapper annotation on the Mapper interface to define the mapping between the sql-lib model and the Java interface.&lt;/p&gt;

&lt;p&gt;In a sql-lib model, you can generate SQL statements via the Xpl template language:&lt;br&gt;
&lt;/p&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;eql&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"syncCartProduct"&lt;/span&gt; &lt;span class="na"&gt;sqlMethod=&lt;/span&gt;&lt;span class="s"&gt;"execute"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;arg&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"product"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
                update LitemallCart o
                set o.price = ${product.price},
                  o.goodsName = ${product.goods.name},
                  o.picUrl = ${product.url},
                  o.goodsSn = ${product.goods.goodsSn}
                where o.productId = ${product.id}
            &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/eql&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Excel Model-Driven
&lt;/h3&gt;

&lt;p&gt;The Nop Platform provides a very powerful model-driven development model. It can parse Excel data model files to automatically generate entity definitions, Mapper interface definitions, metadata definitions, backend GraphQL services, and even frontend add/update/query pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funrx23qs7x8qiyf1ocn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funrx23qs7x8qiyf1ocn4.png" alt="excel-model" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For detailed designs, see:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/what-kind-of-orm-engine-does-a-low-code-platform-need-2-mfj"&gt;What Kind of ORM Engine Does a Low-Code Platform Need? (2)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/data-driven-generic-code-generator-2p9c"&gt;Data-Driven Delta Code Generator&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/docs-en/tutorial/tutorial.md" rel="noopener noreferrer"&gt;Nop Platform: An Open-Source Low-Code Platform Based on the Theory of Reversible Computation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/how-to-add-extended-fields-to-entities-without-modifying-tables-5k"&gt;How a Low-Code Platform Adds Extension Fields to Entities Without Altering Tables&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  IV. Underlying Language
&lt;/h2&gt;

&lt;p&gt;The Nop Platform provides the XLang language designed specifically for DSL development, which includes multiple sub-languages: XScript scripting language, Xpl template language, XTransform structure transformation language, and XDef meta-model definition language. Among them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The XScript scripting language has a syntax similar to JavaScript and supports a Java-like type system; it can be used as a general-purpose expression language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Xpl template language is similar to FreeMarker, supports custom tag libraries, and supports compile-time macro processing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The XDef meta-model definition language is similar to XML Schema; it is a very simple and intuitive meta-model definition language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;XTransform is a general tree structure transformation language similar to XSLT.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdaw58wa1wgty8w1st3yo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdaw58wa1wgty8w1st3yo.png" alt="XLang" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the bottom layer, the Nop Platform has substantially transformed XML handling. It merely uses the basic XML syntax form and does not use the JAXB standard or the commonly used XML parsers in Java. Instead, XML and JSON parsers were written entirely from scratch. Compared to commonly used XML parsers and DOM models, the Nop Platform’s XNode structure is simpler and more intuitive. It has a built-in SourceLocation tracking mechanism and can be directly used as a generic AST node.&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="nc"&gt;XNode&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;XNodeParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;parseFromText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTagName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Read the tag name&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAttr&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="c1"&gt;// Read an attribute&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAttr&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="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Set an attribute&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attrText&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="c1"&gt;// Get a text attribute; returns null if the text value is empty rather than an empty string&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attrTextOrEmpty&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="c1"&gt;// Returns empty string if the attribute value is empty; returns null if the attribute does not exist&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attrInt&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="c1"&gt;// Get the attribute value and convert it to Integer&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attrInt&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="n"&gt;defaultValue&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Return the default value if the attribute value is empty&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attrBoolean&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="c1"&gt;// Read the attribute value and convert it to Boolean&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attrLong&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="c1"&gt;// Read the attribute value and convert it to Long&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attrCsvSet&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="c1"&gt;// Read a string attribute and convert it to a set by splitting on commas&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAttrs&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Get the attribute map&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getChildren&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Get child nodes&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;childByTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tagName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Find a child node by tag name&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;childByAttr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrValue&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Find a child node by attribute value&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getContentValue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Read the node’s content value&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasChild&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Whether there are child nodes&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasAttr&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Whether there are attributes&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasContent&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Whether the direct content is non-empty&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasBody&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;// Whether there are child nodes or direct content&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getParent&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Get the parent node&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cloneInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Clone the node&lt;/span&gt;

&lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cloneChildren&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Clone all child nodes&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;detach&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Detach from the parent&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Remove from the parent&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replaceBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newNode&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Replace this node with newNode in the parent’s children list&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Get the node’s XML text&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerXml&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Get the node’s inner XML text&lt;/span&gt;

&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toTreeBean&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Convert to a TreeBean object&lt;/span&gt;

&lt;span class="nc"&gt;XNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromTreeBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;treeBean&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Convert from a TreeBean to XNode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compared to expression and template languages in the Spring ecosystem, the Nop Platform’s XLang language has stronger design consistency:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Multiple sub-languages share many syntax features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple sub-languages share a global function library.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;General Java functions can be registered as global functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The syntax resembles JavaScript and supports object function calls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A highly customizable expression parser, SimpleExprParser, is provided. ReportExprParser (used in the reporting engine) and RuleExprParser (used in the rule engine) are both customized on top of this expression engine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Systematic support for compile-time metaprogramming, such as macro functions and macro tags.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For further details, see:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/metaprogramming-in-low-code-platforms-4b0h"&gt;Metaprogramming in a Low-Code Platform&lt;/a&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/xdef-a-unified-meta-model-definition-language-to-replace-xsd-2cem"&gt;XDef: A Unified Meta-Model Definition Language to Replace XSD&lt;/a&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/dsl-design-essentials-from-the-perspective-of-reversible-computation-374l"&gt;Design Essentials of DSLs from the Perspective of Reversible Computation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  V. Import/Export
&lt;/h2&gt;

&lt;p&gt;NopReport is an open-source, from-scratch implementation of a Chinese-style reporting engine based on the theory of Reversible Computation. Its core codebase is short—just over 3,000 lines (see the &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/tree/master/nop-report/nop-report-core" rel="noopener noreferrer"&gt;nop-report-core&lt;/a&gt; module)—with high performance (performance test code at &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-report/nop-report-demo/src/test/java/io/nop/report/demo/TestReportSpeed.java" rel="noopener noreferrer"&gt;TestReportSpeed.java&lt;/a&gt;), and a level of flexibility and extensibility difficult for other reporting engines to match.&lt;/p&gt;

&lt;p&gt;Within the &lt;a href="https://gitee.com/canonical-entropy/nop-entropy" rel="noopener noreferrer"&gt;Nop Platform&lt;/a&gt;, NopReport is positioned as a general modeling tool for tabular data structures. Any functionality that needs to generate tabular data can be converted into a NopReport report model object. For example, the database reverse-engineering command provided by the NopCli command-line tool analyzes database schemas and generates an Excel model file. This Excel model is produced by converting an import template into a report output model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jbxelju7ilnvkll31yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jbxelju7ilnvkll31yb.png" alt="cross table report" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cca9agnzrngih9sl4es.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cca9agnzrngih9sl4es.png" alt="cross table report" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compared with other reporting engines, NopReport has the following distinctive characteristics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Uses Excel as the template designer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can directly use domain model objects as data objects; DataSet is only an optional form of data object. (Typical reporting engines only support tabular data.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extends the concept of hierarchical coordinates on top of a general expression syntax rather than using a specially designed reporting expression syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports multiple sheets and loop generation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Beyond data export, NopReport also supports importing custom data structures. No coding is required—only minimal configuration is needed to import Excel data models. All Excel model files used in the Nop Platform, such as ORM entity models and API interface models, are imported via the reporting import mechanism.&lt;/p&gt;

&lt;p&gt;For detailed introductions, see:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/open-source-chinese-style-reporting-engine-using-excel-as-the-designer-nopreport-2j20"&gt;An Open-Source Chinese-Style Reporting Engine Using Excel as the Designer: NopReport&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/canonical/how-to-implement-a-visual-word-template-similar-to-poi-tl-with-800-lines-of-code-31o3"&gt;How to Implement a Visual Word Template Like poi-tl in 800 Lines of Code&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.bilibili.com/video/BV1M14y1271a/" rel="noopener noreferrer"&gt;How to Support Dynamic Columns and Styles When Importing/Exporting Excel&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  VI. Logical Orchestration
&lt;/h2&gt;

&lt;p&gt;The Nop Platform provides engines for business rules, workflow, batch processing, and task scheduling—covering the full description of general business logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ulm250pxgqkhfwj8ixt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ulm250pxgqkhfwj8ixt.png" alt="decision matrix" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See: &lt;a href="https://dev.to/canonical/noprule-a-rule-engine-that-uses-excel-as-a-visual-designer-4a8i"&gt;NopRule: A Rule Engine Using Excel as the Visual Designer&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  VII. Automated Testing
&lt;/h2&gt;

&lt;p&gt;SpringBootTest provides integration between the Spring framework and test frameworks such as JUnit. In the Nop Platform, you can use dependency injection to obtain beans under test simply by extending the JunitAutoTest base class.&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;@NopTestConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localDb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;initDatabaseSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;TestGraphQLTransaction&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JunitAutoTestCase&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Inject&lt;/span&gt;
    &lt;span class="nc"&gt;IDaoProvider&lt;/span&gt; &lt;span class="n"&gt;daoProvider&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Inject&lt;/span&gt;
    &lt;span class="nc"&gt;IGraphQLEngine&lt;/span&gt; &lt;span class="n"&gt;graphQLEngine&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@EnableSnapshot&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testRollback&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;GraphQLRequestBean&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;new&lt;/span&gt; &lt;span class="nc"&gt;GraphQLRequestBean&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;setQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mutation { DemoAuth__testFlushError }"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;IGraphQLExecutionContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphQLEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newGraphQLContext&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="nc"&gt;GraphQLResponseBean&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphQLEngine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;executeGraphQL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&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="s"&gt;"response.json5"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;daoProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;daoFor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NopAuthRole&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;getEntityById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test123"&lt;/span&gt;&lt;span class="o"&gt;)&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="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;Through the @NopTestConfig annotation, you can easily control certain configuration switches related to automated testing.&lt;/p&gt;

&lt;p&gt;What makes the NopAutoTest framework unique is that it provides model-driven automated testing. It can implement automated testing of complex business functions via recording and replay mechanisms—no test code needs to be written by hand.&lt;/p&gt;

&lt;p&gt;See: &lt;a href="https://dev.to/canonical/automated-testing-a-low-code-platforms-perspective-2gbe"&gt;Automated Testing in a Low-Code Platform&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  VIII. Tooling
&lt;/h2&gt;

&lt;p&gt;The Nop Platform provides a code generator integrated with Maven that can be used independently outside the Nop Platform. Based on user-defined model files and user-defined code templates, it generates specified code in a delta-based incremental manner. Typical code generators, whether for models or templates, find it difficult to support fine-grained customization.&lt;/p&gt;

&lt;p&gt;See: &lt;a href="https://dev.to/canonical/data-driven-generic-code-generator-2p9c"&gt;Data-Driven Delta Code Generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NopIdeaPlugin provides a general IntelliJ IDEA plugin. It automatically recognizes the meta-model specified by the x:schema attribute on an XML root node and implements attribute hints, link navigation, and format validation according to the meta-model. For code snippets, it also provides breakpoint debugging.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihvvh5davmyjm9z2wag5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihvvh5davmyjm9z2wag5.jpg" alt="idea completion" width="673" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73syaofmhz4wddmuycvs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73syaofmhz4wddmuycvs.png" alt="xlang debugger" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Compared to SpringCloud, the Nop Platform has the following characteristics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Simple and direct implementation principles. The code size is generally an order of magnitude smaller than Spring components, yet the core functionality is richer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports Delta-based customization. You can add Delta model files under the Delta directory to customize all existing features (including built-in platform features). For example, all data models and all designer pages can be freely customized.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leverages code generation and metaprogramming for automatic inference, greatly reducing the amount of code that must be written by hand and ensuring a high level of internal structural consistency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uniformly uses the XDSL specification to implement DSL models. You can add new DSL models at any time or add new extension attributes to existing DSLs. The IDE plugin automatically recognizes and supports new DSL models without writing specialized support plugins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Model-driven processes are integrated into DevOps. Code generation and model transformation are performed during the Maven packaging process, eliminating the need to deploy a separate model management platform.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Nop Platform can serve as an extension component running atop SpringCloud. It does not conflict with SpringCloud’s built-in mechanisms. Its internal components can be replaced with SpringCloud implementations—but doing so will lose many advanced features, reduce performance and extensibility, and undermine the inferability of the program’s structure.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>spring</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>XDef: A Unified Meta-Model Definition Language to Replace XSD</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Fri, 19 Dec 2025 12:06:23 +0000</pubDate>
      <link>https://forem.com/canonical/xdef-a-unified-meta-model-definition-language-to-replace-xsd-2cem</link>
      <guid>https://forem.com/canonical/xdef-a-unified-meta-model-definition-language-to-replace-xsd-2cem</guid>
      <description>&lt;p&gt;All DSLs in the Nop platform uniformly adopt the XML format rather than custom surface syntaxes, which simplifies DSL design and provides a unified IDE development toolset. Specifically, every DSL uses a unified XDef meta-model to define the concrete syntax of the DSL (the XML structure), and then leverages a series of built-in mechanisms in the Nop platform to automatically generate code, implementing DSL parsing, validation, and other functions.&lt;/p&gt;

&lt;p&gt;The role of an XDef meta-model file is similar to an XSD (XML Schema Definition) file: both add syntactic constraints to XML. However, XDef is simpler and easier to use compared to XSD, while also offering more powerful constraint capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  XDef Syntax Example
&lt;/h2&gt;

&lt;p&gt;Let's look at a simple workflow DSL definition: a workflow contains multiple steps, and each step, upon completion, specifies the next executable step.&lt;br&gt;
&lt;/p&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;workflow&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Test"&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/my-wf.xdef"&lt;/span&gt; &lt;span class="na"&gt;xmlns:x=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdsl.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;displayName=&lt;/span&gt;&lt;span class="s"&gt;"StepA"&lt;/span&gt; &lt;span class="na"&gt;next=&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;c:script&amp;gt;&lt;/span&gt;
                    import app.MyHelper;
                    MyHelper.doSomething();
                &lt;span class="nt"&gt;&amp;lt;/c:script&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt; &lt;span class="na"&gt;displayName=&lt;/span&gt;&lt;span class="s"&gt;"StepB"&lt;/span&gt; &lt;span class="na"&gt;joinType=&lt;/span&gt;&lt;span class="s"&gt;"and"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/workflow&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corresponding meta-model is&lt;br&gt;
&lt;/p&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;workflow&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt; &lt;span class="na"&gt;x:schema=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdef.xdef"&lt;/span&gt; &lt;span class="na"&gt;xmlns:x=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdsl.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;steps&lt;/span&gt; &lt;span class="na"&gt;xdef:body-type=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt; &lt;span class="na"&gt;xdef:key-attr=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt; &lt;span class="na"&gt;displayName=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt; &lt;span class="na"&gt;internal=&lt;/span&gt;&lt;span class="s"&gt;"!boolean=false"&lt;/span&gt;
              &lt;span class="na"&gt;joinType=&lt;/span&gt;&lt;span class="s"&gt;"enum:io.nop.wf.core.model.WfJoinType"&lt;/span&gt; &lt;span class="na"&gt;next=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;xdef:value=&lt;/span&gt;&lt;span class="s"&gt;"xpl"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/workflow&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we can see that the XDef meta-model and the model it describes are in a homomorphic relationship; put simply, by replacing values in the model's XML with type descriptors, you obtain the XDef meta-model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name="!string"&lt;/code&gt; indicates that the &lt;code&gt;name&lt;/code&gt; attribute is of type &lt;code&gt;string&lt;/code&gt;; the character &lt;code&gt;!&lt;/code&gt; means the attribute value cannot be null.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;xdef:body-type="list"&lt;/code&gt; means the node, after parsing, corresponds to a list type; &lt;code&gt;xdef:key-attr="id"&lt;/code&gt; means each element in the list must have an &lt;code&gt;id&lt;/code&gt; attribute, which distinguishes different elements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;internal="!boolean=false"&lt;/code&gt; means the &lt;code&gt;internal&lt;/code&gt; attribute is non-null, of type &lt;code&gt;boolean&lt;/code&gt;, with a default value of &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;joinType="enum:io.nop.wf.core.model.WfJoinType"&lt;/code&gt; means the value of the &lt;code&gt;joinType&lt;/code&gt; attribute is of type &lt;code&gt;WfJoinType&lt;/code&gt;, which is an enum.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;xdef:value="xpl"&lt;/code&gt; indicates the content of the &lt;code&gt;source&lt;/code&gt; node (including its direct text content and all child nodes) is a snippet of Xpl template language code, which after parsing yields an &lt;code&gt;IEvalAction&lt;/code&gt; object (similar to a &lt;code&gt;Function&lt;/code&gt; object in JavaScript).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All attributes in xdef files (excluding built-in attributes in the &lt;code&gt;xdef&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; namespaces) have values of type &lt;code&gt;def-type&lt;/code&gt;. Its format is &lt;code&gt;(!~#)?{stdDomain}:{options}={defaultValue}&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;!&lt;/code&gt; indicates a required attribute, &lt;code&gt;~&lt;/code&gt; indicates an internal or deprecated attribute, and &lt;code&gt;#&lt;/code&gt; indicates a compile-time expression can be used.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stdDomain&lt;/code&gt; is a constraint stricter than a data type, e.g., &lt;code&gt;stdDomain=email&lt;/code&gt;. See the dictionary definition &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-kernel/nop-xlang/src/main/resources/_vfs/dict/core/std-domain.dict.yaml" rel="noopener noreferrer"&gt;core/std-domain&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Some &lt;code&gt;def-type&lt;/code&gt; definitions require &lt;code&gt;options&lt;/code&gt; parameters, e.g., &lt;code&gt;enum:xxx.yyy&lt;/code&gt;, where &lt;code&gt;options&lt;/code&gt; sets the specific dictionary name.&lt;/li&gt;
&lt;li&gt;A default value can be specified for attributes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common XDSL Syntax
&lt;/h2&gt;

&lt;p&gt;The meta-model must be introduced via the &lt;code&gt;x:schema&lt;/code&gt; attribute on the XML root node. For example, &lt;code&gt;x:schema="/nop/schema/my-wf.xdef"&lt;/code&gt; indicates the model is constrained by the &lt;code&gt;my-wf.xdef&lt;/code&gt; meta-model.&lt;/p&gt;

&lt;p&gt;All DSL languages in the Nop platform share some common attributes and child nodes, effectively introducing a common syntax for all DSLs; the &lt;code&gt;x:schema&lt;/code&gt; attribute is part of this common syntax. These common syntaxes are defined in the &lt;code&gt;xdsl.xdef&lt;/code&gt; meta-model, so we specify on the root node &lt;code&gt;xmlns:x="/nop/schema/xdsl.xdef"&lt;/code&gt; to indicate that the &lt;code&gt;x&lt;/code&gt; namespace corresponds to the DSL common syntax space. For details, see&lt;br&gt;
&lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-kernel/nop-xdefs/src/main/resources/_vfs/nop/schema/xdsl.xdef" rel="noopener noreferrer"&gt;xdsl.xdef&lt;/a&gt; and&lt;br&gt;
&lt;a href="https://zhuanlan.zhihu.com/p/612512300" rel="noopener noreferrer"&gt;XDSL: General-Purpose Domain-Specific Language Design&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The XDef meta-model definition language is powerful enough to describe the XDef meta-model itself; see &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-kernel/nop-xdefs/src/main/resources/_vfs/nop/schema/xdef.xdef" rel="noopener noreferrer"&gt;xdef.xdef&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the meta-meta model definition file &lt;code&gt;xdef.xdef&lt;/code&gt;, the &lt;code&gt;xdef&lt;/code&gt; namespace must be treated as an ordinary attribute namespace and cannot be interpreted as XDef meta attributes, so we add the attribute definition &lt;code&gt;xmlns:meta="/nop/schema/xdef.xdef"&lt;/code&gt; on the root node and use the &lt;code&gt;meta&lt;/code&gt; namespace to express meta attributes.&lt;br&gt;
&lt;/p&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;workflow&lt;/span&gt; &lt;span class="na"&gt;xmlns:meta=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdef.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;steps&lt;/span&gt; &lt;span class="na"&gt;meta:body-type=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt; &lt;span class="na"&gt;meta:key-attr=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        ...
    &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/workflow&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Equivalent to&lt;br&gt;
&lt;/p&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;workflow&lt;/span&gt; &lt;span class="na"&gt;xmlns:xdef=&lt;/span&gt;&lt;span class="s"&gt;"/nop/schema/xdef.xdef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;steps&lt;/span&gt; &lt;span class="na"&gt;xdef:body-type=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt; &lt;span class="na"&gt;xdef:key-attr=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        ...
    &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/workflow&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reusing Node Definitions
&lt;/h2&gt;

&lt;p&gt;In xdef files, you can reference existing meta-model definitions via &lt;code&gt;xdef:ref&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import an external xdef file
&lt;/li&gt;
&lt;/ol&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;form&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt; &lt;span class="na"&gt;xdef:ref=&lt;/span&gt;&lt;span class="s"&gt;"form.xdef"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Reference an internal node
You can add the &lt;code&gt;xdef:name&lt;/code&gt; attribute to any node to mark it as a named node, then reference it via &lt;code&gt;xdef:ref&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&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;steps&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt; &lt;span class="na"&gt;xdef:name=&lt;/span&gt;&lt;span class="s"&gt;"WorkflowStepModel"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        ...
    &lt;span class="nt"&gt;&amp;lt;/step&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;join&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt; &lt;span class="na"&gt;xdef:ref=&lt;/span&gt;&lt;span class="s"&gt;"WorkflowStepModel"&lt;/span&gt; &lt;span class="na"&gt;xdef:name=&lt;/span&gt;&lt;span class="s"&gt;"WfJoinStepModel"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/join&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Due to current implementation reasons, attributes such as &lt;code&gt;id&lt;/code&gt; that uniquely distinguish collection elements need to be repeated; other attributes can be directly referenced from other nodes without redefining them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;During code generation, &lt;code&gt;xdef:name&lt;/code&gt; is treated as the Java class name corresponding to the node, and &lt;code&gt;xdef:ref&lt;/code&gt; is treated as the base class of the current node class.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xdef:ref="WorkflowStepModel" xdef:name="WfJoinStepModel"&lt;/code&gt; corresponds to generated code &lt;code&gt;class WfJoinStepModel extends WorkflowStepModel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To simplify node reuse, XDef also defines a special node solely for reuse, &lt;code&gt;xdef:define&lt;/code&gt;, for example&lt;br&gt;
&lt;/p&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;workflow&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;xdef:define&lt;/span&gt; &lt;span class="na"&gt;xdef:name=&lt;/span&gt;&lt;span class="s"&gt;"WorkflowStepModel"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        ....
    &lt;span class="nt"&gt;&amp;lt;/xdef:define&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;steps&lt;/span&gt; &lt;span class="na"&gt;xdef:body-type=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt; &lt;span class="na"&gt;xdef:key-attr=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;xdef:ref=&lt;/span&gt;&lt;span class="s"&gt;"WorkflowStepModel"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/workflow&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;xdef:define&lt;/code&gt; defines a reusable part, equivalent to defining a base class, and nodes can inherit this base class via &lt;code&gt;xdef:ref&lt;/code&gt;. &lt;code&gt;xdef:name&lt;/code&gt; serves as the base class's class name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collection Node Definitions
&lt;/h2&gt;

&lt;p&gt;In addition to using &lt;code&gt;xdef:body-type="list"&lt;/code&gt; to denote a collection node, xdef also provides a simplified way to define collection nodes: use &lt;code&gt;xdef:unique-attr&lt;/code&gt; to denote the unique identifying attribute of collection elements.&lt;br&gt;
&lt;/p&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;arg&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt; &lt;span class="na"&gt;xdef:unique-attr=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"any"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A node with &lt;code&gt;xdef:unique-attr&lt;/code&gt; will be parsed as a collection property; the property name is generally the camelCase form of the node name plus 's', e.g., &lt;code&gt;&amp;lt;task-step xdef:unique-attr="id"&amp;gt;&lt;/code&gt; corresponds to &lt;code&gt;taskSteps&lt;/code&gt;. You can also specify the property name via &lt;code&gt;xdef:bean-prop&lt;/code&gt;, e.g., &lt;code&gt;xdef:bean-prop="taskStepList"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!--
  The following DSL definition is equivalent to the code:
  bp.taskSteps.add({id: 'a', displayName: 'A'})
  bp.taskSteps.add({id: 'b', displayName: 'B'})
--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;task-step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;displayName=&lt;/span&gt;&lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/task-step&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;task-step&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt; &lt;span class="na"&gt;displayName=&lt;/span&gt;&lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/task-step&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The advantage of defining collection properties via &lt;code&gt;xdef:body-type="list"&lt;/code&gt; is that it allows the collection to contain different types of child nodes, for example&lt;br&gt;
&lt;/p&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;steps&lt;/span&gt; &lt;span class="na"&gt;xdef:body-type=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt; &lt;span class="na"&gt;xdef:key-attr=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;xdef:bean-sub-type-prop=&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt; &lt;span class="na"&gt;xdef:bean-child-name=&lt;/span&gt;&lt;span class="s"&gt;"step"&lt;/span&gt;
       &lt;span class="na"&gt;xdef:bean-body-type=&lt;/span&gt;&lt;span class="s"&gt;"List&amp;amp;lt;io.nop.wf.core.model.WfStepModel&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt; &lt;span class="na"&gt;xdef:bean-tag-prop=&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;join&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"!string"&lt;/span&gt; &lt;span class="na"&gt;xdef:bean-tag-prop=&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;xdef:bean-body-type&lt;/code&gt; specifies the type name of the generated collection property.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;xdef:bean-child-name="step"&lt;/code&gt; means the model object will automatically have a &lt;code&gt;getStep(String name)&lt;/code&gt; method to retrieve a child node by its unique identifier attribute.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;xdef:bean-tag-prop="type"&lt;/code&gt; means the node's tag name (&lt;code&gt;step&lt;/code&gt;, &lt;code&gt;join&lt;/code&gt;) will be parsed as the value of the &lt;code&gt;type&lt;/code&gt; attribute during JSON serialization.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;xdef:bean-sub-type-prop="type"&lt;/code&gt; indicates that during JSON deserialization, the &lt;code&gt;type&lt;/code&gt; attribute determines the child node type.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!--
  After conversion to JSON, the structure of the following DSL definition is:
  {
    "steps": [{
      "type": "step",
      "name": "a"
    }, {
      "type": "join",
      "name": "b"
    }]
  }
--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;steps&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;step&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;join&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/steps&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What's the difference between defining with &lt;code&gt;&amp;lt;parent&amp;gt; &amp;lt;item xdef:value="string"&amp;gt; &amp;lt;/parent&amp;gt;&lt;/code&gt; and defining with &lt;code&gt;&amp;lt;parent item="string"&amp;gt;&lt;/code&gt;? There's no difference in the generated Java; it's only a difference in the XML form.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If &lt;code&gt;xdef:body-type="list"&lt;/code&gt; is specified, must its child nodes be object types? How should basic types like int or string be written? I haven't handled this case; if it must be handled, the current approach is something like &lt;code&gt;&amp;lt;list xdef:body-type="list"&amp;gt; &amp;lt;_ xdef:value="int" /&amp;gt;&lt;/code&gt;. Additionally, for common comma-separated list values, you can directly write &lt;code&gt;&amp;lt;list xdef:value="csv-list" /&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a node has already set &lt;code&gt;xdef:body-type="list"&lt;/code&gt; but also has other attributes, e.g., &lt;code&gt;&amp;lt;row name="string" xdef:body-type="list" height="string"&amp;gt;&lt;/code&gt;, what structure will be generated? By default the body content corresponds to the &lt;code&gt;body&lt;/code&gt; property. This aligns with AMIS's conventions: tagName corresponds to &lt;code&gt;type&lt;/code&gt;, and the body content corresponds to &lt;code&gt;body&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>jsonschema</category>
      <category>xmlschema</category>
      <category>programming</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How to Add Extended Fields to Entities Without Modifying Tables</title>
      <dc:creator>canonical</dc:creator>
      <pubDate>Fri, 19 Dec 2025 11:57:33 +0000</pubDate>
      <link>https://forem.com/canonical/how-to-add-extended-fields-to-entities-without-modifying-tables-5k</link>
      <guid>https://forem.com/canonical/how-to-add-extended-fields-to-entities-without-modifying-tables-5k</guid>
      <description>&lt;p&gt;&lt;a href="https://www.bilibili.com/video/BV1wL411D7g7" rel="noopener noreferrer"&gt;Video Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on the NopOrm engine built into the Nop platform, it's very convenient to add extended properties to any entity. These properties support querying and sorting, and are completely consistent with the entity's built-in properties in terms of usage.&lt;/p&gt;

&lt;p&gt;The specific method is very simple: just add the &lt;code&gt;use-ext-field&lt;/code&gt; tag to the data table in the Excel data model to enable global extended field support. Extended fields will be saved in the &lt;code&gt;nop_sys_ext_field&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmu3kz7wystf0qba4te84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmu3kz7wystf0qba4te84.png" alt="use-ext-field.png" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The structure of the &lt;code&gt;nop_sys_ext_field&lt;/code&gt; table is as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;entity_name&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;entity_id&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;field_name&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;field_type&lt;/td&gt;
&lt;td&gt;INTEGER&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;decimal_value&lt;/td&gt;
&lt;td&gt;DECIMAL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;date_value&lt;/td&gt;
&lt;td&gt;DATE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;timestamp_value&lt;/td&gt;
&lt;td&gt;TIMESTAMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;string_value&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Based on the setting of the &lt;code&gt;field_type&lt;/code&gt;, the specific field value is saved in different columns like &lt;code&gt;decimal_value&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  ORM Configuration
&lt;/h2&gt;

&lt;p&gt;During compilation, the &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-persistence/nop-orm/src/main/resources/_vfs/nop/orm/xlib/orm-gen.xlib" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;orm-gen:ExtFieldsSupport&amp;gt;&lt;/code&gt;&lt;/a&gt; tag identifies the &lt;code&gt;use-ext-field&lt;/code&gt; configuration and automatically generates the associated properties:&lt;br&gt;
&lt;/p&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;entity&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"xxx.MyEntity"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;relations&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;to-many&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extFields"&lt;/span&gt; &lt;span class="na"&gt;refEntityName=&lt;/span&gt;&lt;span class="s"&gt;"io.nop.sys.dao.entity.NopSysExtField"&lt;/span&gt; &lt;span class="na"&gt;keyProp=&lt;/span&gt;&lt;span class="s"&gt;"fieldName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;join&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;on&lt;/span&gt; &lt;span class="na"&gt;leftProp=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt; &lt;span class="na"&gt;rightProp=&lt;/span&gt;&lt;span class="s"&gt;"entityId"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;on&lt;/span&gt; &lt;span class="na"&gt;leftValue=&lt;/span&gt;&lt;span class="s"&gt;"xxx.MyEntity"&lt;/span&gt; &lt;span class="na"&gt;rightProp=&lt;/span&gt;&lt;span class="s"&gt;"entityName"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/join&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/to-many&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/relations&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/entity&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If &lt;code&gt;keyProp&lt;/code&gt; is set in a one-to-many relationship configuration, it indicates that this property is the unique identifier property. The &lt;code&gt;IOrmEntitySet&lt;/code&gt; collection provides extension methods like &lt;code&gt;prop_get/prop_set&lt;/code&gt; which can directly access collection items based on this property.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For usage of extended fields, refer to &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-orm/src/test/java/io/nop/orm/dao/TestExtFields.java" rel="noopener noreferrer"&gt;TestExtFields.java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Java programs, we can access extended fields through the following configuration:&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="nc"&gt;IOrmKeyValueTable&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOrmKeyValueTable&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getExtFields&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;prop_get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fldA"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getExtFields&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;prop_set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fldA"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;value&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 XScript scripting language and in the EQL query language, &lt;code&gt;extFields.fldA.string&lt;/code&gt; is equivalent to &lt;code&gt;entity.getExtFields().prop_get("fldA").getString()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fldA&lt;/code&gt; is equivalent to finding the unique record from the one-to-many collection object according to &lt;code&gt;keyProp&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extended Field Aliases
&lt;/h3&gt;

&lt;p&gt;To simplify access, we can add aliases for extended fields:&lt;br&gt;
&lt;/p&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;entity&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;relations&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;to-many&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extFields"&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/relations&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;aliases&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;alias&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extFldA"&lt;/span&gt; &lt;span class="na"&gt;propPath=&lt;/span&gt;&lt;span class="s"&gt;"extFields.fldA.string"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"String"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;alias&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extFldB"&lt;/span&gt; &lt;span class="na"&gt;propPath=&lt;/span&gt;&lt;span class="s"&gt;"extFields.fldB.int"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"Integer"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/aliases&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/entity&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding the &lt;code&gt;alias&lt;/code&gt; configuration, &lt;code&gt;extFldA&lt;/code&gt; and &lt;code&gt;extFldB&lt;/code&gt; become properties on the entity. In Java, you can get the extended property via &lt;code&gt;entity.prop_get(fieldName)&lt;/code&gt;.&lt;br&gt;
In XScript, you can access them via property methods like &lt;code&gt;entity.extFldA&lt;/code&gt;, exactly the same as regular entity properties.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If code is generated based on the ORM model file that defines &lt;code&gt;alias&lt;/code&gt;, corresponding get/set methods will be automatically generated. Thus, in Java we can access extended properties via &lt;code&gt;entity.getExtFldA()&lt;/code&gt; and &lt;code&gt;entity.setExtFldA(value)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If get/set methods are generated, you can no longer use the &lt;code&gt;entity.prop_get&lt;/code&gt; method to get the property value. This is because &lt;code&gt;prop_get&lt;/code&gt; is used to get extended properties that do not exist on the entity. If you want a unified way to get both built-in and extended fields, you can use the &lt;code&gt;entity.orm_propValueByName(name)&lt;/code&gt; method, or use reflection mechanisms like &lt;code&gt;BeanTool.getProperty(entity, propName)&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Moreover, in EQL query syntax, you can directly use extended fields for filtering and sorting. The usage of extended fields is completely consistent with the entity's built-in fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extFldA&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extFldA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'123'&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extFldA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the alias mechanism, we can achieve a smooth transition between extended fields and built-in fields: during initial development, extended fields can be used first, and then basic fields can be added to the entity when performance bottlenecks arise,&lt;br&gt;
while keeping the property names in Java code unchanged.&lt;/p&gt;
&lt;h2&gt;
  
  
  GraphQL Access
&lt;/h2&gt;

&lt;p&gt;Add configuration for properties like &lt;code&gt;extFldA&lt;/code&gt; and &lt;code&gt;extFldB&lt;/code&gt; in the xmeta file to enable GraphQL access for extended properties.&lt;br&gt;
&lt;/p&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;prop&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extFldA"&lt;/span&gt; &lt;span class="na"&gt;displayName=&lt;/span&gt;&lt;span class="s"&gt;"Extended Field A"&lt;/span&gt; &lt;span class="na"&gt;queryable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;sortable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;insertable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;updatable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;schema&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"String"&lt;/span&gt; &lt;span class="na"&gt;domain=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/prop&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dedicated Extended Field Tables
&lt;/h2&gt;

&lt;p&gt;By default, all extended fields in the system are stored in the &lt;code&gt;nop_sys_ext_field&lt;/code&gt; table, which may lead to excessive data volume in a single table and poor performance. To alleviate this issue, we can add the&lt;br&gt;
&lt;code&gt;local-ext&lt;/code&gt; tag to the entity table. Then the system will automatically generate a paired extended field table for the current entity. The extended table name is generally &lt;code&gt;original_table_name + '_ext'&lt;/code&gt;, for example, &lt;code&gt;nop_sys_notice_template_ext&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The structure of the extended table is similar to &lt;code&gt;nop_sys_ext_field&lt;/code&gt;, except it lacks the &lt;code&gt;entityName&lt;/code&gt; field, as filtering by entity name is not needed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pivot Table Transformation (Vertical to Horizontal)
&lt;/h2&gt;

&lt;p&gt;Many low-code platforms use vertical tables to store all data to achieve dynamic modification of database structures, and the vertical-to-horizontal table transformation is a special hardcoded conversion. The Nop platform is different.&lt;br&gt;
Its built-in vertical/horizontal table transformation is a standard mathematical transformation. Not only ordinary vertical tables, but any one-to-many relationship can be transformed into a one-to-one relationship, and the properties of a one-to-one or many-to-one relationship are completely consistent with using the table's native fields at the EQL level.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-orm/src/test/java/io/nop/orm/dao/TestExtFields.java" rel="noopener noreferrer"&gt;TestExtFields&lt;/a&gt; unit test:&lt;br&gt;
&lt;/p&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;entity&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"io.nop.app.SimsExam"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;aliases&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;alias&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extFldA"&lt;/span&gt; &lt;span class="na"&gt;propPath=&lt;/span&gt;&lt;span class="s"&gt;"ext.fldA.string"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"String"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;alias&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"extFldB"&lt;/span&gt; &lt;span class="na"&gt;propPath=&lt;/span&gt;&lt;span class="s"&gt;"ext.fldB.boolean"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"Boolean"&lt;/span&gt; &lt;span class="na"&gt;notGenCode=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/aliases&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;relations&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;to-many&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ext"&lt;/span&gt; &lt;span class="na"&gt;refEntityName=&lt;/span&gt;&lt;span class="s"&gt;"io.nop.app.SimsExtField"&lt;/span&gt; &lt;span class="na"&gt;keyProp=&lt;/span&gt;&lt;span class="s"&gt;"fieldName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;join&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;on&lt;/span&gt; &lt;span class="na"&gt;leftProp=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt; &lt;span class="na"&gt;rightProp=&lt;/span&gt;&lt;span class="s"&gt;"entityId"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;on&lt;/span&gt; &lt;span class="na"&gt;leftValue=&lt;/span&gt;&lt;span class="s"&gt;"io.nop.app.SimsExam"&lt;/span&gt; &lt;span class="na"&gt;rightProp=&lt;/span&gt;&lt;span class="s"&gt;"entityName"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/join&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/to-many&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;/relations&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/entity&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Any &lt;code&gt;to-many&lt;/code&gt; relationship can be configured with a &lt;code&gt;keyProp&lt;/code&gt; attribute to distinguish a unique record within the collection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ext.fldA.string&lt;/code&gt; is equivalent to &lt;code&gt;((IOrmEntitySet)entity.getExt()).prop_get("fldA").getString()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Through the alias mechanism, we can give a simple name to the complex path for accessing extended fields. For example, in the configuration above, &lt;code&gt;extFldA&lt;/code&gt; is equivalent to &lt;code&gt;ext.fldA.string&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;notGenCode&lt;/code&gt; is marked, the get/set methods in Java will not be generated for this property during code generation. Values need to be obtained via methods like &lt;code&gt;entity.prop_get("extFldB")&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In XScript or XPL template languages, the access syntax for extended properties and ordinary properties is exactly the same; you can directly use methods like &lt;code&gt;entity.extFldB = true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the EQL query language, &lt;code&gt;keyProp&lt;/code&gt; is also automatically recognized for structural transformation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;
&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;transformed&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;  &lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent_id&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'myKey'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is, as long as a collection has some unique identifier, mathematically it can always be flattened into an associated property with a unique access path. The ORM engine's EQL query language is responsible for transforming associated properties like &lt;code&gt;o.a.b.c&lt;/code&gt; into table join queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myKey1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myKey2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strValue&lt;/span&gt; &lt;span class="k"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'a%'&lt;/span&gt;

&lt;span class="c1"&gt;-- Will be transformed into&lt;/span&gt;

&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;
&lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent_id&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'myKey1'&lt;/span&gt;
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;
&lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent_id&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'myKey2'&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strValue&lt;/span&gt; &lt;span class="k"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'a%'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a one-to-many related table, adding a &lt;code&gt;key&lt;/code&gt; filter condition naturally turns it into a one-to-one related table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myKey1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myKey2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;

&lt;span class="c1"&gt;-- Will be transformed into&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent_id&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'myKey1'&lt;/span&gt;
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;
&lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent_id&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'myKey2'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to the rules, extracting the related table from &lt;code&gt;o.children.myKey&lt;/code&gt; is, at the mathematical level, a deterministic local transformation rule.&lt;/p&gt;

</description>
      <category>jpa</category>
      <category>hibernate</category>
      <category>prisma</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
