Visual Studio Toolbox

SOLID Design Patterns

Rate this post
(Video Transcript)
Hi, welcome to Visual Studio Toolbox. I’m your host Robert Green, and joining me today is Phil Japikse. Hey Phil.

>> Hey Robert. How are you?

>> Good. Welcome back to the show.

>> Thanks. Thanks for having me again.

>> Phil is an MVP, a trainer, a speaker at conferences, an author and a-

>> And a consultant. I still sling code.

>> Great, so we were at a show recently. We’ve been at a couple shows [LAUGH] recently actually. We were sitting around talking about what types of things that we should be telling people how to do. We spent a lot of time on all the new stuff, bot frameworks and then stuff like Azure and DevOps and Xamarin. There’s a whole bunch of stuff going on. But, one of the things that we sometimes kinda gloss over is kinda the standards. The how would you, no matter what you’re doing, be a better developer? And so, you suggested that we should spend more time doing that kind of stuff.

>> Yeah cuz, one of the things that people want to do, is Greenfield projects. File a new project, build something from scratch, latest technology, play with all the toys. Reality is, most of us are janitors. We spend our time cleaning up either our own code or somebody else’s code. And whether it’s adding features, bug fixes or whatever. The average life cycle of a project is usually about ten years. How do you make that life miserable, and one of the ways is really focusing on the quality of your code.

>> You can obviously upgrade to the latest version of the tool because Visual Studio has new tools and whatnot but this is more about the code your writing, not the IDE.

>> Yeah, so just because there’s new search capabilities in Visual Studio it’s not gonna fix bad code.

>> And what I mean by bad code is, every code you write, even if you wrote it yesterday, you go I could have done it better. So, what we wanna talk about, and we’ve been talking about for a long time, is the solid principles. Single responsibility, open-close and we are gonna go through these. But it’s just some foundational principles that if you think about these as you’re writing code. And everything to sum it up, I like to look at it this way. Pretend the next person looking at your code is an axe wheeling psychopath.

>> [LAUGH]

>> And if you write bad code that they have to maintain they’re gonna get a little cranky with you. Now, in reality, who’s looking at your code next? It’s probably you. Six months down the road you pull some code down, you have to work on it. You’re looking at this code going, this is terrible, who wrote this? And you’re looking at the commit log and you realize you wrote it. And your like, no, no, it’s fine, I love this code, let me clean it up. So, what I wanna do is just go over a few guiding principles I try to follow.

>> And this is, again, this is whether you are starting a new project or neck deep in an existing project that you’re gonna be on for the next several years.

>> And, we talk about that also with the boy scout principle, we’ll get to that. There’s certain things that you can do to clean up technical debt. And, we’ll talk about it’s a balancing act.

>> Define technical debt.

>> So, technical debt is code smells. Code that could have been written better but wasn’t necessarily, not all technical debt is bad. You don’t always have to pay it back. If something works, it’s in production I’ve got code written in VB6 that’s still in production and people are still finding it useful. And I look back at that code very now and then and go, I don’t want my name attached to it. Can I please rewrite it? But it works and they’re not having performance issues and things like that.

>> There is a cast to rewriting.

>> There is a cost to rewriting. So, you have to really decide is it worth paying that debt back? And it’s a balancing act. We all wanna go back and fix it, but it’s not always the best thing for the customer. So, when we talk about solid, Robert Martin, uncle Bob, write wrote this paper. Principles of Object Oriented Design was the official title and everybody just refers to him as the Solid Principles. And it’s single responsibility open closes. Substitution, interface segregation depends on the inversion, right. So I want to take just a few slides, we’re gonna get to code, but a picture’s worth 1,000 words. And I’m sure you probably had a knife, something like that when you were in boy scouts. I had one of those, and you could do anything you wanted to except cut anything because you could never get the little knife out. And the problem that we run into as developers is, I call it the kitchen sink mentality. We’ve got a class out there called something utilities, and we just start dumping stuff in there.

We’ve got the method. If I just add five lines into here, then I don’t have to create a whole new method or a new class. And when we talk about single responsibility, you really wanna have your methods, your classes, focused on one job and do it well. It’s like driving, can you text and drive in Washington State? I think it’s illegal.

>> It’s illegal. It also gets you in trouble.

>> Yes, if you’re texting and driving you’re not gonna do one of them very well. And hopefully it’s the texting you’re not doing while and you don’t cause an accident. Same thing with code. If you’re trying to do 40 different things, or even two different things in a method, you’re not gonna do them optimally. And plus, if you go to change the one thing, you don’t know what kinda side effects you’re gonna get from the other. So, you got this confusion, just have one thing being done in each method. You have lots of really small methods and then you’re gonna have lots of really small classes. And people will say things like, well, then that’s a lot of files. And I say, so what? With Visual Studio these days you can find anything, all the refactoring tools. The next one is the open closed principle. What we want to do is we wanna extend our classes instead of modifying them. And what I like is the picture of the house. If you’re gonna put an extra bedroom, a patio room, a deck, that’s pretty easy to do.

If you wanna put a new basement on your house, that’s significant, and you run the risk of breaking your entire house. Well, if you got code, it’s in production, it’s working, people are using it. Why would you go change that? So, we wanna make sure that we extend code instead of just changing things at the base level because, again, we risk the side effects, those unintended consequences. Ever realized a cold beer, or at least some sort of cold beverage, and what I like about this slide. And we really want derived classes to be able to stand in front of the other call. And what I mean by that is programmed to an interface. So, if I have an eye repository that I’m programming to, I can program in or instantiate anything that holds that interface. It’s like a beer tap. If you go into a bar and they wanna switch over from a winter shanty to a spring, I don’t know, something. I’m not a beer expert. They don’t have to rip out the taps, the lines, the whole infrastructure.

No, they just flush the line, put a new half barrel in and they’re pouring the new beer. And this happened to me in the late 2000, we were writing an application. It was an e-commerce site. We had a certain credit card provider we were using. The CFO calls and says, we have to switch, and this was like six weeks before release. And he says okay, why do we have to switch credit card providers? And he said well, we just have to, you have to use this other one. Well, it turns out that he was playing golf with the sales rep for the new one, lost a round of golf, and we had to switch.

>> [LAUGH]

>> If we had programmed everything to be directly tied into that initial credit card provider. We would have had to rip out a whole bunch of code that had already been tested, had already been through user reviews and QA and everything else. Instead, we actually had an interface that we could program to. We swapped out the old one, put in the new one, had to tweak it some. But basically we were up and running in about a day. The next on is interface segregation, you probably don’t know what that is, that is the control panel on the USS Missouri, the mighty moe. I was fortunate enough to go to Pearl Harbor one time and they had imagine, a room about this size of the studio covered in dials. To shoot the big guns, they had an entire room full of people manly Turning knots. And these guys knew how to do it, they could hit a target 100 yards in diameter, miles and miles away. When they went to bring it out of retirement for the first Gulf War, the Pentagon went, nobody knows how to shoot the guns.

They had to bring a whole bunch of servicemen out of retirement to teach the new guys how to fire the guns. Or that interface is way too complicated. So anytime you have an interface installs great. But if you hit dot and Visual Studio and there’s a scroll bar and the intel says Window, your developer’s gonna be stalking analysis paralysis and go I don’t know which one to use. The log times are very similar. So, we wanna make very fine-grained interfaces specific to the job at hand. Even if that means making your own interface to wrap up an existing framework class, you want it to be as quick as possible for your desk to be productive. The last one’s dependency version. I think it’s the most important and it probably equals in responsibility. Did you drive to get here today?

>> Yes, I did.

>> Did you build the engine before you could drive here?

>> No, I did not.

>> The engine was already there, right?

>> Yes.

>> Yeah. So, think of software. How often do people build the engine before they drive the car? If you’re newing something up in your method and then using it you’re building an engine every time you want to drive the car. You are locked into that specific instance and you can’t use anything else. What we wanna do instead is subscribe to the ICar interface. You have more than one car, you can drive either of them. You’ve had rental cars before. As long as they subscribe to the ICar interface, you can drive it, right? Which is using a steering wheel, an accelerator, and deaccelerator. Some states they have turn signals. Not all states use them, evidently. But you wanna do it in software. So we’re gonna inject those things in like the engine, like the data access layer, like the repository.

>> So when we get to that point you’ll have to explain why. Like I understand, I’ve always understood the principle.

>> Okay.

>> Sometimes explaining why you need to do that, I want to be able to plug different things in, but in my app I’m only using one of them in the first place, why do I need dependency injection?

>> Well, you’re not always using one of them. You have used log4net?

>> No.

>> Okay, so log4net is a logging framework, and based on settings in the web config and app config, you can change the logging level.

>> Mm-hm.

>> And you can have it be very verbose or very, very light.

>> Right.

>> Right, and what we’re doing is we’re setting those properties in a config file which is then being set at run time. And that’s not really the dependency injection, but that is an instance where we’re changing the functionality of something without having to change code. So let’s say that I’m using a credit card provider for my e-commerce site, and I say foo equals new credit card provider, and foo.checkcreditcard, foo.checkaddress, foo.chargecreditcard.

>> Okay.

>> So now I have to switch credit card providers. And now I have bar. And say bar equals new credit card provider, and it’s not bar.checkaddress. It’s bar.address verification. So now I have to change all that code, right?

>> Okay.

>> Whereas if I just had injected in an ICreditcard provider, and then we’ll talk about it with some of the patterns where we could put an adapter around that. So that it subscribes to a common interface, then I can change out the credit card providers.

>> So how is that different than creating a service class? That has a fixed set of methods, and then your service class just calls check address or verify address or whatever, so that your front-end never has to change.

>> Okay, so how are you getting that service class into the method that you’re calling?

>> You dim it up.

>> Okay, you’re VB guy [LAUGH].

>> You said dim. [LAUGH] You dim it up, you new it up, actually I’m a CSharp hack.

>> Either one, they both work. I know, I do that too. So that’s true. But what if that service class has to change? What if I’m going against a-

>> But the service class, and maybe we’re going down a tangent here, but the service class has a method called check address

>> Okay.

>> And it’s always gonna be check address.

>> Yes.

>> I don’t care what the thing I’m calling calls it, check address, verify address, address verify, it doesn’t matter.

>> Okay so-

>> You would have to change the code in the service class. But the thing that calls the service class always calls check address, passes in something and gets back a yes or no.

>> Okay, so that would be coding to an abstraction. And so you’ve solved the problem in one part of your code, and you’ve kicked the can down the road to another part of your code.

>> Okay, all right.

>> So now you need to change something in that service class. Yes.

>> All right, do you wanna change the code, or you just wanna pass in a new object? Here is a better example, that might make more sense.

>> But aren’t you just kicking it down the road to the interface?

>> Hold on, let me say this. So EF Core now has an in-memory provider.

>> Mm-hm.

>> Right? And it’s great for unit testing. So, I’m using SQL Server in my real app. I don’t wanna write unit test, or actually touch in the database, cuz that’s really an integration test and that’s a different type of test. So, I can inject into my ASP.NET Core application a context that’s using the in-memory database, as opposed to SQL Server, and not change any of my code.

>> Okay.

>> So, I’m just injecting in a different database provider, cuz it all holds the same interface.

>> We’re digressing, let’s move on.

>> We are, let’s move-

>> You and I are having fun here but the viewers in that turned us on.

>> You know what? That’s what post-production for.

>> [LAUGH]

>> So, this could be a really short segment if you need it to.

>> I doubt it, and I’m probably just leaving it, so let’s move on.

>> Let’s move on, so everything is dry, right? It’s not one of Uncle Bob’s storage principles but it’s don’t repeat yourself. Anytime you have repeated code, you run the risk of introducing side effect bugs.

>> Okay.

>> All right, so I have always said if you write something once, think about making it a function. If you write something twice, please, please, please, make it a function.

>> Mm-hm.

>> If you write something three times you might wanna stop being a developer.

>> Okay.

>> Because if I’ve got, and you see this all the time with case statements, I’ve got a case statement over here, I’m gonna clipboard inherit it over here, which is an anti-pattern, right?

>> Yeah. You clipboard. And I changed it over here because I’m working in this code and I totally forgot I wrote it over here. So now I can make five different types of pizzas if I’m in this part of the code, but only four types of pizzas if I’m in this part of the code, right? So we really don’t wanna repeat ourselves. The Boy Scout Principle, this what we were talking about when we got to legacy code. So I’ve got this humongous app I’ve inherited. There are things in it, there’s 5,000 line methods called execute with 36 parameters. And if you want to eliminate all that technical debt, you’re gonna spend, who knows how much time, just re-writing code. And there’s some value in that, but not really value that can get translated to return on investment. So what you wanna do is if you have to go into that code, leave it just a little bit cleaner than you found it.

>> Okay.

>> So add some unit tests, maybe extract some methods, really easy in Visual Studio to pull out a method, right? And then add some more unit tests. Don’t fix it all at once. Just chip away at that debt. It’s like if you’ve got a mortgage, you pay an extra payment a year, you cut the life of your mortgage down by five years typically. So just the boy scouts always leave something cleaner than they found it.

>> Right.

>> Hence the Boy Scout principle.

>> Okay. Last is separations of concerns. All right, so I’m a Star Trek fan. Bones would always say, damn it, Jim, I’m a doctor, I’m not an engineer, or a weapon specialist, fill in the blank.

>> Right.

>> Here’s where we wanna make sure that our code is doing what it’s supposed to, and nothing else. And this is very similar to single responsibility, but it’s kind of more of a macro vision of it. When we talk about separation of concerns, let’s have a data access layer that’s isolated, so that if we don’t wanna use it in hibernate, and we wanna switch to Entity framework, all of this code doesn’t change, right? We’re passing in, we’re injecting in an i-respository, that now calls in hibernate or Entity Framework. And if you’ve got UI concerns, MBC’s a great example of that, right? We really have a good separation and concerns in that.

>> Okay.

>> Last thing I wanna show is just a quote. Phil Haack had this on an ALT.NET news groups I used to subscribe to years ago, but it’s such a great quote and it’s so powerful. When we talk about design patterns, so we’ve moved away from solids. Let’s talk about actually how you code in a solid manner.

>> Mm-hm.

>> And design patterns really help us to do that. The problem that I see so often and why I came up with this talk initially is people treat design patterns like dogma, like this is the only way you do it, right?

>> Right.

>> I have a hammer, now everything’s a nail.

>> And the best part of this quote, and your viewers can read it, but I love the fact that he says, the goal is not to bend developers to the will of some specific pattern, but to get them to think about their work and what they are doing.

>> And if you just look at the second part of his statement, to get them to think about their work and what they are doing, that’s what we really want people to do is stop and think, right? Programming is not a typing exercise.

>> Right.

>> It’s a thinking exercise.

>> Okay.

>> So, how can we apply critical thought? How can we learn from others and write cleaner code?

>> Okay. All right, so let’s dive into some code and talk about some. Certainly not all of them, we would be here for days, if we wanted to talk about every pattern there was. This code’s all available in GitHub, it’ll be in the show notes. And I have unit tests around them and I do that for a couple of reasons. I’m pretty fanatical about testing code. But the other reason is, if people wanna download the code and play with it and tinker with it, if they break the unit test, they broke the pattern.

>> Okay.

>> All right, so you’re building a website and you’re gonna use any framework, and firing up a context is the most expensive part. The context that creates the connection, it checks the database, makes sure everything’s in order. So it’s kind of an expensive operation. For most people, not that bad, right? But it’s something that you wanna do on every single database call. So that’s something where you might wanna create a singleton, and a singleton by definition means there will only ever be one of these things in existence per app domain.

>> Okay.

>> And for most of use we just deal with app domains. I mean if you’re doing some multi-threaded stuff it gets a little more hairy. But the way you implement a singleton, or the way you recognize a singleton is here I’ve got two different variables. They’re both set to this singleton instance, and we’ll talk about that shortly. And I’m just running a test. I say, assert that they are the same. Now, AreSame in unit testing means that they are pointing to the exact same item on the heap.

>> Okay.

>> Right?

>> Change the value on one of them, and I make sure that they’re equal on both. So that’s the symptoms, that’s the result of having a singleton. Let’s look at how we build this. And like I said, it’s a very simple pattern. We create a private static instance of the class we’re building and you’ll see in all my demos the names are terrible. I’m really bad at naming things. But the three hardest things in software development are Naming conventions and off by one errors.

>> Uh-huh.

>> We also have this _synclock object. Now I will say there are several different ways to implement Singleton, this is just one, right? A dead giveaway is a static property called Instance. That’s just a convention, not required for the pattern. And then what I’m doing is, I’m checking if the Instance is private static incidence variable is not null, then I’ve already created one, and I can just return it to the calling code. If it’s not already been created, I put a lock, okay, so this makes my code single threaded. If you’re not familiar, I know you’re familiar with locks. If some of your viewers aren’t familiar with locks. And then we do another check to see if it’s null. The reason we do this, is we’ve got multiple threads coming in potentially, get gated by the lock. One gets through, followed by another one. So now they’re single file in line. If this one creates a new instance, and we’re not checking again to see if it exists, this one could create a new instance as well.

So we just throw in our lock and then we simply make the Instance, a new Instance of the class. We’re off to the races. And that’s all there is. So this helps with cutting down in repeated code, and making sure that if you have to have state across different calls, this will do it for you. So like I said, a very simple pattern. The next thing I wanna talk about, and I use this a lot, is the SimpleFactory. And a SimpleFactory is usually used to instantiate different options. So for example, let’s say we’re creating a pizza factory. And I have to give a shout out to Head First Design Patterns, it’s a book. It’s a very, very good book and we’ll put it in the show notes as well. Some of their examples I leveraged for this talk, and one of them is a pizza store. So let’s say we wanna make a different type of pizza. We could put an if then or a case statement everywhere where we’re creating a new pizza in code, but then we’d be repeating ourselves. So we can encapsulate that in a SimpleFactory.

And it’s called a SimpleFactory because it really is very, very simple. A lot of times it’ll be just a case statement.

>> Okay.

>> Right, and we call into this. Now in real code, I wouldn’t just statically create these things. I’d be calling a new database or whatever I’m doing, right? But let’s say, for example, that I run an e-commerce site, and we’re going to try and get different shipping methods, right? If you’re going to Amazon and you buy a book, they’re gonna pack it in a box. If you buy a steak, they’re gonna pack it in dry ice. If you buy something fragile, they’re gonna pack it completely different. So I can get a new instance of that packing class just by using SimpleFactory. Now according to the gang of four, it’s not an official pattern, so I just have to call that out. Me, I’m more pragmatic than academic. So it doesn’t matter to me that it’s not an official pattern. We’re gonna jump ahead to combining the FactoryMethod in the AbstractFactory.

>> Wait, go back.

>> Yeah, certainly.

>> Make sure everybody understands why you’re creating the factory, what’s the difference between those methods?

>> Yeah, certainly. So here in this SimpleFactory, all I want is one place where I can create things. So it’s sort of like your service class, right? You were creating, we were talking about it earlier with the pen scene injection. If we’re creating something, we wanna have one place to create it. So it’s a single responsibility. The factory’s job is just to create things. It doesn’t use them, it doesn’t do anything other than say, hey, I need one of these, and throws it back to the code.

>> Okay, so the IPizza is a pizza. So every pizza is similar.

>> Every pizza, yes.

>> And they’re represented by an IPizza, which looks like what?

>> Certainly. Yep, sorry. We’re on a little bit of a time frame so I was, hey, not hitting that button. We’re in a little bit of a time frame. And so I just wanna say, here’s an IPizza.

>> Okay.

>> It’s got some toppings. It’s got a dough type seasoning, sauce type, and then it’s got some methods that expose this.

>> All right, got it.

>> And those methods will come into play when we expand.

>> Yes.

>> So although there are, depending on the type of pizza you want, you go through a different path but you always return an instance of IPizza.

>> Yes.

>> And that’s why you created a factory like that.

>> Yep.

>> Instead of having four different classes, potentially, for the different pizzas or four different methods and different places.

>> Yeah, and this is just the substitution principle, right? I wanna be able to program to an IPizza. The pizza’s gonna have toppings, it’s gonna have a dough type, you have to cook it, cut it, those type of things. If I had a cheese pizza and a pepperoni pizza class, well, that’s easy. But now let’s say you’ve got 36 different toppings. Let’s say you work at Starbucks, right. And it’s not pizza, but think of all the different combinations and variations of coffees you could order.

>> And when you get right down to it, it’s all the same thing. It’s liquid in a cup.

>> Yep, yep, absolutely.

>> Okay.

>> Thank you for-

>> Delicious liquid in a cup, of course.

>> Absolutely.

>> Let’s not downplay the awesomeness of the experience.

>> Yep, I’ve got my Starbucks up. I’m on band.

>> [LAUGH]

>> All right, there’s two other factory patterns that I typically combine into one, and it’s the AbstractFactory and the FactoryMethod, okay? And it’s easier just to explain holistically how it all works together than to go into the minor details between it. So let’s say we have this, different types of pizza stores. And we’ve got a New York pizza store, and we wanna order a localized pizza. Now New York style pizza is very different than Chicago, right?

>> Yes, yes, it is.

>> And we want a pepperoni. And then we’re just going to assert that it’s a thin dough, it’s a red sauce, and it’s spicy. And so we have a Chicago pizza store.

>> You forgot greasy. [LAUGH]

>> Let’s be nice.

>> I am being nice. It’s good.

>> So a Chicago pizza store and we want a sausage, and it’s gonna be deep dish and tomato, basil, and mild seasonings.

>> Yep.

>> Which can all be changed, but these are just the defaults. Now here’s the important thing. Let’s think about, I have a pizza franchise, right? Or I’m Uno, right, Pizzeria Uno, and I want a franchise or have people franchise my store. We want to control certain things. For example, the order of execution,. So we want them to make the pizza, cook the pizza, cut the pizza, well, actually, there you go, I just messed up the order. Put it in the box, then cut it, right, and then deliver it.

>> Right.

>> If you get that order wrong, bad things can happen, right? You can put all the dough and all the toppings in a box and put it in the oven and light your store on fire. So there’s certain things we wanna control, but certain things we wanna give them flexibility, too. And this is also.

>> And Chicago pizzas are typically not cut first. They just put them in the box.

>> Well, it depends. So the franchise by me cuts it. So not first, but they put it, anyway, we’re getting totally squirreled here. So let’s look-

>> Well, you’re bringing up pizza, what do you want? I like pizza.

>> I know, but that’s why I talk about things that people can relate to, right? So I used to give demos on more businessy-type things. And so like if I was talking about-

>> Expense reports.

>> Banking here, or expense reports, somebody’s going, that’s not how expense reports work. And we get totally lost in the domain as opposed to just looking at the code. So we’ve got a pizza store. And if we look at the pizza store base class itself, it’s got the ingredient factory, and the base ingredients, just, it’s very simple. We’ll talk about those. But here’s what I wanna talk about, the OrderLocalizedPizza. So this combines the factory pattern with the command pattern, which we’re gonna get to a little later, where we say, create your localized pizza. I don’t care what type it is, right? So the inherited store will make them more New York style, West Coast, California pizza style or Chicago. And then we wanna control the order.

>> Okay.

>> And then we’re gonna return it. Now, where this really comes into play, let me go back to that whole e-commerce site. Right, you order something, and you put your money in, and then a couple of days later it shows up on your door.

>> Right.

>> So if you order a book, they’re gonna first all, make sure that it’s in stock. Pack it, well, pick it, pack it, ship it.

>> Right.

>> Right? Same thing with no matter what you order. Those exact commands happen. But how do those commands get executed? Very, very different based on what you’re ordering.

>> Okay.

>> So we wanna control the order, but not necessarily the exact functionality. But we also wanna make sure that the store, the base store, doesn’t care whether you bake it at 350 degrees for 30 minutes or at 400 degrees for 12 minutes. It just says bake.

>> Okay. All right. There’s a lot more we could talk about that, but let’s get to some other patterns.

>> Okay.

>> Let’s talk about the adapter. We’re now moving into structural patterns. So what we’re talking about work creation is three main types. I probably should have said that, structural, behavioral and creational.

>> Okay.

>> So this is structural. So the adapter pattern is also hugely helpful. So if you’re old enough to remember two-prong outlets in your house. I don’t think they build them any more. But invariably, my dad would come home with something that had a third prong, and I’d have a two prong outlet. So we did what everybody done, broke after third prong and plugged it in, right [LAUGH]? But what we were supposed to do-

>> We just plugged it into a three to two.

>> Plug it into an adapter, take the little wire-

>> It’s just the ground, it’s not that important.

>> Attach it to the, Yeah. In software, we do the same thing with an adapter. We make something appear to be something else to make it easier to code, right? Let’s go back to that whole e-commerce thing when they’re switching out. We just wanted to check a credit card to see if it was valid. And then we want to charge it, and we want to check the address, all right. We didn’t necessarily care how all that happened. We just want to be able to call that, and not fight the different names.

>> Right.

>> So let’s say we’ve got three types of cartoon characters. We’ve got a moose.

>> Yes.

>> And we’ve got a flying squirrel.

>> Yep, moose and squirrel.

>> And we’ve got a bad guy.

>> Okay.

>> Okay? Now the problem with the bad guys and the squirrels and the meese? Moose? Moose.

>> Meeses.

>> Meeses, we’ll call it meeses. So a bad guy can only do two things, it can drive and it can shoot, right? If we look at the flying squirrel, it can only do two things, fly and drop acorns. And if we look at a moose, it can run and it can charge.

>> Okay.

>> Right.

>> But now we wanna operate-

>> It can also do magic tricks.

>> They can do magic tricks, too, I should add that in. That’s not part of the interface, so that’d be an extension as opposed to a modification. So if we look at these, we can certainly work on them in a list. So if we’ve got one squirrel, one moose, and two bad guys, we can put them in an array list which is not strongly typed. And then if we want to act on them, we would say okay. If object is of type, then call this method. But then every time we want to act on those, we have to remember to translate those methods into something that makes more sense holistically. So what we want to do is we wanna make them all look like an ICharacter.

>> Okay.

>> And an ICharacter has three methods, chase, flee and attack, so we wanna map those.

>> Mm-hm.

>> So the way we do that is by making adapters. Now I will say from assuming responsibility standpoint, I’ve broken things here. Because I have multiple interfaces and multiple classes in one file. Really not a good idea for supportability and maintainability. It’s demo code, it makes it quicker to get from one to another.

>> Okay.

>> So I did want to point that out. So, The way we turn a moose into an Icharacter is we have this MooseAdapter class. So we inject in an Imoose, right, we’re always coding to an interface. So we don’t care which moose it is, right. It could be something that derives from Imoose, right. It could be baby moose, it could be Bullwinkle, it could be Bullwinkle’s wife.

>> Okay, so right here-

>> Yes?

>> In this application, you have a moose.

>> Mm-hm.

>> So you could pass in moose.

>> I could.

>> Now the benefit to passing in IMoose is that you are pre, you’re getting ready for if, in the future, you would ever have different types of meeses, or mooses. Meeses, are meeses the plural of mice? I don’t know. Mooses, [LAUGH] right?

>> Bullwinkles.

>> So In this instance right here, that’s just a, it’s not 100% necessary immediately, right? Because it’s instead of dealing with a moose, you’re dealing with a moose and an IMoose. It can seem like you’re overcomplicating, given that there is a moose. Is that correct?

>> Well, so-

>> Or what would you say to somebody who says that to you? So.

>> Because that’s extra work, what am I gaining?

>> Well it’s not a whole lot of extra work. I’m really just saying IMoose instead of Moose.

>> I know.

>> There is the YAGNI, right, you ain’t gonna need it, right? So there are times when you want to just back off a little bit.

>> Okay.

>> What I have found with things like programing to an interface is it never hurts.

>> Okay.

>> And quite often comes in handy.

>> Okay.

>> So there are things that I would consider overkill, like using an IOC container, inversion and control container. Which when your viewers download the code, I use Unity, not the game engine, but the IOC container that Microsoft wrote. To do some of this in the longer version of this talk.

>> Right.

>> Right.

>> Even a classic example is MVVM where even though the standard is that you name your view model after the page. And then, in the page you instantiate a version of the view model, right? You don’t do that, you use a view model locator.

>> Right.

>> Which you’re in the customer page. You’re going to call the customer view model. That’s the convention, right? And then, there it is under view models, customer view model. So you might ask yourself, why am I going through adding all this complexity of a view model locator, which I now have to learn how to use? It’s not a problem getting one, there’s plenty out there. But now I gotta learn how to use it when I’m in the moose page. And I’m gonna call the moose view model, let’s move on.

>> Right, so there’s a couple things to that. And I totally agree that a lot of times, using those locator is overkill. If you’re moving to .NET Core-

>> Right, so somebody could argue that this is overkill.

>> They could argue.

>> Okay.

>> Right, and in this particular code example, I couldn’t really refute that, right? I could easily change this to that.

>> Right.

>> And it wouldn’t break the code, it would work just as well.

>> Right, so the question is, what’s to be gained by switching into the habit of calling the interface in these simple type of examples?

>> If you get in the habit of always coding to an interface, then when you have to start paying back that technical debt, then you can start injecting different things. You can use mocks to unit test, right? So I could write a unit tester about this entire adapter, and not have a moose class.

>> Right, okay.

>> I can create a mock representation of an IMoose, put it in here and make sure that this code works. And I actually have unit test with mocks in here to show how to do that.

>> So that’s interesting. So in an application we you’re calling data, it would make it a heck of a lot easier to use fake data while you’re developing.

>> Absolutely, yeah.

>> Because you’re bringing in an Imoose, and your real moose, which calls the moose factory, which then goes out to the database and brings stuff in. Or, you’re passing in the mock Moose, which is just hard coded data, sample data so that you can.

>> Yeah, and my unit test wants to make sure that if I call Chase, it’s really calling the run method on the moose, on the IMoose.

>> Right.

>> Right, and not actually executing it. What if the run method was charge credit card?

>> Right.

>> And I had to pass in a real credit card number, and it would charge it.

>> Right.

>> Right, but I could bring in a fake credit card processor and just assert that that method was actually called through the mock framework.

>> Right, okay, cool.

>> But from a strict coding standpoint, in this example, you could argue that you don’t have to code to an interface. But if you do get in the habit of coding to an interface, it’s very little overhead, if any, and it’s just a good habit.

>> Well, I’ve seen these types of talks quite a bit. And I think they sometimes tend to just focus on the mechanics of what you’re doing without stopping to remember that you do it this way, there are potential benefits.

>> Right.

>> Which you may or may not realize in this particular example. But if you understand now, I see. This will make it easier in the future for me to do something like this. And it’s one more letter, IMoose versus moose. It’s worth setting yourself up for being able to take advantage of it if you then understand what the benefit is down the road.

>> Right, absolutely, and actually, several books have been put out by some of the software luminaries that say you shouldn’t use the IMoose name, you should just call it moose. Because everything should be an interface. And it should just be assumed that everything you’re talking to is an interface. We’re not there yet as an industry. Speaking of mocking and testing-

>> Yes.

>> Look at this, right? So I have my IMoose, and I’m creating a mock, which is just a proxy around the IMoose. And I’m saying the behavior is strict, and I’m using the free version of JustMock for this. And what behavioral strict says that if I’m calling something that doesn’t exist.

>> Yep.

>> Like if there’s a method that I try and call, it’s gonna throw an exception.

>> Yep.

>> So I arrange that when I call Charge, it actually is going to return 10, and it must be called. So this says if anywhere in this test Charge is called, return 10. And I’m saying it had to be called, right? So this is an expectation. So I can go then, assert that these things were called appropriately.

>> Okay.

>> So I’m testing my adapter without having to have a real moose.

>> Right.

>> All right, so I have the different adapters here. Flying squirrels maps it to one thing to another. And the other reason I like adapters is not just We don’t normally program around Bullwinkle and Rocky and Natasha and Boris. But a lot of times, we have legacy code we have to call into. Or we have something in the framework that’s difficult to use. Or we’re using a third party app that is confusing, but it’s mission critical. I can write an adapter around that to simplify it. And I’m gonna show. Actually, you know what? Let’s just go on to the facade because a facade is very similar to an adapter. But the difference between the facade and the adapter essentially is an adapter is I’m taking one thing and shaping it to look like something else. And a facade, I can take many different things and make it look like one thing, right? So let’s say that I’ve got, This class that implements IConfusing and IOverdone. So IOverdone, again, just made up names. But we’ve got this business critical assembly that we have to call into.

>> Okay.

>> And we’ve got these wonderfully meaningful names. DoSomething, DoSomethingElse, and DoSomethingAgain with x, y and z. And, oops, I ran out of letters. I have to start over at a, right? Not very maintainable code. This would be significant type of code debt in my mind. And we got this other one, it’s IConfusing. And it’s a great feature. So we’ve got Execute, always a great name for a method. Method1, Method2 is just somebody learning how to use Visual Studio to add a new method. And then another Method2 as an overload. Well, I’m calling into this all the time, right? I have to because that’s the way my workflow goes. But now what I have to do is if I want to remember which one of these methods I should call. I either have a bunch of post-its on my desk. Or I have to use reflection or reflector or some tool. Then I look at the source and see what it is. So what we want to do is we wanna build a facade. So somebody has to bite the bullet. And take the time to learn which of these methods we need.

And call them something better, and wire them up. So we really need these two methods and our overload. So AddThreeNumbers, AddThenMultiply for some different items. So when we build this class, We’re just going to call into the methods on the body classes.

>> Okay.

>> So that as I’m coding and I need to add three numbers, I just say, foo = new betterAPI foo.AddThreeNumbers.

>> So the facade’s just the middleman, basically.

>> Yeah, it just cleans it up, makes it nicer, easier to use.

>> Okay.

>> Right? All right. Decorator is absolutely awesome. I wish I would have known this a long, long time ago. I wrote an application, it’s still in production. And it’s a configurator for high end bicycles. And it’s all written in JavaScript, long before we had all these great JavaScript frameworks, those plain old JS. And it’s easily, I don’t wanna say it out loud, 5,000 lines of JavaScript. If you pick this frame, then I go through and say, well these are the tire for rims that are available. These are the brakes that are available. And just imagine a tree, configuring a bicycle from the ground up. And I actually volunteered to rewrite it for the guy for free, just to get my name off of it, right? Cuz it’s in JavaScript, so anybody can look at the source. There’s so much better ways to do it. And this design pattern is phenomenal. It’s called a decorator. And what we do is we take a base something and we decorate it. Let’s go back to Starbucks, right? You start with some coffee.

And you’re gonna add some syrup. You’re gonna add cream, whipped cream, change temperature. All these different things that can affect the price.

>> Yep.

>> So instead of having one class for every single combination, let’s just have an ICoffee interface. Or in this case, an ICar interface, and let’s decorate the car. So let’s say I was watching. Sometimes I write demo code.

>> Explain what that means.

>> All right, I will.

>> Okay.

>> But I also have to just say that I was watching the remake of Speed Racer when I was watching this, so hence the cars. So I have a base car. And it has a drive, attack and defend basically hit point value, okay? Let’s say I wanna have an armored car. The armored car drives a little slower, attacks the same. Doesn’t change from the base car, but it defends much better.

>> Okay.

>> All right, let’s go down and look at the race car. Obviously, it’s faster, doesn’t attack as well. It’s lighter, doesn’t defend as well. And then an attack car, right? So we go through. So if I’m building the classes to support making the movie, Speed Racer, this is very simple. We could all do this. We’ve got different styles of cars.

>> Okay.

>> But halfway through the movie, Speed Racer says, well, I gotta double armor it. I’m gonna soup up the engine, and I’m gonna put better guns on it. Was this another class? Think about all the combinations that you would have to come up with.

>> Right.

>> So instead of creating a class for each of these options, we decorate it. The way we decorate it is let’s look at the armored car. Is all of them implement ICar, right? Which has drive, attack and defend. And we pass in an ICar into the constructor. And we’re gonna decorate, we’re gonna armor this car. We’re gonna put some more plating on it. Well, because we’re adding additional plating, the drive speed decreases. But the defense power increases. And we’re not modifying the attack vector.

>> Okay.

>> If I look at the attack car, we do the same thing. We pass in an ICar. And it doesn’t drive quite as fast. But it attacks much better and its defense is lower.

>> Okay.

>> So I can take my base car, factory standard. And I’m going to pass it into an armored car decorator, put some armor on it. I’m gonna do it again, put it back into an armored car decorator, put some armor on it. So what I’m doing is I’m creating these circles around it. So I’m just assuming an ICar. This doesn’t know that this attack car decorator has no idea what the ICar already has.

>> Mm-hm.

>> The trick here is that we’re not setting values, We’re decorating the values, right? Taking a little decoration off, adding a little decoration. Taking the thanksgiving decorations down, putting the holiday decorations up, right? You’re not changing your house, you’re just decorating it.

>> Okay.

>> So that’s a phenomenal pattern, I think. Especially because it would have saved me so much time in the configurator.

>> And if you didn’t do that, then you’d have to create a car. And then you’d have to manually set all the properties.

>> Right.

>> And remember what the rules were for setting the properties. And now you’ve got just all those properties all in one place at the same point you created the car. So you’re not getting separation of concerns. You’re not getting much reusability.

>> Right, you’re not getting any reusability. And let’s say that I wanna-

>> And it’s really easy to mess up.

>> Right, and let’s say I wanna armor it three times.

>> Yeah.

>> Well, now I have to create yet another class. And then remember that one I armor, well, this is the attack. Let’s say, okay, so when I attack, I increase it by 30. Well, what if I’ve forgotten and then I increased it by 40?

>> Right.

>> Right?

>> Yeah.

>> It just creates some kinds of-

>> Next time you wanna create a double armored car in a different part of your code, you gotta copy that code. Create the car again, and then copy all of those properties.

>> Yep.

>> Or extract that into a method. But now you’ve got multiple different methods for every time you wanted to do it differently. Yeah, it’s a mess.

>> Yeah, and that’s about the time that you update your resume and look for a new job.

>> [LAUGH] Or you learn how to do this.

>> Or you learn how to do this. There’s only a couple more patterns.

>> Okay.

>> The command pattern, really, really simple. And I demonstrate how simple it is. The command pattern always has a controller that calls the commands. Think of a remote control, right? You’ve got a remote control and in part, it says cable, TV, DVD. Or VCR if it’s an older one. And you push that button, push the VCR button, and the VCR turns on. Push it again, it turns off. The remote control has no idea how to turn on that VCR, right? It sends a command. The VCR recognize the command as, I need to do something with this. So I’ll turn it on.

>> Right.

>> So here, I have a very simple control. I’m sorry I should point. This doesn’t help your viewers. So I’ll point to this very simple controller. I’ve got a Light. And I’ve got a LightCommand. The LightCommand is very, very simple. It just, if the light is on, gonna execute it, turns the light off, right? But first, so you can also do undo. But then with undo, you have to track the commands are executed. So this is just a very simple example. And then the controller literally, all this do is controls. Now, remember when we talked about the factory pattern. We have some commands, bake, cut, box. When we talk about e-commerce, pick, pack, ship, charge your credit card, those are just commands. So if your controlling code doesn’t have to know anything about that, and says by the way, they ordered this item, go pick it, right? And it gets send to some other system, and the system says here’s this queue. It’s a book. I can pick up manually, or automated, with a robot arm.

It’s 1,000-year-old vase. I’m gonna send a human to go grab this very carefully and pull it over. Your calling code has no idea what’s going on, right? So now you’ve got separation concerns. You’ve got pseudo responsibility.

>> Yep.

>> I am responsible for picking this. I am responsible for packing this, I’m responsible for shipping, right? So when you start combining these patterns together, you get much cleaner code, and much more sensible.

>> Yeah.

>> So now we’re gonna start selling boats on Amazon.com, which is a whole different style of delivery.

>> Right.

>> But you’re UI, the code that controls the commands and the work flow, doesn’t care, right?

>> Mm-hm.

>> Now I extend it, I create this new set of commands. And I can keep building onto my site.

>> Very good.

>> All right. The last one, strategy. So the strategy allows us to change the functionality of something at runtime. I mentioned log4net earlier and we were talking about DI. And really it’s a better example of the strategy pattern. So the strategy pattern says, I’m doing something. I’m gonna get some sort of input and I’m gonna do something different, right? Log4net, no logging. Now, there’s a problem on your production server. I’m gonna crank logging up to eleven, which hits performance, but it gives me all his data, then I can turn logging back off. Now I go analyze the data.

>> Okay.

>> Right? Cuz one of the problems we always have is what works on my machine, I can’t reproduce the problem.

>> Right.

>> So, what we’re going to do here, is we’ve got some superheroes. They all have different powers. So Spider-Man, we all know weaves webs. Superman flies. Batman fights. And if I could do italics, right, cuz Batman would fight.

>> [LAUGH]

>> Going old school a little bit. And they’ve all got these powers, right? And that’s fine. But let’s go a and look at Peter Pan. Not Peter Pan, Peter Parker. And so Spider Man is going out to meet the bad guys. And he’s shooting his webs. And what happens is as soon as he sees Maryjane, his web slinger jams. So he was to get a new super power. He can’t go time out. I’m gonna go back to my aunt’s house and change my super power, come back. Well, the bad guys are gonna be gone, right? So in the middle of the fight, he has to switch what he’s doing, right? So now he has the new fight super power. And he doesn’t really fly but he can jump up buildings. And then if his web slinger’s working, he can go. So this is awesome. So to do’s are our codes now. This to do’s probably been in here for four years. And every time I get to this point, I’m like, I need to fix that. And then I forget. So that’s great. Again, we’re not writing software about Rocky and Bullwinkle or Superman or Spiderman.

But let’s say we go back to this e-commerce site. And there’s a power outage on the east coast and our cheese factory’s on the east coast. And the cheese is gonna melt. Not melt, go bad, right? And so we want to change the price of cheese without deploying a whole new release. So through this strategy pattern and the commands, right? So pricing is one of those things, so I’d say give me your price. Again, you front end knows nothing about how to calculate prices.

>> Right. But cheese knows how to price itself. You change that capability at run time. And we can do that through dependency injection. So we can just create a new assembly, or a new configuration. Really, what do we do in real life? We change the database value. But what are we doing when we change the database value? We’re changing the way something operates at run time. So that’s an example of using this pattern. And we only want this sale to go on until the power comes back on. And when the power comes back on, we wanna immediately go back to our normal pricing.

>> Okay.

>> And we don’t wanna, again, have to deploy a whole new site to do this. We wanna be able through configuration, through the version IOC containers, be able to change things at run time.

>> Okay.

>> So that’s the last one I had for you to show today.

>> Cool, so do you have for each of these examples of the old way of doing it, and then how you would do it once you adopt these patterns? Do you do that?

>> That’s a great idea. I don’t have that.

>> [LAUGH]

>> Excuse me.

>> You should think about that.

>> What I recommend people do is get a book like they had first designed patterns book and read them. And go out to something like Project Euler, E-U-L-E-R. Which is just a bunch of Math problems and program them and just do code as code cutters, right. Practice writing the code, delete it. Practice writing the code, delete it. Cuz what we want you to get to is the point of where to borrow a matrix reference you won’t be able to see the lady in the red dress.

>> Mm-hm.

>> One thing that I use design patterns for, when I’m running teams, is when we’re talking about how to design a system, I don’t let people use a white board. Cuz as soon as you give an engineer a dry erase marker and white board, they’re off drawing shapes and figures and naming things, right?

>> Right.

>> And you get totally down a rabbit hole. But if we can just sit back and talk about, well, how would you build this as the configurator? Well, should we consider a decorator? Well, yeah. Okay, we won. What’s the next thing that we have to design, right? And so it becomes a language, a way of communicating without going into all these great details.

>> Mm-hm.

>> So, just practice. You know what? I’ll probably add some examples of the bad way of doing things. I won’t say the bad, the not as optimal way of doing things.

>> Okay, I’ll go back and look at a couple apps that I’ve built and see if we can come up with some examples. Maybe we’ll do a follow-up show.

>> Yeah.

>> Where we’ll actually show-

>> Refactoring and.

>> Yeah, refactoring, right and then why.

>> Yeah.

>> Okay.

>> That’d be great.

>> Cool. Well, thanks for having me on the show again.

>> Thanks for coming on.

>> Yeah.

>> All right, hope you find that very useful and let’s make this the beginning of the conversation.

>> Sounds good.

>> And we will see you next time on Visual Studio Toolbox.

>> All right, take care.

 

Read the video

In this episode, Robert is joined by Phil Japikse for a chat about design patterns. Software design patterns have been around long before the MVC Framework gained momentum. Phil starts with a review of Robert C. Martin’s (Uncle Bob) SOLID macronym. After building the proper foundation,he reviews several design patterns, their C# implementation and when and how they should be used in modern software development.

Get the code samples here.


Comments to SOLID Design Patterns

  • This discussion/topic is extremely important. There is not enough time in this video to approach it with the proper depth.It is very nice that Channel 9 is opening some space for the principles and practices preached by Robert Martin.Code quality and being a better coder is in the very heart and soul of this channel, I think Channel 9 should dedicate more time to that subject. Good tools helps, but does not make you a good or better developer. Those principles do.Maybe start a series to discuss those topics, one by one, with the proper importance and depth.

    Andre Vianna January 11, 2017 9:48 am Reply
  • @Andre Vianna: That is an excellent idea. Would love to hear more about what you think this series should be. You can reply here or email me. My alias is rogreen.Robert

    rogreen January 11, 2017 12:05 pm Reply
  • Agree with Andre. Maybe a series where you develop a practical application from start to finish. Thanks!

    David Rimshnick January 11, 2017 9:41 pm Reply
  • @rogreen: Excellent idea. I will spread the series in our local community. There are tons of resources that talks about the principles in general, but I would love to see it as close as possible to C#, .NET (Core), ASP.NET MVC or UWP.

    Liero January 12, 2017 12:07 am Reply
  • @rogreen, it could be very useful series. I like your idea to talk about refactoring next time. Keep going and thanks!

    resnyanskiy January 12, 2017 1:36 am Reply
  • I agree with the others that a dedicated series on patterns and practices would be valuable especially one targeted at .NET (Core) and ASP.NET. I’m particularly fond of juxtaposing a kind of before and after that highlights how following a particular principle makes the code cleaner, clearer, more testable and ultimately easier to maintain.Too many sample applications are done in a way that would not be acceptable in normal practice, a comprehensive end to end example with refactorings as it progresses would make for an excellent resource for novices and students.

    AndreArtus January 12, 2017 4:57 am Reply
  • Yeah this stuff is brilliant. So good to see Uncle Bob's actually being given the proper respect he deserves.

    Chris R January 12, 2017 5:54 am Reply
  • Should start a series to discuss the topics like design patterns and refactoring technique (book from Martin Fowler)

    Dev_Raj January 12, 2017 8:00 am Reply
  • Nice job, I found it very useful and pragmatic.

    majidrafigh January 12, 2017 11:46 am Reply
  • Nice episode ..@rogreen is the demo will be shared on GitHub?!!

    Hishamco January 13, 2017 6:21 am Reply
  • Totally agree with Andre. It will be nice to have one by one episode with some app example. Thank you for this!

    AlmirVuk January 13, 2017 12:20 pm Reply
  • Robert and I are in discussions about more episodes. Thank you everyone for your kind words. The code for this presentation is on github in the https://github.com/skimedic/presentations repo.

    japikse January 14, 2017 5:07 pm Reply
  • Thanks @japikse

    Hishamco January 16, 2017 2:52 pm Reply
  • I gave this a shot with some videos. Please see below for a link to my humble attempts. I *really* like this idea and I hope to see it take off on Channel9 as your production quality is much higher than mine. ;)I can tell you from my experience that there are plenty of hungry developers out there that want to know more about the craftsmanship side of things. For example – the cookie cutter entity framework examples you find are great but it’s something special when you mix EF with yield and an iterator pattern. Then you naturally find yourself thinking about how that might work when async/await is involved. Great conversation topics even for experienced developers.There’s so much in .NET/C# that allows you to write really good code quickly that few people know how to take advantage of!https://www.youtube.com/user/DRYByDesign/videos?view=0&shelf_id=0&sort=dd

    AriUgwu January 16, 2017 6:49 pm Reply
  • LOVE IT!

    Xterminator January 18, 2017 12:28 am Reply
  • Excellent video. It could be expanded so more details are discussed. Overall very helpful as an inroduction or a refresher.

    pquintero January 18, 2017 6:36 am Reply
  • Very good topic and would love to see more like this on patterns and practices.  Thanks Phil

    dyardy February 2, 2017 7:33 am Reply
  • Terrific video. A lot of information covered for someone like me who is new to these concepts. Phil’s explanations were good – I need to review parts of the video and look elsewhere for more detail, but I understand this was only a whistle-stop tour in the time available.Robert’s questions were very valuable and often exactly what I was thinking – why do it this way rather than the "old" way. The questioning about a service class versus an interface was particularly intriguing and not sure we got an answer in the end why interface is better.Thanks to both Robert and Phil for this video. A followup video (with examples of refactoring old code as suggested) with more details and showing why these approaches are beneficial would be most welcome.

    JamesA99 February 11, 2017 9:05 am Reply

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...
1Code.Blog - Your #1 Code Blog