Waiting..
Auto Scroll
Sync
Top
Bottom
Select text to annotate, Click play in YouTube to begin
00:00:02
all right today we're going to be as crusty as we could possibly be we're going to be contrarian we're going to complain about things that you're otherwise being told are the best practices in software architecture which they may actually be we're not going
00:00:15
that badly uh so today just quickly a little bit uh first before we we get later into this and you're wondering who am I to question some of some of this wisdom coming down from on high from the
00:00:28
Uncle Bob's of of the past so I'm Jerry Miller this is my third time third time speaking in DC uh woodwind here in 2020 to finally finally meet oscar but the world had other ideas in 2020
00:00:42
um I'm a long time open source developer in inside of.net specifically I want to call out structure map not that it's an exciting project structure map was the first production ready ioc container
00:00:56
in.net so in about 30 minutes when somebody are shaking your head saying this guy clearly does not understand dependency inversion I I do got me a little Slack
00:01:08
um that's going to come up a little bit just just my experience have also having to help other people through using some of these tools in my daily work today for the moment I am the senior director
00:01:21
of software architecture at media analytics that's a medical analytics software company in the US and Ukraine um in the next week or two I'm going to be transferring um starting my own company called Jasper
00:01:34
FX software and that is going to be all about services and product offerings on top of some other open source tools the the Critter stack over in Martin this
00:01:44
talk is not about those things but some of the work we're doing with those tools is definitely informed by our experiences working with with big long-running architectural long-running Enterprise systems and I
00:01:58
want to show you some of the ideas that we're trying out to kind of go off in a little bit different direction but that's later all right so the last last five to ten years uh
00:02:11
through Consulting gigs working in product companies um whoever it's in working with large companies smaller product shops that nevertheless built very large systems
00:02:22
and even working with with some charitable foundation work consistently seeing some Trends across very large very long running systems we're talking about systems that have
00:02:35
been in very active production for five to ten years where the problems start to happen the code has been very hard to follow to reason about one of the systems I'm helping with right now it's very
00:02:48
difficult to predict that hey if we go into this one place if we cut if then statements and do a little bit of conditional logic here for this one specific customer off the side does it end up shattering the business Logic for
00:03:00
a bunch of other customers down the line it's just very hard for us to know call Stacks are big the consequences are not really clear that's a problem some of these code bases are very high
00:03:12
friction code becomes scattered all over closely related code becomes scattered all over a very large solution the things that you care about at that very moment are not necessarily right
00:03:25
together in one nice tidy little package that's a problem upgrades upgrades are very hard um just pulling something something out as an example we have a very very large
00:03:37
system at work that uses in hibernate once upon a time I think I was part of the in hibernate Mafia even though I hated that name and heavily invested that as a tool but it's had its day it's
00:03:50
it's aluminum wiring not as many people understand it today our younger developers which means everybody but me now our younger developers are not familiar with it EF core Dapper other tools
00:04:03
vastly more googleable that's a quality all by itself we'd kind of like to hear we'd kind of like to Mosey on from and hibernate but in our giant monolith application nah too big can't do it
00:04:17
performance is a problem not necessarily because people are starting out to write slow code but when these systems get big and I think it's especially around the databases it's
00:04:29
hard to understand where are we making Network hops where are we making sequential database calls where deep in this call stack are we making even similar calls to the database but we
00:04:42
can't really see it because the code is too spread out performance problems creep in really badly when the code just gets big and you can't see it anymore now all these systems were written by
00:04:54
people who cared about their jobs all of these people they had a plan they started out with a well-defined architecture they were they were coming to conferences like in DC they were going to the workshops on clean
00:05:07
architecture onion architecture whatever it's going to be but the problem is everything works up front so That's Mike Tyson originally uh I was
00:05:20
going to do like a Elmer Fudd getting knocked out and I went for the meaner one too so Mike Tyson's quote years and years ago he had some high-profile fight coming up when when people still paid
00:05:33
attention to boxing and they were asking him hey Michael Spinks says he has a plan on how to beat you or maybe it was a Vander Holyfield I don't know and he says hey everybody has a plan until they get punched in the face
00:05:46
right software architecture everything works at first whatever you pick is probably going to work absolutely fine in the early stages of a project
00:05:59
that's when you're paying attention to things the most so you're going to find problems and alleviate problems that's when the use cases are simpler so potential frictions aren't necessarily
00:06:11
showing up yet so you got to be careful this this project plan we started with is architectural idea it's great right now all of the absolute worst systems I've seen in my life has been from
00:06:23
somebody purposely consciously professionally picking an architectural plan and following it but following it even when it stopped working
00:06:37
all right so um any any other Generation X programmers in the room okay just a few hints so I originally did a
00:06:49
version of this this talk for my 19 year old son and I was going to try to use the the Alanis Morissette isn't it ironic you know so the 10 of you now have that that song just buried in your mind for the rest of the day but my son
00:07:01
had no earthly idea what that was so instead I went for the classic 90s movie right so I but ironically uh the some of the
00:07:13
elements that I think have led to these big systems being hard to work with are exactly the kind of things that we are told that we maybe we believe are exactly what you use to make these systems be maintainable
00:07:26
hexagonal architectures clean architecture the onion architecture and then I admittedly I have a special hatred for the onion architecture the the this is
00:07:37
somewhat personal that leads people to trying to do unusually complicated things with ioc tools which means they usually end up on my doorstep asking for help
00:07:50
it's a little bit of bitterness there's an older older form another prescriptive architecture called idesign that is all about how do you divide responsibilities in an architecture where do you put service boundaries it's
00:08:03
prescriptive architecture it has a lot of good stuff with it but it can lead to a very over complicated system that's slow um database abstractions we'll hammer on
00:08:18
this a little bit later you know we we know we think we want to abstract the database a little bit maybe for testability maybe we think we swap the database out layer later maybe that's so
00:08:29
maybe it's not but what database abstractions can do is it reduces your database technology to a least common denominator approach um it also I think gives developers an incentive to
00:08:43
go down to pulling out a single entity at a time and it's going to make you chatty and potentially make you very very slow we'll get into that anti-corruption layers you know we know
00:08:57
that in some cases we don't want to share our Rich domain model entities over a web service so we'll put some kind of mapping layer in there specifically to not share types
00:09:08
go too far with that um that's why I design shows up go too far with that and what you do is you add a lot more mental overhead to understand the system how many jumps does any data
00:09:21
element in the system go through mapping layer to service layer to mediator to a command over here everything you do for the sake of loose coupling also comes with a little bit of cost of just extra
00:09:34
junk to try to keep track of and then finally we're definitely going to talk about prescriptive coding structures and here what I mean is one of the early days of my current
00:09:46
position I was asked hey Jeremy can you put together a reference architecture a reference template for what microservices or services are going to be and I partially out of laziness somewhat out
00:09:59
of hey that's actually kind of dangerous when you set up a detailed reference architecture we'll get into this a little more the the key risk there is people will actually follow it
00:10:12
all right so I think it's probably going to come out that I'm going to bash on the clean architecture the the onion architecture the what all these prescriptive architectures are the things that you've
00:10:26
probably already gone to workshops for today Ian Cooper has a great talk on clean architecture I want to be a little bit more nuanced here these aren't necessarily horrible things by
00:10:38
themselves but there's some bad that can creep in with them so we'll go to this old folks thing which again my 19 year old had never heard of we don't want to throw the baby out with the bathwater
00:10:50
the elements of good design that the clean architecture gives us we want to keep that the problems that it that it will incur in large systems let's try to throw that out with the bathwater it's just just kind of getting a kind of
00:11:06
a general sense make sure we're all together on what we mean here by layered architecture and here I'm talking about the whole category of hexagonal architectures anything any architectural
00:11:17
style clean hexagonal itself ports and adapters the onion architecture anything that tries to make you think in terms of technical layers or layers of
00:11:29
responsibility that's what I mean here these architectural styles are great they promote the idea of separation of concerns the idea that I want to get my infrastructure out of my business logic
00:11:43
that's going to be very important I think that's very important they give you predictable rules developers don't necessarily have to spend a lot of time thinking about where should this code go just follow the
00:11:55
rules and the code goes where it goes whether that's a good idea in the end is is not as black and white as the rules say all right this all sounds great
00:12:10
tons of tons of workshops people doing pluralsight videos a lot of you are probably having success with this today and I don't want to take that away from you I think in limited perspectives we
00:12:22
have had success in my own work but this comes with some problems when these things go off the rails I'll switch the code there's a little bit of contrived except what's not contrived is it's
00:12:37
absolutely real so what you see in one of these large systems yeah this is not admittedly.netcentric but we end up with
00:12:50
having a separate project a jar an assembly for every technical stereotype of the system when you start out small that's no big deal you have your domain you have entities in one place down to
00:13:04
another one there's infrastructure I copied this from somewhere so it's not as be it's a junk drawer lots of Base types the entities what happens when there's a hundred different classes in your
00:13:22
entities holder which I've seen multiple occasions you get to a point where finding the code that you want at any one time hopefully you're good with your IDE
00:13:35
shortcuts you know got to do that no matter what but closely related code making changes in the system making a simple change of hey this customer has
00:13:46
this extra data element or maybe they their workflow is a little bit special our customers God love them they just kill us with exception cases right um when we have to go and change one of
00:14:00
these systems built on this kind of layered architecture approach you end up doing shotgun surgery write a little bit of code up here come and make a little bit of change way down here another change way down there when you're writing it you get the
00:14:13
boiling frog problem you don't notice this at first when you're just dropping a few new classes in this adds up when you get really late 10 years later five to ten years later I despise this kind
00:14:25
of layered architecture if you see me on Twitter gripe about clean or onion or whatever it is it's this this needs to go away a couple other problems that show up
00:14:40
we'll get into just a second later so already talking about how to ameliorate this a little bit um and this talking at this point of talk I always make some kind of joke I'm a real developer that's why I'm not
00:14:53
super great with PowerPoint I'm always awkward with this stuff oh I reordered it oh my goodness I'm sorry folks hmm I thought I reordered it so one of the ways to really write this so those
00:15:12
layers we were off the rails when those those layers become very huge part of the research I was doing to get ready for this talk make sure I did an okay job while my flight delays kept piling
00:15:25
up today um one of the things that proponents of clean architecture will talk about is well you can upgrade you can easily upgrade uh your application or you can
00:15:38
switch database engines right everybody's everybody's heard that at some point and if you've got a good abstraction right and you switch databases no not really in reality in reality if you have a
00:15:52
large enough horizontal layer you are not able to practice practically upgrade because it's just too much regression testing no matter what even if you got the best abstraction in the world which
00:16:05
you don't because databases are actually different um we just don't have the time we can't tell product owners we can we just can't take on upgrading that whole horizontal
00:16:18
stat horizontal spread all at one time it's just not practical Instead This is the mild change a lot of the issues my whining with with layered architectures can be ameliorated
00:16:31
by what folks can now call vertical slice architecture just the idea that I am going to organize first by cohesive features within the system
00:16:43
a bit of functionality and I'm trying to show this here I'm showing separate databases it doesn't necessarily mean you're automatically having a giant modular monolith that's targeting six
00:16:55
eight totally different databases just that if a segment of the database whether it's a schema a set of collections if at least between features could be a little bit Loosely coupled
00:17:07
from each other that even if you're a monolith if you could do upgrades this at a time one feature at a time that's practical you can convince product owners of hey we can do this
00:17:19
upgrade in our case it's it's not necessarily an upgrade it's cheap right we kind of like to replace SQL server with postgres and some of our big systems just purely cost savings it
00:17:32
would be nice if we could do that if we could tackle it more bit wise a Sprint by Sprint we could deliver in a Sprint we could deliver switching part of the app from SQL Server to postgres but there's no way in hell within one
00:17:45
Sprint we could ever do the whole whole horizontal layer that's something to think about other weakness layered architecture they talk about well you can reason about one layer at a
00:17:58
time you never reason about one layer at a time you reason about one use case at a time the full vertical stack hopefully you can concentrate on only the business logic or only the data access logic but
00:18:10
likely when you have customer problems when you have integration tests failing you need to trace tightly related code from entry point to controller level to
00:18:21
data access layer to service level to entity the tightly related code put it together keep it as close together in your code as you possibly can that means you're going to lose out on
00:18:33
some of that that rigor that people try to do through project references people try to force this kind of loose coupling rule by setting all those kind of rules of you know this project can only access
00:18:45
that project and can only have these Tack and all that that's great um it's extra overhead it's extra friction on you it's just better if
00:18:57
developers can be disciplined instead okay I want to keep harping on keep harping on a little layered architecture just a little bit so now you start talking about advice
00:19:13
all right your reference architecture so you'll download people have these things all over GitHub here's what a microservice would look like and I'm going to have a controller that calls to mediator level the calls to a service
00:19:27
layer the calls to a repository abstraction that's hopefully persisting entities and talk to the real database right that consistency is great except what
00:19:38
happens in reality sometimes I just find out it doesn't work sometimes it's unnecessary complexity you see shallow pass-throughs everybody's probably seen this in their code right following a template you see nothing but a service
00:19:50
layer that just immediately delegates the next layer down that's silly I think a much bigger problem is when these things become way too bloated so we switched it code just one quick
00:20:02
second here the other killer problems um I'm always kind of kind of lame um let's say our problem problem is an invoice
00:20:15
so a really common practice is to try to organize these controllers and repositories and entities around really crud-centric thinking saying that let's have a folder or let's have an invoice
00:20:28
controller which means we're going to have an invoice invoice service and invoice repository so on and so forth right and this is all spread out all over the system
00:20:39
what happens longer term you get a lot more operations than just crud as this grows I've seen plenty of cases where these controllers can have
00:20:53
10 to 15 different operations so you end up with controllers that just have massive dependency lists because you have all these unrelated endpoints that everything that touches an invoice or an order or whatever your entity is
00:21:07
you're going to have one big method here that calls one big method here it calls one big method here so on and so forth that gives developers a disincentive to
00:21:20
think about what else should be there as use cases grow much much larger by having one method one calling one method one method one method one method it's a disincentive to start extracting
00:21:33
methods out because you really have a junk drawer of unrelated operations that just Loosely follow under the Aegis of an entity so developers I'm sure some of you've
00:21:47
seen this developers will bloat these things like crazy because that's all the template says to do right what they need to do instead is they need to be breaking out of the template they need to realize hey in
00:22:00
this case that template no longer works we're going to come back to the organization by entity because I think that's that kind of crud-centric thinking based on nouns I think that's actually a root cause of a lot of the
00:22:12
bloated problems in these kind of big systems but first let's contemplate Winnie the Pooh for just a second um well I get a drink so
00:22:30
out of this this whole whole talk if there's one and only one thing I want you to take away from this um most of us here are probably technical leaders within our within our
00:22:42
organization or are you certainly aspire to be Fair statement folks right so you probably learned this lesson the first time out I was a technical leader SEC first time I was a
00:22:54
technical lead I just did all the coding and had the other people do nothing the second time when I actually tried to be a tech lead um I learned a horrible lesson um I tried to write out in great detail
00:23:08
because I was getting yelled at so much for not giving enough guidance so I wrote down this really detailed guidance of how to do a coding task and handed it off to the developer and when I got the
00:23:19
code back it was horrible what was horrible about it I'd given him the wrong advice and he had just followed what I did he didn't think it he didn't question it didn't change just
00:23:32
did what I told him to the the hard lesson I learned is when you're giving technical advice technical Direction it's much more important to explain the why why are we
00:23:44
using this template when is it applicable and also creating a decision tree of when does this not work so that this advice that I gave you thinking about these three use cases when you hit
00:23:57
use case four that's something totally different you have some tools to know of hey this is wrong this this doesn't apply I should do something different trying to avoid that problem with bloated controllers bloated service
00:24:09
service layers all right now there's a balance here we do these prescriptive approaches so developers don't have to think all right just proceed and do problem is it doesn't work it just
00:24:22
doesn't give you good results in harder harder systems so technical lead always got to be explaining why are we doing things understanding trying to explain the rationale and always give
00:24:33
the other developers space to challenge what what we're doing and always have a little bit of room to innovate when they hit into something different or at the very least your very most Junior developer should at least be comfortable
00:24:47
coming back to you and saying hey this just doesn't seem to work what do you think at least getting that kind of negative feedback of hey this reference architecture it ain't working for me so um going for more Gen X this is even
00:25:06
a little before my time you know so we're criticizing a lot of things we're going to criticize more database abstractions a minute but what is good Conan what is best in life right um what I'm going to say it's not
00:25:19
necessarily the stuffy rules who can call what project structures reference architectures it can be helpful but that stuff's um at all times you want to keep very closely related code together as close
00:25:32
as you can you want to be able to work at the speed that you can think I want to even be able to and we'll show sample in a minute I want to be able to just put put controllers that call services that call mediators I want to put it in
00:25:45
the same file while I'm working on it from the beginning it's real easy that way I can just scroll up and down I can think all the time I don't have to distract myself with remembering this goes in this folder and this one goes
00:25:57
there um the single biggest thing what I would say the single most guaranteed and reliable way to get the quality in any code base it's iteration and adaptation
00:26:09
it's that is the only perfectly reliable way to ever get to something good so you want to purposely choose to work in a way that makes iteration and adaptation possible and easier so having effective
00:26:24
test automation coverage I think is actually more important than the rules about layering and abstractions and all that kind of thing that gives you reversibility this gives you the ultimate ability to change make the code
00:26:38
soft and change the code and when I say effective here I mean it's fast you can run it locally anytime you want obviously I'm griping a little bit about selenium Suites here
00:26:50
it's fast it's reliable you can count on it it's relatively comprehensive again going down that theme of iteration I want to use lower ceremony code and
00:27:02
what I think there is an example I'm thinking of in our system we it's a good thing we adopted open Telemetry very early on but we've
00:27:14
adopted it much earlier than our messaging bus Frameworks had it so we're manually writing open Telemetry tracing calls in every single message Handler in some cases
00:27:26
right that's not hard code but it's ceremony in its bloat now we hit cases where we're finding message handlers that really need to be broken up for various reasons actually in this case
00:27:39
it's trying to open a connection make an external web service call come back and finish the transaction out it's horrible on your database we want to break this up and be doing multiple calls but to
00:27:53
break up those message handlers we have to recreate all that open Telemetry tracing that's extra ceremony but instead you know as we move into newer tools or just upgrade the tools we have if you don't have to manually do those
00:28:05
extra explicit steps it's cheaper it's lower cost for you to change change your message handlers break them up dropping down the bottom we've covered some of this um
00:28:22
we're about to go into database database right now so what I'm going to tell you is I think the absolute most important thing for business logic is to keep infrastructure concerns out of your business logic
00:28:34
I didn't necessarily say abstract the database that may be the answer but the single best thing you can is keeping all technical concerns out of business logic
00:28:46
or workflow logic and we'll look at some other approaches that doesn't automatically mean database abstraction but that that's important okay um and then
00:28:57
something to soften this up again with these stuffy rules of you got to build up you got to build an adapter interface so that you can swap out the database or stick an in-memory database in blah blah blah this is something something I think
00:29:11
has been a big change in the last five ten years is we're starting to have more and more Technologies where it's actually relatively easy to incorporate them as integration tests um and if your technology is easier to
00:29:23
Easy in integration tests I'm not going to worry so much about pulling layers and adapters and in-memory stuff I'm just going to code through the real stuff and as long as my testing is good and fast I'm happy with
00:29:36
it okay so obstructing the database is it a good idea is it not um and it's it's it depends it's always it depends
00:29:54
we switched code oh I'll make the code really big oh the font here oh yeah hold on like I said I'm always conquered with this stuff man you heard my bad joke of the the the
00:30:15
people who are really good with AV it's because they don't code it's obviously not true all right so this kind of this kind of eye repository of tea um I don't know how common this really
00:30:33
is anymore it was really common a decade ago I see it pop up um I think this is really problematic in the end I think this causes more harm than good especially with a bigger more complicated system this is a very close
00:30:47
reflection of exactly what the underlying technology does um it just doesn't add a lot of value it's pretty well close to a straight up password and then
00:31:00
y'all have believe me and also again go back to this idea of crud um trying to organize code around entities
00:31:15
it's not really how it works in the real world um it's just very common you're going to hit operations where you're Crossing into different cred boundaries you're using different entities you know
00:31:26
here I'm making up you're touching a user you're touching an order you're touching an invoice at the same time and now I need to have a transaction boundary around all of these and and you have to get those transaction boundaries right you cannot screw that up or your
00:31:40
system is going to be really bad so now you might start adding more unit of work abstractions so you get these these really bloated controllers where they just pull in so many different dependencies
00:31:53
because they need a separate repository for whatever it is the underlying persistence Tech probably probably would happily let you use one thing okay
00:32:06
you just try to make the point here so here's a version of invoice repository just to basic crud operations in this case I use Martin because I wanted to
00:32:19
um it's mostly just just pass through except right off the bat this is common I'm committing transactions in here directly um so right there you're kind of losing your ability to do transaction boundaries between multiple operations
00:32:32
which absolutely happens see that as easily more problems with this kind of kind of Repository so performance issues one of the very
00:32:50
common causes of performance issues it's database chattiness this kind of database abstractions like oh you can swap out Dapper for for a hibernate or EF core it forces you into
00:33:03
lowest common denominators you're not using the power of a system so here I wanna jump into something real quick which is going to require me to remember where I put it sorry folks
00:33:31
okay oh and then I immediately threw it away last conference I did they would not let you do live coding they made this big thing of you're not allowed to do it everything you have to have like every code sample saved to a static file
00:34:05
because we just flat out don't trust you so this is using a little bit of Martin a little bit of Martin but let me explain what what mark because again this isn't a modern talk
00:34:19
um let's say that we have an operation where uh we're this is a banking application I'll use in a little bit at one time we need to get both a user's bank account and some customer
00:34:31
information so we could pick off things like email preferences whatever that is so we need two pieces of closely related data uh with the database I'm using a little bit of of barely Advanced smart and
00:34:43
functionality to go grab these two related documents in one database round trip right anything you can do generally with databases to avoid database round trips to batch up queries to grab data at one time to avoid doing sequential
00:34:57
calls all right that's that's going to be a performance boost or flipping that around the other way in plus one query problems where you query a bunch of data and then you Loop through the data to go
00:35:09
do other queries that's a pretty common performance problem so I'm using right here just the point is I'm using some Martin functionality that's specific to Martin that really doesn't necessarily
00:35:21
fit inside of that that very thin what I call prophylactic abstraction you know the ibase repository it only lets you work on one entity at a time there's
00:35:34
no concept of batching queries or or getting included included things looking at other problems again trying to use the power of your system
00:35:46
um and and to some degree this is this is a little bit based on me having a lot of investment in building developer tools because it's obviously a frustration when you try to build a really good tool
00:35:59
and then somebody puts a bad abstraction around it that throws away most of the power look at the code that's highlighted and this is.net Centric um let me kind of talk about this directly expose exposing I queryable
00:36:13
that is is the programmatic uh strong type type querying language inside of.net various tools have very different dialects and support for for iqueryable
00:36:26
even if you're trying to do it within memory approach I've been burned very badly when an in-memory approach behave very very differently from uh in that case back then it was using Raven DB
00:36:38
where we weren't using Raven DB indexing in an intelligent way whatsoever because it was behind a naive abstraction you got to watch out for that that's a world of trouble trying to abstract away I
00:36:50
queryable behind an eye Repository but folks still do it okay let me get it back here so just kind of review do you track the
00:37:05
database or not I don't think I would even bother the things that are simple add delete save changes I personally wouldn't wouldn't bother it's just not that hard to do find and replace if you want to
00:37:19
swap your tooling but more importantly if we are breaking your system into modules where it's easier to upgrade one module at a time I don't think we need so much of that overhead of of the
00:37:31
database abstractions that's my thinking about it we'll get into testing in a second too all right um let me gosh it does talks going faster than I thought it
00:37:46
would all right one of my claims one of my claims is that if you just use tools that are actually quite nice to use in integration testing yeah not to
00:38:07
worry about about coupling so Martin uh Martin is a librarian that let's use postgres is a document database on top of postgres document databases kind of Awesome
00:38:21
there's no orm mapping this is a Json serialized version of your data your data can be you can have Rich types it can be nested objects it can have collections it can be all kinds
00:38:33
of things it doesn't really matter as long as it's realizable there's very low friction in putting it together all right so in tests let's say uh let me look at the actual
00:38:46
Handler here I'm going to build a message Handler um I want to show this message Handler okay
00:39:00
um message Handler for withdrawing funds from a bank account a little bit of logic you know we need to look up what's the current account is we need to we're going to execute a command
00:39:13
I'm going to use Martin to save data which eventually is all it's here so a little bit of branching logic if the balance is lower than accounts minimal
00:39:25
threshold then we're going to raise another low balance see Tech you know for me having a college age College age son you know hey he's his
00:39:42
bank account's way too low because he's going out to eat way too much right um that kind of thing so I want to test this this logic and certainly have that this isn't a point where it can be
00:39:54
unit tested we'll see just pure pure integration so using tooling that is first integration test friendly so
00:40:13
this one's a big thing um Docker for local dependencies and development development time yeah there's quite a few hands so I think that's I think that's been like one of the best
00:40:24
things in the last 10 years being able to spin up databases rapid queue little things just on the Fly being able to trash them stand them up whatever it's going to be that's very developer
00:40:36
friendly that's integration test friendly in the case of Martin that's all I've done here is I've just spun up a little postgres container um without doing anything else um let's let's look jump into a quick
00:40:49
little bit of a test harness um the Cinemax unit mechanics X unit I think is a little awkward for integration um this is uh this is effectively using um web host Builder this is just spinning
00:41:05
up the actual application spinning up an eye host using some other tools here doing a little bit of Wolverine stuff and Martin has a feature
00:41:16
specifically for integration testing we're going to say if I need some reference data for testing I can just kind of establish a baseline set you always need that kind of thing um
00:41:28
just here just so that when we spin this up in tests completely from scratch Martin can fill itself with Baseline reference data so you can go to go to town start working so a shared app fixture that's just
00:41:46
standing up our application it's running the I host exactly the way it is it's running our program program.main [Music] so I personally like to do integration testing just take the normal application
00:42:00
a little bit stand up it's got Martin in it it's got Wolverine um stand that up in tests so you're using the ioc container built exactly
00:42:12
right just some little extra stuff the test itself building the test harness uh to have a clean database per you know this does cut our ability to to
00:42:29
parallelize tests but just go with it for now every test for automated tests work you have known input so if it's in this case because it's
00:42:41
built into Martin if it's really easy to tear down a database say it and reset it to exactly a known State your tests are more reliable way more reliable than depending on external scripts to set a
00:42:53
database up so now let's do a little so now you can finally have a real integration test where I set up well if I have an account
00:43:09
and I'm going to write that to the database so it's already there now again this is a little more helping functions around Wolverine and Martin this is its test automation to say all
00:43:21
right I'm gonna go invoke this message I don't know wait for all activity to be done so if it spawns extra work wait and finish it and then finally I can go I can go kind of check well I'm just
00:43:33
going to load the database and see what database changes were made you know still more work than unit testing but not a huge amount and then I can even track um hey I rigged this up
00:43:46
um now we could we could have checked to see if it sent the low balance detected message as necessary all my point there besides sneaking in a little bit of sell job on Martin
00:44:00
Wolverine just point there whether it's microservices or something else if we can pick technology that plays nicely an integration test you can go with a much simpler approach
00:44:14
you can use you can just use straight up procedural coding as long as so that's integration testing now we talked quite a bit about keeping infrastructure out of the database or
00:44:32
excuse me keeping database out of your business logic the go-to move is to wrap wrap info wrap abstractions around the database so you can mod it you can stub it that that is an approached and maybe
00:44:45
what you want to do but the biggest thing is um I like what Jim Shore describes as the A-frame architecture uh let me just kind of kind of show an example here we're going to go to Wolf
00:44:58
Wolverine so this withdrawal funds Handler this is the message Handler here um this is this is Wolverine Wolverine's trying to embrace this whole idea of
00:45:10
A-frame when we were running this the whole process it's actually a compound first um I'm gonna having an incoming command I'm going to go look up the necessary
00:45:24
data which this case maybe it's just the account data I'm going to go get the account data and I'm going to push that into the actual message Handler it's not exactly there but you want to
00:45:36
put get to the point where the message Handler the place where it's business logic you want to try to make that a pure function here's some inputs tell me what your outputs are
00:45:46
which case is mutating the account and then also returning hey these are the next steps I need you to do um being able to test this the business
00:45:59
logic by mostly it's not perfect yet because we've still got an eye document session abstraction there but mostly being able to push hey if you have this account and this command what are the
00:46:11
responses that you send back out and how do you modify the account taking this a little bit farther hopefully in a month or two there'll be an example of this that doesn't have eye document session in there
00:46:24
um being able to accomplish the same thing when when Jim says A-frame what he means is there is some kind of coordinator up top that's talking to both service providers which would be maybe your
00:46:36
database and your business logic the controller up top is invoking as necessary it's invoking the infrastructure getting all the data that is necessary for the business logic and then pushing it to the business logic
00:46:49
Gathering the results from the business logic and then pushing it back at the infrastructure to make the changes it's just a separation of responsibilities it doesn't automatically imply that you have to
00:47:01
have abstractions but still keep the business logic away from your database stuff so the approach trying to take with with Wolverine
00:47:15
actually let's make it more fun there's also the ability to do this with middleware trying to build that that whole idea of A-frame architecture completely inside
00:47:32
of the message handling framework itself so it's doing much more work to push data to you it's invoking the data and then doing the push trying to drive
00:47:43
again to the goal of getting very low ceremony code the theory is well this stuff is a little bit better we probably issue some of the more complicated code format
00:47:57
layouts I'm not going to worry about having separate projects for data access this or that I may even embed functionality that is specific to a command I may put the data access itself
00:48:11
directly into the message Handler but as a separate function that can be called separately all right this is a theory this is the part where I'm going to start losing people um but this is this is maybe an
00:48:22
alternative approach I am interested in exploring over the next couple years um again it's back to the theory keep closely related code together try to enable your developers to make changes
00:48:36
in isolation just think about this we're using bed bucket at work a lot of using GitHub when you're reviewing a pull request is it easier when there's a few files changes or is it a little
00:48:48
harder to review when you get the shotgun surgery thing where there's a couple lines of code changing in 2030 files maybe that's only my life but that's what I hit
00:49:01
and folks I think this first time I've done the talk I did a little bit yesterday um one last thing I want to throw out
00:49:14
since we're getting down a little early um this so organizing your code I know one of the first questions people are going to ask is well how do you do your
00:49:26
folders now do you do folders by features or whatever it's going to be I'm also going to say I'm talking about it with my my colleagues of work the still going down the approach even doing
00:49:38
feature folders by entities by saying all the order operations are going to be here I think because of the way things cross in these cross and operations
00:49:53
you want to organize more on operations than you do on a static data Centric model view of your system that's more likely to get you code that's closely related together
00:50:05
and enable to keep you from having files to become way too boldly bloated all right folks um on that one so I think you all been to to NDC plenty
00:50:19
of times you know how we do how they do the speaker evaluations so today I was purposely trying to joust at some software architecture windmills trying to be provocative this is for the first
00:50:31
time ever I was probably actually purposely trying to see if I can collect some red cards at the end of this hey I'm done I'm done speaking after this you want to come argue with me all day
00:50:42
long or please don't please don't do Uncle Bob says but um I I am down for it I hope even if you I didn't convince you to do anything differently I hope at least gave you a
00:50:56
little bit of understanding of the approaches you're already using maybe some some kind of look ahead of oh here's some potential problems we don't have it yet but maybe we have it later so y'all you have been a great audience
00:51:08
thanks for being patient with me coming in a little bit late thank you so much [Applause]
End of transcript