Giter VIP home page Giter VIP logo

buckpal's Introduction

Get Your Hands Dirty on Clean Architecture

This repository implements a small web app in the Hexagonal Architecture style, as discussed in the book "Get Your Hands Dirty on Clean Architecture".

The code has been updated to the 2nd edition of the book.

Get the print book

Get Your Hands Dirty on Clean Architecture cover

Get the e-book

This is the self-published version, which is only available electronically.

Get Your Hands Dirty on Clean Architecture cover

Companion Articles

Prerequisites

  • JDK 17
  • this project uses Lombok, so enable annotation processing in your IDE

About the book

All About Hexagonal Architecture

  • Learn the concepts behind "Clean Architecture" and "Hexagonal Architecture".
  • Explore a hands-on approach of implementing a Hexagonal architecture with example code on GitHub.
  • Develop your domain code independent of database or web concerns.

Hexagonal Architecture

Get a Grip on Your Layers

  • Learn about potential problems of the common layered architecture style.
  • Free your domain layer of oppressive dependencies using dependency inversion.
  • Structure your code in an architecturally expressive way.
  • Use different methods to enforce architectural boundaries.
  • Learn the consequences of shortcuts and when to accept them.
  • ... and more.

Dependencies

What Readers Say

Tom Hombergs has done a terrific job in explaining clean architecture - from concepts to code. Really wish more technical books would be as clear as that one!

Gernot Starke - Fellow at INNOQ, Founder of arc42, Author of Software Architecture Books, Coach, and Consultant

Love your book. One of the most practical books on hexagonal architecture I have seen/read so far.

Marten Deinum - Spring Framework Contributor and Author of "Spring 5 Recipes" and "Spring Boot 2 Recipes"

A book taken right out of the machine room of software development. Tom talks straight from his experience and guides you through the day-to-day trade-offs necessary to deliver clean architecture.

Sebastian Kempken - Software Architect at Adcubum

Thank you for the great book, it helped me gain significant insight into how one would go about implementing hexagonal and DDD in a modern Spring project.

Spyros Vallianos - Java Developer at Konnekt-able

After reading it I had one of these 'aha' moments when things finally click in your brain.

Manos Tzagkarakis - Java Developer at Datawise

Table of Contents

  1. Maintainability
  2. What's Wrong with Layers?
  3. Inverting Dependencies
  4. Organizing Code
  5. Implementing a Use Case
  6. Implementing a Web Adapter
  7. Implementing a Persistence Adapter
  8. Testing Architecture Elements
  9. Mapping Between Boundaries
  10. Assembling the Application
  11. Taking Shortcuts Consciously
  12. Enforcing Architecture Boundaries
  13. Managing Multiple Bounded Contexts
  14. A Component-Based Approach to Software Architecture
  15. Deciding on an Architecture Style

buckpal's People

Contributors

benjaminknauer avatar mdeinum avatar thombergs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

buckpal's Issues

BookPalApplication failed to start


APPLICATION FAILED TO START


Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

Action:

Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

Cycle buckpal-application, buckpal-testdata

Hi

when trying to import the projects into Eclipse (with Buildship for Gradle) I had a few issues, when trying to simply import it with the wizard; when using the automatic project detector from a git repository I finally managed to have projects imported but I get this error on most projects:

One or more cycles were detected in the build path of project 'buckpal-application'. The paths towards the cycle and cycle are:
->{buckpal-application, buckpal-testdata}

Indeed in buckpal-application there's a

dependencies {
...
    testImplementation project(':buckpal-testdata')
}

and in buckpal-testdata there's a

dependencies {
    implementation project(':buckpal-application')
}

I'm a Maven user and I'm not familiar with Gradle at all, but the above actually looks like a cycle to me...

In general, is the project meant to be imported in an IDE such as Eclipse?

Location of application.properties

Hi Tom,

First of all, Thanks for the nice demo project for hexagonal architecture. :)
This project is the best implementations I've ever seen!

I'm quite a newbie on Spring Boot, so my question would be quite silly.
As I see this project, I cannot find application.properties or application.yml. I guess this should exist if I want to add some configuration like DB connection.

Could you let me know why configuration file is missing in this project?

Thanks!

Mappers cause JPA entities to "detach"

Hi @thombergs

Thanks for a very good and informative read! Great job!

I have an issue regarding updating existing entities. Since the *JpaEntity objects will be mapped to domain object once read from the database and then back to *JpaEntity objects once they're again passed to the appropriate outgoing port, these objects will no longer be the same objects that were originally retrieved from Hibernate. This causes all the calls with updated entities to *Repositoy.save(jpaEntity) to fail with the javax.persistence.EntityExistsException. What would be the appropriate way of handling this case?

Thanks!

Run error? Request method 'GET' not supported

Hi, Tom

I am new to java project.

According to the article https://reflectoring.io/spring-boot-gradle-multi-module/
Start the application by ./gradlew bootRun
And test by input the url in browser http://localhost:8080/accounts/send/41L/42L/500.

Here is what I get.
2020-05-13 11:38:41.481 WARN 41785 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]

Is this the right method to access the buckpal application?
Any comment will be help.

Instantiation of ValidatorFactory leads to performance issues

Hi 👋

My team used your book on clean architecture as reference for implementing new microservices. We absolutely love your book and the architecture approach.

Nevertheless, we want to share a major performance issue we encountered while using your template for the SefValidating abstract class:
During load testing, we noticed that our application used a lot of memory and requests took a long time even under small loads. Using profiling, we noticed that creating a ValidatorFactory during instantiation of every domain object was the problem.
We solved the issue by adding the ValidatorFactory as a static attribute in the abstract class.

Cheers,
Benjamin

public SelfValidating() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}

Suggestion for the SelfValidating abstract class

Hi,

I've read your book Get Your Hands Dirty on Clean Architecture and I liked it very much. In your book you showed an interesting class called SelfValidating which inspired me. I wanted to thank you for it and share my thought on this.

I have refactored this abstract class io.reflectoring.buckpal.common.SelfValidating into an interface that other classes can implement. The Interface version has a default method validateSelf that works the same as your version of the abstract class. By using this interface you're able to perform a validateSelf call and still be able to extend another class if that is required.

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Set;

public interface SelfValidating<T> {

	/**
	 * Evaluates all Bean Validations on the attributes of this
	 * instance.
	 */
	default void validateSelf() {
		ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
		Validator validator = factory.getValidator();

		Set<ConstraintViolation<T>> violations = validator.validate((T) this);
		if (!violations.isEmpty()) {
			throw new ConstraintViolationException(violations);
		}
	}
}

Example class implementing this interface:

class Example implements SelfValidating<Example> {

	@NotBlank
	private final String name;

	public Example(String name) {
		this.name = name;
		validateSelf();
	}

	public String getName() {
		return name;
	}
}

Kind regards.

How does Exception Handling integrate into Clean Architecture?

Hi @thombergs, thanks for a great book, it was really a great eye-opener to bring clean architecture into practice.

In general, I have problems to connect the dots in one topic: How does exception handling conceptionally fit into the picture?

For example the LoadAccountPort defines loadAccount interface/communication channel but the concrete adapter implementation throws an EntityNotFoundException if an account is not found. Instead of an implementation detail isn't this a property of the communication port, which all adapters of this port should comply with? Or asked the other way round, how can I force/lead implementeers of port interfaces to throw "expected" exceptions?

Another area where I am not sure about is global error handling: Say I want that the EntityNotFoundException should relate to a 404 and the service ThresholdExceededException should lead to a 403, both with a default error response body (i.e based on rfc7807). If I create now a global error handler in the web adapter, isn't then also the web adapter implementation depending on implementation details (EntityNotFoundException) of the implementation detail of another out adapter impl.?

How can I publish domain event?

I want to publish domain event when changed domain. What should I do?

For example

public class Account {
    public boolean withdraw(Money money, AccountId targetAccountId) {
        // codes..

        Event.raise(new AccountWithdrawEvent(targetAccountId, money));    // <-- here
    }
}

Organizing Code

it seems that the codes are organized by Layer, not the "Expressive Package Structure".

Doesn't AccountMapper violate the Single Responsibility Principle?

SRP (Single Responsibility Principles) states that "a module should have one reason to change".

I see you have multiple methods to map to different Entities in the one class. Doesn't this violate the SRP? The class now has multiple reasons to change. I know SRP is just a guideline, it would be great if you explained why you decided on the trade off.

https://github.com/thombergs/buckpal/blob/master/adapters/buckpal-persistence/src/main/java/io/reflectoring/buckpal/adapter/persistence/AccountMapper.java

NoOpAccountLock bean is not clear

Hi Tom,

I read your book and explore the repository associated with it and I must say my long search for clean architecture implementation with spring and java, have reached to some conclusion now. It helped me understand few misconception about dependency inversion and SOLID principles and I am still trying to embrace it for large enterprise project.

However, I am not able to understand the lock and release part in code, although I do understand it in context of business domain but not sure if you have just demonstrated it with dummy singleton bean or is it real implementation of locking behaviour in this context?

Thanks a lot for sharing your thoughts with a book and all the resources online.

Extract hexagonal archunit code to its own project

Hi,

I read the book yesterday (which is excellent, thank you very much) and one of the things that I liked was the archunit "hexagonal architecture" extension. Would it make sense to actually make this a first class component and extract it to its own module? Maybe even release it to maven central?

Thanks!

Something confusing me.

Hi @thombergs ,
A query here, in the book "Get Your Hands Dirty ond Clean Architecture", you have used the term/word UseCase, for the stuff in ports/in interface. But at many places, I have seen use case is not interface but implementation of input port interface.
So should the UseCase be considered here as port (interface) and application.domain.service as its implementation.
Like, in general
Input port >>>implemented by >>> UseCase class
But you termed it as
UseCase >>>implemented by >>> application.domain.service

Please reply, as its getting confused when compared with other learning stuff on internet.
Thank you.

Regards,
Nishant

About Transactions

Hi @thombergs,

I was taking a look at the implementation of the SendMoneyService (https://github.com/thombergs/buckpal/blob/master/src/main/java/io/reflectoring/buckpal/account/application/service/SendMoneyService.java).

It seems you are implementing pessimistic locking by explicitly locking the banck accounts with the AccountLock.

I can see that you also handle the transaction (either commit/rollback) with javax's Transactional.

Given that the locks on the bank accounts are released before the transaction is committed/rollback, how can you make sure that in between (ie, when the locks are released but before the commit/rollback is done) there's not another transaction executed with the same bank accounts before this one is fully finished?

Thanks

Question regarding the example

Hi Tom,
I had read your book about clean architecture a month ago. I really like it as it was straightforward to the facts and no beating around the bush. 

Now, after that, today I was going through the code sample you had shared in the book ie. the buckpal example (https://github.com/thombergs/buckpal)

Looking at the send money use case, I understood the flow as follows:

  1. Load the source account.
  2. Load the Target account.
  3. Withdraw from Source
  4. Add to target. 
  5. save the activities on the accounts. 

Now here are some of the questions I had. 

  1. On the  line 
    LocalDateTime baselineDate = LocalDateTime.now().minusDays(10);

I see you are loading the account with a date of only 10 days back. Then account state is created based on the activities only 10 days back. So aren't we losing the account activity prior to that day to calculate the baseline account value? isn't this like the incorrect state of the account to perform withdrawal?

  1. In case we decide to load all the activities to calculate the account's baseline value, aren't we querying a lot of data from the database? 

What I had in mind, would be to also persist the baseline account value in the account entity, which would be the aggregate value of all the withdrawals and deposits. And we can then fetch the current baseline value, which would be like a single query
select * from account where accountid=1
then

  1. you make a change based on the activity to the baseline value
  2. persist the activity to the database
  3. persist the account entity with the new baseline value.

I feel every time to get all the activities for the account and calculate the baseline every time I load the account is a waste of CPU and also puts pressure on the database to return a lot of data for the account.

I may be wrong In thinking this... could you enlighten me on what advantage I am missing by the calculation of the baseline everytime I load the account?

Suggestion: Non-multi-module project

Thank you for the very informative book "Get your hands dirty on clean architecture"
For the newbies to Springboot+gradle+multimodule can we have a new branch with single module project version? It is kind of hard to map the project structure mentioned in the book and the implemented version in github

How does the control flow relate to the "Clean Architecture" control flow?

Hi @thombergs,
I'm trying to understand your version of flow of control.
It seems that you're advocating for a controller->usecase->controller->web sequence of control flow.
I'm struggling to understand your concept of the output port - it seems to refer to it as being a persistence boundary interface, that is not what my understanding of clean architecture by Uncle Bob is saying.
When Uncle Bob talks about output port he is referring to a Presenter concept, not persistence.

Also, from the flow of control diagram we see that the control is passed from the controller -> usecase -> presenter where the controller is the input port and the presenter is the output.

https://softwareengineering.stackexchange.com/questions/357052/clean-architecture-use-case-containing-the-presenter-or-returning-data

am I missing something? Can you please clarify this from me.

Confusing layers

Hello.
I am getting confused about some packages in this example.
I see port package in the application layer. I think It should be in the domain package, Am I wrong ?

Also, the use case is an implementation of an input port, so why SendMoneyUseCase is an interface ? and why it is in the application layer ??

Spring Configuration

Hi
Which module to put common spring configurations such as security and JPA auditing?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.