The road to Atlantis - Right past that bend beyond Temporal Coupling Lane.
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 |
| |
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/51427 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
NDC Oslo 2013113 / 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
Temporal logicRight anglePhysical lawCodeLine (geometry)Stack (abstract data type)Client (computing)Service-oriented architectureMilitary operationSystem callTerm (mathematics)Proxy serverOptical disc driveCalculationPhysical systemState of matterSoftwareGreen's functionLine (geometry)Service-oriented architectureSet (mathematics)CodeComplex (psychology)ResultantTemporal logicDomain nameVirtual machineBoundary value problemComputer programmingSystem callPhysical systemNeuroinformatikCategory of beingProcess (computing)Installable File SystemOrder (biology)Regulator gene1 (number)Pattern languageType theoryMultiplication signSound effectProgrammer (hardware)WritingStack (abstract data type)MereologySystem programmingWeb serviceDimensional analysisException handlingNumberError messageRight angleArchitectureMetropolitan area networkOperator (mathematics)Open setArithmetic meanRoot systemGoogolCylinder (geometry)CircleImage resolutionSocial classXMLUMLComputer animation
08:42
Physical systemMilitary operationScale (map)ArchitectureExtension (kinesiology)Programmer (hardware)CodeElectronic mailing listArchitectureCycle (graph theory)Software testingException handlingQuicksortMultiplication signNumberService-oriented architectureOperator (mathematics)Client (computing)AreaOrder (biology)Point (geometry)Term (mathematics)Physical systemRun time (program lifecycle phase)SoftwareSystem callProduct (business)ResultantVirtual machineMathematicsMereologyIntegrated development environmentMultiplicationSpring (hydrology)Control flowRow (database)Revision controlINTEGRALSound effectOptical disc driveRight angleCodecExact sequenceWordGoodness of fitComputer programmingConnected spaceComputer animation
17:20
Extension (kinesiology)ArchitectureSolid geometryComponent-based software engineeringPhysical systemDistribution (mathematics)Euclidean vectorEvent horizonSoftwareMessage passingConnectivity (graph theory)Order (biology)Multiplication signMereologyProcess (computing)Equaliser (mathematics)Structural loadAutonomic computingEvent horizonClient (computing)Type theoryDiscounts and allowancesExtension (kinesiology)Rule of inferencePoint (geometry)Entire functionCASE <Informatik>Physical systemSystem callSoftwareMessage passingState of matterEndliche ModelltheorieGoodness of fitLogicDatabase normalizationElectronic visual displayDifferent (Kate Ryan album)Customer relationship managementDatabaseNeuroinformatikReading (process)Service-oriented architectureBitCodeOperator (mathematics)Solid geometryTerm (mathematics)Moment (mathematics)Projective planeWhiteboardModule (mathematics)GradientDependent and independent variablesTheory of relativityArithmetic meanLevel (video gaming)Line (geometry)Computer animation
25:58
SoftwareEvent horizonMessage passingOrder (biology)EmailDiscounts and allowancesLimit (category theory)AdditionAbstractionSoftware frameworkService-oriented architectureTransportation theory (mathematics)Client (computing)Pattern languagePhysical systemCodeBus (computing)TelecommunicationEvent horizonType theoryWeb 2.0Customer relationship managementMereologyDefault (computer science)Order (biology)WeightMessage passingArchitectureMultiplication signMultilaterationProcess (computing)PlastikkarteDatabaseCASE <Informatik>FrequencyElement (mathematics)Decision theoryDiscounts and allowancesDifferent (Kate Ryan album)Form (programming)INTEGRALEnterprise architectureEntire functionLogicDependent and independent variablesTerm (mathematics)Right angleVideo gameBoss Corporation7 (number)Real-time operating systemSequelRevision controlHeat transferArmWeb serviceComputer animation
34:36
Inclusion mapNumeral (linguistics)Internet forumNormed vector spaceHill differential equationDemonWorld Wide Web ConsortiumPersonal identification numberMenu (computing)Execution unitLie groupMaxima and minimaProjective planeWordLibrary (computing)Order (biology)Shared memorySystem callEvent horizonBus (computing)Message passingCustomer relationship managementService-oriented architectureClient (computing)Port scannerMereologyQueue (abstract data type)Social classBinary fileCodeFunction (mathematics)Server (computing)Type theoryConfiguration spaceProcess (computing)WindowRevision controlComputer fileComputer programmingMathematicsBoss CorporationImplementationNumbering schemeDesign by contractTheory of relativityInterface (computing)7 (number)Point (geometry)Computer iconFigurate numberDimensional analysisRight anglePhysical systemArchitectureIdeal (ethics)Vulnerability (computing)SineComputer animation
43:13
Hill differential equationSummierbarkeitOvalMaxima and minimaFluxVacuumConvex hullInterior (topology)Bus (computing)Event horizonClient (computing)Statement (computer science)Visualization (computer graphics)Order (biology)Multiplication signQueue (abstract data type)Decision theorySequenceBootingProcess (computing)WindowMereologySocial classCodeType theoryPhysical systemExistenceModal logicCASE <Informatik>Revision controlCategory of beingInterface (computing)Message passingLogicContext awarenessVideo game consoleNamespaceInstance (computer science)Configuration spaceLine (geometry)IdentifiabilityDebuggerKey (cryptography)Phase transitionData structureRight angleBoss CorporationNumbering schemeLevel (video gaming)Rule of inferenceBootstrap aggregatingService-oriented architectureWhiteboardDisk read-and-write headDefault (computer science)Software frameworkProduct (business)7 (number)Flow separationComputer animation
51:51
User interfaceInstallation artExecution unitMenu (computing)IRIS-TSynchronizationInclusion mapDuality (mathematics)Event horizonPoint (geometry)Arithmetic meanSocial classData storage deviceConfiguration spaceMessage passingVirtual machineCASE <Informatik>Run time (program lifecycle phase)Projective planeBoundary value problemBus (computing)Queue (abstract data type)Client (computing)AdditionServer (computing)Service-oriented architectureDependent and independent variablesMappingCodeElectronic mailing listRight angleInterface (computing)MereologyPay televisionMathematicsLogicBoss CorporationPerspective (visual)Execution unitNumbering schemeHoaxDefault (computer science)Library (computing)Orientation (vector space)BlogUsabilityPlastikkarteVideo game consoleCustomer relationship managementDiscounts and allowancesPhase transitionValue-added networkFlow separationLine (geometry)Theory of relativity1 (number)Multiplication signType theoryDot productComputer animation
01:00:29
XMLUML
Transcript: English(auto-generated)
00:04
Good afternoon, everybody. I hope you had a nice lunch. And this is fantastic. And I'm super excited to be here. And first of all, thank you, Jacob Bradford and his team for yet another fantastic conference this year.
00:25
So first of all, my name is Indu. Indu Alegar saw me, and I'm a freelance software programmer. I consider myself programmer mainly. And I also wear other hats, designer, architect,
00:40
whenever the time calls for it. And in this session, what I want to talk about is temporal coupling and how it affects when we design distributed systems, what are the impacts, and how, as programmers, sometimes we don't notice this type of coupling
01:02
when we're designing distributed systems. So how can we identify it, and how can we make sure we're not doing this, consciously looking out for it. And in the course of this talk, we'll also write some code, hands-on code, which will show other patterns,
01:23
like event-driven architecture, and we'll be using publish-subscribe messaging pattern to implement some code and see how we can design distributed systems that are not temporally coupled. So for me, writing software is absolutely fun,
01:47
and that's the reason I'm here, and I'm sure you guys are too. Programming has been fantastic. In my school, when I was an eighth grader,
02:00
my school opened its first computer center, and the only way you could get into the center to play Pac-Man was to actually take a programming course. So in the summer, they offered some courses for programming for BASIC, and I wanted to get onto a computer, so I wanted to check out Pac-Man.
02:21
So I took some classes, and during the course, I came across this program. It was a few lines of code. It was trying to draw a circle, but you could change the coordinates,
02:41
and when you executed this code, it generated this cylinder-looking tunnel thing, which was mind-blowing at the time. I was like, wow, just these four lines of code, and I get this? That got me hooked, and it still got me hooked. Not BASIC, but other things.
03:04
When we're trying to solve the business problems, we tend to use the practices and patterns that we've known along the way, and we try to use them. We try to solve problems effectively.
03:21
That's our goal. We all start out that way. What is beautiful code? Is it a few lines of code? For me, it was. When I saw those four lines do these magical things, it was great. It was those four lines. In those four lines, the computer did something awesome.
03:42
What is beautiful code? Is it a few lines? What are we trying to optimize for? Wow, what is this? In the course of solving problems for businesses, this, by the way, is some code compliance regulatory process
04:03
for West Columbia, somewhere in the U.S., and thanks to Google, where would we be without Google? This here describes some business process, what the code compliance inspector has to do
04:23
if he finds a property that's in violation. There's a whole bunch of processes that goes through some absolute regulations that they have to follow in order to fix these compliances and so on. In the course of trying to implement this business process,
04:43
there's a lot of ifs and elses and thens and so on. Our way of thinking, we tend to lean towards this call stack way of thinking. Hey, do this first, grab this data now, and then go do this part.
05:02
It's very easy to fall into this kind of stuff. What we tend to do is we have some yellow services, yellow things, that try and accomplish something. There's purple stuff, and there's green stuff, and you have all these services
05:21
that's trying to talk to each other, to get the data or whatever state that it needs, and it tries to accomplish this business process. Every business domain is different, has its own set of complexities.
05:41
You might have your own set of complex problems to solve. What we end up with is sometimes we end up with services calling each other. You have a service A, and you have a service B, and it tries to call a method.
06:04
Microsoft made this super easy. Write a WCF service, three lines of code, boom, you're done. All you got to do is just instantiate your web service or WCF service, and you knew it up,
06:21
and you can make calls on it as if it's residing locally in your process. What these three lines of code do is it essentially hides all the complexities that are around. For example, this service could be in a completely different machine.
06:45
We all know a local call is fast. The second you cross the network, you're paying a latency cost. It's not the same as if you're calling a method locally in process versus what you do when you cross the network boundary.
07:04
That's hidden here. It's as if this thing was running locally on your machine. We all know that network is not reliable. If someone asked you, hey, what do you think? Do you think network is reliable?
07:22
We all know, hey, no. We know that network is not reliable, yes. We understand the fallacy of distributed computing, number one. Yes, the network is not reliable. But we end up with code that's like this, where we assume that the network is reliable.
07:41
When you call this operation, you expect a result. This expects that your network is always around. It's making that call, grabs that result, and gives you the expected result you're looking for.
08:00
This kind of code hides the latency, and you end up with, it works 95% of the time, but occasionally, hey, there are some errors. When they happen, of course, we log it.
08:22
We have to log exceptions. What is temporal coupling? Temporal coupling is coupling when the dimension of time is involved. You have a service A, and you have a service B.
08:40
When one part of the system actually depends on the other in order to perform whatever it's trying to do, and it cannot proceed if it cannot get that result from the other service. These calls are blocking synchronous calls.
09:05
This here expects that service B is always around. Whenever I call it, I get the result that I need. But what if service B is not around or service B is down?
09:22
The machine could be down. What then? Then service A cannot complete whatever it's trying to do. There are other what ifs. Let's say you made a call, and the call on the other side, B got it.
09:44
It's doing its operation. But on A's side, on the client's side, you received a timeout exception. The timeout exception doesn't tell you the operation did not complete on B. It tells you, hey, I've given up.
10:00
I've lost connection. I'm giving up after this time. You don't really know if whatever you were trying to do in B actually succeeded or not. You're in some sort of a limbo here when you get that timeout exception. What do you do? You could retry or log the exception.
10:24
When you retry, are there any consequences of retrying? What if B had already succeeded doing that operation that A wanted it to do? If you call it again, are there going to be any bad side effects?
10:46
In essence, what we're trying to say is, is that operation item potent? Can you call it multiple times without any side effects? Will the code exactly behave the same way regardless of how many number of times you call?
11:02
Can you guarantee that? These are some of the problems that you run into, and this ends up being coupling at runtime. There are some traits. This is just a very small list.
11:22
I'm sure some of you that have been to other talks have longer lists of what is and what is not a good architecture. For me, some of the things that I find are it's reliable where it needs to be. The thing that I depend on the most for the business,
11:42
it needs to be up and around and reliable. It's simple. I love Dan North. I think it was last NDC. He said, let me see if I get this right. He said, Don't simplify, simplicate.
12:03
Don't try to... Oftentimes, we tend to end up with things calling things, and at a higher level, the solution is much, much more complicated than it needs to be.
12:21
After five months, another programmer comes along and says, What the heck was this guy thinking? We've all run into code like that where we find it's more complicated than it ought to be. Of course, keeping it simple is often the hard part.
12:42
The other big, big thing is the software we write primarily serves a purpose. It serves the needs of the business. When business comes to us and says, Hey, we have this brand new requirement, and if it's going to take us
13:03
in order to implement that requirement, you look at our architecture. You've got to make changes here. You've got to make changes here, here, here. There's 15 places where we've got to make this change in order to implement this simple requirement. Of course, the QA person is going to tell you,
13:23
Oh, no, you touched that? I've got to regress test the entire thing because I don't trust you. The QA cycle takes long. Some of you that have to take this code through multiple environments
13:42
where you've got dev, integration, QA, staging, that's a very long road to production. Business is going to get upset, or it's like, Why is this taking so long? I just wanted this.
14:01
How is our architecture doing? Can it extend with the business needs? Is it capable of growing along the needs? Suddenly, business is booming. Now you've got 20,000 orders instead of whatever, 1,000 orders.
14:25
How fast can you grow? If you have to go back and say, In order to scale, I think we have to rewrite the system, then that's not really good because the whole point of trying it out was to make money for the business.
14:41
To me, I consider these as some good traits that I look forward to, or I look for, when I'm trying to develop, when I'm trying to design the system. As if we don't have acronyms,
15:00
I'm adding a new one. Good architecture is serene. Serene is actually a rock-climbing term. I go climbing. Just to take a little off-bat, in climbing, you have the climber
15:21
and you have the belayer. The climber climbs. There's two ways of climbing. One is you set up the anchor. You just hike up all the way to the top, the mountain. You set up your anchor, and you pass through your ropes. Then you either rappel down,
15:42
and you have the climber and the belayer. Climber is the one that's trying to climb. One end of the rope, the end of the rope is attached to the climber's harness. The belayer is actually handling the rope. As the climber climbs, he makes sure that even if he slips,
16:02
he's got the brake on, so by holding the rope down below, the climber doesn't just fall off the cliff. Even if he slips, he's just kind of hanging there. He lost his footing. She lost his footing, her footing. You don't lose much. You just need to get back on the rock and climb back up again.
16:23
The way this works is, in order to be able to do that, the anchor system that we set up at the top needs to be really, really good because the whole rope goes through this anchor system. You're pretty much relying on that to hold.
16:41
You don't want that thing popping off, and you're falling down 800 feet into the abyss. You don't want that. Lead climbing is where the climber puts protection as they go up and clip in the rope. Once they reach the top,
17:01
again, they set up this anchor system which goes through the rope. In leading, you're only protected by the piece that you put in. Oftentimes, there's a risk of you falling off. If you fall, then you're protected by the last piece that you put in.
17:20
Regardless of how well you climb, in the end, you've got to go up and set up these anchors that protect the next person that's climbing. In order to design a good anchor, there's this system called Serene. It needs to be solid, redundant,
17:41
equalized, and no extension. What the heck does that mean? Solid is, you need to make sure that the anchor is built off of solid components. We're relying on these bolts on the rocks. Are these bolts wibbly, wobbly, rusty? Are they good? Can we trust it?
18:01
It's built off of solid components. I love Aston Martin, but in, I think, 76, I was barely born, there was this model of Aston Martin. They designed this car with state-of-the-art technology
18:22
at the time and with cathode ray displays and all that jazz. According to Time Magazine, it was a mechanical disaster. It ended up as the top 50 worst cars ever made.
18:41
It doesn't matter if this thing that we build is super cool designed. If it doesn't do what it's meant to do, it's going to end up in the junkyard. Redundant. This is very important in climbing. We've got two bolts here
19:00
and the anchor system, the rope, goes through both. What this essentially does is it protects the climber. If in case one bolt that you should have looked carefully and you failed, somehow it popped off.
19:21
You are still protected by the other bolt, by the other carabiners that your rope is going through. In the end, you're still protected. When one part of the system bombs out, it doesn't bring the whole entire system down. Equalized.
19:41
What it means is all these pieces take the load on equally. Not one part of the system is doing too much work. If it's doing too much work, chances are that piece can fail. If it's distributed equally, then the chances are it's a good system
20:02
and you are really safe. It's okay to fall and it's okay. Nothing's going to happen. In order to increase the strength of the overall system, when we distribute the load equally, it increases the overall strength of the system.
20:23
No extension is kind of weird. In rock climbing terms, it's like if something pulls off, you don't want the rope to drop off, even if it's five feet or two feet even, because you could be leading or you could be climbing
20:40
and all of a sudden something happens at the top and you're here and suddenly you drop. That's not a good thing, especially when the first time you're trying to actually climb without any protection, that could be even more crappy. If something craps out,
21:01
then we don't shock-load the entire system. When my climbing buddy actually gave me this book, he's been trying to get me to actually start lead climbing and I'm really, really nervous. He gave me this book about setting up anchors
21:21
and he's like, hey, read this book. This talks about setting all these anchors. As I'm reading through, I'm thinking to myself, dang, this sounds a lot like distributed computing. These concepts of having strong components,
21:41
making sure that stuff is redundant, making sure that when one part of the system fails, the whole entire system doesn't blow up. I'm thinking, the geek in me is saying, hey, this looks a lot like what we do. Going back, we have this code
22:03
where we've got service A calling service B. In this case, if B fails, the whole entire operation of A is down. That doesn't sound very reliable or good.
22:25
What we're trying to do is how could we address this to a model where A and B can live happily even if one of them are not around?
22:45
What we have is event-driven architecture. Our world operates on events. Everything that we do is event-driven, and yet it's very easy for us to, when we're writing code, that we have this request-response,
23:02
request-response type of thing where we try to get something and then based on the state or based on that value, we go do something else. If we stop for a second and take our approach a little bit different, how would it be if our software
23:23
was acting on events? We would have two pieces of things talking to each other by messages. It wouldn't be a synchronous call. It would be one way, fire and forget,
23:41
where we send a message to whoever is doing what we want it to do, and we're done. We go on to do what this piece of software is supposed to do. Here, there is no polling. There is no constantly checking the database.
24:03
Am I done? Am I done? Should I do this now? Should I do this now? The process actually kicks off based on an event. Let's say customer relations is watching all the orders that were placed in the system. It's listening to every time an order got accepted.
24:22
It's got some logic in there that would tell it to, there's some business rules to say, hey, is this good? Can we call this client a preferred client because he's been doing X amount of sales
24:41
over this amount of time? According to our rules, we can make this customer preferred. That happens at a completely entirely different point of time into how the order processing works and how orders are being accepted in the system.
25:02
They're completely different. They're happening in different points of time. Now, the customer relations module, when it publishes, client became preferred. Sales can listen to that event and say, hey, this customer is now preferred, and I have to give this customer a 5% discount
25:25
because that's our rule where we'd like to offer some discounts for repeat customers. There is no sales asking customer relations, hey, here's my client ID.
25:41
What should my discount be on every order that it's trying to process? These are basically autonomous. They can live on its own, and they process things differently, and they start processing as and when they receive these events.
26:01
So that's basically publish, subscribe. It's a messaging pattern, and it's one of the messaging patterns described in the book. If you guys have read the Enterprise Integration Patterns
26:20
by Gregor Hope and Bobby Wolf, there's probably 140 more of them that describes the various different messaging patterns. One thing about publish, subscribe is that it makes this design very explicit about the staleness of the data.
26:44
Just to go back. Now, going back to this, let's say the customer relations publish, client became preferred, and maybe there was a latency, maybe sales didn't get that event,
27:02
or maybe he was busy processing the event, other events. There could be a time where, A, the customer maybe didn't get the discount that he was supposed to, or let's take the opposite case.
27:21
This customer hasn't placed enough orders over a period of time, so customer relations is now saying, hey, this guy is no longer a preferred customer. He's been kind of inactive for a few months, so we're downgrading his status, so he publishes that event. Let's say the guy placed an order,
27:41
but our sales hasn't processed that message yet where we've downgraded that particular customer, so we haven't downgraded the discount, so you could end up giving him that discount. This data, you are operating on stale data, but the data is eventually consistent,
28:02
so eventually it's up to the business. In the case of going back to request-response, our goal is, the reason we're trying to do request-response real-time, trying to look up to the minute, up to the second consistent data,
28:21
is so we want the actual data. Oftentimes when we're writing these web services, we might end up caching. We're not hitting the database every single time. There may be some caching logic in there that returns the value and then updates from the database.
28:41
You could potentially have cached it before, but it's not explicit. In publish-subscribe, you're actually making this staleness be explicit, and you're actually taking decisions based on that fact.
29:01
The other nice thing about publish-subscribe is it makes things, if you need to extend, it becomes a lot easier. Suppose you had another business requirement that said, hey, business is trying to do some promotion,
29:21
so we want to do something, whenever customers became preferred, we would like to try this short-term thing. We don't know if it's going to work or not, but we just want to try and see how it might be. When we make this client preferred,
29:41
we'd like to offer him something else, I don't know, some Hertz membership gold card status, something else, maybe dealing with another third-party system. In order to implement that, we don't actually have to go and change the code that we have
30:02
that processes this client became preferred that does something else. We could introduce a whole new subscriber that also listens to this event, and it could do the exact thing what we want it to do. The beauty of it is, you can run this at the same time,
30:22
so you don't have to take your entire system down just to add this new subscriber. You can bring up this new subscriber while the other processes are up and running, and as soon as this process is live,
30:40
when customer relations start publishing, client became preferred, your new subscriber is going to then get that event, and then it's going to process whatever this cool new promotion is. It can handle that logic. You've essentially added a whole new feature without having to disrupt the rest of the stuff,
31:03
and that's great because you don't have to QA the rest of the stuff, the sales and the other parts of the code that was trying to do stuff. This new code is independent. It does one thing, and later on, if business decides,
31:20
like, okay, we've tried this promotion, A, we want to keep it, no problem. B, you want to retire it, still no problem. You can decommission just that one piece, and you're still good. You're not affecting the entire system. So that's the biggest, or for me,
31:41
one of the biggest advantages that I see in Publish Subscribe, where you could bring on subscribers at any time without touching or modifying your existing parts of the system. So what we can do right now is
32:03
let's actually go ahead and implement this Publish Subscribe system, and let's say that we'll do the same thing where we have the customer relations. Let me go back to this.
32:21
So where we have this customer relations and sales, and we want to say that, hey, whenever customer relations publishes, client became preferred, sales can take that event and do something with it. So how would we implement that?
32:41
So one way is I'd like to implement this using end-service bus. Who here have used end-service bus before? Cool. So end-service bus is, for those of you that haven't used it,
33:04
it's a framework that allows this bus style of architecture to, in order to do Publish Subscribe and other messaging patterns, it's a framework that's built for .NET that you can use in your system
33:22
in order to do this type of architecture and this type of event style communication. So in end-service bus, it uses, for messaging, it uses transports. The default transport that it uses is msmq.
33:40
So all these messages that are going from one part of the system to the other uses msmq by default. And in their later versions, they've implemented new transports, additional new transports like RabbitMQ, AxivMQ, SQL broker.
34:02
Probably missing more. So the idea is you could plug in any messaging transport, one of these supported frameworks that you want. And the code that you write is agnostic. It hides the internal details.
34:20
Hey, if I need to talk to Rabbit, this is how I need to write code. If I need to talk to Axiv, this is how I need to write. It abstracts all that for you. It's the same bus. The API is the same, regardless of the transport that you use. To send, you would just do bus.send. If you want to publish an event, you would do bus.publish.
34:41
So that API is the same. So let's write some code. First off, when we're writing
35:03
the publisher and the subscriber, the one thing that they share is they're listening to events. And one of them is publishing the event. One of them is listening or subscribing to the event. So both these things
35:21
need to be aware of the message schema. So that's the only thing that they share is the message schema. So one of the tenets of service-oriented architecture is you don't share your implementation, but you share contracts or schema. So same thing. The endpoints that we write
35:42
will be sharing the schema. So first off, let's create a new project, a class library. We'll call this Oslo.
36:08
So we want to create the schema for the messages that we're trying to publish and subscribe. And since customer relations is the guy that's going to publish,
36:21
I will create a library called customer-relations.messages. So let's go ahead and create that. So we now need the actual event.
36:40
Let's say client became preferred. And of course we would need the client ID. So there you have it.
37:02
You have your client became preferred event. So in nservice bus older versions or from 3.0 and above, you don't need to take a dependency on nservice bus when you're defining your messages. And with 3.0 and above,
37:21
you have what is known as the unobtrusive way. So your events can just be POCOs. And you can consume these events and nservice bus will know how to process these events when it needs to publish or when it needs to send these commands. So for right now,
37:41
we'll leave them as POCOs. So we've got this. Great. Now let's go ahead and build our subscriber. So we would make a new project. Again, it's a class library. We could host this bus,
38:01
the actual bus that we're trying to use in order to publish to do these exchange of messages between the different processes that we write. We could either host them in our own Windows services or we could let nservice bus handle the hosting for us. And this piece that's either publishing the event
38:21
would actually live within nservicebus.host. So all we need to do is create a class library. And I'm going to call this guy customer relations. Okay. And we go to nuget
38:46
and we say install package nservicebus.host project name ndcoslo.customer-relations. I'm going to use the newer version,
39:03
which is the most recent RC version that was released. So we do this nuget, and what this will do is it will pull down the dependencies for nservicebus,
39:21
and it would add the needed dependencies into this project. And it would also bootstrap it so it's ready for F5 debugging. So when you hit F5, it's ready to go, to run. And it'll add the necessary configuration.
39:41
And it says, okay, it's changed the project file, so we'll reload. What it essentially did was it... So for F5 debugging, it automatically added the start external program and added the nservicebus.host at the end.
40:01
So we don't need to go ahead and change the project setting file to do this. And the other thing that it also did was it added this class which implements this IConfigureThisEndpoint, and it's set as a server.
40:22
So what nservicebus does is upon startup, it actually scans the output bin folder, and it looks for these marker interfaces, and it knows how to configure this. So here, we're specifying as a server.
40:41
It's just a type of configuration that tells nservicebus what type of guarantees does it need when it's processing these messages. Do we need to have these queues be transactional? So in other words, when we're processing this message,
41:01
something blows up. Then that message is not lost, but it will be rolled back, and the message will be sent back to the queue. And it also scans part of the scanning. It also scans and it looks for these messages, the schema DLLs that we have,
41:21
and it knows how to configure it. But since we had this guy as a POCO, it doesn't know yet. So first of all, we have to add reference to our messages project because the publisher needs the schema. It's trying to go in to publish events, so it needs that.
41:41
So now we've got the schema reference. We said this guy needs to be a publisher, so we will tell nservicebus, hey, we need to be a publisher. So next is we said that we want to keep these guys as POCOs,
42:03
so we will add a class that defines the message conventions, which will tell nservicebus what conventions should it use
42:22
in order for it to process these assemblies, what is considered as an event, what is considered as a command, and so on. First of all, here we've got client became preferred. This guy is actually an event, so I'm going to name-space it properly
42:42
and say, hey, this is an event. And events actually are important. They usually convey something of significant importance for the business, so that the business wants to act on. And usually when that happens,
43:00
you have multiple parties that might be interested in listening to it. So you can look out for things like when is the word. So when this happens, if we need to do something, then that's your precursor for finding events in your system.
43:20
And usually they're past tense because the publisher is trying to look at consistent data, up to the consistent data. It's making the decision. And then when it publishes this event, it's not changeable. You can't say, hey, I've shipped this order.
43:43
And then as soon as you make that statement saying that this order is shipped, there could be other downstream processes that rely on that event that could have triggered and started already. So once you publish the statement, you can't go back and say, hey,
44:01
oh, wait a minute, I'm so sorry. I didn't really mean that. I didn't really ship it. You can't do that. So events are, therefore, things that have occurred in the past. So the publisher only publishes this event after this has actually happened. So let's go ahead and add that.
44:23
In order for us to define this, there is another marker interface I want to run before configuration that tells Nservice Bus where we can tell Nservice Bus to say,
44:41
hey, configure instance defining events as anything whose namespace is not null
45:02
and m.namespace.endswith events. Treat it as an event. So we're telling Nservice Bus framework,
45:22
hey, anytime when you're doing this assembly scanning, if you come across types whose namespace ends with events, I want you to go ahead and treat those as actual events. So the other way is,
45:40
if you don't want this to be a poco, you could add the I event marker interface, and for that you will need the Nservice Bus interfaces as a dependency. So that's what we're trying to avoid. We don't want that because then when you're upgrading versions, you don't have to touch the schema,
46:00
go upgrade Nservice Bus because the schema is going to be the same regardless of what versions you upgrade. So we've got that. And now we need to write some code that actually does the publishing. So we'll go ahead and add a quick bootstrapper. In your actual code,
46:21
you might have some particular business case where there's some decision, business rules, logic where you might be actually publishing this. But for right now, we'll say, hey, when I start up my process, every time I press enter or any key, I want to go ahead and publish the event.
46:41
So again, there's another marker interface. It says I want to run when the bus starts. And stops. So whenever Nservice Bus host starts, we can, by having this class,
47:04
Nservice Bus, again, part of the assembly scanning, it's looking for these marker interfaces. So you could have several boot-up processes that you might need, and you could have them in separate classes to keep it nice and contained.
47:24
And part of the scanning process, it'll identify all the types that actually implements this interface, and then it'll call the run method on all of them. So all your boot-up sequences would get executed. So here, we need to be able to publish here.
47:43
We said that we want to publish an event every time enter is hit. So in order to publish the event, we need the bus. So public IBusBus gets set. Nservice Bus uses heavy use of dependency injection,
48:04
and all of its types are registered with the container. By default, it uses AutoFAC, but it could be swapped. We could write some simple, just like how we configured to tell Nservice Bus these are messages. We could write some simple initialization code
48:21
to swap out the container. We can tell Nservice Bus don't use AutoFAC. I like StructureMap. Use StructureMap or Ninject or any of the other containers that are supported. And this IBus is available after the bus has been started up.
48:40
It's available in all of the message handlers and your code. And you could have your interfaces register with the bus as well. So part of the message handling logic, you might have your own interfaces that needs to get invoked. We could do that as well. But here, okay, let's console.readLine,
49:06
not null, writeLine, press something to publish an event.
49:21
Okay, so now the bus.publish. Client became preferred. Get that in there. And some client ID.
49:51
Voila, we have a new client ID.
50:01
Okay, so there we go. bus.publish. And you give it whatever event that you're trying to publish and fill in the required properties. And that's it. So writeLine,
50:21
client became preferred. So there's our publisher. Whoops, how about now?
50:46
So let's go ahead and start up this publisher. Hopefully it starts right. And I haven't made any crazy, silly mistakes. So when it starts up,
51:02
again, it does the startup. And as you notice here, there's some warnings. When you run this code from within Visual Studio, it recognizes that you're within the context of a debugger. And these queues for the endpoints
51:21
that you just tried to create don't exist. So it automatically creates the necessary queues for you. But when you're trying to actually deploy this code in production, you wouldn't be using Visual Studio. You'd be actually running these guys as Windows services. So part of the install time, when you run your deployment
51:42
and when you install this as Windows service, the queues at that time will be created for you, not at the time of startup. So now that we've created this, we can publish events.
52:02
But the thing is we're publishing, but nobody's listening. So there's nothing really going on. Because when we configure something as a publisher, the publisher keeps a list of who's interested in this event,
52:21
that list, in a serializable storage. So whenever the code is trying to publish an event, it'll check to see, hey, who told me that I needed to be informed when I published this event?
52:40
There's a list. And what it would do is it will put a message on each of those guys' queues whenever this event happens. But right now, nobody's registered to receive this event, so we'll need to add a subscriber. So let's do that really quick. Again, it's a class library, sales,
53:12
feed the subscriber, and you go to package manager console, do the same thing, swap that guy to sales.
53:29
We pull down the dependencies, Friend Service Bus. So for the subscriber, the subscriber needs another thing in addition to you referencing the schema. It also needs some code that needs to get executed
53:43
when this event occurs. So, okay, let's go ahead and add the reference. I forget which one. Okay, here we go. We added the reference.
54:00
And this guy, by default, he's a server. He can be a server. If sales needs to publish an event, then at that point we would change that configuration to be a publisher, so it can have its configuration storage, the persistence storage configured
54:22
for listening to subscribers. So, again, and Service Bus needs to know how to treat these events, so we will add the same conventions. You could add existing item. You could put this in a separate class library,
54:51
a project reference, and just refer to the DLL. It doesn't matter because, again, it scans the runtime and it finds it out.
55:01
So we've got that. We've got the conventions. We've got the configuration. Now we actually need to write some code that gets invoked. So, client became preferred handler,
55:20
and it implements the interface I handle messages. Client became preferred, and we'll implement that interface.
55:44
So, hey, client is now preferred. Do the discounts, blah, blah, blah.
56:02
So the way Publish Subscribe works is, first of all, the subscriber needs to tell the publisher, hey, I'm very, very interested in receiving this particular event. Only then the publisher is going to know, okay, whenever I publish this event, I need to notify you. So we haven't done that part,
56:21
and that part is done in the app config. So in the Unicast bus config, so where we tell the bus what are the events that we're interested in receiving, we will add a mapping that will tell Nservice Bus,
56:47
when you start up, I need you to let this endpoint know that I'm interested in receiving the messages. So we called our assembly ndc-oslo.customer-relations.messages,
57:05
and the type that we're interested in is .events, .client became preferred.
57:24
Is that right? Yes, to make sure. And who is this guy responsible for publishing that event? So in our case, it's ndc-oslo.customer-relations.
57:51
So we can't, if this code is running on a different machine, we would specify what machine it's running at, and that's all that's required.
58:02
And we cannot have two endpoints that publish the same event, because as a subscriber, how will you know? If two people tell you, one guy tells you client is preferred and the other guy tells you he's not preferred, how are you going to handle that from a sales perspective?
58:21
So events are very, very, again, goes back to the tenants of service orientation. Boundaries are explicit. The guy that owns the event is the publisher. No two guys can own the same event. So you define that boundary explicitly, and there's only one guy that always you go to
58:44
in case of receiving events. That doesn't mean that this publisher cannot be running on multiple machines. We're saying that logically they can run only on that machine. So we've got the subscriber, so let's go ahead and build,
59:00
and let's go ahead and start up both our publisher and subscriber.
59:21
So again, when the subscriber comes up, if the queues are not created, it'll go ahead and create it. And here we said that client became preferred. It sent a subscription message to the publisher
59:44
to let the publisher know. So as we publish, the client is now notified. So if the subscriber goes down for whatever reason, and there have been several events that's been published at that time,
01:00:03
your messages are still safe. They're in the queue. This sales has these 16 client became preferred events. So now when we start up the sales endpoint, it's going to come back up,
01:00:20
and it's going to find all these messages in the queue, and it's going to process them. So you haven't really lost any stuff.