Hexagonal Architecture Explained Simply
37sQuick, clear introduction to a complex topic with a promise of practical application, appealing to developers seeking to improve code structure.
▶ Play ClipThis video explains hexagonal architecture by applying it to a previously built book API. The host, Mark Bradley, draws a diagram to show how the architecture separates the application into layers: an HTTP controller, a business logic layer, and a data repository, all connected via interfaces. The goal is to demonstrate how this pattern makes the code loosely coupled, testable, and easy to modify without affecting the core business logic.
The video will look at hexagonal architecture, a way of designing applications to be loosely coupled, created by Alistair Cockburn.
The hexagon shape is arbitrary; the center contains business logic. The diagram starts with the business logic layer.
A circle on the left represents the HTTP controller implementation. It understands HTTP, REST, and JSON, and knows how to handle incoming requests and respond.
An interface (e.g., 'IsbnBookRetriever') sits between the controller and business logic. The controller only needs to pass an ISBN to this interface to get a book.
The business logic layer (Book Manager) implements the interface. It also depends on a repository interface to obtain books.
A second interface (e.g., 'IsbnBookRepository') is created for the repository. The repository implementation (e.g., PostgresBookRepository) handles database communication.
This structure follows the Single Responsibility Principle, making each layer testable. It also allows swapping out external components (e.g., HTTP for gRPC, Postgres for MongoDB) without affecting business logic.
Hexagonal architecture keeps business logic central and isolated, enabling easy swapping of external components and improving testability. The video encourages viewers to apply this pattern to their own APIs.
"The title accurately describes the video's content, which is a guide to designing an API using hexagonal architecture, with a focus on PHP code."
What is hexagonal architecture?
A way of designing applications to be loosely coupled, created by Alistair Cockburn.
0:27
What does the hexagon shape represent in hexagonal architecture?
The shape is arbitrary; the center contains business logic.
1:30
What does the HTTP controller understand?
HTTP, REST, and JSON.
3:27
What is the purpose of the interface between the controller and business logic?
It allows the controller to pass an ISBN and retrieve a book without knowing the business logic details.
5:41
What is the role of the repository interface?
It allows the business logic to obtain books without knowing how they are stored.
10:19
How does hexagonal architecture improve testability?
By separating each layer with a single responsibility, making each layer testable independently.
13:07
What external components can be swapped out using hexagonal architecture?
The front interface (e.g., HTTP to gRPC) and the data store (e.g., Postgres to MongoDB).
16:00
Definition of Hexagonal Architecture
Provides the core definition of the architectural pattern discussed throughout the video.
0:27Hexagon Shape is Arbitrary
Clarifies a common misconception about the hexagon shape in the architecture.
1:30Controller Understands HTTP/REST/JSON
Highlights the single responsibility of the controller layer.
3:27Interface Decouples Controller from Business Logic
Shows how interfaces enable loose coupling between layers.
5:41Repository Interface Hides Storage Details
Demonstrates how the business logic remains unaware of the data storage implementation.
10:19Single Responsibility Principle Applied
Connects hexagonal architecture to the SOLID principles, specifically single responsibility.
13:07Swappable External Components
Illustrates the practical benefit of being able to change external technologies without affecting business logic.
16:00[00:00] in this episode we are going to look at
[00:02] hexagonal architecture
[00:04] hi i'm mark bradley and welcome to
[00:06] testing all the things
[00:08] a screencast in which we use live coding
[00:10] to demonstrate different types of
[00:11] testing tools and techniques
[00:15] in this video we're not going to write
[00:16] any code we're going to look at the code
[00:19] we wrote
[00:20] over the previous episode to create our
[00:22] book api
[00:23] and we're going to draw out the
[00:25] architecture that we used
[00:27] hexagonal architecture this is a way of
[00:31] designing applications to be loosely
[00:33] coupled
[00:35] the idea was created by alistair
[00:36] cockburn
[00:38] let's look at the code
[00:48] in the videos where we created our book
[00:51] api
[00:52] i tried to avoid using the architectural
[00:54] pattern we were going to use
[00:56] i wanted to concentrate it on the test
[00:58] we were creating
[01:00] but now i think it's important we look
[01:02] at the architectural decisions we made
[01:05] you saw how useful they were in the aid
[01:07] of testing each layer
[01:10] now let's look at how they can improve
[01:12] your
[01:13] applications in other ways hexagonal
[01:16] architecture is very simple to
[01:18] understand
[01:19] there are many diagrams on the internet
[01:20] that show how to use it but i thought
[01:22] it'd be very useful to apply it to the
[01:24] code we've been writing
[01:25] so the first thing we should look at is
[01:27] this the hexagon of our diagram
[01:30] the hexazon doesn't actually mean
[01:31] anything in particular it was just a
[01:33] shape that was picked
[01:34] but in the center of the hexagon is
[01:36] where our business
[01:37] logic and our business codes it i'm
[01:40] going to put that
[01:41] in our diagram straight away this is
[01:43] where
[01:44] business logic sits
[01:50] stretch out
[01:56] we're going to start over here on the
[01:57] left hand side of our diagram
[01:59] i'm going to add a circle
[02:03] that sits here
[02:15] now this circle represents the
[02:18] implementation of our http
[02:20] handler
[02:23] if we if we go and look at the code
[02:31] we called that
[02:34] the book by isbn
[02:48] controller
[03:14] click those two things together
[03:20] okay so this is our controller and the
[03:23] idea here
[03:24] is this controller understands
[03:27] http and rest and jason
[03:32] that's all it understands about our
[03:34] application
[03:38] what comes in and out of here from the
[03:40] real world
[03:59] what comes in and out of this controller
[04:01] is http
[04:04] rest and json those are the things it
[04:07] understands it knows how to
[04:09] handle an incoming http request look at
[04:12] the
[04:12] uri and recognize the
[04:15] isbn in within the pattern of the uri
[04:19] and it knows how to respond with json
[04:21] for different circumstances
[04:24] that's all it understands not quite
[04:26] there's one other thing it understands
[04:27] it knows it has access to an interface
[04:36] ships here sits
[04:39] in between our http controller
[04:42] and our business logic layer
[04:51] like so we've got this interface here in
[04:56] our code
[04:58] we called this interface we can see if
[05:00] we open up our isbn controller
[05:02] an isbn book retriever and that's just
[05:06] an interface
[05:07] with one function retrievebook by isbn
[05:11] if we go back to our diagram we label
[05:15] the interface
[05:27] if we link that
[05:32] like so
[05:41] so now we're starting to develop some
[05:43] understanding that so this
[05:44] isbn book retriever is the interface to
[05:48] our business logic layer
[05:50] our controller layer doesn't need to
[05:52] understand
[05:53] anything that happens within here it
[05:55] just needs them to know
[05:57] that once it's got its isbn from the
[06:00] request that came in the http request
[06:03] once it's done its thing it then needs
[06:06] to pass an isbn
[06:07] over into this interface and this
[06:10] interface
[06:12] retrieve a book for it to render into
[06:14] json
[06:15] and return so that's what we have here
[06:19] it's very simple interface in fact i'm
[06:21] just going to put
[06:22] i here so we know that it's an interface
[06:33] and then this jumps into our business
[06:34] logic so our business logic is the thing
[06:37] that implements
[06:38] the function within this interface
[06:42] which is retrieve book by isbn
[06:46] which we called the book manager so if
[06:49] we go and
[06:50] label our business logic area
[06:56] this is our book manager
[07:05] it's there okay so our business manage
[07:08] logic layer here is our book manager
[07:12] and it knows it has to implement the
[07:14] interface here that sits
[07:16] between it and something that gives it
[07:18] an isbn
[07:19] so it knows it needs to return a book it
[07:22] also knows it then
[07:23] is responsible for obtaining a book from
[07:25] somewhere
[07:26] and this is where we start looking at
[07:28] the left-hand side of our screen at the
[07:30] right hand side sorry of our screen
[07:34] and this is where we start looking at
[07:36] the right hand side of our screen
[07:39] our implementation our business logic
[07:41] layer takes a book
[07:43] repository as a dependency
[07:46] and again this is another oh okay
[07:51] it should have been an interface so
[07:53] let's
[07:54] go back and maybe we we could have had a
[07:56] refactor here added that
[07:58] interface which would have been better
[08:00] um
[08:02] and maybe we should do that so let's go
[08:05] back and implement the interface
[08:08] stuff set up in the code so we want to
[08:11] create another interface
[08:12] that sits here
[08:17] okay whatever interface that sits here
[08:31] and we will give this a name now
[08:41] so i will quit i
[08:44] sbn book repository
[08:52] and that's gonna be another interval
[09:06] interface
[09:09] i'll go and create the interface in the
[09:11] code after this and just push it i won't
[09:13] make you watch me create an interface
[09:14] and make those
[09:15] code changes but we'll create that
[09:17] interface and we'll call it that
[09:19] and we know that that interface is
[09:22] implemented
[09:23] by a book repository so let's
[09:27] create the implementation on this side
[09:32] yeah okay
[09:42] okay i'm going to give that a label and
[09:43] that was the book repository
[10:05] our book manager businesslogic layer
[10:09] now implements interface it knows that
[10:10] it has to
[10:12] respect and it also makes use of an
[10:14] interface
[10:15] that it can use to obtain books a
[10:18] repository
[10:19] a storage solution for books because of
[10:22] the interface
[10:23] we should have created it doesn't have
[10:26] any knowledge
[10:27] of how those books are stored how
[10:29] they're retrieved
[10:30] it just knows that if it gives a isbn
[10:34] book repository
[10:35] an isbn then a book will be returned
[10:38] and it can then fulfill its interface
[10:41] with
[10:42] over here and return that book to the
[10:45] thing that's been asking for it
[10:47] we could have done some better naming
[10:49] here this could have been a refactor
[10:51] that we
[10:51] we could do as well so our book
[10:53] repository again it doesn't really give
[10:55] us much information
[10:56] by the class name so we could have
[10:58] called this book repository
[11:00] instead of just book repository we could
[11:02] have called it
[11:03] postgres book repository or psql book
[11:06] repository
[11:08] to give the user of the book repository
[11:12] not the user of the interface but the
[11:13] user of the repository the understanding
[11:16] that
[11:16] this book repository uses postgres
[11:20] we know now that this book repository
[11:23] needs to talk to something
[11:25] in the outside world so let's represent
[11:28] that
[11:40] okay and this is i'll stick a label on
[11:42] it
[11:48] the sql doesn't fit with it now
[11:53] there we go
[11:57] okay so the book repository here
[12:01] is completely responsible for the
[12:02] communication in and out of
[12:11] psql
[12:21] there we go so this is responsible for
[12:24] implementing the interface
[12:26] at least one of the interfaces we know
[12:27] about the isbn book repository
[12:30] and interacting with the outside world
[12:33] so this shows you kind of how these
[12:36] hexagonal architecture diagrams relate
[12:38] to the code
[12:39] we've created so i know we've got a bit
[12:42] of
[12:42] stuff that sits around over here which
[12:44] is our application which probably
[12:45] actually
[12:46] imagine sits around all of the code
[12:47] we've got here we'll ignore that we're
[12:49] just looking at the
[12:51] the details of application not the the
[12:54] bootstrapping provided
[12:56] by the slim framework so hopefully you
[12:59] can see
[13:00] why this way of structuring your code
[13:02] and following this
[13:04] architectural pattern makes your code
[13:06] very testable
[13:07] one thing that can make your code very
[13:09] testable is following the
[13:11] s of the solid principles the single
[13:13] responsibility
[13:14] and this is a really good way of
[13:16] separating out your code so each layer
[13:18] has a single responsibility
[13:20] if you imagine here but it's nice over
[13:23] here the controller is responsible
[13:26] for handling http understanding http
[13:29] rest and json so not
[13:32] masses of stuff really sitting over here
[13:36] just got one responsibility and it has
[13:39] knowledge if one thing passes
[13:42] it's once it's done its thing it can
[13:44] pass an isbn
[13:46] into our business logic layer now
[13:48] business logic layer
[13:50] okay it's at this point it's very simple
[13:52] its responsibility is very low
[13:54] it is to it knows it has access to
[13:57] something that
[13:58] holds a number of books and it can
[14:01] access those books by the isbn it's been
[14:03] given
[14:05] but if this is if we had this business
[14:08] logic layer
[14:09] it was responsible for the saving of
[14:12] books or the creation of books
[14:14] then the business object layer might
[14:16] also do some validation
[14:18] of the data that comes into it
[14:21] and reject books for saving if they
[14:24] don't have an offer or they
[14:25] have too many numbers of pages or
[14:27] something like that and then
[14:30] we would have another interface sitting
[14:32] on this hand side would be would be
[14:34] book store interface our book repository
[14:37] would then implement two interfaces
[14:40] and interface with our database
[14:44] and again small amount of responsibility
[14:47] over here sitting here
[14:49] our repository is just responsible for
[14:51] taking data and throwing it to its data
[14:53] store
[14:54] in this case a postgres database that
[14:57] shows
[14:58] that's what that covers why this
[15:01] way of writing code and separating code
[15:04] out
[15:05] makes testing very easy the other thing
[15:08] it's really
[15:08] useful for is it means that because
[15:11] you've got your business object that
[15:12] sits
[15:13] in the center and business object would
[15:15] be
[15:16] reasonably stable okay then you know my
[15:19] feature changes
[15:20] might slightly tweak the business logic
[15:23] layer
[15:24] and yes that would have um
[15:27] cascading changes potentially on the
[15:30] controller side over here on the left
[15:31] and possibly on the repository side over
[15:33] there on the right
[15:34] it might be more data need to be stored
[15:36] and more data be returned or something
[15:38] like that
[15:40] but if we want to make more sweeping
[15:45] external architectural changes to our
[15:48] application
[15:50] it means we don't have we can do that
[15:53] very simply without having to affect our
[15:56] business logic
[15:58] so for instance if we wanted to make
[16:00] some changes to the
[16:02] the front interface the access to our
[16:05] application
[16:07] we can easily make these by creating
[16:10] something else
[16:11] that can obtain an isbn
[16:14] and pass it through our interface into
[16:17] our business logic layer
[16:19] so for instance we could change the fact
[16:21] that it is http
[16:22] rest to be a grpc
[16:26] implementation or it could be
[16:29] not grpc we could make it a graphql
[16:31] service
[16:32] or we could have the fact that
[16:36] somehow the communication is not http at
[16:39] all but it goes over
[16:41] a queue or kafka topics or something
[16:44] like that so
[16:45] this part here
[16:48] is completely interchangeable without
[16:52] affecting our business logic layer
[16:55] and the same can also happen on
[16:59] the back end of our syst application our
[17:02] data store
[17:04] so because of the interface here we
[17:06] could have all sorts of different
[17:09] options if we decided we didn't want to
[17:12] use postgres anymore
[17:13] we want to switch out completely we can
[17:16] switch out to
[17:17] mysql a different sql database
[17:20] or we could go and say actually we don't
[17:23] want an sql database at all we want a
[17:25] nosql database
[17:26] or a document store we want to go to
[17:28] using mongodb
[17:30] or elasticsearch we could quite easily
[17:33] again swap out our data store our
[17:36] repository of books
[17:38] into a completely different technology
[17:40] and our business logic would not be the
[17:41] wiser
[17:42] all it knows is begin it's being given
[17:46] something that implements the interface
[17:48] that it needs to obtain books
[17:51] obviously the example we implemented was
[17:53] very simple it was just about retrieving
[17:55] books
[17:57] but we might want if we look think about
[18:00] now the creation of books
[18:02] and we keep with our http rest
[18:05] implementation so
[18:06] a book is given to us via json
[18:10] and we can take that json and the http
[18:13] request
[18:14] and construct the data that needs to be
[18:16] passed over whatever interface we create
[18:18] here
[18:19] isbn book creator maybe interface and it
[18:22] goes into our business logic layer
[18:24] now business only player would know they
[18:26] could store
[18:27] the book that is given into an a
[18:30] bookstore
[18:31] interface and that's implemented by a
[18:33] book repository
[18:34] now as we remember we could say that our
[18:37] our validation of the incoming book
[18:39] would sit within the business logic
[18:40] layer
[18:42] and that's quite simple um but
[18:45] what might happen when we're creating
[18:47] books we might want to do
[18:49] more than just store our book
[18:54] over here on the right hand side we
[18:56] might want to
[18:58] notify something of our
[19:01] book being created so what we might have
[19:04] is another interface that sits over here
[19:07] so book creation notifier maybe
[19:10] and that could be implemented by again a
[19:13] number of different things we could have
[19:14] it sending an email to all the managers
[19:16] that a book has been created
[19:17] or we could have an implementation that
[19:19] sends an sms
[19:21] message or sends a slack notification
[19:24] to people that a book has been created
[19:27] okay so that's kind of power the
[19:29] hexagonal architecture
[19:31] it's nice it gives you the ability to be
[19:32] able to swap things out
[19:34] very simply without having to affect
[19:36] your business logic
[19:38] it keeps your business like central to
[19:39] everything
[19:41] i hope you enjoyed this walk through the
[19:43] architectural design
[19:45] of our api i'll make the changes and add
[19:48] the interface
[19:49] we talked about and add this diagram to
[19:52] the repository
[19:54] see you again soon
[19:58] thank you for watching this episode of
[19:59] testing all the things i hope you
[20:01] enjoyed it
[20:02] if you did please rate and review the
[20:04] video and subscribe
[20:06] to the channel if you did not and you
[20:08] have any feedback
[20:09] please leave a comment in the comment
[20:10] section of the video
[20:12] or contact me on twitter at bradley
⚡ Saved you time reading this? Transcribe any YouTube video for free — no signup needed.