Frontend Architecture Patterns You Need to Know in 2025
FULL TRANSCRIPT
Hey folks, my name is Dimma. I'm a
senior web developer based in Berlin.
I've got more than eight years of
experience across different companies.
I've been through many interviews myself
and conducted plenty as an interviewer,
too. On this channel, we talk about
passing front-end interviews and
advanced front-end topics in general. If
you are preparing for an interview or
working on your career as a web
developer, you will find some really
good stuff here. Today I want to discuss
front- end architecture. Front end
architecture I believe a very overlooked
topic. Not many of us take it seriously
when we are working on projects. But
here's the thing. Front end apps have
become complex enough that we really
need to consider their architecture as a
crucial part of the development process.
In this video, we will look at some
popular front-end patterns, discuss
their advantages, and talk about when we
should use them and when we shouldn't.
Let's dive in.
Now, when developers hear the word
architecture, a lot of them immediately
think about files and directories. And
while that's part of it, it's not the
main idea. Architecture isn't just about
how your files is structured. It's about
how different layers of your app
interact with each other. You might have
heard of MVC or model view controller
which was a pretty common pattern back
in the day. Even though it's not as
widely used now, especially in modern
fronted apps, the concept still helps us
understand how different parts of an
application communicate. And here's the
thing, your architecture can dictate how
your files are structured, but it
doesn't have to. For example, if you put
every single file into one folder, which
of course nobody in your team will like,
you'll still have an architecture as
long as your components interact in a
structured way. So why do we need
architecture? First, flexibility. It
allows different part of the app to be
modified or replaced without affecting
everything else. Realistically, how
often do you replace React with Vue or
View as well? Probably not too often.
But flexibility isn't just about
swapping frameworks. It's about having
clear boundaries between components to
make maintenance application easier.
Testability. Individual layers are
easier to test and scalability. As an
app grows, clear separation of concerns
helps manage complexity. The importance
of architecture depends on three key
factors. Project size. Bigger apps
require more structure to stay
maintainable. Team size. The more people
working on the project, the more
critical architecture becomes. Even if
you're just a two, three person team,
having some architecture is still
beneficial. But in team of 10 to 15
developers, good architecture is a must.
Project lifetime. For short life MVP, we
can prioritize speed over structure, but
long-term projects need solid
architecture to prevent technical depth.
One thing to note, architecture often
slows down initial development, but in
the long run, it makes scaling and
feature development much faster. Okay,
now let's get into MVC or model view
controller. The first pattern that we
will look at.
Hey again, sorry for the quick
interruption. We will continue in just a
minute. I've noticed that almost half of
you aren't subscribed to the channel
yet. I would really appreciate if you
could hit that subscribe button. And
here are three good reasons why. I make
videos rarely but consistently. So, if
you subscribe, you won't miss any new
content. There are no shorts or daily
uploads here, so you definitely won't
get spammed. Based on what I see in the
comments, this is one of the best
channels on YouTube for advanced
front-end developers. That's not my
opinion. That's what I see in the
comments. So subscribing would be a
pretty smart move. And finally, as you
can see, there is no advertising, no
paid content, nothing like that. I don't
earn anything from this. So subscriber
count is honestly one of the main ways I
can tell if I should keep making these
videos. That's it. Thank you for
listening and let's get back to the
video.
Most of you have probably heard of it.
It's been around for over 36 years. And
while it's not commonly used in modern
front ended applications, it still
contains some fundamental concepts and
can be useful in its own right and can
help us to understand more complex
patterns. MVC breaks an app into three
main layers. Model represents the
application data and business logic.
This layer usually represented by back
end, database and sometimes API. View
responsible for displaying data. This is
the UI what the user actually sees on
the screen. Also, it can include UI
logic like opening a model window and
controller acts as a bridge between
model and view. It handles user input,
updates the model and tells the view
what to display. Let's walk through an
example of MVC workflow. Step one, user
input. This is where everything starts.
User clicks a button, types something,
scroll, swipe, basically any kind of
interaction. Step two, view captures the
input and passes it to the controller.
At this stage, the view itself doesn't
process the event. It just forwards it
to the controller. Step three,
controller processes the input and
interact with the model. The controller
takes the input and decided what to do
with it. If the action requires updating
the database, the controller sends a
request to the model. For example, if
the user clicks delete item, the
controller tells the model to remove it
from the database. Step four, model
updates the data. The model, which is
usually the back end or a state
management system, processes the request
and modifies the data accordingly. In
our delete example, it removes the
entity from the database. Step five,
here's where things get interesting.
Both the controller and model can update
the view. The question is how does the
model communicate changes to the view?
There are two common approaches. The
first one is observer pattern. The view
subscribes to updates from the model and
reacts automatically and flow
synchronization. The view explicitly ask
the model for updates when needed. And
finally, user sees the updated UI.
Finally, the changes are reflected in
the UI and the user sees the updated
state of the app. That's the core idea
behind MVC. In the real world, it could
look like this. A user clicks like on a
post. The view captures the event and
sends it to the controller. The
controller updates the model, increments
the like count in the database. The
model sends the updated like count back
to the view. The view updates the UI to
show the new like count. Now, here's
something interesting. MVC doesn't have
to involve a backend server. You can
have a pure front-end MVC structure
where model is your state management
system like Redux, Ves or Pina. Vue is
your React, View or SWEL components and
controller. Well, this part is a bit
tricky. Some say we don't have a
controller in modern front end apps
because the view directly updates the
model. Others argue that hooks,
composables, or middleware act as a
controller like layer. So depending on
how you structure your app, you might
have a clear controller layer or none at
all. Now let's take MSE to the full
stack. Here's how it works. View the
front end UI built with React, View,
Angular or any other web framework.
Controller, the API layer handling
client ser communication and model the
back end containing business logic and
the database. So in this structure, the
front end only handles UI logic and no
any business logic. The API or
controller handles communication and
requests. The backend model processes
and stores data. Now, what happens when
you're working on a huge app? Well,
instead of having one massive MVC
structure, we break it down into smaller
independent embassy units. This is
called hierarchical MVC where each
feature, model or page has its own MVC
structure. For example, in a Redux
store, we can split the store into
multiple slices, each handling a
different feature. In React or View,
each page can have its own state, logic,
and controller like utilities, hooks,
and composables. So, instead of one big
MVC, we have multiple smaller MVCs all
working together. Let's talk about the
difference between thin and thick
clients. This distinction defines how
much processing happens on the client
side versus the server side. So what is
the theme client? A theme client keeps
most of the processing on the server
while the client web app only handles
the UI and user interactions. This is a
common approach in traditional
multi-page applications and static
websites. You can think of a simple HTML
website or a traditional web app that
reloads every time you click a button.
Every interaction goes to the server
which does all the processing and sends
back an updated page. On the other hand,
we have a thick client, also called fat
clients. A thick clients performs a lot
of logic on the client side, reducing
the server workload. Most interactions
don't require a full page reload.
Instead, there are handled instantly on
the client side, sometimes even offline.
So, the biggest difference between these
two, a thin client is heavily dependent
on the server, whereas a thick client
can work more independently with less
reliance on the back end. Now let's see
how MSC architecture changes depending
on whether we're using a thin or thick
client. In a classic MSC we have a thin
client and back end. The client just
renders data and sends user actions to
the controller. The controller API acts
as a bridge between the client and back
end and the model back end handles all
business logic and data processing. It's
simpler and lightweight front end. Bad
thing every interaction depends on the
server which means slower response time.
The other option is thick client and
back end. This combination is most often
found in modern web applications. The
client view does more than just displays
data. It manage state, handles logic,
and can even store data offline. The
controller API still acts as a bridge.
The back end model is lighter because
the front end takes over more
responsibilities. Good part, it's faster
on powerful devices. Betix can works
offline. Bad thing, heavier on the
client side. This is why SPA,
progressive F apps and local first
applications rely on thick clients. It
improves user experience, but it shifts
more complexity to the front end. With
thick clients, we can implement MVC
entirely on the client side. In
traditional MSE, the server is the
model. In modern frontend MSE, the model
is a state management system like Redux,
VUK or PA. So now instead of the server
handling all business logic we have
model is a state manager and controller
includes composables hooks middleares or
API calls. For example in the react app
with redux when a user clicks delete
item the view captures the event the
controller updates the model redux store
and the view renders automatically based
on store changes. Is MVC still useful
today? Yes, but it has some limitations.
Good things about MVC. It's easy to
understand. This pattern is clear and
logical and it's easy to develop and
maintain. However, we can face with a
fat controller problem. This problem
occurs because views don't handle events
and push them to the controller. This
creates bloated controllers that do too
much. The next problem is blurry
boundaries between model and controller.
Sometimes it's unclear what should be in
the model versus what should be in the
controller. View is also responsible for
receiving updates from model which makes
it not just a pure UI layer. Views are
only supposed to display UI but in
modern applications they also handle
events and observe for state changes.
This complicates testing and
maintenance. And the last problem, MSE
was introduced in 1979 and is mainly
suitable for classic web applications
with just a presentation layer on the
client side, not for modern complex web
applications with client side logic and
client side data stoages. Let's look at
the fat controller problem. Controller
supposed to be a bridge between the view
and the model. This definition sounds
too abstract and actually includes
things like a sending request to the
server, a handling API responses,
synchronization with the back end. For
example, if we use websocket for
realtime updates, controller also manage
client side caching and a bunch of other
things. And that's the problem. The
controller ends up doing way more than
it should becoming a massive bloated
layer. I think it's happening because
MVC was introduced in 1979. It never
supposed to be used for complex web
applications. Back then, client side
state management didn't exist. SPA
weren't a thing and a first application
didn't exist. When we try to follow MVC
strictly, we're most likely forcing
modern web apps into a structure that
wasn't built for them. When is MVC still
be a good choice? MVC can still work for
small to medium-sized web applications.
Also, MVC can be a good starting point
if scalability isn't a big concern. But
MVC is not a good fit for SPA with
complex state management apps with heavy
client side logic and the FL first or
local first applications because these
habs requires stronger separation of
concerns and better handling of local
state. The next pattern is called MVP or
model view presenter. MVP evolved from
MVC to better fit modern web
application. In MVP, the view doesn't
communicate with the model directly.
Instead, everything goes through the
presenter. Remember how in MVC, we had
to put observer logic into the view that
made it too complex. MVP solved that by
moving this logic into the presenter. So
now the view is just a pure UI layer,
nothing more. This makes the system more
predictable because we have no weird
circle dependencies, easier to test
because the view doesn't contain any
logic and more structured. Each layer
has a clear role. Let's take a look at
the difference between these two in the
picture. In MVC, the view always
observes the data update. We have to add
observer logic to the view layer, which
makes it more complex and hard to test.
In MVP, the view layer receives data
updates from the presenter and remains a
pure UI layer. There are actually two
types of MVP. supervising controller
which is more likely like MVC and
supervising controller the view still
handles some simple updates on its own
only complex logic goes through the
presenter that's what I meant when I
said that the view could contain some
logic and a passive view MVP in that
case the view is completely passive all
logic is handled by the presenter good
things about passive view are less
boilerplate less delegation code since
the view handles some task directly and
faster faster development because it
reduces unnecessary directions. However,
view becomes harder to test and maintain
since the view contains more logic. Unit
testing and development become harder.
This approach is suitable for cases of
simple UI where view logic is minimal.
And another option is passive view. Good
thing about it, we have more clear
boundaries between view, presenter, and
model. The view is purely passive and
the presenter contains all the logic
making all parts easier to test.
Downsides requires more code to handle
basic UI tasks and can lead to overhead
in cases where a simple view model
interaction would be enough. This
pattern is suitable for applications
with complex UI logic or when
testability and long-term scalability
are key concerns. Next, let's talk about
pros and cons of MVP itself. The first
benefit is better separation of
concerns. View is purely UI. Presenter
handles logic. Also, it is usually more
testable because view doesn't need to
observe data updates. However, we still
can face with a fat presenter problem.
Just like the fat controller in MVC, the
presenter can become a god layer if not
organized properly. MVP is also not a
very expressive pattern. It doesn't
define where to handle backend sync,
client side caching, and other things
that are not rare in modern web
applications. Use cases for MVP are the
same as for MVC, but MVP also is
suitable for applications with more
complex client side logic because it
provides better layer separation and
testability. The next pattern is called
MVVM or model view view model. The main
idea of MVVM is to separate view logic
from business logic. And I know we have
mentioned these terms before, but let's
make sure we actually get what they
mean. Business logic is when we actually
modify data in some way. For example, if
we change a username, that's type of
business logic. Make a payment, that's
business logic. If we remove an item
from a card, that's business logic.
Basically, if it affects the
application's real data, it's business
logic. Now, compare that to view logic.
View logic is purely UI related stuff.
It's just about what the user sees, but
it doesn't modify real data. For
example, opening or closing a model
window, disabling a button when
something's loading, updating a progress
bar while downloading a file. It's all
about what happens visually, but it
doesn't change the core data. But why
does these matter? Well, when MVC and
MVP were created, websites were simple
HTML, CSS, and a little of JavaScript.
But now, modern web applications are
insanely complex. Think about something
like Figma or Google Calendar. There are
super interactive, tons of UI updates
happening constantly. And if we just
throw all this UI logic into the view
layer like in a things get messy fast.
We need a better way to handle view
logic. That's where MVVM comes in. Let's
look at how it works. MVVM has three
parts. View the UI same as always. View
model handles all UI related logic. And
model handles business logic and actual
data. The new part is the view model.
The view model takes care of all the UI
logic. It updates the view and interact
with the model. It makes sure that the
UI stays in sync with the data. That's
the key difference between MVVM and
older patterns. MVVM introduces another
new concept called two-way bending. You
can see in the picture that view depends
on view model. But the opposite is also
true. This means that when we change
something in view model, the changes
happen in view accordingly. And when we
change the view, we automatically update
the model. This is how two-way binding
works. Let's look at the example how
view web framework implements this
concept. Let's say we have an input
field where the user types their name.
Normally, we would have to manually
track changes like this. The user type
the name, we update the state, the UI
update to reflect the new name. But with
MVVM, this happens automatically using
two-way data bindings. So when the user
types their name, the UI updates
instantly and the data model updates
automatically. If you have ever worked
with Vue, you have already seen this in
action. Let's look again at the key
differences between MVVM and previous
patterns. View model is designed to
store user interface data. The problem
with MVC and MVP is that they don't
distinguish between business and UI
data. The view is isolated from the
model. Many views can share a single
view model. A single view cannot have
more than one view model. The view model
contains all the data and behavior of
the user's interface window but without
any of the controls used to display that
user interface on the screen. When the
view model detects changes to the view,
it updates its own state with two-way
data bindings. If the model needs to be
updated, view model modifies the model
directly. Now, let's look at the
tradeoffs of this pattern. The good
parts, clear layer separation between UI
logic and business logic and
scalability, easier to test, maintain
and scale. The downsides, it has a
stepper learning curve. If you have
never used Vue or KnockoutJS, this
pattern might seem confusing at first
and again an expressiveness. MVVM
doesn't tell you where to handle things
like API requests or error handling. You
will still need to incorporate other
patterns for that. When should you use
MVVM? This pattern works best for
applications with complex UI logic that
needs to be tested. If you are building
an app with lots of user interactions,
forms with live validation or dynamic UI
updates, MVM is a solid choice. But you
probably don't need it for a simple
static websites. The next pattern is
hierarchical MVC. So we already
discussed MVC and one of its problem is
scalability. It works great for small
applications, but once your app grows,
MVC starts to fall apart. What usually
happens is that one controller starts
handling too many things. Instead of
just dealing with one model, it starts
interacting with multiple models.
Instead of handling a simple UI update,
it's now processing data from multiple
APIs, services, and backend sources. And
as a result, CO gets messy. Testing
become nightmare and making changes
takes forever. This is where HMV comes
in. Hierarchical model view controller
is just an extension of MVC that tries
to fix its scalability issues. Instead
of one big MVC structure controlling
everything, we break it down into
smaller independent MVC blocks. Each
block handles a specific feature and
interacts with other blocks only through
controllers. So now instead of one
controller talking to three models
directly, each feature or model has its
own self-contained MVC structure. You
can think of it like this. You have a
user feature. It gets its own MVC model.
You have a dashboard feature. It also
gets its own MVC model. And then if they
need to communicate, they only interact
via their controllers. This decoupling
makes architecture modeler reusable and
scalable. If you have worked with
Angular, this concept should sound
familiar. Angular has feature moders
which are pretty much an implementation
of HMSC in the front end. In a large
Angular app, you don't have one global
MVC controlling everything. Instead,
each feature users, orders, dashboard
get its own separate modus with its own
components, services, and state
management. This model approach makes
the codebase easier to maintain, test,
and scale. Good things about HMBC are
middlearity. An application can be
broken down into smaller modus which
encourage independent development,
facilitate maintenance, improve
testability and send error boundaries.
The model nature promotes code reuse.
Bad things are stepper learning curve.
It's harder to understand and develop
and possible inconsistent across models.
Each model can feel like its own mini
application and different developers or
teams may adopt slightly different
coding standards, patterns, tools or
naming conventions. When should you use
HMV? If you're building a large scale
application with multiple independent
features, a system where different teams
own different parts of the project, a
front-end app that fetches data from
multiple APIs and services, then HMC is
a great choice. If you're working on a
small or mediumsiz tab, probably you
don't need it. To sum it up, HMVC takes
the traditional MVC structure and makes
it scalable by splitting it into
independent MVC blocks. It's a great for
large applications but overkill for
small ones. The next pattern is MVVMC or
model view view model coordinator. I
know that the name is too long probably,
but stick with me. It's actually not
that complicated. If you have already
learned about MVVM, then you already
know most of it. The only thing new here
is the coordinator and its job is to
manage navigation and screen
transitions. Why do we need a
coordinator? Well, if you have worked
with MVVM, you probably run into this
issue. There is no clear place to handle
navigation. Think about it. The view is
just UI. It shouldn't be responsible for
handling coring. The model is just row
data. It doesn't even know the UI
exists. The view model could do it, but
then it gets bloated with navigation
logic. And that's exactly why MVVMC was
created. Instead of stuffing all the
navigation logic into the view model, we
move it into a separate entity, the
coordinator. Now, whenever you need to
navigate between screens, your view
model doesn't handle it anymore. Good
things about it, separation of concerns.
Navigation logic is completely separate
from UI and business logic and better
testability. You can unit test
navigation logic independently. The bad
thing is increased complexity. You are
adding another layer to your
architecture. MVM is suitable for
applications with complex navigation
scenarios like multi-step workflows. For
example, e-commerce checkout flow. The
next button offers even more structure.
It is called view interactor presenter
entity router. The view is a passive
view. It doesn't handle any logic. Just
displays UI and forwards user actions.
The presenter prepares data for the view
and makes sure everything is in the
right format. The interacctor handles
business logic. It is responsible for
fetching and modifying data. The entity
is just row data. No logic, just
structured information. And the router,
it manages screen transitions and
navigation. So the view only
communicates with the presenter. The
presenter talks to the interactor. The
interactor handles data from the entity
and the router takes care of moving
between screens. In Viper, we split the
logic into even more layers to keep
things modular and scalable. Viper is
used mostly in mobile development, but
it can be applied to front- end web
apps, too. It adds more structure than
classic MV patterns. It makes unit
testing easier because each part is more
independent, and it's better for large
scale applications where different teams
work on different moders. Let's also
take a look at how dependencies work in
Viper. View is the part of the UI that
changes most often. So we don't want
other parts to be responsible for view.
View itself is dependent on presenter.
Presenter depends on interractor and
rotor which acts as a highlevel layer
here. And interractor depends on entity
and as usual model but this time with a
different name entity doesn't depend on
anything. Another good thing about viper
which I like is that we can separate
interacctor into services and entity
into model entities. if it's needed. Key
features of wiper are designing
application based on use case. We can
build an application around use cases or
services that define the app course
feature. We have a place for API. In the
Viper architecture, the interacctor is
responsible for fetching data. The wiper
architecture has a place for handling
navigation. It's a router. Wiper offers
better separation of concerns. Each
component has a clear responsibility. It
scales well. It is better suited for
large applications or when multiple
projects are working on different
features. However, we usually need to
write more boilerplate. We have to write
a vast amount of interfaces for classes
sometimes with minimal responsibilities.
Wiper is better suited for complex
long-term applications. For small
applications, MV patterns are more
suitable. Clean architecture. Some of
you might already know this from the
Uncle Bob book. It's a well-known
approach, but let's break it down and
see how it works in front end and full
stack applications. If you look at the
diagram, you will notice it has four
main layers. Entities, the core business
logic, use cases, the application logic,
interface adapters, a bridge between use
cases and external systems, and
frameworks and drivers. Things like
databases, UI frameworks, APIs, and
external services. Dependencies always
point inward. The inner layers don't
know about the outer layers, but the
outer layers depend on the inner layers.
Entities are pure business logic. They
don't care about UI. They don't care
about databases and they don't care
about the frameworks. For example, think
of a banking app. Entity doesn't care if
the data is stored in MongoDB, poss.
It only cares about the business rules
like how transactions works or how
overdrafts are handled. They orchestrate
business logic but don't handle UI or
external services. For example, if we
have a list of bank transactions,
entities might store all of them. A use
case could be get the last 100
transactions. It processes the data but
doesn't store it. This keeps business
logic separate from how data is stored
or how it's presented to users.
Interface adopters layer is all about
adapting data between use cases and
frameworks. It ensures data is formatted
correctly before it reach the UI or
database. It acts as a translator
between different parts of the system.
The interface adapter makes sure that
data is converted properly before it
reached the UI. Framework and drivers is
the outer layer includes things like UI
frameworks, react view or angular
databases, posgrql, or firebase
and other external APIs. This layer is
not essential to the core business
logic. If you swap U for React, the
inner layers don't care. If you move
from MongoDB to posgress SQL, the core
logic stays the same. This is why clean
architecture is so modular and scalable.
Two principles of clean architecture.
Separation by dividing the software into
layers. The entity and external
interface layers are mandatory. Other
layers can be discarded if they are not
needed. Additional layers can also be
added. And the dependency rule. The rule
says that outer layers depend on inner
layers but inner layers cannot depend on
outer layers. Nothing inner circle can
know anything at all about something in
an outer circle. Let's imagine we have
no back end or don't need to think about
it. For example, if you're building an
offline first app that stores data in
index DB, the structure remains the
same. entities, local data models, use
cases, data manipulation logic,
adapters, bridge between UI and index DB
and frameworks, UI, React, and index DB
API. So instead of calling a database
API, the use cases interact with index
DB instead. And the last example is a
pure UI web app with just a view logic
on the client side. In that scenario,
the core logic is all UI based. Instead
of database models, we have view logic
at the center. The back end becomes just
a framework. It doesn't define core
logic. So clean architecture can even
apply to UI heavy apps where the all
business logic leaves on the back end.
Good things about clean architecture.
It's highly testable. Clean architecture
allows for testing each layer
individually making it easy to identify
and address errors and database
independent. The application is
decoupled from the database making it
easier to make changes at the database
level. UI dependent. The UI framework is
isolated. So making changes at the view
level is easier and the bad things
higher barrier to entry depends on
experienced and disciplined team to use
it well and increased complexity.
Implementing clean architecture can
introduce significant complexity
especially for smaller projects due to
managing multiple layers and ensuring
proper separation of concerns. The next
pattern is called hexagonal
architecture. Like other patterns that
clearly separate layers, hexagonal
architecture makes distributed
development easier. Chims in different
locations can work in different parts of
the same application independently using
integration test and mocks so that
components can be tested in standalone
mod. Another name for hexagonal
architecture is ports and adapters. If
we look at the diagram, we will see how
hexagonal architecture works. We have
business logic at the center. Then we
have input and output ports. Input ports
are for the driving side. Output ports
are for the dreaming side. On the image
you see a scenario how two teams front
end and backend teams are working on the
app. Team B is responsible for business
logic and ports. We can think of this
team as a backend team. They build the
logic without worrying about the UI.
They just define ports, entry points
where other parts of the system can
connect, retrieve data or modify data.
Team A is the UI team. They work on the
adapters and the UI itself. They don't
need to know how the back end works
internally. They just know that input
ports exist and use them to send and
receive data. Of course, it might be one
team or full stack developers team. This
architecture can be applied to the web
applications. On the driving side, left
side, we have user events, web sockets
and server events. On the driven side,
right side, we have the user interface,
client storage and local storage. So the
driving side controls the application
whereas the driven side is controlled by
the application logic. Like other
patterns with a clear separation between
layers, the hexagonal architecture
facilitates distributed development.
Hims in different locations can build a
single application using integration
tests and mocks so that components can
be tested in standalone mode. Now let's
talk about contracts. This is something
we can add to make development even more
stable and predictable. Contracts define
clear separation for interactions
between ports in the adapters. To
enforce contracts, we can use response
validators like Zot, Joy or Yube and
integration tests. So between the
adapters and the ports, we place these
contracts. They can be types, graphical
schemas, open API specifications or
others. How they work? For example,
client sends a request to the input
port. The back end validates the request
body, query params, and body structure.
On the client side, we also have a
contract to ensure the UI always gets
what it expects. This prevents
unexpected API changes and ensures front
end and back end remains in sync. Using
contracts helps our team work
independently and then synchronize their
work and multiple interfaces. If your
app interacts with REST API, GraphQL,
SLI or multiple UI and rich web
applications. If your front end has
business logic or it is a local first
app, hexing architecture can be a great
fit. It's not recommended for simple
apps. Overhead is unnecessary if the
project is small and small teams and
projects. If your team is small or the
scope is limited, hexagonal architecture
might be too much complex without clear
benefits. Now if we compare clean
architecture and hexagonal architecture,
we see some key differences. Clean
architecture is newer and evolved from
hexagonal architecture. It focuses on
layer separation within a single
application. Separates concerns into
entities, use cases, controllers and
infrastructure. Hexagonal architecture
older but in my opinion still very
effective. Best suited when your system
involves multiple distributed parts. It
focuses on interactions between services
and external interfaces. So if you have
multiple interfaces, hexagonal
architecture makes more sense. I
personally like it. I think it's easier
to understand and it gives clear
separation of concerns without being
overly rigged. The next concept I want
to describe is crimite.
This concept is not about how models
interact with each other. Instead, it's
about how we should structure our code
and how we should name our entities.
Screaming architecture was introduced by
Robert Martin. The idea behind it is
that the architecture of a software
system should be immediately
recognizable just by looking at its top
level structure. Things like packages
name, model names, and directories in
the codebase. In other words, the
architecture should scream the intent
and purpose of the application. It
should be obvious what the system does
without needing to dig into the details.
I added this concept here because I
think screaming architecture is useful
for understanding another concept we
will discuss later. Screaming
architecture is all about emphasizing
entities in our code. If you are
familiar with DDD or domain driven
design, you will see some parallels.
Both approaches focus on describing
architecture in terms of the business
model. For example, we shouldn't
structure our application around
technical details like React or Vue,
MongoDB or posgressql. Instead, we
should focus on what our application
actually does. So, if we are building a
to-do list, for example, our features
should be named accordingly, like tasks
or to-dos. If you have a user management
system, let's call it users, not
controllers or handlers. That's the main
idea of screaming architecture. Imagine
this case. You open a project, you take
a quick glance at the directory
structure, immediately you should know
what the application does. That's what
scream architecture is about. It ensures
that by just looking at the structure,
you can tell what this project is for,
what the main entities are, and how the
business logic is organized. A good
tople design should tell the reader
about the business, not technical
details. Focus on the business domain.
Structure the codebase around core
business concepts and use domain
specific names for models and features.
Organized by features, not layers. Each
feature should contain everything it
needs. logic, data handling and UI
components and hide technical details.
Things like frameworks, databases or
APIs should be abstracted away. Keep
them in lower level models, not on the
top level. In a system design interview,
we should primarily focus on the
architecture rather than the
organizations. The final organization
can be changed easily at any stage of
the project by changing the
architecture. Once a project has grown,
it's difficult if not impossible. That's
what I call tough decision. something
that we cannot easily revert. We should
avoid this decision if we have no enough
information to make it. Of course,
sometimes it's not possible. For
example, architecture is a tough hard to
reverse decision. It's not just because
our team is used to working with a
particular architecture. It's because as
the application grows, the codebase
becomes massive and that's completely
normal for enterprise projects.
Rewriting an entire architecture, it's
not just difficult, it's time consuming
and often not feasible. In most cases,
the only realistic way to migrate to new
architecture is to completely rebuild
the application from scratch. And if you
have worked on real world projects, you
probably know how rarely companies have
the budget for such a massive rewrite.
This is why when you start working at a
company, you might realize that
architecture is outdated and ask
yourself, why does this huge company
still use such an old abandoned
architecture? And the answer is usually
simple. It's just too hard to rewrite
everything from scratch. At the same
time, choosing the perfect architecture
at the start of the project is nearly
impossible because in the beginning, you
don't know what the application will
evolve into over time. It starts in one
form and a few years later, it might
look completely different and at the
start it's almost impossible to predict
how exactly the application will
transform as it grows. However, that
doesn't mean we shouldn't try and
eventually, I believe, choose at least a
good enough architecture. The file
structures and naming conventions are
the opposite of architecture decisions.
They are easily changeable. If you want
to rename a file or refactor the
structure, it's not a big deal. We just
rename files, update imports, and we're
done. That's why we don't focus too much
on discussing file structure because
file naming and file organizations are
easy to reverse. Let's move to the next
and last architecture pattern in our
list. Vertical slices. I would say that
vertical slices are probably the most
modern architectural style on this list.
And at the same time, I would also say
that it's one of the most widely used
today. To understand what vertical
slices are, let's go back to clean
architecture in our minds. Remember that
clean architecture follows a layered
approach where each layer is a technical
entity. But here's the issue. Clean
architecture tell us how to separate
layers, but it doesn't tell us how to
organize features within those layers.
This lack of internal structure can
sometimes be confusing. Vertical slices
solve this problem by promoting a
feature-based approach where each
feature is a business case. Think of
vertical slices as an internal structure
for your architecture layers. For
example, in clean architecture, we have
entities, use cases, controllers, and
external interfaces. Now, instead of
treating each of them as a separate
layer covering the entire app, we slice
the application vertically into
self-contained features. Each slice
contains its own entity, its own use
case, its own controller, and its own
external interface. Every feature is
self-contained inside a slice. This make
the architecture more modeler, easier to
scale, and more maintainable. We can
also combine vertical slices with other
architecture patterns. For example, in
an MVP application, we usually have
three layers, but we don't know how to
internally structure them. With vertical
slices, we create one slice per feature.
For example, create to-do slice, delete
to-do slice, and update to-do slice.
Each slice internally follows MVP
architecture, but each of them remains
independent. Vertical slices can give us
better code organization. Each feature
is self-contained, making the codebased
modeler and easy to manage. It's easier
to work on by multiple teams. Each slice
is independent, so multiple teams can
work on different slices simultaneously.
However, there is a potential for over
engineering. If developers try to
strictly follow vertical slices
everywhere, even for simple features, it
can lead to unnecessary complexity and
extra boilerplate code and inconsistency
between teams. Because teams work
independently on slices, different teams
might structure things differently. This
can lead to inconsistencies across the
codebase. Possible solutions are use
common design guides, enforce linting
and formatting rules and rotate
developers across teams. When to use
vertical slices? Large scale
applications. Vertical slices
architecture is particularly beneficial
in a large scale applications with many
distinct features. It helps keep the
codebase organized by feature making it
easier for teams to work in different
parts of the application independently.
and crossunctional teams. In
organizations where teams are
crossunctional, vertical slices allow
team to take ownership of specific
features from end to end. This promotes
better collaboration and quicker
delivery of complete features. We
probably should use something else for
simple applications. Overhead is
unnecessary for simple fullstack
applications or thin web clients and
small teams and projects. The
application architectural complexity
might not pay off if your team is small
or the project scope is limited. The
future slice pattern was defined. I
would like to share a final thoughts on
front- end architecture. First of all,
while we are explored several patterns,
we certainly didn't cover all of them.
My goal was to focus on the most widely
used ones such as MVC, MVP, clean
architecture. However, it is impossible
to cover every pattern. There are likely
hundreds of them or even thousand and
covering them all was never my
intention. I also wanted to introduce
you to some less common front-end
patterns. For instance, we discussed
wiper which is traditionally used in
mobile development. But as I mentioned
earlier, just because a pattern is
primarily designed for mobile
application doesn't mean we can't
extract valable ideas for front-end
development. In fact, front-end
developers regularly borrow useful
concepts and patterns from back-end
development. It is completely normal for
ideas to migrate across different areas
of software development. The topic of
front architecture has been overshadowed
for a long time. And I think that's
wrong. Even though front end usually
doesn't have complex business logic,
modern front end applications have
become extremely complex. Think about
it. local first application, a flying
first applications, highly interactive
UI, state heavy applications like Figma,
notion or Google Docs. The front end is
no longer just rendering views. The
front end is no longer just rendering
views. It often has managed state,
caching, data persistence and even
synchronization with backend services.
That's why I think front end
architecture should be more widely
discussed than it's now. Another
important thing, patterns are not meant
to be followed rigidly. Well, each
pattern has its own core concepts.
Doesn't mean we can't or shouldn't
adjust them to fit our specific needs.
In fact, I would argue that we must
adopt them. For example, we can add more
layers if necessary. We can remove
unnecessary layers if they don't add
value. No two web applications are
completely identical. Every project
differs in terms of challenges that we
need to solve. That's why there is no
single perfect pattern that works for
every situation. Each application is
unique. So we must tailor our
architectural approach accordingly.
Another reason why using patterns is
important because they provide a common
language for developers. For instance,
if I describe a system using terms like
model, controller, and view, most
developers will immediately understand
what I mean. Even if there are small
differences in interpretation, that's
one of the biggest advantages of using
established patterns.
That's all for today. I hope you found
this video useful. If you did, please
don't forget to hit the like button and
subscribe to the channel. See you in the
next one. Bye.
UNLOCK MORE
Sign up free to access premium features
INTERACTIVE VIEWER
Watch the video with synced subtitles, adjustable overlay, and full playback control.
AI SUMMARY
Get an instant AI-generated summary of the video content, key points, and takeaways.
TRANSLATE
Translate the transcript to 100+ languages with one click. Download in any format.
MIND MAP
Visualize the transcript as an interactive mind map. Understand structure at a glance.
CHAT WITH TRANSCRIPT
Ask questions about the video content. Get answers powered by AI directly from the transcript.
GET MORE FROM YOUR TRANSCRIPTS
Sign up for free and unlock interactive viewer, AI summaries, translations, mind maps, and more. No credit card required.