Architect Tips by Clear Measure
Created to help .NET development teams move fast, deliver quality, and run their systems with confidence. This series is led by Chief Architect Jeffrey Palermo as well as other Clear Measure team members, publishing short clips of helpful tips to empower you to achieve more! Visit www.clearmeasure.com to view other content and learn more.
Architect Tip: What is Technical Debt?
Architect Tip: What is Technical Debt?
Welcome to Architect Tips presented by Clear Measure, a software architecture company. Empowering .NET development teams to be self-sufficient, able to move fast, deliver quality, and run their software systems with confidence. Make sure to subscribe on YouTube or your video podcast feed. If you have a question for the show, send them to ArchitectTips@Clear-Measure.com and the next tip could be yours!
What is Technical Debt?
Now we all want to move fast and deliver consistent quality and run our software in production with confidence knowing that everything works and we won't be surprised by bugs getting through. And at this point, if you haven't been paying attention to the podcast, we sponsor the Azure DevOps podcast, then check that out and specifically, listen to Episode 150 with Capers Jones. I highly encourage you to do so. Capers is probably the most prolific publisher of research in the software industry, and his research shows quality precedes productivity. And if you want your team to go fast and you focus on that, then your quality is likely to suffer. You won't go fast at all. It's an interesting dynamic, in an attempt to move fast. You may skip some automated test cases or push something out without fully thinking through all the aspects of the design and then when a production bug happens, a developer stops working on a feature and spends time fixing the bug. And in this instance, we discovered new work. We've known about new work that had to instantly move to the top of the priority list pushing back, other prioritized feature work and it's very likely that the developer loses half a day or more fixing the bug. And then there's more pressure after that to finish the feature. And if that feature doesn't have a complete design or complete level of automated testing coverage, then a bug in it will surface at some point soon. Repeating the cycle and on aggregate, the discovery of bugs and the efforts to fix them can end up consuming a lot of development time. And from the outside of the team, it can appear that development doesn't move very fast. But in reality, the development of new features people are waiting on move pretty quickly. They can be pretty simple features. But because of the quality issues, the remaining development capacity left in the week to actually work on new features is not a full-time effort. It could be a fraction of the development week. The point at which all development time in a week is used to fix existing defects or we're not working on developing new features at all. We're just fixing things that broke that is complete development bankruptcy, where were sunk.
Now, some people call this Dynamic Technical debt, and it's called this to invoke the metaphor of interest payments on a credit card. If my paycheck is $4,000 per month and I pay $100 per month to pay the interest that has accrued on a credit card on the amount that I've charged, then I can keep going and manage that because I have $3,900 per month left of available cash and pay other expenses, whatnot.
But if I continue spending above my means and charging it to a credit card, then there will come a time when I'm paying all of my money that I have every month just to pay the interest on the rather large balance. And at this points its all over a cliff, my margin for adjusting my r recovery is gone. I can't pay it down. I just don't have the means. So technical debt in software is in complete design and sufficient automated test coverage. You could think that hey, I paid for a feature or your business partners or customers paid for a feature and development. We pay for a feature by working on it, spending time on it. If I pay for a feature, but if I only pay for some of it, then the rest is technical debt. And so the rest of it I put on the charge account to be paid in the future and in the future when a bug surfaces because of an incomplete design or insufficient test coverage.
Architect Tip: How Often to Deploy to Production
How often should you be deploying your software to production? Welcome to Architect Tips, presented by Clear Measure, a software Architecture company, empowering .NET development teams to be self-sufficient, able to move fast, deliver quality and run their software systems with confidence. Make sure to subscribe on YouTube or your video podcast feed. If you have a question for the show, send them to architecttips@Clear-measure.com and the next tip could be yours.
Welcome to Architect Tips. I'm Jeffrey Palermo and today we're going to talk about how often to deploy to production. And if you have a question for Architect Tips, send it to email@example.com and from those submitted, we will pick a question. And if I can put it in to a short five-minute bite-size chunks, I'll do it. Otherwise, I’ll just send you an e-mail and answer it for you. So how often should you be deploying your custom .NET software applications to production no matter the size of the software or
individual chunks? Let’s dig into that and you're going to answer the question for yourself, but it's going to depend on a number of factors. The first one and foremost is the pace of your business. And if your business needs to give new things to customers once every three months. Well, then deploying to production... The minimum to deploy to production is once every three months. If your business needs to roll out changes to customers every week or even every day, then that's the slam dunk answer. Now, let's suppose that your business doesn't really intentionally roll things out to customers, but every few months you are still making improvements to the software, you're increasing the quality of your telemetry. You're making it run faster, you're making it scale better on fewer server resources and so you'll still be doing production deployments even if you're not actually giving anything to the customers and so the answer is you need to deploy at least as fast as your business moves and faster for other scenarios. Now let's back up from that question and talk about the pace of your testing because if you are testing performance, improvements or stability improvements, well that's also going to determine the frequency at which you deploy. Even if you give, let's say, product management the button to press to production and say, hey look, build such and such as ready for production. As soon as you press that button, it's going to go. If you're ready, and they're never waiting on engineering, that's success. Product management should never be waiting on engineering, engineering should be waiting on product management. Whatever form that takes in your company, whether it's Joe next door or whether you are in a larger organization with more formalized product management. But the pace of your testing can determine how often you deploy to a pre-production testing environment because every DevOps environment has three categories
of environments. The first is production, everybody has at least one of those. Next is a manual test environment. You need at least one of those, a lot of organizations have many of those, that's one category. The third category is automated test environments or test automation environments. I like to call those environments The TDD environment to invoke test-driven development so you have three categories of testing. Now the pace of your development is also going to impact how often you would deploy, not only to production but to test and your test automation environment and that the raw ability to deploy quickly comes back to how you do code branching, and if you are doing branches that live for days and weeks on end, you're not going to be able to do production deployments on any kind of frequency. So you need to have every individual change beyond its own short-lived branch. And when I say every change, if you're changing the way a button operates, that’s a branch. If you are adding a new screen, that's a branc
Architect Tip: Testing Polymorphic EFCore Mapping
Welcome to Architect Tips presented by Clear Measure, a software architecture company. Empowering .NET development teams to be self-sufficient, able to move fast, deliver quality, and run their software systems with confidence. Make sure to subscribe on YouTube or your video podcast feed. If you have a question for the show, send them to architecttips@Clear-measure.com and the next tip could be yours.
Howdy! Welcome to Architect Tips. Today I want to talk about strategies for writing and maintaining automated tests for object-relational mapping whenever you have a hierarchy that you have mapped. And so on the screen, I have a sample just from a car auction, a car auction application, where we have an auction entry, but then we have three different types of entries. In an auction, things are typically called a lot. And if you're selling that, that sweet Chevrolet Corvette will be lot number such and such. And so you have competitive Lot, C of Consortium Lots, where multiple people can go in by organizations and you have an add-on only lot for donations, but they all derive from auction injury. So, in the code, you would see that a derived type lot would inherit from auction entering, okay? Well, what about your mapping? This is Entity framework and entity framework core or just entity framework and .NET 5 as well. And so, we're going to go to all auction injury map. We use this convention for every type of map, an aggregate root in domain design speak. We have an actual class so that the mappings don't get out of control and you want to be able to have a class per map. And if I go over to my data context, you can see that we have a method here that just kind of lists all of them and we can control the schema and in some cases, you want to put them in a different schema. That's just an aside but an auction entry, we've inherited, we've established it as table per hierarchy. So we've added a discriminator, okay, that's great. Just follow the documentation and in, in our code, we can find Consortium lot map and we can see that here, we have declared that our base type is auction injury. Although, even if you don't put that there, any framework, kind of figures it out. And this is our discriminator, it's only in the database, it's not in the object model and this derived type has an additional property in additional collection that are not on the base type. And so likewise we can go to another, the competitive lot. We can also go
to the, I add normally lot allow the donation that basically stays the same. There's no differences just yet. Although, this will grow. But over in our test, that's where it gets interesting. So I'm actually going to go to auction entry mapping tester and control F12. Notice that I have six different tests and over in Consortium, lot mapping tester only have two tests. However, because Consortium lot is at entry that means that all of the different queries and all of the different persistence and rehydration scenarios that work on auction entry should work for Consortium lot. So I have to duplicate those tests, the answer is no and this is how. So in our auctions remapping tester, we all we do is we take all of the tests that create an auction entry and instead we factor that out. We extract that as a method that returns auction entry and we market virtual. That gives us the ability to add some polymorphism given that our mapping is polymorphic when they are tests to be polymorphic as well. So we're going to do here, Control Alt B, we're going to look at derive types, and you can see that I have a mapping tester class for each of the drive types. And so if I look at Consortium lot, mapping tester, it, in fact, does inherit it overrides create auction entry and the usages of this are not found in this file. They're used in the base file. And so then we only have to actually have two more tests. Now, if I run it, my shortcut key. Alt Up and I run it, control TR. Let's let this run. And look, I hav
Private Build Structure
Welcome to Architect Tips, presented by Clear Measure, a software architecture company. Empowering .NET development teams to be self-sufficient, able to move fast, deliver quality, and run their software systems with confidence. Make sure to subscribe on YouTube or your video podcast feed. If you have a question for the show, send them to architecttips@Clear-measure.com and the next tip could be yours.
Hello and welcome to Architect Tips. Today, I want to talk about the essentials of a private build and a lot of people are trying to do continuous integration but they only have a manually, triggered or an automatically triggered compile process which is only one of the steps of continuous integration. Continuous integration has three steps. Actually, the first is the private build. We do it locally. The second, the commit phase,
has the integration build where you run on a build server and that's the bill for your team. In the third step is the first deployment and fully deploy test suites. And so, the continuous integration has those main three stages and a lot of the tooling makes it easy to have an automatically triggered compilation process but a lot of people leave it there. So I want to talk about the first step which is not even on the build server yet, but it is just something you have for the application itself. Whether it's a visual studio solution representing a big application, or whether it's a solution representing a small microservice that’s just a stand-alone Azure function or just an individual job of some sort. And so let's go through this and this is a build script that you can actually follow the structure. If you're familiar with my book, .NET DevOps for Azure, you can find the build script in the download tools in the download files there but I'm just going to go all the way to the bottom.
This is just straight power shell. At the bottom, we have a function called CI build, and then right above it, we have private build. And so if we look at what it's doing the private build, we have some chocolatey packages that this application needs. And so we use the build script to install those directly so that somebody can just clone the git repository and immediately run the build as opposed to get the Clone the git repository, then install this, then install that. Then configure this, then configure that and you know, we want the experience of, you know, the big things like you have to have the right visual studio version installed on the computer, clone the git repository, run the private build. So we're installing the chocolaty packages then in it essentially does clean compilation. That's running .NET, .EXE, or msbuild then we're going to do some environment set up in this application. And a lot of times, we have a SQL Server database or database of some sort. So we need to create a shell of a database locally and then after that, which is after unit tests to run, then we run the integration test that typically do a lot of data access as well as other things. So, that's the structure of it. And then I'm going to go back up to the top and kind of walk through each one of these individually.
So, up at the top again, this is just straight Powershell and all of the uniqueness. You could literally copy this power shell file. And there are so many, go back to 2005. I think almost every application and client that I have worked with has taken this structure, this layout, this template of a build script and used it in their applications. Now, of course, in 2005, it was not running with cruise control .NET. But essentially the same you need a script file that does the stuff, you pull all the unique stuff up into properties at the top. And so you see the project name, my project and later on, you'll see that we can just use that name and then put a .SLN on the back of it. Now we have our Visual Studio
Solution file. We have a source directory where the unit tests are, where the integration tests are, wh
Architect Tip: Developer vs Architect
Welcome to Architect Tips presented by Clear Measure, a software architecture company. Empowering .NET development teams to be self-sufficient, able to move fast, deliver quality and run their software systems with confidence. Make sure to subscribe on YouTube or your video podcast feed. If you have a question for the show, send them to architecttips@Clear-measure.com and the next tip could be yours.
What's the difference between an architect and a developer? Let's talk about that. Now, as a developer, when you're joining a team, you're shown the ropes. You have a new workstation and you're given a tour of the documentation of the software at the source code and you're given a first assignment. You're given the spec or the design for something to change first, where to go, what the process is, how to build the software, how to test the software, run the automated test Suites, build, and deploy to not only locally, but maybe a test or a TDE environment before ready for manual testing and then you get to work. Now, I understand that some of your experiences as a developer are that you get thrown in there, you're told nothing, software has no documentation, the source code is disorganized, there's no build, no automated testing. No nothing. And you're given a bug and say, hey, go fix this and you’re fending for themselves, for yourself, either one of those scenarios.
You, as a developer, your job is to write code that is a change to the Software System. A change that is determined to be useful by somebody else and to actually make that happen and produce a new build of software with that change without breaking something else. Okay, your job is to do things, is to implement the changes that are necessary. All right. Now let's talk about the world of an Architect.
Architect is what I do. If I'm an architect, well, your umbrella starts with possibly ambiguous conversations with somebody who is funding the software, or maybe who owns the software, and they have some business objectives, outcomes that they want from the software and they're talking about it generally. And it's your job as the architect to just hear what they're saying and what their goals are and to start formulating that
into some type of plan to make that happen and to make that happen via one software application between a mix of changes to a number of software applications, whatever the scope is. Because you as an architect, some architects work at the scope of a single small application, some Architects work at the scope of an entire organization with dozens and dozens of systems that all have a dependency graph between them. So as an architect, your scope can be really, really huge at massive companies and massive organizations or it could be very, very confined for a particular application, but the one common thread of what an architect does is translate the ambiguous to a business outcome facilitated by software and so the developer’s scope in the process is here, when we've already decided what we're going to change, now, go implement it in the code, the Architect’s job is very broad. Starting with whatever conversations with business stakeholders, all the way through breaking down the designs that we're going to select for proof of concept. If necessary, break it down into a sequence of work that can be done in order by a developer or multiple developers, the testing and the overseeing that we have proper quality control promotion to downstream environments. And then, as we push it into production to make sure that the business outcomes that we were designing for are actually happening. Because if it didn't we're not done yet because we were asked for a particular outcome and then we hypothesized that a set of designs will achieve the outcome. We aren't done until we've actually achieved those outcomes because it may take a couple of tries and say when we implement few designs, we made some progress but we're not yet there. Now we need to know
Architect Tip: Application Architecture Diagrams
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 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 Blazor 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 la