Modular Monoliths - with Steve "ardalis" Smith
Durée: 44m50s
Date de sortie: 09/07/2024
In this episode, I was honoured to be joined by Steve “ardalis” Smith to chat about Modular Monoliths! We discussed the benefits of going down the Modular Monolith route instead of moving to microservices. We also chatted about how MediatR can help with this, and also about creating online courses.For a full list of show notes, or to add comments - please see the website here
Hey everyone, welcome to the Unhandled Exceptional Podcast. I'm Dan Clark and this is episode
number 68. And today I'm joined by Steve Smith, also known as our Dallas on the socials.
So welcome to the show Steve.
Hi, thanks for having me.
You're welcome. I know I've got a feeling that you probably need no introductions because you're
quite well known in our community. But for those that haven't heard of you, could you give
the listeners a quick intro into yourself and what you do?
Here, my name is Steve Smith. That turns out to be a super common name. So I've been going by our Dallas
online for a couple decades now, because usually I can get that username. And I work for Nibble
Pros, which is a company my wife and I run. And we have a small consultancy where we help teams
build better software faster. And one of my passions for the last 20 years has been mentoring
and training developers on how to write code that's more maintainable and higher quality. And so
things like design patterns, domain during design, clean architecture, testability, all that
stuff are near and dear to my heart and things I enjoy sharing with others.
I don't you mean about names because Dan Clark is also a very popular name. So that's just I couldn't
believe I managed to get the domain name Dan Clark.com. This was a long time ago, I grabbed it and
then I got contacted by someone that was a racing car driver called Dan Clark. He wanted it. So I said,
you can have it for x 1000 pounds or whatever. And they quickly said, no, that's alright. And I
could see they've got something else now. So I've kept that all along.
There was a time when when I was in the first page of Google results for Steve Smith, but that
that time has long since passed.
So before we jump into monolithes, just a quick reminder to everyone that this podcast does
have a Discord community. If you head over to the website unhundredexceptionpodcast.com,
there's a big Discord link there. And also a thank you to Everstack for sponsoring the podcast.
Everstack's my own company providing software development and consultation services.
For more information visit Everstack.com. And speaking of sponsors, the show is currently
looking for additional sponsors. If you're interested, the details are on the website.
Right. So module monolithes. So of small confession, I really wanted to watch all of your course
before we did this recording. And I got about 50% of the way through, but time, you know,
if it's like, but so I've seen, I've seen half of it. But it might actually be a good thing that
I've not listened to the full course, because I guess it means my questions aren't ceded by
like knowing questions, and it can be a bit more of an organic conversation.
So this podcast is a dotnet podcast. And your course is, it's module monolithes,
but it is for dotnet. So to help listeners visualise this a bit better, can we first
start off with just talking about, from a code point of view, from dotnet, what a module is in
terms of this dotnet stuff? Because I think when I've looked at this initially, I've heard lots
of abstract stuff, but I wanted to visualise this as a dotnet developer. So it is a module,
is that literally just a dotnet project, like an assembly?
It can be. And that's mostly the approach that I take in this course. There's a few
related classes. And there's some reasons for that. The thing about CCHAR is that it doesn't
support friend assemblies. And so there's no way for you to expose part of your project to
another project or certain other projects, in order to allow for modularity, but also allow
for encapsulation. And I'm a big fan of, if you're doing object-oriented programming, of
using encapsulation so that you can enforce invariance and have a contract that you maintain
with your collaborators, with your clients, then allows you to change the inner workings of your
class however you want, but more importantly, to make sure that other things can't go in and
just fiddle with the data inside of your class. And that's really one of the real big reasons
why people ought to be thinking about building more modular systems, whether monoliths or
microservices, is because if you don't, if you just have a typical application with one database,
and maybe many applications all sharing a database, that's more common,
at least in the enterprise, you have no control over who can touch any of your data.
Because any application has access to that database can insert or update records anytime
they want. And that makes it really difficult for you to make any kind of guarantee about the
state of your system. I've worked, and I'm sure we all have, with lots of legacy code bases
where over time, lots of developers have touched this and different design patterns have used.
And as you're saying, different things are talking to different parts of the system,
different databases, all the same database even, and treading on each other's toes.
And just when you look at almost like a kind of N depends diagram, and you've got spaghetti
lines of code everywhere and stuff, it just feel like, I guess, if you were starting from scratch
and not doing microservices, would you ever build a monolith that isn't modular? Is this mainly
about improving legacy, ball's above modern life, where it's got to this state?
Yeah, I don't know that I would necessarily start with a modular monolith every time. It would
depend on what I expected the scope of the application to be. So this would be, you know,
most applications should just be built as simply as possible with a single project,
and get some stuff working and get some fast feedback from stakeholders. But as it continues
to grow, it's going to slow down because of the fact that it's going to get more and more
complicated. And every new feature you add has to interact with all the existing features.
And it's at that point that you need to start having some more discipline and
some more thought into how can I make sure that when I do add additional features, I'm not
breaking the things that are already there. And that's what tends to slow companies down and
code bases down, is where you used to be able to get a feature done in a day. And now,
it's like, maybe we can get a feature done in a month, but we're also going to have to spend,
you know, two weeks fixing bugs everywhere every time we try and do that,
because everything is a tightly coupled big ball of mud.
Yes, I know that one well. It starts off so fast with the Greenfield project development and
knocking features out left, right and center, then over time, it becomes, yeah, just like
wading through a big ball of mud, really, I guess. Right. A very good term.
You mentioned about databases before. So, like, obviously, if you're doing,
when doing microservices, it tends to be recommended where like each service or
what's the DDT term? Each bounded context. Bounded context, that's what I was after.
So each bounded context has its own database and things. And with modular monoliths,
is it the same concept that each module would have its own database? Yes.
You can think of each module and a modular monolithe as being equivalent to a microservice.
And in terms of all the rules that you would apply to a microservice,
typically in terms of design, like the fact that they should be
independent from one another, they should be able to be deployed independently,
they shouldn't share global state through a database or some other mechanism.
All those rules apply to modules in this modular system. That's what makes them modular.
If they, if they did have tight coupling to other modules, then they wouldn't be modular, right?
Imagine if you had Lego bricks, but you glued them together.
Like, you no longer have two Lego bricks, right? You have one bigger Lego brick.
So that's important to keeping that separation for this to work.
Yeah, it definitely does feel like way more productive doing it this way.
Because I know I've worked with a couple of systems that tell more
quotes microservice kind of architectures. And that were,
if it's all in one solution, one solution, it can be pretty much a function call,
which is super easy. You can debug into it. You can do all this stuff.
Well, when it's always HTTP or gRPC calls, and you've got to manage the,
like the actual DTOs and like, if you debug it, you can't just step into it and that kind of thing.
Feels way more productive. It feels like there's so many pros and cons to
using microservices versus like a modular monolith.
It feels quite hard for a team to decide.
Is, have you got some good questions that a team should ask themselves?
Or is this kind of just a module monolith is a good stepping stone to actually
start with that. And then if you need to go to microservices,
you can then break it down further.
Yeah, there's, there's a diagram that a lot of people have used,
and I use it in my module monolith course and think of it with, with two axes, right?
So horizontally on the x axis, there is the number of things you deploy for your application,
the number of, you know, independent services, let's say, right?
And so on the left, you've got one, which would be a monolith.
And on the right, you've got many, right? However many.
And so microservices would be, you know, in the right column, let's say.
But now vertically, we've got, we've got two options as well.
We've got zero modularity, where, where everything could touch anything else.
And, and we haven't put in place any kind of boundaries,
like, you know, when we're talking about a bounded context, it has boundaries around it.
And so if you have no boundaries, if you have no modularity,
then you're at the bottom of the vertical axis.
And if you have modularity, if you have boundaries, then you're higher up, right?
And so every application starts in the bottom left, right?
You do file new project and it says hello world.
You have no modularity, you just have one project, you have one deployable.
And that's where you stay.
And you may stay there for, for a long time, right?
Many years, you might build a huge system there.
But if you get a really large complex system,
then it does tend to turn into a big ball of mud
because it doesn't have that modularity.
And so many developers, especially in the last 10 or 15 years,
have seen that to be a problem.
And the industry has told them the solution,
the salvation, is to go to microservices
because that is the only way that you could decouple all your logic
and have them be, you know, bounded.
And in this case, the way we're going to make them separate
is because we're going to put a network between these two things.
So the only way they can talk to each other is over,
you know, some, some out of process communication channel.
And so you're moving diagonally, right?
You're moving to the right by deploying more services
and you're moving vertically
because you're achieving modularity.
And it turns out that that's a really big step.
That's a really big learning curve for a lot of teams.
Because understanding, architecting,
building and maintaining a distributed architecture like that
is leaps and bounds more difficult than a monolith.
And so yes, my proposal for many teams would be,
you know, unless you have a really good reason
to go to a microservice architecture,
it makes more sense to only move across one axis, move up,
and add modularity to your monolithic application.
So that now everything is still in one process.
You can still build it and run it and debug it in one solution.
And when you deploy it, it's one thing.
But you still have all the benefits of modularity,
which means that you can develop these different modules
with separate teams, if you want.
Right? A lot of folks use microservices
as a way to scale up the number of developers
they can throw at the problem.
But you can do that with modules in a monolith
just as easily as you can with microservices.
And all the other benefits you get from that modularity,
without having to deal with all the fallacies
of distributed computing that come along with microservices.
Makes total sense.
And I guess, presumably, you can do a hybrid as well.
So if you've got like one module
that really has to be scaled out separately
for whatever reason,
then you can keep the whole system as a module monolith.
But just pull that one thing out
because you've broken everything down nicely
in the first place into these modules.
Yeah, exactly.
Martin Fowler has a nice article from,
I don't know, 10 years ago,
talking about how to go to microservices.
And basically, the article says,
build a monolith first.
But if you try and just build microservices up front,
here there will be dragons.
And he's got a nice little picture with dragons on it.
Um, so, you know, the better thing
is to build that monolith, understand the system,
build it in a modular fashion.
And then when you say, like,
oh, the video transcoder thing
needs to scale independently from everything else.
And it's its own module.
Right? We'll just take that module
and put it into a microservice.
And great.
Everything else is still as efficient
as it possibly can be
in terms of developer productivity
and performance.
Because when everything's in process,
performance is much better.
Your hosting costs are lower
when everything is deployed in a single thing.
But those individual things that make sense
as microservices could certainly still be pulled out.
Exactly.
How does this work with, like, frontends?
So, like, as I say, I'm half a year course,
so I saw that you were using APRs, as an example.
And as an aside, it was quite nice
to actually see fast endpoints in action
because we've heard, when was it?
I don't know what episode it was,
but Nick Chapsas has been on a couple of times.
The first time he mentioned this.
And it's been, do you know how you,
every developer's got a long list
of things they want to play with,
but it's always a long list.
And it gets bigger.
It's been on my list for quite a while,
so it's quite good to see that in action.
But anyway, I kind of diverged
from what I was initially saying then.
Yeah, so is it okay to have, like,
your entire back end
being kind of a modular monolith,
but then multiple frontends
if you've got different applications
that need to use that logic?
You could have,
if you're building a bunch of APIs,
like in my course,
and you could certainly have
multiple different clients of that.
If you're building a single application,
then you can still use
a modular monolith approach
for the back end.
And then, depending on
what your technology is for your UI,
there's various different ways
to be more modular in your UI.
So if you're using Angular or React,
they each have different ways
of using components and routes
and things like that
so that you could have
different sections of the app
that correspond to, I don't know,
this is the order processing section
and this is the reports section
or what have you.
And so you can build
modular user interfaces
just like you can build modular backends.
And if you are sticking strictly to .NET,
Blazor has support for this
with Blazor,
Razor libraries,
and if you're even just using MVC,
I mean, you can use areas,
you can use Razor pages,
you can use controllers and views,
and those could live in separate projects,
but all still get pulled together
at runtime
and hosted as a single monolithic
ASP.NET Core application,
even though all their pieces,
all the UI components,
would live in separate modules
and perhaps be owned by separate teams.
We're talking about scalability
and to be honest,
I very rarely see an issue
where I need to scale out
one particular thing
because I'm not building Twitter
or X now
or Stack Overflow or anything.
Even like Stack Overflow,
I think they did a post a few years ago
that they showed that running
everything literally on one server.
So it's correct.
With their load,
if they don't have to,
then nothing,
the average developer is building,
probably has to as well,
very often anyway.
But one thing I do like about microservices
is the independent deployability side
where if there's quite a few developers
working in different teams on a system
and say I need to make a change
to an email service,
for example,
off the top of my head,
then I can quickly make that change
and know that I'm not redeploying everything.
And I don't know whether that's actually
an issue redeploying everything
or whether it's just a mental barrier,
I guess,
where it feels a big thing redeploying everything.
It is true that when you have a monolith
and you deploy any piece of it,
you have to deploy the whole thing.
So, I mean, that is a trade-off
and there's pros and cons to that.
Like when you deploy the monolith,
you know that if you have a good CI CD pipeline,
you know that that thing that you just did
in your module
is being integrated with everything else
and all the tests are running for all of it
before it gets to production,
assuming that you're running it through the CI pipeline first.
Whereas it's much more difficult
to guarantee that when you're a team
that just runs the email sending microservice
and you want to make a small update
and you send it up.
Like it's quite unlikely
that you have a bunch of integration tests
in that case
that make sure that you are going to operate
with every live version of every microservice
and application that's out there currently.
Some teams do that,
but it's more rare.
Et si tu fais ça,
ça te donne un grand plus grand hurdle
pour que tu aies de l'entraînement
de tout le temps que tu veux.
Donc, c'est tout des trade-offs.
Mais je encourage les teams
à utiliser des toggles
et à déployer comme souvent possible.
Donc, tu devrais être déployé
dans votre monolithe modulaire
à peu près plusieurs fois par semaine
si pas, vous savez, d'aimant.
Donc, ce n'est pas un grand deal à déployer.
Comme, oui, on a déployé un peu d'heures,
tout le monde a bien regardé,
on va déployer encore maintenant,
tout le monde a bien regardé.
C'est pourquoi tu as un CI CD pipeline
pour assurer que les choses
sont tous en train de travailler ensemble,
pour que tu sois confident
quand tu déployes ça,
que les choses vont encore travailler.
Et si elles ne sont pas,
parce que tu as déployé
et que ça a été travaillé
quelques heures plus tard,
ou d'ailleurs,
tu n'as qu'une petite quantité
de choses à regarder
pour savoir où est le problème.
Où les teams vont être en honte
avec ces monolithes,
c'est quand ils ne déployent pas
par semaine ou par mois.
Et puis ils se font
et tout le monde se débrouille
et ils tentent de savoir
ce qu'est ce qui a déployé.
Et ils ont des semaines de travail
pour plusieurs développeurs
pour essayer de se tracer
sur ce qu'il pourrait être.
Je peux définir,
je l'ai vu quelques fois,
même avec plus de architectures
et pas seulement monolithes,
où si, pour quelque raison,
quelque chose n'a été déployé
pendant un temps,
c'est là que les problèmes
vont être déployés par le prode.
Ou alors,
comme vous le dites,
si tu n'as qu'une commission
qui est à l'aim,
ça va être une commission
et ça va être le cas.
C'est vraiment clair
ce qui a été écrit
à la fois,
à la fois,
en tout cas.
Oui, et si tu dois rouler,
c'est généralement
assez facile de rouler
si c'est juste un commission.
Oui, c'est certain.
Donc,
je pense que je suis sûr
de ce que tu as fait.
Si tu as un
single base code
et tu as le bon nombre
séparé dans les modules,
et puis tu as différents développeurs
de différents niveaux d'expérience
travaillant sur ce base code,
parce que je peux te dire
que c'est assez facile
pour un développeur
de venir
et juste
sans réaliser ça,
et couper
d'un autre point où tu ne veux pas.
Est-ce une technique
pour éviter ça ?
Oui, je veux dire,
les reviews de code
vont toujours être vos amis
là-bas
et le programme de paire
sont constant.
Donc,
il y a un niveau de discipline
dans le team
pour éviter les erreurs
ou les gens qui font des choses
qu'ils ne devaient pas
ou qui ne devaient pas.
En termes de la structure
de la solution,
il n'y a pas de façon
comme une façon de faire ça.
Donc, j'ai mon approche
que je vous ai partagé
dans le cours de domes.
Et ce que je fais
est que
je dévoile
le système de projet
sur .NET
profondement.
Et je me rends sûr
que les références du projet
ne permettent que les choses
qui doivent parler
pour les autres
pour faire ça.
Et ce qui signifie
est que
chaque un des modules
est une petite collection
de projets,
généralement trois.
Et donc,
il y a un projet
modulé
qui est le truc.
Comme,
on dirait,
c'est un module d'émail.
Il y a un file de
sceaux de sceaux de sceaux
qui est le projet
qui a l'actualité logique.
Mais maintenant,
d'autres choses
doivent être pu communiquer
ça.
D'autres modules
veulent envoyer l'émail.
Comment vont-ils faire ça ?
Bien,
si ils veulent appeler un méthode
qui vit dans un classe
dans l'émail
de l'émail,
la seule façon dont ils peuvent faire ça
est d'adresser une référence en projet
à l'émail.
Et si ils font ça,
maintenant,
c'est que ils sont parmi
l'émail
littéralement
parce que c'est un référence en projet,
mais aussi
cela fait que
il n'y a pas de manière
pour l'émail d'un module
qui dépend de l'un de eux.
Parce qu'ils n'ont pas
une référence circulaire
dans le système de projets.
Donc, pour décrire ça,
ce que je fais
est que j'ai ajouté
un projet d'émail.center.contract.
Et ça est
essentiellement
l'interface publique
pour cet émail.
Et donc,
ça dépend de
l'émail d'un module
et rien d'autre
n'est pas possible
avec l'exception de son projet.
Donc, c'est le troisième projet.
Donc,
chaque module
a trois projets.
Le module itself,
les contrats,
et les tests,
les tests uniques pour le module.
Et donc,
tout autre chose
peut dépendre
de l'émail d'un autre module.
Et vous n'aurez pas
une référence circulaire
de cette façon.
Si vous avez
un module A, B et C,
A peut dépendre
de l'émail de B et C
et B et C
peut dépendre
de l'émail d'un autre 2
de l'émail de C
et cela ne sera jamais
un cycle.
Et donc, c'est de la façon
de l'émerger du problème de la dépendance
et c'est de la façon de l'enforcer
que les modules différentes
seulement dépendent
de l'émail d'un autre
par ce projet public-contract.
Donc, ça vous permet
de penser à l'exemple des services,
un service d'utilisation
et,
je ne sais pas,
un service d'ordre d'ordre ou quelque chose.
Mais vous avez deux modules différentes
et ils doivent parler
à l'un de l'autre.
Vous le faites par ces contrats?
Oui.
Et les contrats
sont typiquement
utilisés par le médiateur.
Donc, je définis les commandes
et les handlers et les DTOs
qui sont dans ces contrats.
Donc, imagine
que le contract est
comme l'application de votre
swagger ou d'un document API
pour un API.
Il définit
ce que les différents types
de messages sont
que vous pouvez utiliser
et ce sont les types de retour
que vous avez.
Et puis, dans mon exemple,
je fais un utilisation de médiateur.
Mais il y a d'autres techniques
que vous pouvez utiliser
si vous n'avez pas de médiateur
pour quelque chose.
Mais si
le module d'ordre
veut parler
au module customer
et peut-être
avoir des informations de customer,
le module customer
contract,
le projet,
a un query
de détail de customer,
pour dire,
et aussi un DTO de customer.
Et donc,
le module d'ordre
peut juste dire
au médiateur,
hey,
je veux envoyer un query
avec cette information,
une D123 de customer
et vous voyez,
envoyer ça.
Et le handler
pour ça
vit dans le module customer.
Donc, il va avoir
ce command,
ce query
et il va faire
ce qu'il faut faire
pour avoir le data.
Il va faire un appel
à son database
et appeler
à quoi qu'il soit.
Et il va envoyer un DTO de customer.
Et maintenant,
le module d'ordre
a ce DTO de customer.
Et c'est très similaire
de ce que vous pourriez
arriver
dans l'application de micro services.
Mais la différence est
que dans les micro services,
vous avez eu
à avoir
le service d'ordre,
faire un call
de l'HDP ou de l'HDP,
de l'application de synchronous,
pour le service de customer,
sur la chaine,
attendez pour ça
pour que ça revienne
et puis continue.
Et ça s'oppose
que ce autre micro service
est en train de se faire
et que tout est en train de travailler.
Et donc,
votre compétition de votre système
s'étendu
spécifiquement
quand vous faites ça
parce que
si vous êtes en temps
pour que vous ayez un service
de micro services
comme 5 nains,
si ils ont besoin
de parler à l'autre,
ces nains vont commencer
à se droiter rapidement
parce qu'ils ont besoin
d'être en temps même.
Dans le module de monolithe,
c'est tout en processus.
Même si je suis en train de utiliser
un mediateur,
vous pouvez toujours
le faire
avec un débugger.
C'est toujours
en train de se faire
dans les nanoseconds,
pas
sur le temps de la copine.
Un temps.
Oui, ça fait un total de sens.
Et vous avez juste dit
que si les gens n'ont pas de fonds
de mediateurs,
qui n'a pas de fonds de mediateurs?
Je ne sais pas ce que vous vous dites.
Il y aura d'autres listeners
qui sont en train de se faire
et d'autres qui n'ont pas de fonds de mediateurs.
Oui, il y a des gens
qui pensent que le mediateur est sain
et il y a des moyens
pour le faire vite.
Vous pouvez probablement
utiliser la génération source
et faire un moyen de faire vite.
Et il y a un argument
que le mediateur
vous donne
trop d'accès
à tout le système.
Donc, c'est difficile de
logiquement dire
que quand je dis
un command de mediateur,
où ça va?
Quelles sont mes dépendances?
Il y a un cas pour être
un mediateur
qui est un peu trop
trop grand
d'une implementation
pour ce qu'il fait.
Mais c'est super convenu
et qui fait des structures
comme ce que je fais
dans ce cours.
C'est vraiment simple de le faire.
Donc, je suis toujours fan.
Oui, moi aussi.
Je me disais ça en geste.
Je sais que
comme vous le dites,
il y a une relation
de la relation de fonds de mediateurs.
Mais je suis un grand fan,
à l'heure.
Je ne suis pas un mapeur automatique
que les gens n'aiment pas.
Même Jimmy n'aiment pas les mapeurs automatiques.
Donc, mais un mediateur
a encore beaucoup de fonds.
C'est drôle.
Je ne vais pas en détail.
Mais juste hier,
dans un de mes clients
et des chaînes de team,
et des conversations
sur l'automap,
donc c'est assez coincident.
Mais je ne vais pas en détail.
Mais c'est juste drôle.
En parlant de mediateurs,
si vous utilisez un mediateur
et que le mediateur a un concept
de envoyer des réquests,
donc de la utilisation des commandes
et des queries et des choses,
il y a aussi un concept
de notifications,
qui est presque,
vous pouvez presque,
même si c'est un call de fonction,
vous pouvez presque penser
à ce que ce soit pop sub,
qui est parfois dans mes petits projets,
j'ai utilisé ça pour,
vous savez,
presque à simuler les messages,
même si c'est,
comme conceptuellement,
il s'agit de,
vous pouvez faire un évènement,
quelque chose a été passé,
et vous pouvez avoir un peu de choses,
comme les commandes,
ou les intergéments,
ou tout le monde.
Oui, c'est drôle pour ça.
Dans un modje monolithe,
vous pourriez aussi,
parce que, évidemment,
c'est un call de fonction,
donc vous ne vous en avez pas le tout,
comme si vous utilisez un proper message broker,
comme un service bus,
ou un rabit,
ou tout ce que vous voulez utiliser,
où vous avez un peu plus de résilience,
parce que les choses peuvent se faire,
et les messages se restent
sur le message broker.
Oui.
Vous utilisez encore un proper message broker,
quand vous vous en avez un modje monolithe?
Je ne pense pas que c'est dommage,
personnellement,
parce que le monolithe,
imagine que ce n'était pas un modje,
et vous n'aviez pas utilisé le message passant,
et vous avez juste un modje,
et ça a fait des calls de fonction,
et ça va descendre.
Comme ça, ça se passe,
les monolithes vont descendre,
et personne ne dit que,
hey, tout le call de fonction que vous faites
dans votre monolithe
devrait être de persistance,
en mass transit et en MQ,
alors que si,
si par chance,
sur cette ligne de code,
le système crée que nous aurons encore
ce message,
prêt à aller quand il revient,
comme ça n'est pas un truc.
Donc, on travaille déjà
avec les applications,
où à quel moment,
sur une ligne de code de execution,
le système pourrait râler,
et le mediateur est en train de travailler
à ce niveau,
c'est juste des calls de fonction.
Donc, je ne me sens pas besoin
quand vous travaillez en process
avec des calls de fonction pure
pour essayer de persister
à tout ça,
à quelque part,
en ce moment,
sur la chance de la ligne de use
que l'app peut râler à ce moment.
C'est un risque légère,
mais c'est le même risque que vous avez maintenant
dans les applications que vous utilisez
des calls de méthodes.
Donc, on a déjà accepté ce risque.
Comme vous le disiez,
c'est un trade-off,
c'est comme si vous allez sur cette ligne,
il y a beaucoup plus de complexité,
et ça fait plus de temps,
donc c'est comme si,
est-ce qu'il est plus d'un temps
de complexité et d'une maintenance en haut,
versus juste de la cise,
de la cise,
je n'aime pas l'actuale cise,
cise d'acronyme.
Donc,
je me dis toujours,
c'est super simple
parce que ça reste toujours
cise,
c'est pas ça.
C'est un autre risque.
C'est simple,
c'est un autre risque.
exactement.
Si vous ne voulez pas les call de la cise,
vous pouvez toujours utiliser
cise d'acronyme.
D'où je veux utiliser
la message avec la durabilité,
c'est que dès que vous avez
des calls de méthodes,
c'est bien.
Dès que vous dites
que je ne communique pas en process,
je parle d'un micro-service
ou je parle d'un autre système,
c'est là que je pense que ça fait sens
de utiliser la mass-transit
ou en service bus,
RabbitMQ,
Azure service bus,
tout ça.
Parce que à ce point,
vous avez tous les issues de la distribution de la compétition
et la probabilité que quelque chose
va falloir en entre la sondage
et la recevée
est des ordres de magnétude.
Je pense que le scénarisme que je pense
est un acteur,
il faut quelque chose
sur le côté de l'arrivée
pour faire quelque chose
qui fait un usage de l'air
peut-être CPU ou de la mémoire ou quelque chose
où, si vous pouvez juste
mettre un message
et laisser quelque chose d'autre
se défendre synchroniquement,
je pense que c'est bien,
mais si vous avez un casque,
c'est ce qu'il y a de la particularité,
vous pouvez le couper,
mais la plupart de la chose,
juste parce que vous avez un casque
qui fait ça,
ça ne veut pas que vous avez
à la fin de l'architecture,
un micro-service de l'architecture.
C'est vrai.
Et vous pouvez impliquer ça
sans utiliser la message,
oui?
Donc, dans mon cours,
j'ai un module d'émail
et l'émail est
certainement quelque chose
qui n'a pas besoin d'être passé
en attendant l'http request
d'une fois.
C'est vrai.
Ça peut être décevé
et envoyé.
Et donc, l'émail module
s'utilise de MongoDB
pour montrer que vous n'avez pas
besoin d'utiliser le même database
pour tout ça.
Et dès que ça a un message
pour envoyer l'émail,
il a un pattern de boxe
que ça utilise.
Il juste write un record
de MongoDB
et ensuite, il y a un
travailleur de l'arrivée
dans ce module
qui est en train de regarder
ce table
et juste pique les choses
sur le boxe
et en fait, il envoie
le message,
mais c'est un processus separate.
C'est toujours partie de monolithe,
mais pas partie de l'émail.
Donc, vous avez le bénéfice
d'être able de envoyer le code
separatement
et vous avez la durabilité
où,
comme le record
a été écrit dans l'émail,
si le whole système
arrive à ce moment,
quand il revient,
il va encore regarder l'émail
et envoyer l'émail.
C'est un point de point
avec l'esp.net.
Vous pouvez avoir un travailleur
et vous pouvez...
Ce n'est pas juste
les réquests qui sont venus.
Vous pouvez ajouter des choses.
Et
qu'est-ce que
l'émail
qui est assez populaire ?
Hangfire.
Il y a Hangfire
et il y a un autre.
Quarts.
Quarts.
Je pense que c'est Hangfire
que je pense.
Mais vous pouvez utiliser
des choses comme ça.
Mais ça peut être ensemble.
Donc, oui, oui.
Je l'ai fait,
quand est-ce que
il y avait quelques jours
d'avoir entendu
parce que vous étiez
sur le site.
Donnet Rocks
en parlant de la même chose.
A l'endemain,
je ne m'en souviens pas,
qui,
je pense que c'était Carl qui l'a envoyé,
c'est que vous avez un cours
en arrière,
ou ça dépend de
si c'est encore ou non,
de la reverse
de la service micro
pour le module monolithe.
C'est vrai.
Oui,
ce cours a été publié
au lendemain de l'endemain
de 2024.
Donc,
c'est en live maintenant.
Et c'est moins technique,
c'est plus pour
un décision de technologie,
pas beaucoup de code,
et plus de...
Ce sont toutes les choses
qu'il faut considérer
et comment
poursuivre les choses
des services micro
dans votre module monolithe.
Et un peu de études de cas
pour vous montrer
que vous n'êtes pas fou.
D'autres entreprises
que vous avez oublié
d'avoir l'amazon
et Twilio
ont publié des études de cas
sur pourquoi ils sont
sur les services micro
pour le module monolithe
afin de sauver
les preuves et les performances
et un host de choses.
Donc,
c'est ce que
ce cours est tout à fait
de vous donner
la permission
pour vous considérer
le fait
que tout le monde
dit que les services micro
sont la seule façon
et qu'ils sont...
non.
Je vous aime
donner la permission
parce que
c'est presque comme si
vous avez fait beaucoup de travail
pour aller au service micro.
Et
je peux imaginer
les gens qui pensent
que ils sont presque
stupides
parce qu'ils ont fait
ce décision et le commitment.
Et c'est intéressant
que vous avez
fait la course
pour aller de l'autre façon
en retour à un module monolithe.
Est-ce que...
est-ce que...
encore une fois,
sur DoamTrain?
Oui.
Oui.
C'est mon troisième module monolithe.
Donc,
les premiers deux
sont
des modules monolithes
pour
les développeurs
et peut-être les architectes.
Et dans le troisième,
comme je l'ai dit,
c'est pour des
des décisions techniques
et des architectes
qui tentent
de planter
comment fixer
le fait
qu'ils ont fait trop loin
au service micro
et au service micro
et peut-être qu'ils auraient
envie de
retourner un peu
quelque chose simple
et plus cher.
Ah,
vous avez un cours
sur DoamTrain,
alors
je dois en avoir une.
Ah, oui.
Je dois avoir deux plus
que ce que je fais
en prochain mois.
c'est une race.
Oh,
vous allez gagner
cette race.
J'ai pas de temps
à la fois.
Alors, j'ai hâte de l'enquêter.
Mais oui.
C'est assez intéressant
parce que j'ai eu
quelques des
des authors de DoamTrain
sur le podcast.
Oui.
Et on est toujours
sur le sujet
de comment vous avez trouvé
en créant un cours
parce que l'un des choses
que j'ai trouvé un peu différent
avec DoamTrain
c'est que
les cours,
évidemment,
les authors ne ont pas
les réputés.
Et c'est un grand différence
que les webcoms sont en place.
Et comme un author,
c'est une expérience
qui n'a pas été fait.
Je sais pas
que vous avez des cours de pluralsight,
n'est-ce pas?
Oh, oui.
Un peu de cours.
Comment vous trouvez
la différence entre les égis
quand vous avez
votre webcom?
C'était très différent.
J'étais heureux
avec le fait que
c'était ok
de avoir des coups de jump
dans les édits.
Si je voulais faire
un bon take
de chaque clip,
ça aurait été
très, très difficile.
J'ai de la chance
d'avoir un nouveau set
de outils
parce que tout ce que j'ai fait
avec Pluralsight
c'était toujours avec Camtasia.
Et je pense que vous pouvez
utiliser Camtasia
pour quelque chose
avec un live vidéo,
mais j'ai décidé
de juste suivre
Nick's lead
et utiliser DaVinci Resolve,
ce qui est un plus
capable,
je pense,
d'un tour d'édit
pour le vidéo,
mais aussi
un curve d'entrée plus
plus basé.
Donc ça m'a pris
un peu de temps
pour me faire
le gist de ça.
Mais
les choses comme
essayer de faire
que je ne me regarde
plus ou moins
les mêmes,
à moins
par un seul module,
même si je ne l'ai pas
récordé tout à l'heure,
comme ce sont les défis
que vous n'avez
pas vu,
c'est la première fois que je l'ai
parce que ça m'a pris beaucoup plus
plus longtemps
parce que c'était la première
pour que,
comme vous le dites,
il y a un curve d'entrée de la
DaVinci Resolve et tout,
je ne pensais pas
des choses comme les hauteurs
et des choses comme ça.
Donc c'est comme
à la fin de la fin,
je devais avoir une hauteur,
alors que ma haute
a complètement changé,
où
dans la deuxième
je fais
la course de la coubinette
cette année,
avant de commencer la recording,
j'ai eu un hauteur
et je savais que je ne devais pas
avoir ça.
Et des choses comme ça,
je ne pense pas que
mais
c'est un grand cours de la course,
mais c'est un grand cours de la course,
donc je suis très heureux
de voir ça,
parce que c'était une
opportunité
Oui, c'est drôle.
Il y a beaucoup de travail,
et je suis totalement
délicaté maintenant,
mais comme je le disais,
j'ai deux courses,
j'ai besoin de finir bientôt,
et puis, je ne sais pas,
je vais prendre un petit break
pour faire plus de courses,
parce que je suis
assez derrière
un peu de choses.
Vous avez votre consultant,
est-ce que les proches nimbles
sont les plus grands?
C'est vrai.
Donc vous avez votre compagnie de consultations
aussi,
donc oui,
le temps est valable,
c'est pas vrai?
Oui,
j'ai des clients qui
aimeraient plus de mon temps,
mais je le dis maintenant,
j'ai trop de bêtises,
donc je vais essayer
de travailler sur ces courses
et de les faire
plus près de leur ligne de délicat.
Donc c'est le
c'est le challenge.
Oui, je pense que
le dire non est une
powerful
skill,
ce qui beaucoup de gens ne ont pas,
donc je pense que c'est très
bon pour le management de stress,
d'être au point de dire non
aux choses,
donc ils ne sont pas trop
beaucoup de choses.
Oui, donc est-ce qu'il y a
quelque chose d'autre
que comme je le disais,
j'ai eu un cours,
il y a aussi des choses
que je n'ai pas pensées
de vous demander,
est-ce qu'il y a quelque chose
d'autre qui est en train de
sur le module de monolithe?
Il y a un couple de choses
que je peux couvrir
un peu plus sur le côté technique
si vous voulez.
Oh, oui.
Un de eux,
j'ai fait des vidéos YouTube
sur ceci,
et c'est aussi
couvert dans mon cours,
mais l'un des bénéfices
de l'utiliser
quelque chose comme un médiateur
est que vous pouvez construire
vos propres pipelines de la moyenne
dans votre application.
Donc, pour exemple,
si vous avez
une validation
que vous voulez toujours
faire sur les messages
qui viennent des choses,
en lieu de avoir
une classe de service
qui s'en prend
des paramètres,
et que tous les méthodes
doivent être validées
sur ces paramètres
pour faire surement
que ils soient en range ou tout.
Si vous avez l'embrasse
cette message passée
avec le style de médiateur,
vous pouvez envoyer
une query
ou un command
sur l'ordre de la handling,
et vous pouvez avoir
une validation fluente
ou quelque sorte
de validation que vous voulez
utiliser.
Et chaque message
va passer par cette manière,
et va être validé.
Et si c'est invalidé,
il va reprendre
de cette manière.
Avant, il va même
aller au service
ou au handler
qui va finalement
exécuter.
Encorement, j'ai une manière
pour la logger,
et donc,
chaque single call
s'est loggée.
Et donc, je n'ai pas besoin
d'adverter des statements de log
pour chaque méthode
pour dire que je commence
et que je finis
et que je l'ai pris tout ça.
Tout ça est fait par une single
manière
que chaque single
query ou
événement ou commande
s'y passe.
Et donc, dans mes logges,
je peux voir
comme ça,
c'est exactement la façon
que cette réquestée a pris
de venir vers un point de vue
et puis de là
de aller vers un query,
vers un query ou commande,
vers un commande, etc.
Et donc, je suis un grand fan
de ces comportements
pour les questions de cross-cutting.
Des choses comme validation
et logging, comme je l'ai mentionné,
mais il y a un peu plus
si vous pensez à ça.
Vous pouvez utiliser ça
pour l'authentification
et l'authentisation.
Vous pouvez utiliser ça pour le cacher
et beaucoup d'autres choses
que vous pourriez venir.
Bébé, si vous regardez
votre méthode,
que vous faites dans votre logiciel,
et que tout un d'entre vous
commence avec
un log que je commence
avec cette méthode,
vous pouvez essayer
de faire des validation
ou des clauses de garde.
Faites le travail
et puis, vous avez un cacher
et un autre statement de log.
Si tout un d'entre vous
a la même chelon
de code sur le travail réel,
tout ce que vous pouvez faire
peut être étendu
à ces comportements
et utilise ce qu'on appelle
le « chaine de responsabilité »
qui est exactement
ce que l'ASP.Core
fait avec ses outils.
Donc, vous avez déjà utilisé
cette pattern
si vous faites l'ASP.Core.
Ça vous donne un moyen
d'utiliser dans votre logiciel
de application
pour que ce soit pas
couplé à l'ASP.net.
Oui, c'est certain.
Comme je vous l'ai dit,
nous avons utilisé des médias
pour beaucoup de temps.
Et c'est ce que vous avez
juste découvert avec des logs.
Nous faisons le même
avec les traces.
Donc, vous savez,
comme les traces
d'open telemetry.
Oui.
Donc, c'est exactement
ce concept que vous avez
juste découvert.
Mais pour tous
nos médias
de nous,
nous n'avons pas
de faire des changements
parce que nous avons
une comportement
qui fait ça
et commence
et arrête cette trace.
Et nous l'avons
en train de le mettre
dans le cloud
pour que nous puissions
voir les traces.
Et si vous faisiez ça
manuellement
pour tous les médias
de la hands-on,
vous n'aurez pas de beaucoup
de ces traces.
Mais,
comme vous le dis,
on n'oublie pas
parce que c'est automatique.
Donc, oui,
très, très fort.
Oui.
Et puis,
le autre chose
qui est important
avec les modulaires et les modulaires,
je pense,
est cette idée
d'avoir
quelque chose de plus grand
que une classe
comme une boundary de encapsulation
ou même un agrégat.
Oui.
Et donc, je parle
beaucoup de ça
dans mes courses
et des workshops
que je fais.
Mais quand vous pensez
dans les boundaries de encapsulation
dans l'Aix-Sharp
ou dans votre software,
c'est vraiment
au niveau le plus bas,
où vous avez
un variable
qui est un peu
comme une boundary de encapsulation
et une abstraction.
Et puis,
vous avez un méthode.
Et un méthode a
des variables locales
qui sont seulement valides
là-bas.
Et ça a valeur
parce que
vous savez
que si vous faites
un variable local
et que vous utilisez
ce méthode,
vous n'allez pas
faire de l'autre
dans votre programme.
Et c'est très important
de savoir.
Et puis,
là-bas, vous pouvez aller
à une classe
et à la classe,
vous pouvez avoir
privé et protégé
et interne
et d'autres keywords
pour faire
l'accès à ça.
Mais,
parmi ça,
on n'a pas
un autre niveau de granularité
vraiment
dans l'Aix-Sharp.
Et donc,
l'idée
de utiliser les modules
comme un moyen
d'achever ça
par avoir un projet
de contracte separate
et de le faire
pour que...
Je n'ai pas vraiment mentionné
ça, mais le module principal,
le
e-mail,
le service d'envergage,
tout ça,
tout là-bas
devrait être
assez interne.
Alors que
les autres
choses, même si ils ont
un projet de référence,
ils ne pourraient pas
avoir des choses
dans leurs
parce qu'ils sont tous
marqués internes.
Et puis,
vous pouvez utiliser
les interne visibles 2,
ce qui est l'une des
tools
qu'on a available
pour nous,
pour faire les interne visibles 2,
votre projet de test,
et si nécessaire,
vous pouvez les faire visibles 2,
votre projet de contracte,
aussi.
On ne va pas l'utiliser
parce que
la façon dont les dépendances
travaillent.
Mais,
par le fait de la déclencher
ça, vous le faites
pour que vous avez
encore la capteur de encapsulation
au niveau module
qui est plus grand
que les classes individuelles.
Et c'est là où
vous avez ce problème
de la grande balle.
C'est parce que,
les développeurs,
même si ils sont
très bons
avec l'objectif de programmation,
les tools ne sont pas
là
dans un projet de singlee
pour pouvoir encapsuler
tout ce folder
de tout ce folder.
Nous n'avons pas
n'importe quoi
qui dit
des choses dans ce folder,
des choses dans ce spécificat,
ne devraient pas être
référentes
par les choses dans ce spécificat.
Et donc,
vous devez utiliser
le système de projet
pour atteindre ça.
Ou vous pouvez aussi
utiliser un
unite arc,
qui est un test
d'architecture,
ça peut le faire aussi.
Mais ensuite,
vous ne pouvez pas le faire
en temps de compilation,
vous ne pouvez pas le faire
quand vous êtes dans le test.
Oh,
vous avez joué
et vous avez piqué
mon tip de détail.
Il y a des...
Je ne sais pas
que je l'ai entendu,
mais c'est pas le
genre que vous avez mentionné,
il y a quelque chose
que j'ai vu récemment
par un autre
qui s'appelle Ben Morris,
qui s'appelle
net arc test,
ce qui est
tout ce que vous avez
décrit, je pense.
Oui, il y a deux de eux.
C'est l'autre.
Oui.
Regardez le readme,
il dit
inspiré par
l'arch unit,
libraire pour Java.
Oui, il dit
inspiré par l'architecture,
libraire pour Java.
Oui, il dit
inspiré par l'architecture,
libraire pour Java.
Oui, il dit
Oui, il dit
inspiré par l'architecture,
libraire pour Java.
Oui, il dit
inspiré par l'architecture,
libraire pour Java.
Oui, il dit
libraire pour Java.
Oui, il dit
inspiré par l'architecture,
libraire pour Java.
Oui, il dit
inspiré par l'architecture,
libraire pour Java.
inspiré par l'architecture,
libraire pour Java.
Oui, il dit
inspiré par l'architecture,
libraire pour Java.
Oui, il dit
inspiré par l'architecture,
Sommar,
spécifique cause
c'est something that's
I don't know who first coined the term.
I know it's been around for a while.
I've got a cartoon I post every now and then
on my Twitter that's like,
you know, aliens coming down
and telling people that they shouldn't
just build microservices.
They should start with a modular monolithe.
And you know,
even when that cartoon came out,
I think it was like in 2019 or 2020,
it was a term that had been around for a while.
So it's not really new,
but it's becoming more popular,
I think, because so many people have found themselves
in the morass of microservice hell
and are trying to find a way out
that doesn't lead them back
to the big ball of mud hell
that they came from.
And just to call back to that diagram
that we kind of mentally talked about
with the two axes,
right, toward the top was
things that were modular,
toward the right was things that had many services.
The problem a lot of companies come into
is they try to go microservices,
but they don't decouple them, right?
So maybe they'll share a database.
And so you end up in the bottom right of that quadrant
where you've built a distributed ball of mud
or a distributed monolithe,
which is the worst of all worlds, right?
You got all the problems of a distributed system
and you're still in a tightly coupled
big ball of mud problem
inside of your architecture.
So, you know,
definitely try to avoid ending up there.
I will include, if it's okay with you,
that diagram in the show notes,
just so the listeners have some context.
And also that comic you mentioned
about the aliens coming down.
So I'll include those in the show notes.
Cool. So we are almost running out of time
and I've already done my dev tip
because it came up earlier
and I think you had a dev tip as well.
Sure.
One of the tips I often share
is that when you're doing maintenance programming,
you should default to writing new code
in a new class or in a new method
rather than just going in and hacking
some existing code
or adding some code to an existing method.
The reason why that is preferable
is that especially if you're building a new class,
and this was great advice
for when you're working on legacy systems
that have huge, you know,
thousand line long methods
and they're just a mess, right?
When you create that new class,
you could write unit tests for it
because it's brand new.
You can design it to be unit testable
and you can construct it
in whatever way makes sense to you.
Name it the way you would name it,
you know, design it
with all the best practices you know
or patterns you want to use
and then just new it up and call it
from whatever, you know,
giant method that you had before
that you were trying to,
you know, insert some logic into.
And if you do that long enough,
eventually,
that giant method is going to be composed of,
you know, smaller classes
that are unit testable
that only do one thing
and the system will gradually get better over time.
It also makes it much easier
for you to use things like feature flags and stuff
if you've got, you know, logic,
there's, you know, logically separated
into its own structure
into its own class or new method
than if it was just in line
into an already too long method.
So that's my tip
is if you're doing maintenance programming,
try and default to writing new code
in new classes
instead of just editing
and doing surgery
on existing ugly code.
Yeah, that makes total sense.
Awesome.
So was there anything before we wrap up?
Is there anything else you wanted to cover?
A mention?
We've mentioned Nimble Pros.
Any shout outs out?
Yeah, I mean,
the courses are live on Dome Train.
I've got a whole sample there
that I walk you through how to build.
So I also have a template
that you can use to create modules
and create a modular monolith architecture
which is our Dallas slash module lith
like a modular monolith module lith
and that'll be in the show notes too, I'm sure.
So yeah, that's probably good.
Yeah, I'll definitely include links
to all the different stuff in the show notes.
Cool.
So well, with that,
a massive thank you for joining us on the show.
It's been amazing having you on.
Thanks.
Glad to be here.
See you next time.
And thank you everyone for listening
and a quick reminder
that this podcast is sponsored by Evestac
which is my own company
providing software development
and consultation services
for more information.
Visit Evestac.com
and if you enjoy the podcast,
please do help me spread the word
on social media.
I normally use the hashtag
unhandledexception
and I can be found on Twitter
at Dracan or X now.
But the best place to get in touch
with me is on Discord.
And as I mentioned earlier,
we've got our own Discord community
which is linked to on the website
and all the stuff
including that Discord link
and the show notes
can be found on unhandledexceptionpodcast.com
Sous-titres réalisés par la communauté d'Amara.org
Episode suivant:
Les infos glanées
TheUnhandledExceptionPodcast
Tags