From 3c82755a3c042178fdf5509776b5bf7f7f173360 Mon Sep 17 00:00:00 2001 From: Suchismita-Deb Date: Mon, 31 Mar 2025 01:15:40 +0530 Subject: [PATCH 1/8] #3230 - Clean Architecture. --- clean-architecture/README.md | 278 ++++++++++++++++++ clean-architecture/pom.xml | 62 ++++ .../com.iluwatar.cleanArchitecture/App.java | 35 +++ .../com.iluwatar.cleanArchitecture/Cart.java | 23 ++ .../CartController.java | 21 ++ .../CartRepository.java | 11 + .../InMemoryCartRepository.java | 43 +++ .../InMemoryOrderRepository.java | 13 + .../InMemoryProductRepository.java | 18 ++ .../com.iluwatar.cleanArchitecture/Order.java | 26 ++ .../OrderController.java | 13 + .../OrderRepository.java | 5 + .../Product.java | 25 ++ .../ProductRepository.java | 5 + .../ShoppingCartService.java | 40 +++ .../iluwatar/cleanArchitecture/AppTest.java | 19 ++ .../cleanArchitecture/CartControllerTest.java | 41 +++ 17 files changed, 678 insertions(+) create mode 100644 clean-architecture/README.md create mode 100644 clean-architecture/pom.xml create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/App.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Cart.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartController.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartRepository.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryCartRepository.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryOrderRepository.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryProductRepository.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Order.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderController.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderRepository.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Product.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ProductRepository.java create mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ShoppingCartService.java create mode 100644 clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/AppTest.java create mode 100644 clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/CartControllerTest.java diff --git a/clean-architecture/README.md b/clean-architecture/README.md new file mode 100644 index 000000000000..823b0104ef64 --- /dev/null +++ b/clean-architecture/README.md @@ -0,0 +1,278 @@ +--- +title: "Clean Architecture - A Software Maintainable Architectural style." +shortTitle: Chain of Responsibility +description: "Learn the Clean Architecture Style in Java with real-world examples, code snippets, and class diagrams. Enhance your coding skills with our detailed explanations." +category: Behavioral +language: en +tag: + - Decoupling + - Architectural Style +--- + +## Intent of Clean Architecture. + +The clean architecture is a software design architectural style which ensures the software application is easy to understand, maintainable and can be extend easily as per business requirement. + +## Detailed Explanation of Chain of Responsibility Pattern with Real-World Examples + +Real World. + +A real world example of clean architecture is like teh shopping mall example. There some employee is assigned to work on the filling of the products in the counter, one person is responsible for the billing purpose, one person is taking care of the security, one person is taking care of the product they have in storage. The work of every individual is separate and they are focussed on the specific task. Clean architecture also suggests to make the component separate and each component should perform some task. Clean Architecture proposes a layered architecture with clear boundaries between different system components to achieve independence of frameworks, UI, databases, and delivery mechanisms and the possibility to test in isolation. + +In plain word + +It help to make the system more maintainable and easy to extend. + +## Also known as + +* Hexagonal Architecture + +Wikipedia says + +> The clean architecture proposed by Robert C. Martin in 2012 combines the principles of the hexagonal architecture, the onion architecture and several other variants. It provides additional levels of detail of the component, which are presented as concentric rings. It isolates adapters and interfaces (user interface, databases, external systems, devices) in the outer rings of the architecture and leaves the inner rings for use cases and entities. +> +> The clean architecture uses the principle of dependency inversion with the strict rule that dependencies shall only exist between an outer ring to an inner ring and never the contrary. + +## Programmatic Example of Chain of Responsibility Pattern + +## Clean architecture Class Diagram + + +![Clean Architecture](./etc/clean-architecture.png "Clean Architecture class diagram") + +## When to Use the Clean Architecture Pattern in Java + +In all application we can use the clean architecture style and make the component separate and business logic separate from the UI and database. + +## Real-World Applications of Chain of Responsibility Pattern in Java. + +In the application say Ecommerce application user gives teh order and the application is represented using teh clean architecture pattern. + +There are facility like the **product** where user can see the product details like the price and the features, **Cart** user can add the product they have selected and the **Order** where user can see the total order and calculate the price of the order. Learn how to implement this design pattern in Java with the following code snippet. + +First we have the entity class like the `Product`, `Order` and teh `Cart` +```java +public class Product { + private String id; + private String name; + private double price; + + public Product(String id, String name, double price) { + this.id = id; + this.name = name; + this.price = price; + } +} +``` + +```java +public class Cart { + private Product product; + private int quantity; + + public CartItem(Product product, int quantity) { + this.product = product; + this.quantity = quantity; + } + + public double getTotalPrice() { + return product.getPrice() * quantity; + } +} +``` + +```java +public class Order { + private String orderId; + private List items; + private double totalPrice; + + public Order(String orderId, List items) { + this.orderId = orderId; + this.items = items; + this.totalPrice = items.stream().mapToDouble(CartItem::getTotalPrice).sum(); + } +} +``` +The repository interfaces are created. +```java +public interface CartRepository { + void addItemToCart(String userId, Product product, int quantity); + void removeItemFromCart(String userId, String productId); + List getItemsInCart(String userId); + double calculateTotal(String userId); + void clearCart(String userId); +} +``` +```java +public interface ProductRepository { + Product getProductById(String productId); +} +``` +```java +public interface OrderRepository { + void saveOrder(Order order); +} +``` + + +The in memory data store in the cart and order. +```java +public class InMemoryCartRepository implements CartRepository { + private final Map> userCarts = new HashMap<>(); + + @Override + public void addItemToCart(String userId, Product product, int quantity) { + List cart = userCarts.getOrDefault(userId, new ArrayList<>()); + cart.add(new Cart(product, quantity)); + userCarts.put(userId, cart); + } + + @Override + public void removeItemFromCart(String userId, String productId) { + List cart = userCarts.get(userId); + if (cart != null) { + cart.removeIf(item -> item.getProduct().getId().equals(productId)); + } + } + + @Override + public List getItemsInCart(String userId) { + return userCarts.getOrDefault(userId, new ArrayList<>()); + } + + @Override + public double calculateTotal(String userId) { + return userCarts.getOrDefault(userId, new ArrayList<>()) + .stream() + .mapToDouble(Cart::getTotalPrice) + .sum(); + } + + @Override + public void clearCart(String userId) { + userCarts.remove(userId); + } +} +``` +```java +public class InMemoryOrderRepository implements OrderRepository { + private final List orders = new ArrayList<>(); + + @Override + public void saveOrder(Order order) { + orders.add(order); + } +} +``` + +```java +public class InMemoryProductRepository implements ProductRepository { + private final Map products = new HashMap<>(); + + public InMemoryProductRepository() { + products.put("1", new Product("1", "Laptop", 1000.0)); + products.put("2", new Product("2", "Smartphone", 500.0)); + } + + @Override + public Product getProductById(String productId) { + return products.get(productId); + } +} +``` + +The order controller. +```java +public class OrderController{ + private final ShoppingCartService shoppingCartUseCase; + + public OrderController(ShoppingCartService shoppingCartUseCase) { + this.shoppingCartUseCase = shoppingCartUseCase; + } + + public Order checkout(String userId) { + return shoppingCartUseCase.checkout(userId); + } +} +``` +The cart controller. +```java +public class CartController { + private final ShoppingCartService shoppingCartUseCase; + + public CartController(ShoppingCartService shoppingCartUseCase) { + this.shoppingCartUseCase = shoppingCartUseCase; + } + + public void addItemToCart(String userId, String productId, int quantity) { + shoppingCartUseCase.addItemToCart(userId, productId, quantity); + } + + public void removeItemFromCart(String userId, String productId) { + shoppingCartUseCase.removeItemFromCart(userId, productId); + } + + public double calculateTotal(String userId) { + return shoppingCartUseCase.calculateTotal(userId); + } +} +``` + +The clean architecture in action. +```java +public static void main(String[] args) { + + ProductRepository productRepository = new InMemoryProductRepository(); + CartRepository cartRepository = new InMemoryCartRepository(); + OrderRepository orderRepository = new InMemoryOrderRepository(); + + ShoppingCartService shoppingCartUseCase = + new ShoppingCartService(productRepository, cartRepository, orderRepository); + + CartController cartController = new CartController(shoppingCartUseCase); + OrderController orderController = new OrderController(shoppingCartUseCase); + + String userId = "user123"; + cartController.addItemToCart(userId, "1", 1); + cartController.addItemToCart(userId, "2", 2); + + System.out.println("Total: $" + cartController.calculateTotal(userId)); + + Order order = orderController.checkout(userId); + System.out.println( + "Order placed! Order ID: " + order.getOrderId() + ", Total: $" + order.getTotalPrice()); + } +``` + +The output of the code. +```md +Total: $2000.0 +Order placed! Order ID: ORDER-1743349969254, Total: $2000.0 +``` + +## Benefits and Trade-offs of Clean Architecture Pattern. + +Benefits: + +The main benefits of the Clean Architecture involves - +**Scalability** - It allows to add new features without any issue. +**Modularity** - It makes the code loosely coupled and making the change in any component becomes easier. +**Testability** - The architecture promotes unit testing, integration testing, and acceptance testing of different layers independently. + +Trade-Offs: + +Initially the design needs to be done with high precision and the UML diagram should cover all the architectural structure. It will in return help to make it more channelised and the code extensibility will increase. + +## Related Java Design Patterns + +* Dependency Injection - Dependency Injection (DI) is a key concept in Clean Architecture. It promotes loose coupling between classes by allowing dependencies to be injected rather than directly created by the class itself. +* Singleton Pattern - The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance. This is often used for shared services or resources, such as a configuration manager, logging service, or database connection pool. + +## References and Credits + +* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI) +* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq) +* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3PAJUg5) +* [Refactoring to Patterns](https://amzn.to/3VOO4F5) +* [Pattern languages of program design 3](https://amzn.to/4a4NxTH) \ No newline at end of file diff --git a/clean-architecture/pom.xml b/clean-architecture/pom.xml new file mode 100644 index 000000000000..a348cf6f0968 --- /dev/null +++ b/clean-architecture/pom.xml @@ -0,0 +1,62 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + clean-architecture + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.cleanArchitecture.App + + + + + + + + + diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/App.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/App.java new file mode 100644 index 000000000000..b0b26f5570a9 --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/App.java @@ -0,0 +1,35 @@ +package com.iluwatar.cleanArchitecture; + +public class App { + + /** + * Program entry point. + * + * @param args command line args + */ + public static void main(String[] args) { + + ProductRepository productRepository = new InMemoryProductRepository(); + CartRepository cartRepository = new InMemoryCartRepository(); + OrderRepository orderRepository = new InMemoryOrderRepository(); + + // Initialize Use Case + ShoppingCartService shoppingCartUseCase = + new ShoppingCartService(productRepository, cartRepository, orderRepository); + + // Initialize Controllers + CartController cartController = new CartController(shoppingCartUseCase); + OrderController orderController = new OrderController(shoppingCartUseCase); + + // Simulating User Operations + String userId = "user123"; + cartController.addItemToCart(userId, "1", 1); // Add Laptop to cart + cartController.addItemToCart(userId, "2", 2); // Add 2 Smartphones to cart + + System.out.println("Total: $" + cartController.calculateTotal(userId)); + + Order order = orderController.checkout(userId); + System.out.println( + "Order placed! Order ID: " + order.getOrderId() + ", Total: $" + order.getTotalPrice()); + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Cart.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Cart.java new file mode 100644 index 000000000000..f5db4ca42b3c --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Cart.java @@ -0,0 +1,23 @@ +package com.iluwatar.cleanArchitecture; + +public class Cart { + private Product product; + private int quantity; + + public Cart(Product product, int quantity) { + this.product = product; + this.quantity = quantity; + } + + public double getTotalPrice() { + return product.getPrice() * quantity; + } + public Product getProduct() { + return product; + } + + public int getQuantity() { + return quantity; + } + +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartController.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartController.java new file mode 100644 index 000000000000..8a1765d546c8 --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartController.java @@ -0,0 +1,21 @@ +package com.iluwatar.cleanArchitecture; + +public class CartController { + private final ShoppingCartService shoppingCartUseCase; + + public CartController(ShoppingCartService shoppingCartUseCase) { + this.shoppingCartUseCase = shoppingCartUseCase; + } + + public void addItemToCart(String userId, String productId, int quantity) { + shoppingCartUseCase.addItemToCart(userId, productId, quantity); + } + + public void removeItemFromCart(String userId, String productId) { + shoppingCartUseCase.removeItemFromCart(userId, productId); + } + + public double calculateTotal(String userId) { + return shoppingCartUseCase.calculateTotal(userId); + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartRepository.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartRepository.java new file mode 100644 index 000000000000..ec104a61746a --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartRepository.java @@ -0,0 +1,11 @@ +package com.iluwatar.cleanArchitecture; + +import java.util.List; + +public interface CartRepository { + void addItemToCart(String userId, Product product, int quantity); + void removeItemFromCart(String userId, String productId); + List getItemsInCart(String userId); + double calculateTotal(String userId); + void clearCart(String userId); +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryCartRepository.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryCartRepository.java new file mode 100644 index 000000000000..fe284a2cd4f5 --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryCartRepository.java @@ -0,0 +1,43 @@ +package com.iluwatar.cleanArchitecture; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class InMemoryCartRepository implements CartRepository { + private final Map> userCarts = new HashMap<>(); + + @Override + public void addItemToCart(String userId, Product product, int quantity) { + List cart = userCarts.getOrDefault(userId, new ArrayList<>()); + cart.add(new Cart(product, quantity)); + userCarts.put(userId, cart); + } + + @Override + public void removeItemFromCart(String userId, String productId) { + List cart = userCarts.get(userId); + if (cart != null) { + cart.removeIf(item -> item.getProduct().getId().equals(productId)); + } + } + + @Override + public List getItemsInCart(String userId) { + return userCarts.getOrDefault(userId, new ArrayList<>()); + } + + @Override + public double calculateTotal(String userId) { + return userCarts.getOrDefault(userId, new ArrayList<>()) + .stream() + .mapToDouble(Cart::getTotalPrice) + .sum(); + } + + @Override + public void clearCart(String userId) { + userCarts.remove(userId); + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryOrderRepository.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryOrderRepository.java new file mode 100644 index 000000000000..c1035a22257b --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryOrderRepository.java @@ -0,0 +1,13 @@ +package com.iluwatar.cleanArchitecture; + +import java.util.ArrayList; +import java.util.List; + +public class InMemoryOrderRepository implements OrderRepository { + private final List orders = new ArrayList<>(); + + @Override + public void saveOrder(Order order) { + orders.add(order); + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryProductRepository.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryProductRepository.java new file mode 100644 index 000000000000..6d06e8d4189a --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryProductRepository.java @@ -0,0 +1,18 @@ +package com.iluwatar.cleanArchitecture; + +import java.util.HashMap; +import java.util.Map; + +public class InMemoryProductRepository implements ProductRepository { + private final Map products = new HashMap<>(); + + public InMemoryProductRepository() { + products.put("1", new Product("1", "Laptop", 1000.0)); + products.put("2", new Product("2", "Smartphone", 500.0)); + } + + @Override + public Product getProductById(String productId) { + return products.get(productId); + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Order.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Order.java new file mode 100644 index 000000000000..4aa9affa83fb --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Order.java @@ -0,0 +1,26 @@ +package com.iluwatar.cleanArchitecture; + +import java.util.List; + +public class Order { + private String orderId; + private List items; + private double totalPrice; + + public Order(String orderId, List items) { + this.orderId = orderId; + this.items = items; + this.totalPrice = items.stream().mapToDouble(Cart::getTotalPrice).sum(); + } + public String getOrderId() { + return orderId; + } + + public List getItems() { + return items; + } + + public double getTotalPrice() { + return totalPrice; + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderController.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderController.java new file mode 100644 index 000000000000..621b78f293f9 --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderController.java @@ -0,0 +1,13 @@ +package com.iluwatar.cleanArchitecture; + +public class OrderController{ + private final ShoppingCartService shoppingCartUseCase; + + public OrderController(ShoppingCartService shoppingCartUseCase) { + this.shoppingCartUseCase = shoppingCartUseCase; + } + + public Order checkout(String userId) { + return shoppingCartUseCase.checkout(userId); + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderRepository.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderRepository.java new file mode 100644 index 000000000000..e9878841fb3b --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderRepository.java @@ -0,0 +1,5 @@ +package com.iluwatar.cleanArchitecture; + +public interface OrderRepository { + void saveOrder(Order order); +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Product.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Product.java new file mode 100644 index 000000000000..4d6196444519 --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Product.java @@ -0,0 +1,25 @@ +package com.iluwatar.cleanArchitecture; + +public class Product { + private String id; + private String name; + private double price; + + public Product(String id, String name, double price) { + this.id = id; + this.name = name; + this.price = price; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public double getPrice() { + return price; + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ProductRepository.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ProductRepository.java new file mode 100644 index 000000000000..80c412f8b878 --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ProductRepository.java @@ -0,0 +1,5 @@ +package com.iluwatar.cleanArchitecture; + +public interface ProductRepository { + Product getProductById(String productId); +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ShoppingCartService.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ShoppingCartService.java new file mode 100644 index 000000000000..a33c5760d0c6 --- /dev/null +++ b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ShoppingCartService.java @@ -0,0 +1,40 @@ +package com.iluwatar.cleanArchitecture; + +import java.util.List; + +public class ShoppingCartService { + private final ProductRepository productRepository; + private final CartRepository cartRepository; + private final OrderRepository orderRepository; + + public ShoppingCartService(ProductRepository productRepository, + CartRepository cartRepository, + OrderRepository orderRepository) { + this.productRepository = productRepository; + this.cartRepository = cartRepository; + this.orderRepository = orderRepository; + } + + public void addItemToCart(String userId, String productId, int quantity) { + Product product = productRepository.getProductById(productId); + if (product != null) { + cartRepository.addItemToCart(userId, product, quantity); + } + } + public void removeItemFromCart(String userId, String productId) { + cartRepository.removeItemFromCart(userId, productId); + } + + public double calculateTotal(String userId) { + return cartRepository.calculateTotal(userId); + } + + public Order checkout(String userId) { + List items = cartRepository.getItemsInCart(userId); + String orderId = "ORDER-" + System.currentTimeMillis(); // simple order ID generation + Order order = new Order(orderId, items); + orderRepository.saveOrder(order); + cartRepository.clearCart(userId); + return order; + } +} diff --git a/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/AppTest.java b/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/AppTest.java new file mode 100644 index 000000000000..f42827d7a0a7 --- /dev/null +++ b/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/AppTest.java @@ -0,0 +1,19 @@ +package com.iluwatar.cleanArchitecture; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +class AppTest { + /** + * Issue: Add at least one assertion to this test case. + * + * Solution: Inserted assertion to check whether the execution of the main method in {@link App} + * throws an exception. + */ + + @Test + void shouldExecuteApplicationWithoutException() { + + assertDoesNotThrow(() -> App.main(new String[]{})); + } +} \ No newline at end of file diff --git a/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/CartControllerTest.java b/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/CartControllerTest.java new file mode 100644 index 000000000000..7a1023ef63a1 --- /dev/null +++ b/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/CartControllerTest.java @@ -0,0 +1,41 @@ +package com.iluwatar.cleanArchitecture; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class CartControllerTest { + + private ShoppingCartService shoppingCartUseCase; + private CartController cartController; + + @BeforeEach + public void setUp() { + ProductRepository productRepository = new InMemoryProductRepository(); + CartRepository cartRepository = new InMemoryCartRepository(); + OrderRepository orderRepository = new InMemoryOrderRepository(); + shoppingCartUseCase = new ShoppingCartService(productRepository, cartRepository, orderRepository); + cartController = new CartController(shoppingCartUseCase); + } + + @Test + void testRemoveItemFromCart() { + cartController.addItemToCart("user123", "1", 1); + cartController.addItemToCart("user123", "2", 2); + + assertEquals(2000.0, cartController.calculateTotal("user123")); + + cartController.removeItemFromCart("user123", "1"); + + assertEquals(1000.0, cartController.calculateTotal("user123")); + } + + @Test + void testRemoveNonExistentItem() { + cartController.addItemToCart("user123", "2", 2); + cartController.removeItemFromCart("user123", "999"); + + assertEquals(1000.0, cartController.calculateTotal("user123")); + } +} \ No newline at end of file From 10f3788bdc24ecef44f9e5e3b6024c8a2278dbfd Mon Sep 17 00:00:00 2001 From: Suchismita-Deb Date: Mon, 31 Mar 2025 12:20:33 +0530 Subject: [PATCH 2/8] #3230 - Clean Architecture. --- clean-architecture/README.md | 20 +++++++++--------- .../etc/cleanArchitectureUMLDiagram.PNG | Bin 0 -> 43432 bytes clean-architecture/img.png | Bin 0 -> 38386 bytes 3 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 clean-architecture/etc/cleanArchitectureUMLDiagram.PNG create mode 100644 clean-architecture/img.png diff --git a/clean-architecture/README.md b/clean-architecture/README.md index 823b0104ef64..0e2e7f5da99e 100644 --- a/clean-architecture/README.md +++ b/clean-architecture/README.md @@ -1,6 +1,6 @@ --- title: "Clean Architecture - A Software Maintainable Architectural style." -shortTitle: Chain of Responsibility +shortTitle: Clean Architecture description: "Learn the Clean Architecture Style in Java with real-world examples, code snippets, and class diagrams. Enhance your coding skills with our detailed explanations." category: Behavioral language: en @@ -9,11 +9,15 @@ tag: - Architectural Style --- +## Also known as + +* Hexagonal Architecture. + ## Intent of Clean Architecture. The clean architecture is a software design architectural style which ensures the software application is easy to understand, maintainable and can be extend easily as per business requirement. -## Detailed Explanation of Chain of Responsibility Pattern with Real-World Examples +## Detailed Explanation of Clean Architecture Pattern with Real-World Examples Real World. @@ -21,11 +25,7 @@ A real world example of clean architecture is like teh shopping mall example. Th In plain word -It help to make the system more maintainable and easy to extend. - -## Also known as - -* Hexagonal Architecture +It helps to make the system more maintainable and easy to extend. Wikipedia says @@ -33,12 +33,10 @@ Wikipedia says > > The clean architecture uses the principle of dependency inversion with the strict rule that dependencies shall only exist between an outer ring to an inner ring and never the contrary. -## Programmatic Example of Chain of Responsibility Pattern ## Clean architecture Class Diagram - -![Clean Architecture](./etc/clean-architecture.png "Clean Architecture class diagram") +![Clean Architecture](./etc/cleanArchitectureUMLDiagram.png "Clean Architecture class diagram") ## When to Use the Clean Architecture Pattern in Java @@ -50,6 +48,8 @@ In the application say Ecommerce application user gives teh order and the applic There are facility like the **product** where user can see the product details like the price and the features, **Cart** user can add the product they have selected and the **Order** where user can see the total order and calculate the price of the order. Learn how to implement this design pattern in Java with the following code snippet. +## Programmatic Example of Clean Architecture Pattern + First we have the entity class like the `Product`, `Order` and teh `Cart` ```java public class Product { diff --git a/clean-architecture/etc/cleanArchitectureUMLDiagram.PNG b/clean-architecture/etc/cleanArchitectureUMLDiagram.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f107d34a14d861e809efe6c0ec2431b97c3cc99a GIT binary patch literal 43432 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 Wx(~->c;lNQP*PM^sE{{*_J09c4b_VP literal 0 HcmV?d00001 From d7109ab56add5e2adf1e3afeb97dba0a797a14a2 Mon Sep 17 00:00:00 2001 From: Suchismita-Deb Date: Tue, 1 Apr 2025 18:49:08 +0530 Subject: [PATCH 3/8] #3230 - Clean Architecture. --- clean-architecture/pom.xml | 2 +- .../com.iluwatar.cleanArchitecture/App.java | 35 ---------------- .../com/iluwatar/cleanarchitecture/App.java | 41 +++++++++++++++++++ .../iluwatar/cleanarchitecture}/Cart.java | 2 +- .../cleanarchitecture}/CartController.java | 3 +- .../cleanarchitecture}/CartRepository.java | 2 +- .../InMemoryCartRepository.java | 2 +- .../InMemoryOrderRepository.java | 2 +- .../InMemoryProductRepository.java | 2 +- .../iluwatar/cleanarchitecture}/Order.java | 2 +- .../cleanarchitecture}/OrderController.java | 2 +- .../cleanarchitecture}/OrderRepository.java | 2 +- .../iluwatar/cleanarchitecture}/Product.java | 2 +- .../cleanarchitecture}/ProductRepository.java | 2 +- .../ShoppingCartService.java | 2 +- .../AppTest.java | 2 +- .../CartControllerTest.java | 4 +- pom.xml | 1 + 18 files changed, 58 insertions(+), 52 deletions(-) delete mode 100644 clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/App.java create mode 100644 clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/Cart.java (90%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/CartController.java (93%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/CartRepository.java (88%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/InMemoryCartRepository.java (96%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/InMemoryOrderRepository.java (86%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/InMemoryProductRepository.java (91%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/Order.java (92%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/OrderController.java (88%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/OrderRepository.java (63%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/Product.java (90%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/ProductRepository.java (67%) rename clean-architecture/src/main/java/{com.iluwatar.cleanArchitecture => com/iluwatar/cleanarchitecture}/ShoppingCartService.java (97%) rename clean-architecture/src/test/java/com/iluwatar/{cleanArchitecture => cleanarchitecture}/AppTest.java (91%) rename clean-architecture/src/test/java/com/iluwatar/{cleanArchitecture => cleanarchitecture}/CartControllerTest.java (92%) diff --git a/clean-architecture/pom.xml b/clean-architecture/pom.xml index a348cf6f0968..e47a9df796e5 100644 --- a/clean-architecture/pom.xml +++ b/clean-architecture/pom.xml @@ -50,7 +50,7 @@ - com.iluwatar.cleanArchitecture.App + com.iluwatar.cleanarchitecture.App diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/App.java b/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/App.java deleted file mode 100644 index b0b26f5570a9..000000000000 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/App.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.iluwatar.cleanArchitecture; - -public class App { - - /** - * Program entry point. - * - * @param args command line args - */ - public static void main(String[] args) { - - ProductRepository productRepository = new InMemoryProductRepository(); - CartRepository cartRepository = new InMemoryCartRepository(); - OrderRepository orderRepository = new InMemoryOrderRepository(); - - // Initialize Use Case - ShoppingCartService shoppingCartUseCase = - new ShoppingCartService(productRepository, cartRepository, orderRepository); - - // Initialize Controllers - CartController cartController = new CartController(shoppingCartUseCase); - OrderController orderController = new OrderController(shoppingCartUseCase); - - // Simulating User Operations - String userId = "user123"; - cartController.addItemToCart(userId, "1", 1); // Add Laptop to cart - cartController.addItemToCart(userId, "2", 2); // Add 2 Smartphones to cart - - System.out.println("Total: $" + cartController.calculateTotal(userId)); - - Order order = orderController.checkout(userId); - System.out.println( - "Order placed! Order ID: " + order.getOrderId() + ", Total: $" + order.getTotalPrice()); - } -} diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java new file mode 100644 index 000000000000..904e92a3f464 --- /dev/null +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java @@ -0,0 +1,41 @@ +package com.iluwatar.cleanarchitecture; + +import lombok.extern.slf4j.Slf4j; + +/** + * Clean Architecture ensures separation of concerns by organizing code into layers, making it scalable and maintainable. + * + * In the example there are Entities (Core Models) – Product, Cart, Order handle business logic. + * Use Cases (Application Logic) – ShoppingCartService manages operations like adding items and checkout. + * Interfaces & Adapters – Repositories (CartRepository, OrderRepository) abstract data handling, while controllers (CartController, OrderController) manage interactions. + */ +@Slf4j +public class App { + + /** + * Program entry point. + * + * @param args command line args + */ + public static void main(String[] args) { + + ProductRepository productRepository = new InMemoryProductRepository(); + CartRepository cartRepository = new InMemoryCartRepository(); + OrderRepository orderRepository = new InMemoryOrderRepository(); + + ShoppingCartService shoppingCartUseCase = + new ShoppingCartService(productRepository, cartRepository, orderRepository); + + CartController cartController = new CartController(shoppingCartUseCase); + OrderController orderController = new OrderController(shoppingCartUseCase); + + String userId = "user123"; + cartController.addItemToCart(userId, "1", 1); + cartController.addItemToCart(userId, "2", 2); + + LOGGER.info("Total: ${}" + cartController.calculateTotal(userId)); + + Order order = orderController.checkout(userId); + LOGGER.info("Order placed! Order ID: {}, Total: ${}", order.getOrderId(), order.getTotalPrice()); + } +} diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Cart.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java similarity index 90% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Cart.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java index f5db4ca42b3c..7ddfa5e92d5f 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Cart.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; public class Cart { private Product product; diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartController.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java similarity index 93% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartController.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java index 8a1765d546c8..d3b48af07f07 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartController.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; public class CartController { private final ShoppingCartService shoppingCartUseCase; @@ -11,6 +11,7 @@ public void addItemToCart(String userId, String productId, int quantity) { shoppingCartUseCase.addItemToCart(userId, productId, quantity); } + public void removeItemFromCart(String userId, String productId) { shoppingCartUseCase.removeItemFromCart(userId, productId); } diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java similarity index 88% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartRepository.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java index ec104a61746a..d44a6834c5c0 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/CartRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; import java.util.List; diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryCartRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java similarity index 96% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryCartRepository.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java index fe284a2cd4f5..72796038c2a6 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryCartRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; import java.util.ArrayList; import java.util.HashMap; diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryOrderRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java similarity index 86% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryOrderRepository.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java index c1035a22257b..379f80f64ba0 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryOrderRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; import java.util.ArrayList; import java.util.List; diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java similarity index 91% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryProductRepository.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java index 6d06e8d4189a..210b398f1a6d 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/InMemoryProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; import java.util.HashMap; import java.util.Map; diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Order.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java similarity index 92% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Order.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java index 4aa9affa83fb..6fc0811ce1de 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Order.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; import java.util.List; diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderController.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java similarity index 88% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderController.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java index 621b78f293f9..b44c7f19d73f 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderController.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; public class OrderController{ private final ShoppingCartService shoppingCartUseCase; diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java similarity index 63% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderRepository.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java index e9878841fb3b..865ef7c927b6 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/OrderRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; public interface OrderRepository { void saveOrder(Order order); diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Product.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java similarity index 90% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Product.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java index 4d6196444519..c35ae178f742 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/Product.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; public class Product { private String id; diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java similarity index 67% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ProductRepository.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java index 80c412f8b878..25531d1ce2b8 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; public interface ProductRepository { Product getProductById(String productId); diff --git a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ShoppingCartService.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java similarity index 97% rename from clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ShoppingCartService.java rename to clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java index a33c5760d0c6..483ff06b4f95 100644 --- a/clean-architecture/src/main/java/com.iluwatar.cleanArchitecture/ShoppingCartService.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; import java.util.List; diff --git a/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/AppTest.java b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java similarity index 91% rename from clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/AppTest.java rename to clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java index f42827d7a0a7..263b991d3180 100644 --- a/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/AppTest.java +++ b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java @@ -1,4 +1,4 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; import org.junit.jupiter.api.Test; diff --git a/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/CartControllerTest.java b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java similarity index 92% rename from clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/CartControllerTest.java rename to clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java index 7a1023ef63a1..580f10f8b6f1 100644 --- a/clean-architecture/src/test/java/com/iluwatar/cleanArchitecture/CartControllerTest.java +++ b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java @@ -1,10 +1,8 @@ -package com.iluwatar.cleanArchitecture; +package com.iluwatar.cleanarchitecture; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - public class CartControllerTest { private ShoppingCartService shoppingCartUseCase; diff --git a/pom.xml b/pom.xml index 83d430bff114..14e4bd8f1614 100644 --- a/pom.xml +++ b/pom.xml @@ -75,6 +75,7 @@ flyweight proxy chain-of-responsibility + clean-architecture command interpreter iterator From 61b1e70739e85e1b1b1b78a77ea0011c271b5542 Mon Sep 17 00:00:00 2001 From: Suchismita-Deb Date: Tue, 1 Apr 2025 22:41:39 +0530 Subject: [PATCH 4/8] #3230 - Clean Architecture. --- .../com/iluwatar/cleanarchitecture/App.java | 46 ++++++++++++++++--- .../com/iluwatar/cleanarchitecture/Cart.java | 27 +++++++++++ .../cleanarchitecture/CartController.java | 28 +++++++++++ .../cleanarchitecture/CartRepository.java | 27 +++++++++++ .../InMemoryCartRepository.java | 27 +++++++++++ .../InMemoryOrderRepository.java | 27 +++++++++++ .../InMemoryProductRepository.java | 27 +++++++++++ .../com/iluwatar/cleanarchitecture/Order.java | 27 +++++++++++ .../cleanarchitecture/OrderController.java | 29 +++++++++++- .../cleanarchitecture/OrderRepository.java | 27 +++++++++++ .../iluwatar/cleanarchitecture/Product.java | 27 +++++++++++ .../cleanarchitecture/ProductRepository.java | 28 +++++++++++ .../ShoppingCartService.java | 41 +++++++++++++++++ 13 files changed, 380 insertions(+), 8 deletions(-) diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java index 904e92a3f464..546812c4d91a 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java @@ -1,23 +1,54 @@ +/* + * 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.cleanarchitecture; import lombok.extern.slf4j.Slf4j; /** - * Clean Architecture ensures separation of concerns by organizing code into layers, making it scalable and maintainable. + * Clean Architecture ensures separation of concerns by organizing code, + * into layers and making it scalable and maintainable. * - * In the example there are Entities (Core Models) – Product, Cart, Order handle business logic. - * Use Cases (Application Logic) – ShoppingCartService manages operations like adding items and checkout. - * Interfaces & Adapters – Repositories (CartRepository, OrderRepository) abstract data handling, while controllers (CartController, OrderController) manage interactions. + *

In the example there are Entities (Core Models) – Product, Cart, Order handle business logic. + * Use Cases (Application Logic) – ShoppingCartService manages operations + * like adding items and checkout. + * Interfaces & Adapters – Repositories (CartRepository, OrderRepository) abstract data handling, + * while controllers (CartController, OrderController) manage interactions. */ @Slf4j public class App { + private App() { + throw new UnsupportedOperationException("Utility class"); + } + /** * Program entry point. * * @param args command line args */ - public static void main(String[] args) { + public static void main(final String[] args) { ProductRepository productRepository = new InMemoryProductRepository(); CartRepository cartRepository = new InMemoryCartRepository(); @@ -33,9 +64,10 @@ public static void main(String[] args) { cartController.addItemToCart(userId, "1", 1); cartController.addItemToCart(userId, "2", 2); + Order order = orderController.checkout(userId); LOGGER.info("Total: ${}" + cartController.calculateTotal(userId)); - Order order = orderController.checkout(userId); - LOGGER.info("Order placed! Order ID: {}, Total: ${}", order.getOrderId(), order.getTotalPrice()); + LOGGER.info("Order placed! Order ID: {}, Total: ${}", + order.getOrderId(), order.getTotalPrice()); } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java index 7ddfa5e92d5f..8f49eaae3180 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java @@ -1,5 +1,32 @@ +/* + * 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.cleanarchitecture; +/** + * Cart + */ public class Cart { private Product product; private int quantity; diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java index d3b48af07f07..4543a4c2c123 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java @@ -1,5 +1,33 @@ +/* + * 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.cleanarchitecture; +/** + * CartController + */ public class CartController { private final ShoppingCartService shoppingCartUseCase; diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java index d44a6834c5c0..5e8077cdf3b1 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java @@ -1,7 +1,34 @@ +/* + * 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.cleanarchitecture; import java.util.List; +/** + * CartRepository + */ public interface CartRepository { void addItemToCart(String userId, Product product, int quantity); void removeItemFromCart(String userId, String productId); diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java index 72796038c2a6..3a49b87822df 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java @@ -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.cleanarchitecture; import java.util.ArrayList; @@ -5,6 +29,9 @@ import java.util.List; import java.util.Map; +/** + * InMemoryCartRepository + */ public class InMemoryCartRepository implements CartRepository { private final Map> userCarts = new HashMap<>(); diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java index 379f80f64ba0..a83843aec6e7 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java @@ -1,8 +1,35 @@ +/* + * 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.cleanarchitecture; import java.util.ArrayList; import java.util.List; +/** + * InMemoryOrderRepository + */ public class InMemoryOrderRepository implements OrderRepository { private final List orders = new ArrayList<>(); diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java index 210b398f1a6d..b6be4adb9c61 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java @@ -1,8 +1,35 @@ +/* + * 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.cleanarchitecture; import java.util.HashMap; import java.util.Map; +/** + * InMemoryProductRepository + */ public class InMemoryProductRepository implements ProductRepository { private final Map products = new HashMap<>(); diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java index 6fc0811ce1de..6fb3a6203123 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java @@ -1,7 +1,34 @@ +/* + * 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.cleanarchitecture; import java.util.List; +/** + * Order + */ public class Order { private String orderId; private List items; diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java index b44c7f19d73f..e9bd3cc22576 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java @@ -1,6 +1,33 @@ +/* + * 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.cleanarchitecture; -public class OrderController{ +/** + * OrderController + */ +public class OrderController { private final ShoppingCartService shoppingCartUseCase; public OrderController(ShoppingCartService shoppingCartUseCase) { diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java index 865ef7c927b6..7582e7220f29 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java @@ -1,5 +1,32 @@ +/* + * 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.cleanarchitecture; +/** + * OrderRepository + */ public interface OrderRepository { void saveOrder(Order order); } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java index c35ae178f742..cfea669fd9a2 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java @@ -1,5 +1,32 @@ +/* + * 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.cleanarchitecture; +/** + * Product + */ public class Product { private String id; private String name; diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java index 25531d1ce2b8..1f5b150cde25 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java @@ -1,5 +1,33 @@ + +/* + * 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.cleanarchitecture; +/** + * ProductRepository + */ public interface ProductRepository { Product getProductById(String productId); } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java index 483ff06b4f95..51b832380e1e 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java @@ -1,12 +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.cleanarchitecture; import java.util.List; +/** + * ShoppingCartService + */ public class ShoppingCartService { private final ProductRepository productRepository; private final CartRepository cartRepository; private final OrderRepository orderRepository; + + /** + * + * @param productRepository + * @param cartRepository + * @param orderRepository + */ public ShoppingCartService(ProductRepository productRepository, CartRepository cartRepository, OrderRepository orderRepository) { @@ -15,6 +50,12 @@ public ShoppingCartService(ProductRepository productRepository, this.orderRepository = orderRepository; } + /** + * + * @param userId + * @param productId + * @param quantity + */ public void addItemToCart(String userId, String productId, int quantity) { Product product = productRepository.getProductById(productId); if (product != null) { From 015b1b0766a59cad8d06eb9479cddd16514ecb8f Mon Sep 17 00:00:00 2001 From: Suchismita-Deb Date: Wed, 2 Apr 2025 00:14:12 +0530 Subject: [PATCH 5/8] #3230 - Clean Architecture Sonar. --- .../com/iluwatar/cleanarchitecture/App.java | 43 +++--------- .../com/iluwatar/cleanarchitecture/Cart.java | 43 ++++++++---- .../cleanarchitecture/CartController.java | 48 ++++++++++--- .../cleanarchitecture/CartRepository.java | 36 +++++++++- .../InMemoryCartRepository.java | 53 ++++++++++++-- .../InMemoryOrderRepository.java | 17 ++++- .../InMemoryProductRepository.java | 43 ++++++++++-- .../com/iluwatar/cleanarchitecture/Order.java | 51 +++++++++----- .../cleanarchitecture/OrderController.java | 30 ++++++-- .../cleanarchitecture/OrderRepository.java | 13 +++- .../iluwatar/cleanarchitecture/Product.java | 43 +++++++----- .../cleanarchitecture/ProductRepository.java | 13 +++- .../ShoppingCartService.java | 69 ++++++++++++++----- .../cleanarchitecture/package-info.java | 10 +++ 14 files changed, 374 insertions(+), 138 deletions(-) create mode 100644 clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java index 546812c4d91a..214388c33707 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java @@ -1,27 +1,3 @@ -/* - * 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.cleanarchitecture; import lombok.extern.slf4j.Slf4j; @@ -30,14 +6,16 @@ * Clean Architecture ensures separation of concerns by organizing code, * into layers and making it scalable and maintainable. * - *

In the example there are Entities (Core Models) – Product, Cart, Order handle business logic. - * Use Cases (Application Logic) – ShoppingCartService manages operations - * like adding items and checkout. - * Interfaces & Adapters – Repositories (CartRepository, OrderRepository) abstract data handling, + *

In the example there are Entities (Core Models) – Product, Cart, + * Order handle business logic. + * Use Cases (Application Logic) – ShoppingCartService manages + * operations like adding items and checkout. + * Interfaces & Adapters – Repositories (CartRepository, OrderRepository) + * abstract data handling, * while controllers (CartController, OrderController) manage interactions. */ @Slf4j -public class App { +public final class App { private App() { throw new UnsupportedOperationException("Utility class"); @@ -49,13 +27,14 @@ private App() { * @param args command line args */ public static void main(final String[] args) { - ProductRepository productRepository = new InMemoryProductRepository(); CartRepository cartRepository = new InMemoryCartRepository(); OrderRepository orderRepository = new InMemoryOrderRepository(); - ShoppingCartService shoppingCartUseCase = - new ShoppingCartService(productRepository, cartRepository, orderRepository); + ShoppingCartService + shoppingCartUseCase = + new ShoppingCartService( + productRepository, cartRepository, orderRepository); CartController cartController = new CartController(shoppingCartUseCase); OrderController orderController = new OrderController(shoppingCartUseCase); diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java index 8f49eaae3180..0ec51e34bd9b 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -24,27 +26,40 @@ */ package com.iluwatar.cleanarchitecture; +import lombok.Getter; + /** - * Cart + * Cart. */ +@Getter public class Cart { - private Product product; - private int quantity; + /** + * Product. + */ + private final Product product; + + + /** + * quantity. + */ + private final int quantity; - public Cart(Product product, int quantity) { - this.product = product; - this.quantity = quantity; + /** + * + * @param prod + * @param qty + */ + public Cart(final Product prod, final int qty) { + this.product = prod; + this.quantity = qty; } + /** + * + * @return double + */ public double getTotalPrice() { return product.getPrice() * quantity; } - public Product getProduct() { - return product; - } - - public int getQuantity() { - return quantity; - } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java index 4543a4c2c123..a586ea10c516 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -26,25 +28,55 @@ package com.iluwatar.cleanarchitecture; /** - * CartController + * Controller class for handling shopping cart operations. + * + *

This class provides methods to add, remove, and calculate the + * total price of items in a user's shopping cart.

*/ public class CartController { + + + /** Service layer responsible for cart operations. */ private final ShoppingCartService shoppingCartUseCase; - public CartController(ShoppingCartService shoppingCartUseCase) { - this.shoppingCartUseCase = shoppingCartUseCase; + /** + * Constructs a CartController with the specified shopping cart service. + * + * @param shoppingCart The shopping cart service to handle cart operations. + */ + public CartController(final ShoppingCartService shoppingCart) { + this.shoppingCartUseCase = shoppingCart; } - public void addItemToCart(String userId, String productId, int quantity) { + /** + * Adds an item to the user's cart. + * + * @param userId The ID of the user. + * @param productId The ID of the product to be added. + * @param quantity The quantity of the product. + */ + public void addItemToCart( + final String userId, final String productId, final int quantity) { shoppingCartUseCase.addItemToCart(userId, productId, quantity); } - - public void removeItemFromCart(String userId, String productId) { + /** + * Removes an item from the user's cart. + * + * @param userId The ID of the user. + * @param productId The ID of the product to be removed. + */ + public void removeItemFromCart(final String userId, final String productId) { shoppingCartUseCase.removeItemFromCart(userId, productId); } - public double calculateTotal(String userId) { + /** + * Calculates the total cost of items in the user's cart. + * + * @param userId The ID of the user. + * @return The total price of all items in the cart. + */ + public double calculateTotal(final String userId) { return shoppingCartUseCase.calculateTotal(userId); } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java index 5e8077cdf3b1..9e3c7dfe94ca 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -27,12 +29,42 @@ import java.util.List; /** - * CartRepository + * CartRepository. */ public interface CartRepository { + /** + * Adds an item to the user's cart. + * + * @param userId The ID of the user. + * @param product The product to be added. + * @param quantity The quantity of the product. + */ void addItemToCart(String userId, Product product, int quantity); + /** + * Removes an item from the user's cart. + * + * @param userId The ID of the user. + * @param productId The ID of the product to be removed. + */ void removeItemFromCart(String userId, String productId); + /** + * Retrieves the list of items in the user's cart. + * + * @param userId The ID of the user. + * @return A list of items in the cart. + */ List getItemsInCart(String userId); + /** + * Calculates the total price of the items in the user's cart. + * + * @param userId The ID of the user. + * @return The total price of all items in the cart. + */ double calculateTotal(String userId); + /** + * Clears all items from the user's cart. + * + * @param userId The ID of the user. + */ void clearCart(String userId); } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java index 3a49b87822df..b107a428517a 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -30,41 +32,78 @@ import java.util.Map; /** - * InMemoryCartRepository + * Implementation of {@link CartRepository} that stores cart items in memory. + * + *

This class maintains a map of user carts where each user has a + * list of cart items.

*/ public class InMemoryCartRepository implements CartRepository { + /** + * A map storing user carts with their respective cart items. + */ private final Map> userCarts = new HashMap<>(); + /** + * Adds an item to the user's cart. + * + * @param userId The ID of the user. + * @param product The product to be added. + * @param quantity The quantity of the product. + */ @Override - public void addItemToCart(String userId, Product product, int quantity) { + public void addItemToCart( + final String userId, final Product product, final int quantity) { List cart = userCarts.getOrDefault(userId, new ArrayList<>()); cart.add(new Cart(product, quantity)); userCarts.put(userId, cart); } + /** + * Removes an item from the user's cart. + * + * @param userId The ID of the user. + * @param productId The ID of the product to be removed. + */ @Override - public void removeItemFromCart(String userId, String productId) { + public void removeItemFromCart(final String userId, final String productId) { List cart = userCarts.get(userId); if (cart != null) { cart.removeIf(item -> item.getProduct().getId().equals(productId)); } } + /** + * Retrieves all items in the user's cart. + * + * @param userId The ID of the user. + * @return A list of {@link Cart} items in the user's cart. + */ @Override - public List getItemsInCart(String userId) { + public List getItemsInCart(final String userId) { return userCarts.getOrDefault(userId, new ArrayList<>()); } + /** + * Calculates the total price of items in the user's cart. + * + * @param userId The ID of the user. + * @return The total price of the cart. + */ @Override - public double calculateTotal(String userId) { + public double calculateTotal(final String userId) { return userCarts.getOrDefault(userId, new ArrayList<>()) .stream() .mapToDouble(Cart::getTotalPrice) .sum(); } + /** + * Clears all items from the user's cart. + * + * @param userId The ID of the user. + */ @Override - public void clearCart(String userId) { + public void clearCart(final String userId) { userCarts.remove(userId); } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java index a83843aec6e7..2dab179a73f4 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -28,13 +30,22 @@ import java.util.List; /** - * InMemoryOrderRepository + * An in-memory implementation of the {@link OrderRepository}. + * + *

This class stores orders in a list, allowing orders to be saved + * but not persisted beyond the application's runtime.

*/ public class InMemoryOrderRepository implements OrderRepository { + /** A list to store orders in memory. */ private final List orders = new ArrayList<>(); + /** + * Saves an order to the in-memory repository. + * + * @param order The order to be saved. + */ @Override - public void saveOrder(Order order) { + public void saveOrder(final Order order) { orders.add(order); } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java index b6be4adb9c61..a0dd6567fd95 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -28,18 +30,49 @@ import java.util.Map; /** - * InMemoryProductRepository + * In-memory implementation of the {@link ProductRepository} interface. + * + *

This repository stores products in memory + * allowing retrieval by product ID.

*/ public class InMemoryProductRepository implements ProductRepository { + /** + * A map to store products by their unique product ID. + */ private final Map products = new HashMap<>(); + /** + * The price of the Laptop in USD. + *

Used in the in-memory product repository + * to define the cost of a Laptop.

+ */ + private static final double LAPTOP_PRICE = 1000.0; + + /** + * The price of the Smartphone in USD. + *

Used in the in-memory product repository + * to define the cost of a Smartphone.

+ */ + private static final double SMARTPHONE_PRICE = 500.0; + + /** + * Constructs an {@code InMemoryProductRepository} and + * initializes it with some example products. + */ public InMemoryProductRepository() { - products.put("1", new Product("1", "Laptop", 1000.0)); - products.put("2", new Product("2", "Smartphone", 500.0)); + products.put("1", new Product("1", "Laptop", LAPTOP_PRICE)); + products.put("2", new Product("2", "Smartphone", SMARTPHONE_PRICE)); } + /** + * Retrieves a product by its unique ID. + * + * @param productId The ID of the product to retrieve. + * @return The {@link Product} corresponding to the given ID + * {@code null} if not found. + */ @Override - public Product getProductById(String productId) { + public Product getProductById(final String productId) { return products.get(productId); } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java index 6fb3a6203123..04ed1ec9e6dc 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -24,30 +26,41 @@ */ package com.iluwatar.cleanarchitecture; +import lombok.Getter; import java.util.List; /** - * Order + * Represents an order placed by a user containing + * the ordered items and total price. + * + *

An order includes a unique order ID, a list of cart items + * and the total price of the order.

*/ +@Getter public class Order { - private String orderId; - private List items; - private double totalPrice; + /** + * The unique identifier for this order. + */ + private final String orderId; + /** + * The list of items included in this order. + */ + private final List items; + /** + * The list of items included in this order. + */ + private final double totalPrice; - public Order(String orderId, List items) { - this.orderId = orderId; - this.items = items; + /** + * Constructs an {@code Order} with the given order ID and list of cart items. + * The total price is based on the individual item prices in the cart. + * + * @param id The unique identifier for the order. + * @param item The list of cart items included in the order. + */ + public Order(final String id, final List item) { + this.orderId = id; + this.items = item; this.totalPrice = items.stream().mapToDouble(Cart::getTotalPrice).sum(); } - public String getOrderId() { - return orderId; - } - - public List getItems() { - return items; - } - - public double getTotalPrice() { - return totalPrice; - } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java index e9bd3cc22576..f7c8e966bfaa 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -25,16 +27,34 @@ package com.iluwatar.cleanarchitecture; /** - * OrderController + * Controller for handling order-related operations. + * + *

This class provides an endpoint for users to checkout their cart + * and place an order.

*/ public class OrderController { + /** + * Service for managing shopping cart operations. + */ private final ShoppingCartService shoppingCartUseCase; - public OrderController(ShoppingCartService shoppingCartUseCase) { - this.shoppingCartUseCase = shoppingCartUseCase; + + /** + * Constructs an {@code OrderController} with the given shopping cart service. + * + * @param shoppingCartUse The shopping cart service used to process orders. + */ + public OrderController(final ShoppingCartService shoppingCartUse) { + this.shoppingCartUseCase = shoppingCartUse; } - public Order checkout(String userId) { + /** + * Processes the checkout for a given user and creates an order. + * + * @param userId The ID of the user checking out. + * @return The created {@link Order} after checkout. + */ + public Order checkout(final String userId) { return shoppingCartUseCase.checkout(userId); } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java index 7582e7220f29..f722a6b43533 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -25,8 +27,15 @@ package com.iluwatar.cleanarchitecture; /** - * OrderRepository + * Repository interface for managing order persistence. + * + *

This interface defines the contract for storing orders in the system.

*/ public interface OrderRepository { + /** + * Saves an order to the repository. + * + * @param order The order to be saved. + */ void saveOrder(Order order); } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java index cfea669fd9a2..b6409341803d 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java @@ -1,5 +1,7 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -24,29 +26,32 @@ */ package com.iluwatar.cleanarchitecture; +import lombok.Getter; + /** - * Product + * Represents a product in the system. */ +@Getter public class Product { - private String id; - private String name; - private double price; + /** The unique identifier for the product. */ + private final String id; - public Product(String id, String name, double price) { - this.id = id; - this.name = name; - this.price = price; - } + /** The name of the product. */ + private final String name; - public String getId() { - return id; - } - - public String getName() { - return name; - } + /** The price of the product. */ + private final double price; - public double getPrice() { - return price; + /** + * Constructs a new Product with the given details. + * + * @param pdtId The unique identifier of the product. + * @param firstName The name of the product. + * @param p The price of the product. + */ + public Product(final String pdtId, final String firstName, final double p) { + this.id = pdtId; + this.name = firstName; + this.price = p; } } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java index 1f5b150cde25..1dde70005bf8 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java @@ -1,6 +1,7 @@ - /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -26,8 +27,14 @@ package com.iluwatar.cleanarchitecture; /** - * ProductRepository + * Repository interface for handling product-related operations. */ public interface ProductRepository { + /** + * Retrieves a product by its unique identifier. + * + * @param productId The unique ID of the product. + * @return The product corresponding to the given ID. + */ Product getProductById(String productId); } diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java index 51b832380e1e..2faf64876e95 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java @@ -1,5 +1,6 @@ /* - * This project is licensed under the MIT license. Module model-view-viewmodel is using + * 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 @@ -28,51 +29,81 @@ import java.util.List; /** - * ShoppingCartService + * Service class for managing shopping cart operations. + * + *

This class provides functionalities to add and remove items from the cart, + * calculate the total price, and handle checkout operations.

*/ public class ShoppingCartService { + /** Repository for managing product data. */ private final ProductRepository productRepository; + /** Repository for managing cart data. */ private final CartRepository cartRepository; + /** Repository for managing order data. */ private final OrderRepository orderRepository; /** + * Constructs a ShoppingCartService with the required repositories. * - * @param productRepository - * @param cartRepository - * @param orderRepository + * @param pRepository The repository to fetch product details. + * @param cRepository The repository to manage cart operations. + * @param oRepository The repository to handle order persistence. */ - public ShoppingCartService(ProductRepository productRepository, - CartRepository cartRepository, - OrderRepository orderRepository) { - this.productRepository = productRepository; - this.cartRepository = cartRepository; - this.orderRepository = orderRepository; + public ShoppingCartService(final ProductRepository pRepository, + final CartRepository cRepository, + final OrderRepository oRepository) { + this.productRepository = pRepository; + this.cartRepository = cRepository; + this.orderRepository = oRepository; } /** + * Adds an item to the user's shopping cart. * - * @param userId - * @param productId - * @param quantity + * @param userId The ID of the user. + * @param productId The ID of the product to be added. + * @param quantity The quantity of the product. */ - public void addItemToCart(String userId, String productId, int quantity) { + public void addItemToCart( + final String userId, final String productId, final int quantity) { Product product = productRepository.getProductById(productId); if (product != null) { cartRepository.addItemToCart(userId, product, quantity); } } - public void removeItemFromCart(String userId, String productId) { + /** + * Removes an item from the user's shopping cart. + * + * @param userId The ID of the user. + * @param productId The ID of the product to be removed. + */ + public void removeItemFromCart(final String userId, final String productId) { cartRepository.removeItemFromCart(userId, productId); } - public double calculateTotal(String userId) { + /** + * Calculates the total cost of items in the user's shopping cart. + * + * @param userId The ID of the user. + * @return The total price of all items in the cart. + */ + public double calculateTotal(final String userId) { return cartRepository.calculateTotal(userId); } - public Order checkout(String userId) { + /** + * Checks out the user's cart and creates an order. + * + *

This method retrieves the cart items, generates an order ID, + * creates a new order, saves it, and clears the cart.

+ * + * @param userId The ID of the user. + * @return The created order containing purchased items. + */ + public Order checkout(final String userId) { List items = cartRepository.getItemsInCart(userId); - String orderId = "ORDER-" + System.currentTimeMillis(); // simple order ID generation + String orderId = "ORDER-" + System.currentTimeMillis(); Order order = new Order(orderId, items); orderRepository.saveOrder(order); cartRepository.clearCart(userId); diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java new file mode 100644 index 000000000000..59bf905a428a --- /dev/null +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java @@ -0,0 +1,10 @@ +/** + * Provides classes and interfaces for the clean architecture + * pattern implementation. + * + *

This package includes classes for managing products, carts, + * orders, repositories, + * and services for a shopping cart system, following the + * clean architecture principles.

+ */ +package com.iluwatar.cleanarchitecture; From 8e8f4cf896c6df2e67553537589914bc57bdff27 Mon Sep 17 00:00:00 2001 From: Suchismita-Deb Date: Wed, 2 Apr 2025 01:14:41 +0530 Subject: [PATCH 6/8] #3230 - Clean Architecture Sonar. --- .../com/iluwatar/cleanarchitecture/Cart.java | 19 ++++++++++++------- .../InMemoryProductRepository.java | 2 +- .../com/iluwatar/cleanarchitecture/Order.java | 2 +- .../ShoppingCartService.java | 18 +++++++++--------- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java index 0ec51e34bd9b..d31fc00b828b 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java @@ -29,25 +29,28 @@ import lombok.Getter; /** - * Cart. + * Represents a shopping cart containing a product and its quantity. + * This class calculates the total price of the product based on its price and quantity. */ @Getter public class Cart { /** - * Product. + * The product in the cart. + * It holds the product details such as name, price, and description. */ private final Product product; - /** - * quantity. + * The quantity of the product in the cart. + * It represents how many units of the product are added to the cart. */ private final int quantity; /** + * Constructs a new Cart instance with a specified product and quantity. * - * @param prod - * @param qty + * @param prod the product to be added to the cart. + * @param qty the quantity of the product in the cart. */ public Cart(final Product prod, final int qty) { this.product = prod; @@ -55,8 +58,10 @@ public Cart(final Product prod, final int qty) { } /** + * Calculates the total price of the products in the cart. + * The total price is the product's price multiplied by the quantity. * - * @return double + * @return the total price of the products in the cart. */ public double getTotalPrice() { return product.getPrice() * quantity; diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java index a0dd6567fd95..e7e0c88826af 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java @@ -69,7 +69,7 @@ public InMemoryProductRepository() { * * @param productId The ID of the product to retrieve. * @return The {@link Product} corresponding to the given ID - * {@code null} if not found. + * {@code null} if not found. */ @Override public Product getProductById(final String productId) { diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java index 04ed1ec9e6dc..673d2108b93a 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java @@ -26,8 +26,8 @@ */ package com.iluwatar.cleanarchitecture; -import lombok.Getter; import java.util.List; +import lombok.Getter; /** * Represents an order placed by a user containing diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java index 2faf64876e95..9f6225a8173e 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java @@ -46,16 +46,16 @@ public class ShoppingCartService { /** * Constructs a ShoppingCartService with the required repositories. * - * @param pRepository The repository to fetch product details. - * @param cRepository The repository to manage cart operations. - * @param oRepository The repository to handle order persistence. + * @param pdtRepository The repository to fetch product details. + * @param repository The repository to manage cart operations. + * @param ordRepository The repository to handle order persistence. */ - public ShoppingCartService(final ProductRepository pRepository, - final CartRepository cRepository, - final OrderRepository oRepository) { - this.productRepository = pRepository; - this.cartRepository = cRepository; - this.orderRepository = oRepository; + public ShoppingCartService(final ProductRepository pdtRepository, + final CartRepository repository, + final OrderRepository ordRepository) { + this.productRepository = pdtRepository; + this.cartRepository = repository; + this.orderRepository = ordRepository; } /** From f129e04a90c1ba41a526dbc83fb0586947b2781a Mon Sep 17 00:00:00 2001 From: Suchismita-Deb Date: Wed, 2 Apr 2025 01:23:32 +0530 Subject: [PATCH 7/8] #3230 - Clean Architecture Sonar. --- .../src/test/java/com/iluwatar/cleanarchitecture/AppTest.java | 1 + .../java/com/iluwatar/cleanarchitecture/CartControllerTest.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java index 263b991d3180..d78baf3510d2 100644 --- a/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java +++ b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; + class AppTest { /** * Issue: Add at least one assertion to this test case. diff --git a/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java index 580f10f8b6f1..ec1d1bb29119 100644 --- a/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java +++ b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java @@ -2,6 +2,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class CartControllerTest { From c09210b4735c0e49ef18a595702a8a4c39c28ace Mon Sep 17 00:00:00 2001 From: Suchismita-Deb Date: Wed, 2 Apr 2025 09:27:05 +0530 Subject: [PATCH 8/8] #3230 - Clean Architecture Sonar. --- clean-architecture/img.png | Bin 38386 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 clean-architecture/img.png diff --git a/clean-architecture/img.png b/clean-architecture/img.png deleted file mode 100644 index cd3a01e6ae060d9c2414ffd97f74407770406827..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38386 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 Wx(~->c;lNQP*PM^sE{{*_J09c4b_VP