Rigging Plan B: How To Go Live Safely With Bubbles, Toggles Obsessive, etc.
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Alternative Title |
| |
Title of Series | ||
Number of Parts | 150 | |
Author | ||
License | CC Attribution - NonCommercial - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/51499 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
NDC Oslo 201343 / 150
3
4
5
6
8
11
12
15
17
22
26
27
31
32
39
40
41
42
44
47
51
53
56
57
59
60
61
63
64
66
67
68
69
71
72
79
80
81
82
83
85
87
89
90
93
94
95
97
98
99
100
101
102
103
106
108
109
110
114
118
119
120
122
125
126
130
132
133
134
135
136
137
138
139
140
141
142
145
00:00
FrictionCodeBuildingOpen setClosed setModul <Datentyp>Function (mathematics)Social classExtension (kinesiology)Domain-specific languageData structureContext awarenessSound effectSlide ruleMereologyRegulator genePiCodeAreaOpen setFunctional (mathematics)Linear regressionSoftware testingService (economics)WebsiteVotingWeb serviceBound stateAxiom of choiceDivisorPerspective (visual)Cheat <Computerspiel>QuicksortArithmetic meanOrder (biology)Focus (optics)System programmingComputer clusterSystem callStrategy gameDatabaseMultiplication signRow (database)ReliefActive contour modelRight angleMachine codeWordINTEGRALProgramming languageIdeal (ethics)Closed setSocial classMathematicsScaling (geometry)Goodness of fitExtension (kinesiology)BitServer (computing)Code refactoringAnalytic continuationBuildingSoftwareMoment (mathematics)Cartesian coordinate system.NET FrameworkComputer animation
09:09
System programmingOpen setWeb serviceEvent horizonStreaming mediaDatabaseSynchronizationWebsiteModel theoryProgramming languageAbstractionLevel (video gaming)ConsistencyMessage passingDomain-specific languageSystem administratorDatabaseWebsiteData structureComputer configurationSet (mathematics)Computer reservations systemBit rateRight angleSystem programmingWritingRoundness (object)Web serviceSquare numberAutonomic computingNumberWage labourQuicksortLevel (video gaming)Repository (publishing)ConsistencyCASE <Informatik>Goodness of fitDifferent (Kate Ryan album)Model theorySoftwareArithmetic meanFunctional (mathematics)Social classLocal ringInterface (computing)Programming languageContext awarenessServer (computing)State of matterSound effectType theoryEntire functionFlow separationEvent horizonDiscounts and allowancesSystem callAxiom of choiceRule of inferenceMereologyPoint (geometry)Pattern languageProcess (computing)Open setRoutingVideo gameUniqueness quantificationNamespaceMultiplication signActive contour modelCharge carrierStrategy gameAbstractionElectronic program guideClassical physicsMobile appStreaming mediaRepresentational state transferDefault (computer science)Computer animation
18:18
Context awarenessLoginAuthenticationPasswordAuthorizationDomain-specific languageBuildingMathematicsCodeProgramming languageMeasurementEvent horizonSource codeRow (database)Mixture modelMixed realityArrow of timeGraph coloringDiscounts and allowancesPoint (geometry)AuthenticationAuthorizationProgramming languageModel theoryContext awarenessArithmetic meanInterface (computing)Mechanism designActive contour modelSystem administratorBoundary value problemPasswordContent (media)TheoryUniform resource locatorMappingWebsiteMobile appLevel (video gaming)QuicksortScaling (geometry)Event horizonMessage passingSequelDifferent (Kate Ryan album)Bit rateMereologyRight angle2 (number)Image registrationLoginWeightWorkstation <Musikinstrument>Ring (mathematics)TelecommunicationAxiom of choiceDiagramAbstractionDisk read-and-write headVideo gameEnterprise architectureDemo (music)Fitness functionEmailTablet computerForm (programming)Ideal (ethics)Instance (computer science)Letterpress printingCASE <Informatik>Multiplication signCuboidSystem programmingCodeFigurate numberMedical imagingAreaNumberLine (geometry)System callAverageCartesian coordinate systemDomain-specific languageData conversionRule of inferenceComputer animation
27:27
MeasurementCodeEvent horizonDomain-specific languageSource codeBuildingRow (database)PredictabilityLattice (order)VacuumDean numberTelephone number mappingDiscounts and allowancesDatabaseEvent horizonFormal languageDiscounts and allowancesSystem administratorQuicksortMechanism designDatabaseLevel (video gaming)CodeCASE <Informatik>Computer reservations systemOpen setMultiplication signDomain-specific languageData storage deviceSystem programmingProgramming languageBroadcasting (networking)Closed setRoutingRight angleAverageCode refactoringFeedbackCalculationOvalDemo (music)Optical disc driveGame controllerFigurate numberTraffic reportingLogicFunctional (mathematics)Office suiteApplication service providerOrder (biology)BitMetropolitan area networkDiagramAuthenticationAuthorizationParallel portProper mapContext awarenessModel theorySoftware testingBit rateNumberSubsetMereologyTheoryPrincipal idealTouch typingGoodness of fitRootkitError messageDivisorField (computer science).NET FrameworkArrow of timeCountingUniform boundedness principleComputer fileConsistencyComputer animation
36:36
DatabaseGamma functionSynchronizationOvalBuildingEvent horizonCodeSource codeRow (database)View (database)Number theoryMassSystem programmingCAN busDecimalDiscounts and allowancesChi-squared distributionMIDIVotingDenial-of-service attackMenu (computing)Interface (computing)Process (computing)1 (number)Bus (computing)Right angleMetropolitan area networkError messageInjektivitätPoint (geometry)Bit rateSystem callMessage passingSystem programmingCodeUnit testingGame theorySoftware testingSource codeData managementNamespaceConsistencyType theoryKey (cryptography)Programming languageEvent horizonCode refactoringQuicksortDomain-specific languageAbstractionLevel (video gaming)Semiconductor memoryBitProduct (business)Moment (mathematics)Revision controlMereologyGame controllerAdditionMathematicsDatabaseCASE <Informatik>Confidence intervalLine (geometry)Linear regressionNumberFormal languageStructural loadHoaxWeb serviceFlow separationProjective planeMultiplication signVisualization (computer graphics)Similarity (geometry)Coordinate systemDivisorBoss CorporationStudent's t-testComputer animation
45:44
VacuumRoyal NavyStrutFactory (trading post)Chi-squared distributionCase moddingMathematicsInclusion mapModel theoryInterior (topology)MathematicsWeb serviceEvent horizonMessage passingMaxima and minimaField (computer science)Type theoryMobile appBus (computing)StatisticsProduct (business)Projective planeSystem programmingDomain-specific languageCodeRevision controlNumberMoment (mathematics)QuicksortMereologyRow (database)Level (video gaming)Multiplication signVideo game consoleDemo (music)Context awarenessDatabaseAxiom of choiceCASE <Informatik>2 (number)Service (economics)Independence (probability theory)Motion captureShared memoryKey (cryptography)Shooting methodControl flowVideo gameRight angleUniform boundedness principleTouch typingPoint (geometry)Sound effectComputer animation
54:53
MeasurementCodeEvent horizonDomain-specific languageSource codeBuildingRow (database)Control flowFocus (optics)Service (economics)Product (business)Vertical directionMenu (computing)Revision controlCompilation albumAbstractionRoutingOrder (biology)System programmingWeb serviceNumberQuicksort1 (number)Branch (computer science)Reading (process)MereologyEvent horizonModel theoryMultiplication signBridging (networking)Boundary value problemAnalogyError messageDomain-specific languageRevision controlIterationSystem administratorWebsiteDifferent (Kate Ryan album)Level (video gaming)Context awarenessBasis <Mathematik>Statement (computer science)Service (economics)Product (business)Query languageSoftwareCuboidTouchscreenStatisticsCASE <Informatik>Process (computing)Message passingMathematicsHookingGodServer (computing)CodeCalculationVideo gameOffice suiteTotal S.A.Perfect groupMilitary baseMoment (mathematics)Right angleComputer animation
01:00:04
Web serviceOrder (biology)Closed setOpen setDomain-specific languageFault-tolerant systemEvent horizonAutomationCodeGroup actionBoundary value problemWebsiteContext awarenessFunctional (mathematics)Interface (computing)Web serviceRevision controlMultiplication signForcing (mathematics)Software testingQuicksortTouchscreenActive contour modelVideo gameSubgroupProduct (business)MereologyLevel (video gaming)Service (economics)Process (computing)Gaussian eliminationLinear regressionAutomationCodeDomain-specific languageConfiguration spaceUser interfacePlastikkarteLatent heatComputer animation
Transcript: English(auto-generated)
00:04
All right, so I already asked, looks like most people are .NET. This is kind of going live for cowards, really. It's kind of how to sort of not blow yourself up if you have a huge whack of legacy code
00:25
and how to kind of not get all these calls to Künderstärte and not to kind of have to deal with all the really, really ancient Külterkoten full of trolls.
00:42
So who's, yeah, everybody got legacy code, but who's doing most of the working kind of messy legacy code, kind of the ugly side of coming to a conference like this for sort of relief? Oh, God, this is so beautiful. This is, unfortunately, you've turned up for the ugly part of the conference.
01:02
This is mostly about messy legacy code and kind of the disgusting things. And let's look at how we can actually get this a little, do this a little safer. Of course, as all of us who work in legacy code know, it's easier said than done.
01:22
I've often considered trying to make a living actually speaking because it's easy compared to the coding, right? So take it, with that we'll have time for questions and so on and see if we can relate that a bit to your daily experience and actual problems you have, what we're going
01:42
to talk about, which is going to be techniques for not having to touch your legacy code unless you, wherever possible. It's a tangled mess. The best way to deal with it is, if you wouldn't have to deal with it, is there something
02:01
you can do? Can you carve out pieces? We're also going to look at ways of when things go wrong. Services go down, database problems, whatever, server problems. Do you just want to sort of sit there and take it at 3 a.m. in the morning when the
02:22
support call comes? Or can we do something? Sort of a more gradual, more systematic degradation of the user experience, perhaps. And we're going to have a brief sidebar into the faster you can turn this around,
02:42
the quicker you can react to something going wrong. But I'm going to keep that one brief. I had originally planned to do that later, but there's already been lots of other speakers on this conference who talked about automation and continuous integration, all the rest of it.
03:01
So I'm going to look at that briefly and specifically for what it means for legacy code and stuff you can do. But the main thing is going to be about how to structure code and legacy code so you don't have to touch too much of the stuff. Now we're taming side effects, we're limiting damage, we're switching the thing off.
03:26
And of course, I've forgotten all about having these fly-in things in the slide, awesome. So legacy code, this is from, I'm actually Bavarian, believe it or not.
03:43
It's been decades I've actually lived there. But this is known as a Volpertinger. A Volpertinger is a southern Bavarian mythological creature made up of many different parts. Part bird, part fish, part badger.
04:02
And that's kind of what legacy code is like. It's got many different concerns and does many different things. So it doesn't make any sense, right? So how can it be divvied up into pieces which make sense? Who here has read up or works actually doing domain-driven design?
04:24
Domain-driven design, Eric Evans and folks come up with this wonderful concept of a bounded context. Going to get into that a little, but it's actually not a technical concept at all.
04:40
A bounded context is a sort of an area of applicability of language. Ordinary sort of business language. So things have a particular meaning within that bounded context. And it's like, we're going to see examples later, how you can use this bounded context and linguistic business-focused language to kind of impose order on your legacy code.
05:06
You can, how you can sort of identify the bucket into which things need to fall. And then you have two choices. You either refactor so you get those buckets, or you don't and you cheat.
05:20
And that's what we're mainly going to talk about later. So let's take a look at that. I'm going to, the cheating part means, well, we're going to try to not touch more than we absolutely have to of that legacy code and yet build new functionality on.
05:44
I did mention it was kind of like a snake oil kind of thing, right? I did mention this is, that's okay, I'm used to that. If you work in legacy code, you usually over-promise. So open-close principle.
06:02
Bertrand Meyer brought this up initially. Those of you who, most of you probably heard that. It's this ideal on how software should evolve. It's kind of open for extension, closed for modification. Once you write a class or something, ideally all changes are additive.
06:24
And this is a nice idea in principle on the small scale as well as on the big scale. Ideally you could extend all your systems by plugging in and adding on new stuff, right? That would be wonderful. Why is that?
06:40
Why is that such a good idea? It's because, in short, it cuts down on regression side effects and regression test effort. If you only add stuff to it, well, there's a slightly lesser chance that you blow something away that already exists. Well, of course, in legacy you usually couple to the large database in the sky,
07:00
which means you're going to do it anyway, but that's okay. The second advantage is much, from a business perspective, is probably more tangible. If you actually haven't changed that lack of code, then no one needs to go away and regression test it. And that means that you can turn around faster
07:23
because who's got sort of in-house QA departments? Most people, right? Just a question of who works in a company of, say, more than 100 people? Wow. More than 1,000 people?
07:42
All right. 10,000 people? Okay, serious legacy code, then. Serious legacy code. Yeah, you get this thing. You know all about working with QA, and one classic thing that always happens, which is great folks and so on,
08:03
but of course there's a lot of manual testing. All this test automation stuff is marvelous. We're going to look at how to get some of this legacy stuff under test in a moment. But the reality is, with the legacy stuff, it just won't be, right? It just won't be. And so what happens, you make your fix, and then comes the part where your code sits somewhere and waits
08:23
until somebody gets around and actually tests it. And so if you can reduce the amount of stuff which actually changes in existing systems, it by definition means there's less to test. And so you might get a faster turnaround. You might just be able to get this stuff done faster
08:43
because you need less QA resources, and fast is good for being responsive. So we're going to look at that. Now, strategies for dealing with legacy systems. There is a concept that comes from Eric Evans and Domain Driven Design
09:04
called a bubble strategy. You have a sort of, your new system or your new features are sitting sort of to the side of the existing system, and the way you achieve that is you write anti-corruption layers
09:22
or what have you, which keep all the messy stuff apart from the existing stuff. So this can go all the way to the system having its own completely separate database. If your new piece of functionality, and we will come to how to actually identify what makes a good piece of new functionality versus a bad piece of functionality,
09:44
as in how to maintain highly coupled or loosely coupled a little later. But if, say, there was a miracle by which you can actually identify such a bubble which is completely internally consistent, the only way into that bubble
10:00
is through its exposed API. The only data it ever uses is from its own local database within that bubble. That would be nice because it's the difference between a big mess where everything flows into each other and everything's coupled together,
10:22
and a little mess, preferably one you and your team made all by yourselves and you know, meaning this little bubble, almost like an app or small piece of software on its own with a well-defined API. Now, it so happens that that's also the definition of a class, really,
10:45
should really have the only way you can do anything in there is through its exposed interface and API. It goes all the way up to a service which is deployed somewhere on a server, I don't know what, a REST service, what have you. In the end, the REST piece is just the transport.
11:03
It's just the thing which talks to a well-defined API. If you really stick with OODesign, every class is that completely isolated world with no way in or out, which means, for starters, it's a lot easier to test, right?
11:21
You don't have to get all sorts of strange databases in the right state. There will be no side effects which you can't, outside the bubble, autonomous. And two types of bubbles are an existing database with an anti-corruption layer
11:42
or a separate database with a so-called synchronizing anti-corruption layer. And I'm not going to talk about the open host service very much. You can look that up in the DVD literature if you want, especially Eric Evans' famous Blue Book.
12:01
And an open host service basically just wraps your entire legacy mess into a big API, and you hope for the best. We're going to concern ourselves mainly with this autonomous bubble concept with a separate anti-corruption layer. And we're actually going to do that by using events to populate
12:24
that separate bubble which will have its own database and so forth. Autonomous bubble, as you can see, you have the great, clouded,
12:43
all sorts of things in it, legacy system in the sky. And say someone wants to make a new sales support system which helps selling, in this case, hotel reservations, sort of get rooms in a hotel booked
13:00
and get occupants in a hotel up and reservations and quotes for prices and so on. And this particular API has a quote function, quote for room booking request. And the other part of the API is you can set a room rate,
13:24
remove a discount rate, add a discount rate. So this is all done here. There is some sort of admin website. I'm sure the guys who work in the really big shops have these, this seems to be a common pattern.
13:40
You have an admin website through which all sorts of default values, all the rest of it, are set. And it's probably an admin website which administers five or six or more or whatever totally complete, unrelated things. And each time you build something new, something else gets kludged into this admin website, right?
14:02
Hardly dare to ask who has got such a beast. Yeah, this is classic, right? So the admin website for this legacy hotel reservation system happens to have something to set room rates, set discount rates, and add a discount rate.
14:20
And then this was used for something totally different in the past. And now all of a sudden they want a sales support system. And so I have a choice of either kludging that on top of the existing system or build one of those autonomous bubbles. And for that, in the bubble are all your business rules,
14:43
all the good stuff, campaigns, frequent guest points, what have you, whatever is in there. And it gets fed from the legacy database via this thing. Doesn't matter what you use. There's a classic sort of ETL job.
15:01
You can use some sort of method calls to post this to some REST API. That's just transport. Or you can make this separate bubble listen to a stream of events. And this is really messaging. Doing this through messaging and events is the route we're going to go in this session,
15:21
because it's the least coupled way of doing that. It's the least. You pretty much, once you publish those events, you can go live very, very safely. Because you essentially don't have to touch anything in the existing legacy system if you have identified the right kinds of events. And in this case, the sales system is just one more subscriber to this thing.
15:43
And you can add as many subscribers as you want, as many systems as you want. And that's, of course, the snake oil part. We're going to look at some caveats and complications for that. Here's a hint. Whenever I've done one of those bubble strategies,
16:02
oh, I don't know, this kind of nice clean stuff, it should be easy to work with, right? Which is why that was often about half of the overall effort going into this. And the full other half of the effort, or more sometimes, goes into writing this anti-corruption layer,
16:21
which is a round peg, square hole kind of thing. And translating concepts and data structures and what have you into things which are understood by this nice autonomous bubble. So there's a number of... Basically, the anti-corruption layer here, it maps between ugly and clean.
16:43
And so it's surprisingly labor-intensive to do that, in my experience, compared to the actual bubble, which is sort of breath of fresh air kind of thing. So, I'm not going to go into this.
17:00
This is a detached bubble where you use a repository pattern and, in this case, sales context doesn't have its own database. We're going to go beyond that. We're going to work in autonomous bubbles. So how do you pick what's in one of these bubbles?
17:24
Because clearly it's been done before, right? Everybody who has to write this new piece of functionality, it's not that anybody deliberately sets out to mash that all together with the existing stuff, right? So what's your guide fence for actually picking what is in your bubble and what's outside?
17:45
This is where this domain-driven design concept of a bounded context comes in. And it's really a business thing. Here's the somewhat cryptical...
18:01
Not cryptic, but within a bounded context, the ubiquitous language of the applicable model is used consistently, naming, namespaces, and so on. And it has consistent levels of abstraction and so on. What does that mean? Let's have a look. Let's say that we have two of these contexts.
18:27
Everybody pretty much has an authentication and authorization context or something like it. And that context is very much one with an established domain language. When you look at logins and authorization and so on,
18:43
you think about users, you think about registration. There's the concept of logins, logout, forgotten passwords, changing passwords, deleted account, roles. And then there is confirm reservation.
19:01
Wait, confirm reservation. That doesn't ring right, okay? That doesn't make any sense. Confirming a hotel reservation, if you put it together, forget the technology, but just language-wise, does that fit into authentication and authorization and logins and so on?
19:22
No. This part where you do your context map, you figure out what the major problem areas, if you will, or solution areas, the major things within which you use a consistent language,
19:44
you figure that out. And it's actually a very, very non-technical activity at this level. It's entirely linguistic. It's entirely pictures in your head. That's how you know what should go into which bubble.
20:02
Because if you can manage to build systems, or in our case, because this is going live for cowards, if you can fake your way up to a point out of having to build such systems, and we're coming to that, then you are in a good place.
20:20
You're in a good place because you won't have such a highly coupled system and it will be easier to test. Why is that? The ideal architecture diagram. We used to do all sorts of UML stuff in the early 2000s, late 90s and so on.
20:43
And I formed this picture in my head what the ideal architecture diagram, which actually makes sense, looks like enterprise architecture. You probably know those sort of enough printouts to fill a wall in some cases. Many boxes, many arrows. What happens to those?
21:00
They're kind of yellow on that wall and no one ever looks at them and they write the code. So that always happens with UML. I never understood why. But I formed the sort of image of the ideal architectural diagram. It has something like no more than six boxes and maybe nine arrows. This is for non-technical stakeholders.
21:21
How to debunk the architecture diagrams you get from your technical folks? Six boxes, nine arrows. Why is that? Because the human mind can't really concentrate and focus and more than six or seven things at the same time. So its point is to make a bigger architecture diagram. Okay.
21:40
So how can you design a system then? Well, you design it on a human scale where people can actually reason about it properly hence that tongue-in-cheek rule. I thought it was tongue-in-cheek but I've actually applied it a couple of times. It's amazing what it does. Look at this thing.
22:02
There's only one arrow between those two bulbs. That was the wrong one. Come on. Awesome. There's only one arrow between these things. By having clean bounded contexts you reduce the number of things
22:21
which move between them. Say, if for example in here you had confirmed reservation for some bizarre reason here in this context can you just about imagine what happens when someone does a reserve on line over here
22:42
and some stage they want to confirm the reservation so they have to call back into this thing here. Of course that's no longer a pure authentication authorization context. It's now something like the Wolpertinger thing. It's now a mixture of many things. It's phish, it's foul.
23:00
It's logins, it's confirming hotel reservations it's all mixed together, right? And that means imagine if just that one concept was out of place you would have another arrow going back there and every arrow is some kind of method call or something and before you know it you get this sort of mess of things which all point at each other and so on
23:20
and the starting point for not having that mess is entirely non-technical it's linguistic, it's meaning and that makes kind of intuitive sense because well, if you look at your average iPhone app it does one thing it does one thing only and does it well it's the thing which does authentication authorization
23:42
well, not likely, but it does hotel reservations whatever and so it makes each one of those things could be its own little website which does nothing but that one thing the fact that it's actually exposed through some API be it an interface in C sharp be it REST listening to messages actually doesn't matter
24:02
these are just transport mechanisms think of each one of those bubbles as its own standalone application suddenly your world consists of small standalone isolated, easy to maintain yeah, that's the snake oil part anyway, easier to maintain applications, right
24:20
so inside those bubbles, if you drill down one level, you'd have more arrows if you care to draw them but at the top level it's at a human scale moreover, it's at a business level scale it's at a stakeholder who aren't geeks who actually absolutely must be in this exercise of establishing those boundary contexts
24:42
and the context maps they must be in there for two reasons first of all, they need to validate this this is actually not the model of some particular system of yours it's the model of your business the other reason why they need to be in that room is because without them in the room we're all gonna geek out
25:00
before you know it, we will talk about JSON, about SQL about all sorts of acronyms right, that has no place in that conversation this is a language and business and a level of abstraction discussion the purpose is to identify what bucket your code goes in so
25:21
beautiful oh, by the way yeah, there's Fowler who talks about those domain events which you can have bounded contexts communicate with ordinary method calls and all sorts of things it's just for this demo I've chosen the most loosely coupled way of doing it which is pops up with domain events
25:40
so yes, well if we had all that we wouldn't actually need to refactor, right so that sounds wonderful in theory but and it is in practice your code isn't like that, but it's not really about the code
26:01
as mentioned before this is business one thing I see a lot is when we get into modeling those bounded contexts and so on we drift into this sort of oh, but the admin side it's not like that and where does the admin side fit into the bounded context
26:22
it kind of doesn't in this it's not in this model it probably has lots of different concerns for example, updating discount rate you have a sort of the reservations domain within that bounded context and it's imagined your legacy code with those bounded contexts kind of superimposed
26:41
so it's a business discussion to identify an ideal world where one bounded context is one system, right and let's say you've had that discussion and for that you absolutely need the business stakeholders in the room because without them well, first of all you learn a lot
27:02
second of all you don't really want to geek out on this stuff then comes the part which is the truly dark magic, which is how, given that you have all this legacy code can you actually go
27:21
and make it behave like that you have two choices you can do the great rewrite the great one year rewrite, why doesn't that work who's tried the great sort of six to twelve months rewrite and yes, did it work? yeah
27:40
why doesn't it work? because it's frustrating for the business, because at the end of that one year rewrite they get what they perceive as they already spent the money on and already have during that year or year or half year rewrite people howl for fixes and new features, all the rest of it so you get these sort of things living in parallel
28:01
who never quite meet and if they meet it turns into a mess, forget it much better to have those bubbles and give incrementally more features and one way to do that, okay if you do the great big waterfall thing where now you go away and you look at your entire business
28:21
and you identify all of those events which move between those bounded contexts at a business level and identify them all and have another huge diagram on the wall remember, you couldn't have more than about six to nine or whatever what we said earlier, nine arrows or so
28:41
it gets complicated, right so you do it one at a time somebody asks for a new feature, the first thing you do is you assess what domain events are needed in order to fulfill that requirement, you do
29:01
something like that exercise we saw with the authentication and authorization and the sales the new sales system context and this is to assess what information would be needed by a new hypothetical bubble which fulfills this new requirement
29:21
the next part is where it gets evil how do we make the legacy code publish the events the theory is there is one place in this code where all the information comes together for example, for entering I don't know, hotel room discount
29:41
hotel room discount rates in the admin system that admin system no matter how messy it is will have one place where all the information pertaining to that comes together and is available and could therefore be pushed out by some sort of event publish subscribe mechanism
30:01
very often the most evil place where that happens is very close to the database where the legacy system hopefully at some stage makes up its mind that it has all the information and writes it to the database so in extreme cases I've been known to resort to triggers to actually then
30:21
fire off some sort of event so you need to identify those seams to see where you can harvest this particular domain event lastly you want to record this thing somehow because it's nice to be able to replay those later for example, if you can throw some sort of event
30:41
store into this you can fake your with emergent design you can fake yourself all the way into a sort of event store CQRS kind of thing without actually touching much of your legacy code it would be really really cool by just adding those event broadcaster things
31:01
open close principle, remember you add those event broadcasting things into your legacy code which hopefully means you don't have to touch too much of all this junk and at the same time you can say you're doing CQRS and event sourcing if you manage to publish events which are good enough to populate aggregate routes
31:21
all the rest of it you can look very very cool if you do this right and that's of course really complicated which is why you do it one small requirement at the time if it's smaller it's less complicated finally one immediate benefit is you can
31:40
now that you've got all those domain events coming out, for example reservations made reservations cancelled things like that, the immediate benefit is you can actually harvest those how many of those how many reservations and cancellations did we have on an average day in July that kind of thing, business will love it
32:00
unlike the one year giant refactoring in the sky, you begin to have feedback and value very very early before you even build this new feature just by virtue of instrumenting your code lastly, you consume the thing who needs to subscribe to the
32:20
events and now comes this is more or less the end of that and now let's look at Kildekoden I call it Stavanger for et or men ek al glent menosk, and I say
32:42
egg instead of, nevermind anyway let's look at some code and if you look at, this is the dumbest reservation system in the world right, it truly is and this being a demo the odds are that it won't even work
33:01
for example like that wait for it there you go, it's a very dumb reservation system
33:21
for starters you can just reserve rooms but it's not for anybody in particular right, I still do that in excel on the side, and you can also only reserve for one day so I can reserve for the 14th for example I can make reservations of 10 available rooms, it's also a pretty
33:41
small hotel, and I can also cancel reservations and it's been done by hippies and it's like it really is legacy, it's absolutely dreadful, so someone says hey, can you do something like we'd really like to know a little more than that
34:01
it tells us nothing, right we would like to see for example some information, we need a report and some information which tells us how many cancellations and reservations we had every day, can you do something, it's kind of like the anyway, I was going to make a
34:21
joke with Kentucky fried chicken, you heard of it Kentucky fried chicken man coming to a veterinarian's office in a panic, carrying a bucket of Kentucky fried chicken, doctor, doctor can you do something anyway, this is legacy code, never mind
34:40
back on topic let's have a look let's have a look at this, it's a very dumb system, and you can see here what this is classic ASP.NET MVC and you can see here that it's a it is a reservation system
35:02
and you have you have a bit of a somebody give a first shot at bracketing that into some acceptance tests which may or may not work there's a checking in, a checking out and so on, given ten rooms available a check in and so on and so on, but that's about as far
35:22
as it goes you have you have your this is the booking controller which is really really messy you can see here we have our vacancy and room rates and calculations and all mixed into the controller
35:41
logic here is this reservation function where somebody wishes, if somebody wants, if somebody posts reserves or cancels it first figures out if it's a reservation or whether it's a
36:01
cancellation and here is a really bad sort of thing which you get in legacy code if this was a proper sort of domain modeling exercise in DDD style language in here shouldn't increment well that's increment and decrement right? What are those? Have you ever seen a hotel
36:21
somebody working in a hotel oh thank you sir for joining us next Saturday to Monday let me just decrement the number of available rooms no no no this is what brings us right back to consistent
36:41
domain language even the code this is really important when it comes to identifying our events and not being led astray by all sorts of technical events like error rates or stuff like that write write down into the code name spaces and everything the name of the game is to write it in such
37:01
a way that the hotel manager could sit here look at the source code and you could with a guided tour this guy would roughly sort of understand what is happening that's the kind of abstraction you want to be at the top level as you drill down eventually you get into
37:21
the more technical stuff but there should be a level of abstraction all the way in your code where business stakeholders can understand that that's the key for divvying this stuff up and not having everything bleed into each other so you can see there's not much here it's really quite there's some sort of a database which does stuff
37:42
like it's a very dumb database for starters it's a memory so if you're looking at a production ready system and so on let's look at the next step here if you recall from our from this we have now we looked at this code and
38:01
we have assessed that what we want is a make reservation and a cancel reservation event so let's go there and load a version of this which actually has that playing
38:28
Russian roulette here with live visual studio and okay so let's look at that same message bus thing in the
38:41
after we've instrumented this thing so you can see here that sorry you can see here that something new has two new things have appeared in the solution a so called message bus and a pile of unit tests let's look at this booking controller
39:01
which we took a look at and the part of the booking controller we were interested in hasn't actually changed at all open close principle we haven't touched that and yet we want to sort of hose out those events which we can later use and
39:21
we already said that sometimes in legacy the only place where you can be sure that nobody mucked with it is the final stop when things go into the database because that's where in the end everything has to come together whether we like it or not and this is not always the case right it depends on what you've got but that's the assumption I made here and so
39:42
let's have a look at what's in this decrement number of rooms available mess the decrement number of rooms available mess has acquired something called publish event reservation made on
40:02
a certain date so it decrements as we had before the number of occupied rooms but now this is additional line right open close principle we haven't actually changed this thing but it now publishes an event here and if you look at what that actually does
40:21
it makes a new reservation a new reservation made event and it publishes that on a mythical message bus here and that message
40:40
bus is actually injected into the reservation db another additive change so your reservation db thing legacy thing has no code changes it only has additions to code
41:00
right and assume for the moment that this has the customary 500 to 5000 lines of legacy code in it this is a good thing because it keeps your regression test load down so additive changes alright that's marvelous so this would probably have been several months projects no it wasn't this is
41:20
actually this actually this message bus piece of infrastructure what actually is that let's have a look nothing it's nothing it's an interface right and it's a stub
41:40
go back to this here's your message bus interface which has one method called publish we've seen that and there's a couple of other ones like there is something called i event which is just like a marker and then it has a stub where it does nothing right so
42:01
how do we wire it up who cares we just do poor man's dependency injection we make a new reservation db which is starting anywhere no rubbish and we wire it up with a stub which does nothing so what's the point of that where's the value in that
42:20
test coverage the value is in suddenly having unit tests around this which weren't there before we're talking about value early we're now talking about for example
42:40
we don't make this reservation if the hotel is fully booked these were tests this was in the legacy code so it should not do that when this thing is fully booked you shouldn't be able to make a new reservation but there were no tests
43:01
around it safe refactoring you need tests and by instrumenting this thing with events it's like a sort of a dipstick where you can sort of get a bit of coverage because you've identified those seams at which all the information is there to make a reservation just before it's written
43:22
to the database or wherever if you had just this one thing in there which sort of sends that message then you can write a test saying whether that message has actually been sent and in this case the way we do this is
43:42
we use a we use a what's it called we just use a mock a fake service bus this is my who's using rhino mocks or something similar this is one called
44:02
fake it easy I find it easier to read anybody using fake it easy? I kind of like it it does the job and it's it's a matter of taste it doesn't matter we fake the message bus and we do the booking for this
44:21
and then we verify that a call to the message bus publish method with an event of the type reservation made must have happened at some point in time so we test the early
44:41
benefit test coverage right? so that's that intermediate refactoring step so good now we have a little more confidence additive changes some test coverage and a fake stub down message bus let's do the next step remember the
45:06
requirement was well we really want this other system which allows us to get some statistics out of this thing and for that we want to have those events cancel and
45:22
reserve published so now we have new systems we have
45:41
a this message bus slash events publisher but it has acquired a major dependency and in this case RabbitMQ which is fine so we implemented our message bus so we can publish events on RabbitMQ anybody using Rabbit here?
46:03
ok so there's that we also have something a new thing called statistics I'm coming to the send online confirmation thing in a moment but here's the statistics thing
46:21
and it does two things again right at the top level this is new code you should be able to see what it does reservation it deals in reservations and cancellations per day and it updates the reservation statistics so it sits here waiting for
46:43
waiting for events to come in and let's see what it does it all depends on whether I actually started ZeroMQ
47:15
this is actually the wrong a little ahead of time
47:20
this is actually the wrong demo you've got a guest phone number here I'm coming to that as you can see here let's leave this one aside if I submit this stuff you can see that on the 14th you have 5 reservations
47:41
and 0 cancellations if I make it the 15th and I make a reservation suddenly that appears and if I make cancellations the stats are updated so this is a completely separate system to which we publish events via RabbitMQ and it basically uses the
48:03
instrumentation you've seen earlier in the earlier example there were no further changes to the legacy system at all none whatsoever except that we now instead of the stub, wired up the actual RabbitMQ publisher apart from that there are no further changes
48:22
again, minimum touchpoints and minimum coupling and simpler maintainability so next well alright so this is kind of wonderful
48:41
but now we really want to have something where we can send these people an SMS message ok you've done a booking, this is part of an online booking kind of self-help context I really would like to get some sort of booking confirmation
49:01
again, we can either crack open the legacy code or we can make another one of those bubbles which is a sort of a guest notification kind of context so what do we need for that? let's take a look at the finished product
49:21
you kind of saw it here if I put in a fictitious phone number then you can see that there is still the statistics update up here but there is also a second quote unquote service which is called a console app
49:40
which sees that room bookings which sends SMSes to these people if they booked rooms there is none which notifies them of cancellations yet but it certainly does it certainly makes those reservations
50:01
and does those sends those SMSes so how did we do that? well, there is a slight complication here compared to the previous one the previous let's look at the events in this for that
50:20
a shared messages project has appeared and shared messages has a reservation cancel event and the only thing it has is a reservation date we had that earlier that was the earlier system which had no concept at all about individuals
50:41
it just knew that one reservation is stupid, but it only knew about one reservation having been cancelled on that day and you had a reservation made which also only knew about a reservation date but we have had a change we suddenly needed
51:01
an additional field the guest phone number because this guy is supposed to get SMS messages somebody reserves we've captured that phone number but how do we get that in here? how do we make sure that this confirmation system, this bubble
51:21
can actually receive that phone number and remember we got these domain events reservation made and reservation cancelled somehow we have to go there and so we have two choices we can either whack this thing in here and just change the already existing reservation made event the reservation event which would violate
51:41
the open close thing we don't want to change it once it exists because what happens if we change this one? we might break the original calculate statistics of number of reservations cancelations by day service we would have to touch that we might break something
52:02
we really don't want that we want that service to keep running safely deployed somewhere so we don't have to go live and do another deployment remember deploying things safely for cowards so what we do is we make a version 2
52:21
version 2 the next version of reservation made has both guest phone number and the reservation date right? and so if you look at the code for the in the actual
52:41
online confirmation part you can see that go in here it checks for the routing key not to get into RabbitMQ too much but it basically checks
53:01
it only accepts this type of domain event it only accepts reservations reservation made version 1 because that version 1 is the only thing which has what it needs which is that phone number to send
53:20
the SMS to conversely if you look at the same thing in the statistics thing the one we had earlier the update stats thing once I drill down to that level
53:41
it deals in the original reservation made and reservations cancelled so it's able if I look into the record thing it's able to to deal in the original event type so I don't have to touch it
54:02
and it keeps running so you have these immutable message versions which live in this shared thing and gradually you add more and more and then you can as you retire old legacy services if you ever do some of those messages won't be needed anymore
54:20
and don't need to be routed anymore but in the meantime it's all additive again, makes it much much safer to go live right, pops up you send those events listeners are there, they update the databases independent small bubbles ok so now we have
54:44
where are we at? we have a system which in our where we've sort of rectified those cancellation and reservation events where we publish all these
55:01
and we've sort of done the entire we've done the entire cycle and we've gone live in two iterations already small iterations one for getting the original statistics calculated and then another one for getting those SMS messages both were entirely additive going live for cowards
55:21
less QA effort the only hairy part in this is where we have to harvest make the legacy code publish the events but that gets less sketchy every time because you understand better where you can hook into this thing and it's still the lesser of two evils
55:41
and so additive changes you gradually build on those little bubbles so last what happens if it goes wrong anyway? what happens if for example oh my god the brand new RabbitMQ server is down nothing works anymore that's where
56:01
sort of final concept I wanted to sort of throw in the pile for going live safely today comes down comes in this is the concept of a domain feature toggle this isn't the same thing as the versioning and source control concept of a toggle who here is using feature toggles?
56:24
are you using it sort of so you don't need to branch or something like that? probably this is a slightly different idea which we actually chance in our shop in sheer desperation you have all these nice services
56:40
which are it's less of a problem the ones which are fed by domain events but if you have a SOA thing some of your services which you need your read models this applies particularly to read models of course in order for the user to see for example what bookings exist at some stage
57:01
you often need to make a query some REST thing who knows what and now you have all these separate services unfortunately the damn box goes down the service is dead one great big clattering error message appears on the user's screen this is reality
57:20
of the legacy stuff and once you pull it apart you have more moving pieces which can go wrong that exactly happened to us this was a new service a bubble context in this case for a toll processing system for a bridge it runs on something which sits on top of the Amazon
57:40
the Amazon EC whatever cloud what's the chances of that ever going down and last year it goes down and we have an entire because this was the analog of this admin side thing which does lots of different things basically our little service the tolling service
58:00
in the back going down took out the entire website in the front which needed to talk to it and if it didn't it blows up so what do you do this is how we went into this into this domain feature toggle sting and what it does it's very very dumb it's in a nutshell
58:22
on a on a per feature basis you have you can switch it off right promotions enabled
58:42
online bookings where you have this where you have this for example the sort of product for which this enter your phone number is in a sort of boundary context sense in this system is online bookings and if I set that to false and switch
59:01
this thing off as you can see here all of a sudden it looks like the old system I can make my reservations and all the rest of it in spite of we assumed here that something in the back which is needed for that new feature which is entering making bookings
59:20
by phone number is no longer available and therefore we switch it off you can just about imagine the messy if statements in the back which do that the key difference to a feature toggle is that it's actually a product thing you can actually use that to monetize a software as a service thing that's kind of in my mind the right way to think
59:40
about it you have this guy your product owner says yeah this user should be able to get those confirmations therefore need to enter the phone number this guy should do this and this and this so it's definitely not a source control thing it's a switch and it's a product level domain feature level kind of switch alright
01:00:03
How does this all then come together? What it comes together as is a gradual degrading of the user experience, a managed, oh God, the entire site fell over, no it doesn't, because you have those reasonably clear
01:00:23
bounded contexts which deal with specific products and functionality they implement. And you can say, okay, that service, which is one bounded context and has a couple of things in it, is down, that is down, that is down, these different services are needed to provide the following user level functionality and affect the user interface in this following
01:00:44
way. Therefore, let's somehow engineer our user interfaces so the feature set sort of gradually gets restricted as the underlying services go bang. So it goes like this, service goes down, then automatically or manually, what you've seen
01:01:02
in the config files go across the chainsaw thing, it's 3 a.m., you whip into production and edit config files, that's the crudest way. You can also do some sort of monitoring when the services go down, something knows what needs those services and therefore knows what features are switched off and could automate
01:01:21
that. So, it screams loudly by sending alerts, then after service is restored, the feature is switched on. So this is how you get yourself a nice, safe fallback with a controlled way of restricting the user experience, hard to do in practice, but we found it worthwhile, it saved us from
01:01:45
a couple of other things. It also means that you can do selectively, make features go live for subgroups of users, offer products, much more flexible, much simpler. And that, seeing as we are out of time, summary, find legacy code seams, identify
01:02:11
those bubbles using bounded contexts and so on, find a way to get data into these bubbles, the one we looked at was publishing those domain events, find a way of safely degrading
01:02:26
user experience if your whole Apple card gets upset and falls over, automate everything so you can do this turning around fast and small pieces to production regularly, and finally, eliminate waste in your processes, and this is a big part of that because it
01:02:43
reduces regression tests and that wait time which happens until they're all done. And that's about it for today's snake oil. Thank you very much. Any questions, I'm here for another 10 minutes or so.