Oct 6, 2020
Welcome to architect tips. I am Jeffrey Palermo. And I am going to show you today how to use architecture diagrams in a really, really easy way. Now as we go through, there is a lot of resources, a lot of, interesting topics on the Azure DevOps podcast. You will want to make sure to check out that as a resource to you and on this show architect tips, I will answer your architect questions. All you have to do is tweet me @jeffreypalermo and I'll pick a question and, if I can put it into a short five minute bite-sized chunk, I'm just going to make one of these out of it. Otherwise I will just send you an email and I will answer it for you.
So, go ahead and send me a question there. And so now let us get into architect, architecture, diagrams, and I want to, I want to make it easy and show you some, diagrams that I use. So, let us take a system you want to communicate. You want to communicate what you want to either be built or what you are going to build with your teammates then you need to draw something.
If it cannot be drawn, it cannot be built. Every profession that creates something has some type of design diagram. And so, we need that here. So, let us pretend that we are starting a work order application. We are going to build a work order application. And so, we need some diagrams that are going to communicate it and bread and butter diagrams is going to be your oo diagram.
You could also think of it as a class diagram also. We are going to make ample use of sequence diagrams. Okay. Then you might have some patterns. In the case of a work order, a work order has a status, and it has a workflow. And so, we need to make use of a state machine diagram. And a lot of times, an activity diagram will be interesting or an overall dependency diagram.
So let's just take these and let's go through one at a time and see how quickly we can use these particular diagrams to describe a work order application in a fashion where you would actually understand what .NET code needs to flow from this. So, let us start with a dependency diagram, you know, I am a fan of onion architecture. If I am laying out a visual studio solution, and I say, you know what, it is going to be.net. It is going to be blazer web assembly. We are going to use a C-sharp nine and we are going to use SQL server, we are going to pull it up Azure. Well, one of the first things is what is my visual studio solution look like.
So, I am just going to quickly spec it out. I am not going to explain why, but I am going to have it core library. That is a, you know, dot net standard two. I am not going to go on all the rest of it. Then we are going to have a UI project. We are going to have a data access project, and I do not, I am not going to worry about my handwriting.
I am just going to do this. And then we're going to have, let's see what else, you know, I know that I need some unit tests, so we're going to have a unit test library and I'm going to have some integration tests. These are going to be projects. And so, you know to have him here and unit tests are going to be linked to core integration tests, going to be linked to data, access, and core most of the time.
And, if I put in acceptance tests, over here, most of the time they are linked to data, access core and UI. So that is our test coverage. Now I did not put any arrows here. We need to communicate that. Well, the core needs to have no other dependencies. Then just .NET standard and whatever, most stable libraries. You are only as stable as your most stable library.
So, I am going to make sure that the UI references core, I am going to make sure that data access references, core unit just references core, ah, all incoming references. I like that. No outgoing references for core acceptance tests that let me just finish these. And I finished all of them. Alright. So that is our dependency diagram.
Now what about our core? Object model or domain model. I love domain driven, design the pattern, the language that it gives us. Let us just put work order right here in the middle. And this is going to be a class diagram or just an object, an object diagram. I have a work order. A work order does need a status.
I think, you know, draft. So, you know, we need to status object and whether it's an enum or a, or an enumerated class, you know, maybe we call it work, order status, all abbreviated here. And we have things like draft, right? Maybe another one is submitted, maybe another one assigned, assigned to a technician and maybe then it is in progress.
And maybe it is completed, and, or maybe canceled, you know, you can cancel a work order. We have a status. Okay, has relationship and, you know, also we need, we need a submitter, somebody who is going to submit the work order. If I have an organization list this year, they say, well, there is another entity and employee is a submitter or what, and then, and then we need them.
Let us see, and then we need someone to assign the work order to so an assigned E and you know, you can assign it to a technician. Okay. Go but you know what a technician is also an employee. Let us say there's a, there is an inheritance relationship, open triangle. And, you know, maybe later on down the road, Well with approvers and whatnot, we may have a manager or a manager kind of is an employee, a technician has a manager, so we can do that. The technician is open I think we will; we will leave it for that. A, A manager is an employee. A technician is an employee, and a technician has a manager. All right. So, there is our object diagram. So, taking that object diagram into, into consideration next, let us try to, let us try to figure out.
How are we going to put this application together? Let us do a sequence diagram for just creating a new work order when we created it. It's going to be in draft status starting out with a sequence diagram to explain this, then I have got my actor and I'm just going to blow through if you've never heard of whatever diagrams, just follow along.
I am not going to go into UI patterns. I'm just going to be abstract and say, okay, UI in the UI, a person who's going to use the UI and there you going to go to a screen and they're going to draft a work order. All right. So, what happens? Well, in the most simplest sense, if we're not really using any kind of scalable patterns, we might say that the UI uses the work order object directly and the controller or the screen code or whatever component is just kind of call the constructor of the work order directly. And then, you know, a common pattern. If I have a work order repository class, you know, maybe the UI then goes directly and says, Hey, go ahead and save, this work order.
And of course, then we have SQL server. And the workload repository is just doing an insert statement. Okay. That could be a possibility, but that doesn't scale at all because now we have to do all that for, for manager or technician employee for it's just puts too much logic and basically guarantees all of your logic except for your SQL statements are going to be right there in the user interface.
So, we do not like that. We want to do something. I am going to do something a little bit better. So, let us talk about drafting. Let us consider an alternative and come up with a pattern and let us use a little bit from CQRS let us draft some commands and let us use a bus pattern.
So, let us try this again. How would we describe if we were going to do another panel? Let us ignore the user interface for a little bit longer, but you know, the actor is still going to draft the work order. Okay. And then instead of going directly to creating our aggregate route in our domain model, which would be work order, one of our entities that serves as a route of an aggregate let's instead craft a command and where we pull away the user's intent, the intent of the user or the request of the user is to draft a work order. So, let us say draft work order command and I am abbreviating, but in C-sharp you would not abbreviate all these become types.
So, we would create this command like a DTO, and then we would pass it to a bus, or I bus, which an abstract. So, I would not say bus dot send. And then this was, you know, look around and look for a request handler. And if we are going to specify this type of pattern, then it is going to look for the right, handler and say, Hey, will you handle this command?
Okay, great. We need to do that one. How do we do that? Well, you know, we need a lot of classes that inherit from here would, this would be a. Draft work, order command, and yes, all your diagrams, like this can be completely flexible. You can mix and match paradigms. The open triangle is inheriting from, and so through an inversion of control, an abstract word in extend this, and it is going to implement the handle method.
Okay. You can mix and match all of these, all these diagrams, all these things. And so, we have a handle method. Well, how does it do it? well, we are going to have a work order object, and this is the class that calls the constructor of the work order and set. So, drag status to draft. And now we need to say that let us say an OMF.
Well, let us, let us see how this, let us see how this continues. So, we have a draft work order, command over here. Or did I say command I am in handler, as some of you are confused. We have a handler class that handles the command. Now in this handler, we can turn right back around, and we can create some type of command to send back to the bus.
So, if I were to say, save, you know, entity or save aggregate command. And then I created the, that command. I passed in the work order to this say baggery command. And of course, I get the object back and then I pass this back and say, bus dot sinned, passing this, save aggregate command. Well, now I am asking about, Hey, here is another, here is another command that you need to handle.
You need to route. And so, then what happens? Well, we go right back to our abstraction. We say, Hey, I need to save an object. and of course in this case, a work order would probably, you know, if you have I entity or some type of interface, you know, you would, you'd kind of do an inheritance relationship there, but let's just say we have a save aggregation handler that, Oh, by the way, inherits from I request handler.
And so, in this case, this is how that relationship would work, it would implement the handle method. And then if I am just having extend this over here for drawing sake, then we would have SQL server and then we would have an insert statement. Okay. So that is how we can, we can use. our sequence diagram to describe what we are doing is a sophisticated application pattern where after you design this every.
Every one of these would then be on the docket for development tasks. Hey, we need the draft work order command. We need the Ibis. We need the, I request handler. We need a draft work order handler. We need, I entity work order class, say that area command a saves aggregate handler. And those would all be code files that we need to create now at work order is, is something that has a process that has a flow.
And so, we can use a state machine. And so, if I have, if I have a work order right here, the first status, the first status that we have is draft. Okay. The next status we have is submitted. All right. And these are all, these are all facts. So, these are all past tense as a status. Okay. It is, it is not a verb because it is something that is submitted or is drafted.
And then another status would be, it is assigned and then maybe the next status is it is in progress. Okay. And the next status is complete. I'm going to ignore canceled for now, but you can, you can, see that we have transitions kind of a synchronous workflow that this work order has now all of these arrows, you name them with a verb.
So, if we are going to. Go from, a draft to submitted. Then we are going to submit the work order to go with this transition. We are going to assign, see that verb. And if we are going to go to assign it in progress, we are going to begin. We are going to go to in progress to complete, we are going to complete it, which.
It is the same verb. Okay. Now let us say I have assigned it, but now I say, no, I want to, I want to bring it back. I want to bring it back to this status. Now we can go backwards, and we can say maybe unsub, not unsubmit but on a sign. And if I go backwards, I can on submit. So. And if it is in progress and Oh, wait a minute.
Well, maybe I can. maybe I can, maybe I can shell it, whatever word you want to bring up. And if I want to, if it is completed and I go in progress, maybe I call it, hey man, I am going to reopen the work order. Now, what do we have here? We have a lot of lines. We have a lot of pebbles. How do we translate this into actual code?
Well, we already have our work order. It is an entity. We have declared it to be the root of an aggregate and domain driven design speak and draft. Is a status. Okay. Whether we use an enumeration or whether we use an enumerated class draft, essentially as an instance of status, same with all these. And then every one of these lines is a command.
So, let us just make up an abstraction. We need an abstraction to talk about and reasonable. So, let us just make one up. I let us see. I state transition. Okay. Or yeah, I, I state changes and that is great. And so, if we have an ice state transition, that means that every one of these lines could represent an implementation of ice state transaction.
All right. So, what would, what would we really need this abstraction to be defined as well? We absolutely need to know if this is valid. Okay. and if we were to, we need the work order to see if it is valid. And then how about, is allowed, is allowed maybe the work order and whatever employee is trying to do it.
And that way we can create an implementation, we can say submitted state transition. Well, Hey, is this one valid? Well, it is. If the status of the work order is drafted. But it is not valid. If the status is something else. Well, is it allowed? Well, let us make up a business rule here if we are in progress. And, if we are in progress, is the assign state transition allowed?
Well, it is not valid. but allowed might only look at who it is. So, if, if the work order is assigned, To the employee that has passed in, well, maybe it is allowed because they can do something next. But if it is not assigned to them, maybe is allowed, no, you cannot, you cannot transition. You cannot do anything with a work order that you are not assigned to.
So, this is how we make these types of pattern decisions. And this is a state diagram. And then. Let us just count. How many of these implementation classes we are going to create? One, two, three, four, five, six, eight. We need eight implementations of this, of this class. And so, as we draw these diagrams, it, then it becomes obvious what.
Tasks to perform and how to fill up our development task board, how to break up a feature. That has come on our Kanban board and decompose it to the different development work that we need to perform. And so, use a whiteboard use paper. I do not immediately go to Visio. I do not even immediately go to plant UML I just use your pen or pencil and draw some of these application architecture diagrams, right.
Because in order to get clarity with everybody, you need to have a picture because if you're just using your words, everybody is trying to get the same picture in their head of what you intend to do and how to do it. Everybody needs to build that picture for themselves. And, and if you let everyone do it just from words, everyone is going to have a slightly different picture.
So, if you can distill your understanding and your decisions into a picture now you've given them the picture instead of forcing them to come up with their own, which is invariably going to be a little bit different than the picture in your head. So, I hope that helps again. If you have an architecture question, just tweet at me at Jeffrey Palermo, and I will be happy to answer your question.
And as always, if you need any architecture help, clear measure, we are a software architecture company. We exist to help you move fast. You deliver quality, you run with confidence, you can do more internally so that you and your team is performing at another level, and you're more capable and you're delivering for your customers and delivering for your company, which is fantastic.
So, thank you so much. And until the next time.