Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolved issue #1323 Two-Step View pattern #3106

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.idempotentconsumer;

import org.junit.jupiter.api.Test;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.idempotentconsumer;

import org.junit.jupiter.api.BeforeEach;
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
<module>function-composition</module>
<module>microservices-distributed-tracing</module>
<module>microservices-idempotent-consumer</module>
<module>two-step-view</module>
</modules>
<repositories>
<repository>
Expand Down
156 changes: 156 additions & 0 deletions two-step-view/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Two-Step View


---

## Also known as

- Template View.
- Model-View Separation
- Separated Presentation
- View Helper Pattern
---

## Intent of Two-Step View Design Pattern
- **Decouple Data and Presentation**: Separate data preparation from rendering for better modularity.
- **Reusable Rendering**: Use templates to reduce duplication.
- **Flexibility**: Render the same data differently with various templates.
- **Maintainability**: Simplify testing and updates by isolating logic.
- **Multi-Format Support**: Prepare data once and render in formats like HTML or JSON.
---

## Detailed Explanation of the Two Step View Pattern with Real-World Examples

**Real-World Example**:
Imagine a restaurant kitchen.

**Step 1**: Preparation – The chef cooks and plates the food, ensuring it is ready to be served.

**Step 2**: Presentation – The waiter serves the plated food to the customer, adding any final touches, such as garnishes.

**In Plain Words**: The Two-Step View Pattern separates the process of preparing data from how it is presented.

**Authoritative Source**: Martin Fowler describes the Two-Step View pattern as transforming domain data into HTML in two stages: first by creating a logical page, then rendering it into HTML.(https://martinfowler.com/eaaCatalog/twoStepView.html)

---

## Programmatic Example of Two-Step View Pattern in Java


#### **Phase 1: Data Preparation (`DataPreparation`)**
- **Responsibility:** Processes raw `Book` data by calculating the discount price and checking stock availability.
- **Method:** `prepareBook(Book book)`
- **Output:** Returns a `BookStore` object with processed details.
- **Example:**
```java
BookStore bookStore = DataPreparation.prepareBook(book);
```

#### **Phase 2: Presentation (`Presentation`)**
- **Responsibility:** Converts the prepared `BookStore` data into an HTML representation.
- **Method:** `presentBook(BookStore bookInStore)`
- **Output:** HTML formatted book details.
- **Example:**
```java
String bookHtml = Presentation.presentBook(bookStore);
```



---

## When to Use the Two Step View Pattern in Java

- **Separation of Logic:** When you need to separate data preparation from presentation for better modularity.
- **Multiple Formats:** When the same data needs to be rendered in multiple formats (e.g., HTML, JSON, XML).
- **Reusable Templates:** When you want to reuse rendering logic across different parts of the application.
- **Maintainability:** When frequent changes in the presentation layer shouldn't impact the business logic or data preparation.
- **Flexibility:** When different rendering methods are required for the same prepared data based on user preferences or contexts.
- **Scalability:** When adding new presentation formats without affecting existing preparation logic is needed.
- **MVC Architecture:** When implementing the Model-View-Controller (MVC) design pattern, where the model (data preparation) and view (presentation) are distinctly separate.
- **Testability:** When isolating and unit testing data preparation and rendering logic independently is a priority.
---
## Two-Step View Pattern Java Tutorials


- **Martin Fowler's Explanation**: Martin Fowler discusses the Two-Step View pattern, detailing its application in transforming domain data into HTML in two stages.(https://martinfowler.com/eaaCatalog/twoStepView)

- **Stack Overflow Discussion**: A discussion on Stack Overflow explores the implementation of the Two Step View pattern in Spring MVC, highlighting its benefits and practical considerations.(https://stackoverflow.com/questions/58114790/spring-mvc-one-step-view-or-two-step-view)

- **Java Design Patterns Tutorial**: This comprehensive tutorial covers various design patterns in Java, including structural patterns that may relate to the Two Step View pattern.(https://www.digitalocean.com/community/tutorials/java-design-patterns-example-tutorial)



---
## Real-World Applications of Two-Step View Pattern in Java

- **Spring MVC**: Separates the logic of data preparation from view rendering, using technologies like JSP, Thymeleaf, or FreeMarker. ([Stack Overflow discussion](https://stackoverflow.com/questions/58114790/spring-mvc-one-step-view-or-two-step-view))
- **Composite View Pattern**: Similar to Two Step View, this pattern involves composing view components into tree structures, promoting separation of concerns. ([Java Design Patterns - Composite View](https://java-design-patterns.com/patterns/composite-view/?utm_source=chatgpt.com))
- **Martin Fowler's Two Step View**: A foundational explanation of transforming domain data into HTML in two stages, applied in web applications. ([martinfowler.com](https://martinfowler.com/eaaCatalog/twoStepView.html?utm_source=chatgpt.com))
---
### **Benefits of the Two Step View Pattern**

- **Separation of Concerns:** Separates data processing from presentation logic, making the system more modular and easier to maintain.
- **Reusability:** Data preparation and presentation can be reused independently across different views or formats.
- **Flexibility:** Easily switch or modify the presentation layer (e.g., HTML, XML, JSON) without changing the underlying data logic.
- **Maintainability:** Changes in the data model or presentation logic are isolated, reducing the risk of side effects.
- **Testability:** Each phase (data preparation and rendering) can be unit tested independently, improving code quality and reliability.
- **Scalability:** Adding new views or presentation formats becomes easier without altering the core business logic.
---

## **Trade-offs of the Two Step View Pattern**

- **Increased Complexity:** Implementing two separate steps adds complexity, particularly in smaller applications where a simple approach may suffice.
- **Performance Overhead:** Dividing the logic into two phases may introduce unnecessary overhead, especially in performance-critical applications.
- **Over-engineering:** For simple applications, the pattern might be overkill, leading to unnecessary abstraction.
- **Tighter Coupling of Phases:** If not designed properly, the two phases (data preparation and presentation) might still become tightly coupled, reducing the pattern's effectiveness.
- **Development Time:** The initial implementation of two phases may require more time compared to simpler, more straightforward methods.
---
## **Related Java Design Patterns**

- **Model-View-Controller (MVC):** Separates data (Model), presentation (View), and user interaction (Controller), which is conceptually similar to the Two Step View pattern.
[Learn more](https://refactoring.guru/design-patterns/mvc)

- **Composite View:** Builds complex views by combining multiple components into a tree structure, promoting modularity in rendering views.
[Learn more](https://java-design-patterns.com/patterns/composite-view/?utm_source=chatgpt.com)

- **Template Method:** Defines the structure of an algorithm but allows certain steps to be implemented by subclasses, similar to separating data preparation from presentation.
[Learn more](https://refactoring.guru/design-patterns/template-method)

- **Strategy Pattern:** Allows the selection of algorithms (e.g., data preparation or presentation rendering) at runtime, offering flexibility in handling multiple views.
[Learn more](https://refactoring.guru/design-patterns/strategy)

- **Decorator Pattern:** Adds behavior or functionality to an object dynamically, which can be useful for enhancing view rendering capabilities.
[Learn more](https://refactoring.guru/design-patterns/decorator)

- **Abstract Factory Pattern:** Creates families of related objects without specifying their concrete classes, similar to abstracting view rendering across different formats.
[Learn more](https://refactoring.guru/design-patterns/abstract-factory)
---
## **References and Credits for the Two Step View Pattern**

- **"Patterns of Enterprise Application Architecture"** by Martin Fowler
A key resource explaining the Two Step View pattern, among other enterprise application design patterns.
[Link to book](https://martinfowler.com/books/eaa.html)

- **"Design Patterns: Elements of Reusable Object-Oriented Software"** by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides
This book outlines foundational design patterns that are conceptually related to the Two Step View pattern, like MVC and Composite View.
[Link to book](https://www.pearson.com/store/p/design-patterns-elements-of-reusable-object-oriented-software/P100000825256)

- **"Refactoring: Improving the Design of Existing Code"** by Martin Fowler
Discusses how to refactor code in a way that aligns with the principles of modularity and separation of concerns, which are also key goals of the Two Step View pattern.
[Link to book](https://martinfowler.com/books/refactoring.html)

- **"Head First Design Patterns"** by Eric Freeman and Elisabeth Robson
A beginner-friendly resource that explains various design patterns, including those related to view rendering, like MVC and Composite View.
[Link to book](https://www.oreilly.com/library/view/head-first-design/9780596007126/)

- **"Java Design Patterns: A Hands-On Experience with Real-World Examples"** by Vaskaran Sarcar
Provides practical examples of design patterns in Java, with potential applications for the Two Step View pattern.
[Link to book](https://www.amazon.com/Java-Design-Patterns-Hands-Experience/dp/1788621754)

- **"Design Patterns in Java"** by Steven John Metsker
A book that covers Java-specific examples of design patterns and explores how they can be used effectively in enterprise applications.
[Link to book](https://www.amazon.com/Design-Patterns-Java-Steven-Metsker/dp/0321192958)



65 changes: 65 additions & 0 deletions two-step-view/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).

The MIT License
Copyright © 2014-2022 Ilkka Seppälä

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.26.0-SNAPSHOT</version>
</parent>

<artifactId>two-step-view</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
sharara6 marked this conversation as resolved.
Show resolved Hide resolved
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.model.view.presenter.App</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
60 changes: 60 additions & 0 deletions two-step-view/src/main/java/com/iluwatar/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar;

import java.util.logging.Logger;

/*
* The Two Step View Pattern:
* Separates generating dynamic web content into:
* 1. Data Preparation: Raw data is structured for presentation.
* 2. Data Presentation: Prepared data is rendered into a display format (e.g., HTML).
* This enhances modularity, maintainability, and testability by decoupling preparation and presentation.

* Implementation in this Example:
* 1. Data Preparation: `DataPreparation` transforms a `Book` into a `BookStore` object, calculating discount prices and stock status.
* 2. Data Presentation: `Presentation` generates an HTML view of the `BookStore` object, focusing only on rendering.
*/

/** Main class. */
sharara6 marked this conversation as resolved.
Show resolved Hide resolved
public class App {
private static final Logger logger = Logger.getLogger(App.class.getName());

/** Main function. */
public static void main(String[] args) {
// Create a Book instance with sample data
Book book = new Book("Batman Vol. 1: The Court of Owls", 11.60, true, 10);

// Convert raw book data into a structured format
BookStore preparedData = DataPreparation.prepareBook(book);

// Converts the prepared book data into an HTML string for display
String htmlOutput = Presentation.presentBook(preparedData);
sharara6 marked this conversation as resolved.
Show resolved Hide resolved

// Output the rendered HTML
logger.info(htmlOutput);
}
}

47 changes: 47 additions & 0 deletions two-step-view/src/main/java/com/iluwatar/Book.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar;
import lombok.Data;

/** Represents a Book. */
@Data
public class Book {
String name;
double price;
boolean discount;
int stock;
Book(String name, double price, boolean discount, int stock) {
if (!name.isEmpty()) { // Make sure is not empty
this.name = name;
}
if (price > 0) { // Make sure price is set with a realistic value
this.price = price;
}
if (stock >= 0) { // Make sure stock is not negative
this.stock = stock;
}
this.discount = discount;
}
}
Loading
Loading