Coding Blocks - SOLID as a Rock!

Episode Date: March 3, 2014

This week we tackle the SOLID principles in .NET and discuss the eternal struggle between perfect code and looming deadlines. Please leave us feedback in your Podcasting app of choice! Update: Great c...omments/debate on reddit! About Solid SOLID Principles for writing maintainable and extendable software Michael Feathers and “Uncle Bob” Robert Martin May be impossible […]

Transcript
Discussion (0)
Starting point is 00:00:00 You're listening to Coding Blocks, Episode 7. Subscribe to us and leave us a review on iTunes, Stitcher, or more using your favorite podcasting app. Visit us at CodingBlocks.net where you can find show notes, examples, discussion, and more. Send your feedback, question, and rants to comments at CodingBlocks.net. And be sure to follow us on twitter at codingblocks and with that welcome to codingblocks i'm joe zach i'm michael outlaw and i'm alan underwood and today's show is about solid solid wait is that soiled that's all right yeah i'm glad they went with solid and so the soiled yes It would have been a lot more interesting.
Starting point is 00:00:46 So SOLID is an acronym. It's five letters that were come up with by this guy, Michael Feathers, who if you live under rock and haven't heard of him, he's one of the object mentor guys. He's internet famous. He wrote Working Effectively with Legacy Code. He's kind of a big wig in the programming world. And he came up with this term SOLID as an acronym for kind of some rules to follow for creating good, well-designed software. And object-oriented.
Starting point is 00:01:22 Object-oriented, yeah. And well-designed means that it works. Yes. So what exactly... Wait, I was right? So, I mean, what exactly does well-designed code mean, though? Right? To me, it means easy to change successfully.
Starting point is 00:01:38 And what about reading and maintainability? That's debatable. Yeah. That's not really debatable it's got to be easy to read right but um as we talk a little bit about this um a little bit more we're gonna see that a lot of the principles that these five letters stand for end up with a lot of typing initially but uh i'd like to argue that the initial writing of something isn't that important because you're going to end up reading it and maintaining it, you know, 100 times over what it takes to originally write the code. Yeah, and before we get into this whole thing, because this is something that's repeated throughout, a lot of these solid principles, they actually state that you don't necessarily want to do these starting out. Because when you get into these things, you'll find out that you end up writing a lot more code to do them.
Starting point is 00:02:29 So the whole idea is there's this fool me once, shame on me, fool me twice, shame on me. So the whole idea is if you find a need, then start going in and refactoring your code to follow some of these principles. Now, some of these principles you want to try and adhere to as much as possible, but others really do take a lot of work to get into. So that's just kind of, you know, prefacing what we're about to get into. Well, yeah, I can't speak, speaking from my own experience, a lot of times it's more, there's so many times where it's just exploratory what you're doing. Yes. So you don't always have a clear
Starting point is 00:03:06 cut class library in in mind that you're going to write out yeah so it that's that's just a forewarning you know these are things that you should try to adhere to but um as we get to some of the principles we'll mention those specifically as to um you know which ones you're probably not going to just start out writing that way. Right. And I would also mention that, you know, these are five principles for writing well-designed code, but there are other principles too, like Alan talked about Yagni, you know, you ain't going to need it. And there's also this rule of three that Jeff Atwood recently mentioned in a blog post,
Starting point is 00:03:40 but basically the more reusable and well-designed something is, the longer it takes to write and initially maintain. Yeah, and there's also DRY, don't repeat yourself. I mean, there's a lot of principles out there, but this is a pretty good one. This is fairly encompassing, so that's why we chose to go with this. Because it's solid. It's solid. And speaking of DRY dry specifically the first principle
Starting point is 00:04:06 the the s stands for the single responsibility principle and um this actually um is one i struggle with a lot specifically when it comes to dry because if i've got these classes that only have a single responsibility only one reason to change and i have a lot of classes then a lot of times some of these classes end up kind of looking similar to other classes and it's because these classes don't know about each other not using the same code and so i kind of end up following and do certain types of patterns with them which is you know maybe a good thing maybe not yeah so depending on which route you go you will be in conflict with one of the other types of principles out there.
Starting point is 00:04:47 But, you know, again, generally speaking, we think these are pretty good. So getting into the single responsibility principle, as he mentioned, that's just, you know, it should do one thing and do it well. And that's it, right? It really follows the rule of encapsulation, right? Everything should happen within that class that needs to happen in that class, and each method should only do one thing, and it should be fairly short and concise. Well, I'm just trying to follow along with Joe's comment, though, that he made regarding S and adhering to dry, though.
Starting point is 00:05:19 Yep. So what I kind of mean there is that if I'm doing some sort of like, let's say, a tic-tac-toe program and I'm trying to do it in a solid way and I'm by no means an expert and end up kind of creating a ton of classes, a lot of times some of the classes will have a lot of, not necessarily boilerplate, but a lot of the same kind of pattern. So what I mean for that is if I'm trying to truly be dry in a tic-tac-toe game, then I might have a class that says whether a particular game is a horizontal win. I might have a class that says it's a vertical win. I might have one that's diagonal. This is probably way overkill, but it's kind of an example of something you could see where you've got three classes that have very similar functionality that if you really do those in three separate classes then you're you're going to be duplicating some code yeah maybe some inheritance there i
Starting point is 00:06:12 don't know maybe that maybe that's a difficult example to follow but that actually follows another pattern we'll get into in a little while but um yeah and one thing um the thing like i mentioned i struggle with the single responsibility principle all the time. And I think that if you really try to work on it, if you really try to adhere to this principle, then you are going to experience some serious pain. But as a programmer, I think you've got to kind of like this kind of pain anyway. So, you know, it's not so bad. Are we all masochists now? Yeah. I don't know that you can ever have any piece of code that adheres to every rule out there that somebody's going to be able to put a rubber stamp on and go, yep, this is awesome, it's solid, it's dry, it's whatever.
Starting point is 00:06:53 But we can try. We may never finish what we're trying with, but we can try. Actually, if you did that, the application would probably do absolutely nothing. That's my guess. Yeah, it would be too abstract yeah it may would that be maybe just a class with an empty implementation an interface one interface with nothing in it we've solved the problem of all applications now perfect software some an interface that defines some method do stuff that's right so what's what's one
Starting point is 00:07:25 of the downsides of this i think joe already touched on a little bit and that's that's just a ton of classes right absolutely every time i try to go down this path i end up with classes upon classes upon classes and they're all really small and easy to understand in isolation but the big picture gets messy and i'm probably just doing it wrong. But every time I try, I mean, we're talking like multiples. Maybe some aspects would help you out there. Yes, that's why I need more frameworks. So you get a ton more classes. Wait until we get to dependency inversion.
Starting point is 00:07:58 Yeah, it's coming up, guys. You get a ton more classes. You get a lot more arguments. And, you know, honestly, it becomes a little bit more challenging to follow because you do have so many classes and so many files and whatnot, right? But it makes the unit tests a whole lot easier. Unit tests are a huge reason why you want to do this. Yeah. Absolutely.
Starting point is 00:08:17 So you can actually test your code easily. Yep. One thing I think that's really funny about the SQL responsibility is, um, it kind of flies in the face of, uh, all sorts of easy stuff. Um, the things where you might cheat, like,
Starting point is 00:08:30 uh, you know, throwing something in session memory and accessing it, you know, uh, like a few pages later in a web application or, or maybe using like a singleton or something. Um,
Starting point is 00:08:39 all sorts of easy patterns, just throwing a query in the page or in the, in the application. These things are like strictly forbidden if you're trying to adhere to the single responsibility principle yeah i don't know why you gotta throw my singleton pattern in there i love that guy i do too and you know we're sharper it always gives you the the little squigglies to let you know when you can make something like a static class or static method and it's great because it's efficient
Starting point is 00:09:02 but you know a lot of times you're creating these singletons which are bad because they create their control their own creation life cycle and they often hide dependencies and every class that calls them is um is directly coupled to that concrete class not an interface so it's cheating i could show you some examples where it's not where it can still be interface driven yeah but a lot of them if you've if you've got a singleton like um you know i always think of static classes the singletons but it's really not the same thing but if you've got a singleton that does stuff like you know has a method like get user ID or something like that, then a lot of times that's, you know, we're actually talking to a database or to a file system or to something that, you know, you're directly coupling now to your classes and to your entire
Starting point is 00:09:55 application. Yeah, I guess I was just thinking like the – we're way off the topic of single responsibility, but I was just thinking of the singleton because I got to defend my guy here. I got to defend my boy. The singleton could implement an interface though, and you could still have some way of extracting that away so that you're not directly aware of the concrete class. That's true. And actually, as far as dependency injection goes, it's pretty easy to configure something as a singleton. And so your calling classes don't even know that you've only got one instance of it.
Starting point is 00:10:33 But it's just kind of a more difficult way of setting that up. Yeah. All right, so moving on to the next one, we have the open-close principle, which is the O in solid. So this one is pretty straightforward. It's saying that the class itself should be closed for changes but open for extending. And, I mean, that's pretty good design practices. You don't want to go in and start changing the underlying pieces in a class because anything that's been used in that class will potentially break at that point i mean you can go to great measures to make sure this
Starting point is 00:11:09 backwards compatible and all that kind of stuff but anytime you start touching uh code that's been out there for a while that other people are using you run the risk of breaking things well if i could put that into different words though the the idea here is that if you want to extend a a class so you have some base class and you want to um make a subclass of that then you shouldn't need to modify that parent class in order to uh make that to make that child class work yeah but i can think of some examples where that's been really helpful. For example, equals. String equals equals string. The actual equals method that belongs to the actual object can be overridden.
Starting point is 00:12:00 And it's really convenient for something like a string where these two things have different references. They're reference types. But the actual string compares. The characters in the string match up with the characters of the other string, and so they kind of override that method in order to provide that expected functionality. But that's not what this is talking about, like overriding a method.
Starting point is 00:12:14 No, that is. That is part of the open-close thing. Yeah, no, so that's... I thought it was like if you had to actually modify the code of the parent class. You shouldn't. You're not modifying the code of the parent class here.
Starting point is 00:12:26 In a subclass, you are overriding a method. Right. To give it a new meaning. Right. And that's good. You're actually overriding slightly different. They talk about extending, which would be overloading as opposed to overriding. Right? as opposed to overriding, right? Like if you, so what they typically speak about is instead of having an equals,
Starting point is 00:12:48 you might have another equals that takes in a different type of parameter, something along those lines so that you overload the method. So you're not changing the original meaning of the class, but you can extend the meaning of that class. Right, and it's kind of a weird thing to think about. And I love the equals thing for strings in particular, but if you have an array of objects and you compare it to an array of other objects
Starting point is 00:13:10 and some of those objects are strings, then they're going to behave differently. They're not just going to be looking to see, am I really the same instance? They're going to be comparing the actual value of the characters. So it's kind of a weird situation, but it's helpful, and I imagine it's a calculated risk, and Microsoft decided that it was worth it.
Starting point is 00:13:29 Yeah. Well, yeah, I stand by my understanding of it, which was that it's saying that you shouldn't have to modify the base class. Yes, that's true yeah yeah over overwriting a method is okay right it's slightly different you're not really extending it at that point you're just kind of changing what is i don't know maybe maybe we have a slightly you're not changing the base class so that's good that again that went to what you just said that's good you never you basically if you create an abstract class or a base class or something like that you shouldn't be changing it pretty much um you should be able to extend it so okay
Starting point is 00:14:18 now if i can quote from wikipedia the open close principle is such that an entity can allow its behavior to be modified without altering its source code. Yeah, the code, right. And so in the override example, you are not changing the source for, say, object, right? But you are modifying some subclass's behavior by overriding methods and functionality, right? So that's okay. But you should be able to treat a subclass. This is kind of getting into the next one,
Starting point is 00:14:59 the Liskov substitution principle, but you should be able to treat a subclass indistinguishable from its parent. Well, okay. And so in your equal, equal example, right?
Starting point is 00:15:10 Like you, you don't want to know or care what the specific types are, but you expect that if you call equal, equal that you're going to get a Boolean result, right? Right. Yep. So you don't have to care like which specific one is it.
Starting point is 00:15:24 I just know that I can call this method and I'm going to get back a result. Of a boolean, right. The expected result. Regardless of how it got that. So getting into this, one of the, or getting further into it. Yeah, getting further into this. There's a couple of things that are important in this. And one is using interfaces, which will come up quite a bit in this and using things
Starting point is 00:15:49 like, uh, template methods. And really all we're saying is, is it's important if you have abstract classes or if you're using interfaces, the way that you make this happen with the open close principle is you can just override the, um, the the abstract classes methods which is what my cloud outlaw just said or you start implementing the interface methods so pretty much when you go that route you now further extend those classes without changing the source of the base class which is huge um the next is the uh is strategy pattern. And this one took me a minute to wrap my head around because it's, it's so close to some of the other ones, but, um, essentially what you're doing is instead of using just polymorphism,
Starting point is 00:16:38 which required classes to implement the same method repeatedly, you're basically creating classes that have, let's do the example that they actually had on Wikipedia, and we'll include the link in the show notes. They said, so you have a car class, and in this car class or interface for this car class, you have a braking method and the thing is that's all fine and dandy when you've just got three cars because you've only got three implementations of braking now when you start getting into hundreds of cars these are all implementing this braking method and they all basically are doing the same thing well i want to be clear here because you you said that you have to implement this method over and over and over. So you're talking about like an abstract where you're expecting that that's going to be.
Starting point is 00:17:30 Well, let's say you have an interface that says that it requires a braking method. And now every single car that implements from this car class using this interface now has to implement that braking method. And the whole problem here is when you have a hundred cars, most of them all break the same. And so you were basically repeating code over and over and over again, you know, potentially up to a hundred times. So the solution in this strategy pattern is instead of having, having these, these methods all self-implemented on each one of the car types is you have types, is you have various braking classes that override from the interface. So you might have braking with standard brakes, braking with ABS brakes,
Starting point is 00:18:17 braking with drum brakes, braking with disc brakes. And then that way, now you only have four classes that each one of these car classes have a reference to for their braking type and now you haven't duplicated the braking code over and over you have these different ones that that are using the all come from that interface and so now when you call the brake method they know exactly how to do it properly without duplicating the code so that's a strategy pattern and that that allows you to keep that open close thing because now if you want to implement a new type of braking they come out with something great in the future for
Starting point is 00:18:55 i don't know air driven brakes or something uh for cars then you just add a new carbon there we go carbon brakes right so now you add a new uh brake with carbon brakes and you didn't have to change anything else in the class that's available to all the other um all the other classes that need to be able to break with that type so you're not having to go and you don't have to peek into every single car type now to see what the braking methods are you can actually see oh this one's breaking with uh carbon brakes i've just got to go look at that you know your jaguar is breaking one way and your ford's breaking another way all you have to do is look and see the type of class that it implemented and then you're good i feel okay so uh i mean that those are ways to maybe help adhere to it.
Starting point is 00:19:46 Yeah, yeah. No, it's a pattern that you use to adhere to the open-close. So the whole point is now you don't have to go back into that base class and change any braking methods. It's all self-contained classes that inherit or that implement that, you know, whatever the ICAR with the breaking method is. Um, did that make sense?
Starting point is 00:20:11 Yeah. Except I, I mean, um, but, but again, at its purest though, like what this one is saying though,
Starting point is 00:20:19 is that if you have that class car and you want to, uh, you know, make a, make a, a subclass from it, then you shouldn't have to modify car. And that's exactly what this does. You're not even having to modify the braking method. That car class is going to have a reference to a braking class that implements an interface that defines the braking method. Now, that way, you're never touching that class again. That car class now has a reference.
Starting point is 00:20:55 I think I follow what you're saying in your example, is that in that child class, you would then set that, like that would be some variable. Yes. You know, braking. Yes. set that like that would be some variable yes um you know breaking yes or you know brakes and uh you you would set that to you know new carbon brakes yes all right i i follow where you're going with that now so now and the the thing that that does is it allows you to not repeat your code everywhere because now you don't have a hundred different cars that all have the same carbon brakes on them all defining their braking exactly the same.
Starting point is 00:21:26 You're not copying that code everywhere. You now have one class that defines that for you. So that is the strategy pattern. There's another one that Joe likes a lot that is the template pattern. And do you want to give that one? Yeah, sure. and um do you want to give that one yeah sure um somehow this is just one of those patterns that i picked up along the way and find myself keep uh keep on implementing but uh what i'll do is i'll have like a collection of um like rules or commands and i'll loop through until um i find one that um
Starting point is 00:21:59 that meets some sonic sort of criteria and then i'll execute that action or command and then kind of buck out of there. And I'm not totally sure I'm doing it right, but this is just something I found helpful over and over and over again. And what it allows me to do is basically add and take away rules. These are little independent kind of chunks and I can focus just on those little areas. So if you've got a sales engine or something, I might have a little rule that says, um, if this category, if this item is on sale, then reduce price by X percent. And I might have another rule that says, if this item is eligible for buy one, get one free, then, you know, return zero for the price or something like that. And so I've got these little kind of, um,
Starting point is 00:22:40 very small classes that each do one little thing that I can work on in isolation. And, uh, just seems to work out really well for me and I abuse it. Um, now the interesting part is we talked about earlier is you typically don't write this stuff this way starting off. Um, this is what he just said about the sales thing is a perfect example. When you first do it, you know, let's say that you're writing your own cart, you know, you basically have an item price and that comes in and you say, Hey, if the item price, if it comes, if it has a sales price, then use the sales price. Otherwise use the regular price. That might've been how you wrote the thing starting off. Then all of a sudden your boss comes to you and says, Hey, we need to do a buy one, get one now you've gone in there you've got if if sales price or if buy one get ones on the item then use that else if sales price is on there then use that otherwise
Starting point is 00:23:33 use price now you've had to go back in and modify it at this point you can probably look at that and say oh man they might be trying to do buy buy to get one next go around so at this point is probably when you'd want to come in and think about refactoring this code to give like a pricing engine like what what joe just said where you have rules and it runs through and executes those rules so then the next time that comes in all you have to do is add a new rule and it will automatically loop through those rules find out which one applies and then run it so this also oh sorry well i was gonna say like uh where i've used this a few times has been in a situation where um in in a base class there's a method that you know is expected to be to be ran and it'll have have a bunch of hooks in it that it calls out to virtual methods that may or may not have been implemented and still provide for a consistent experience.
Starting point is 00:24:57 Yeah, you won't get any runtime errors because that virtual method is basically saying, hey, if it's not there, it's just going to be a void call anyways. Or an empty method call. Or an empty, yeah. So, yeah, all these things that we just said are basically saying if you know that there's things that are going to be called in external places or you're going to need to check multiple things, you can basically set these up in a way to where there are classes that implement an interface that the base class knows how to call, and then you're pretty much safe at that point, and it's very extensible. You just need to add a new class in the future, add it to whatever list or collection you might be using,
Starting point is 00:25:35 and you've just now extended it without ever touching the base class. Right, and this also ties back into the single responsibility principle where the example of kind of having the if it's sale i am or if it's buy one get one free those are all examples of multiple reasons why a class would change so if you've got one class that knows all these different rules then this is a class that you're probably probably going to be modifying all the time yeah if you see a bunch of if else's then that's probably a good indication that it's a it's a place where you could start abstracting this information away yep and i like that that also kind of ties into like what michael
Starting point is 00:26:11 and i were saying and i was totally wrong about which is basically the um the close for modification um the source code is inviolate and what that means in part is that the classes that touch your class shouldn't have to be retested. So you shouldn't be changing these small little classes that often. And when you do change them, it should be something that still kind of lines up with your expectations of how it worked in the beginning. So these classes that end up, you know, a couple years later being used all over the place, it's kind of scary to change. So what you want to do is have these little tiny things that are safe to change and still adhere to their interface and uh just kind of keep on working yep all right so uh yeah this was the one with the uh the don't call us we'll call you yeah so the motto yeah they call it the hollywood principle and it didn't make sense to me as far as why they call it the Hollywood principle. But the example that Outlaw gave is what it means.
Starting point is 00:27:08 So he has a base class that's making a call to methods from classes that implement an interface. So this base class assumes that this method exists in whatever base classes are being defined. So what he was talking about with the virtual methods. Not necessarily interface. It could be in the child classes. It could be the virtual, like what he just mentioned as well. But basically, that base class is going to be calling a method, and it expects it to be there, and it expects it to be implemented in a way
Starting point is 00:27:35 that's not going to throw an exception. So from that perspective, that's saying the base class is going to call the methods and the things, not the other way around so your code shouldn't be calling it the the class that implemented those should so it's pretty interesting um yeah and so we've talked about the single responsibility principle that's the s and the open close principle the o the next one up is the Liskov substitution principle. And I actually got a little bit ahead of us talking about the modifications. But this is the one that I'll give you the definition first.
Starting point is 00:28:11 It's basically objects in a program should be replaceable with instances of their subtype without altering the correctness of that program. And this is where you, if you've ever heard of the famous example of the square and the rectangle, where a square is a type of a rectangle, but it's got these additional restrictions where the width and the height have to be the same. And so this is basically kind of a violation of this Liskov substitution principle because there are things you can do to a rectangle that you can't do to a square, like squish it, whatever. So if you had a method that maybe took a rectangle or a shape object
Starting point is 00:28:48 and stretched the width, then that would be something that should break the square class. And now you've got an example of something where you can do something to a parent but not a child, which is kind of a backwards way of thinking about that relationship. Yeah. backwards way of thinking about that relationship yeah you guys never heard of it well no i guess what i was thinking of is uh like and i was just trying to figure out like how to put it into words um you know if you if one i'm trying to think like which one would be the parent, the square or the rectangle. But if you had a class where, uh,
Starting point is 00:29:29 you were setting the property for it and you just assumed, well, width and height, they're going to be the same. Right. And that's, that's part of the square rectangle thing that breaks it. Yeah.
Starting point is 00:29:39 But I was also thinking too, the, um, this, uh, substitution principle fits in nicely with the, uh, base class example that I was talking about, too, though, that this substitution principle fits in nicely with the base class example that I was talking about before where the child class can run the same as the base class. Right. Substitutable for the other in terms of execution, which brings me into this little note that I had here, which is, you know, when when in school you're taught from a object oriented perspective, the is a relationship for classes. And so I wrote here when we were putting our show notes that is a,
Starting point is 00:30:25 has been deprecated and replaced with is substitutable for. Yep. Okay. Nice. Yeah. And what I kind of like about this is if you reverse this, let's go a little bit and kind of think about it in a different way. It also kind of implies that you can take in a higher level of
Starting point is 00:30:42 abstraction. So if you've got a class that takes in a car and prints out the two-string of it, then maybe you could just take a string instead and do something with basically the highest level of abstraction that you can deal with. That wasn't a great example. But for me, the way I actually think about it a little bit more tangibly is I go around and if I've got a HTTP request class and IHTP request class, then I can go ahead and swap that HTTP request argument out with the IHTB request interface. So I should
Starting point is 00:31:28 only be dealing with those methods through the interface and I can do that sort of thing because I can trust, or I should be able to trust that those behave in the same way. There's a note here as well that if you have to inquire as to
Starting point is 00:31:47 the type of whatever object but you gotta say this like like this was a perfect jeff foxworthy moment if jeff foxworthy were a software developer if you have to inquire as to the type of your object your code smells nice so what that really means though is if you're having to look at all the objects pass in and say is this type box or is this type uh square uh then do this if this is type rectangle then do this if this is type circle then do this then the problem with that is it might seem perfectly fine when you only have three or four objects but as more come in now you have a triangle now you have an octagon now you have a pentagon all of a sudden you're having to go back in and change those base classes which i can think of an example where this is done quite often
Starting point is 00:32:34 oh really can can you guys you guys got any type of javascript stream format uh the example that i was thinking of um go back to your web form days, is in a repeater. And you're doing the, if it's a list alternating item or a list item, you're inspecting what the type is and deciding whether or not you want to act on it or not. Right. Or how you want to act on it or not right yeah how you want to act on it or not because there's a lot of there's a lot of event-driven type um objects where you're getting the lowest common denominator back object you know you know into it and then from there you're trying to inspect you you have to inspect it um to say like okay well what actions do i need to take from here yeah and so just as a heads up for the way to avoid that instead of having is type of
Starting point is 00:33:32 square is type of rectangle is type of circle instead let's say that you're trying to run the area of them each one of those objects themselves would have a method called get area and then you would be able to take in an eye shape, a type of eye shape, and you would say, you know, get area. So then now instead of you having to inspect each object to find out what it is and then call get rectangle area, get square area, get whatever, they all have the same method on it. You just say get area.
Starting point is 00:34:01 And so that's how you get around that is type of you know whatever well there was another note that i had here too and that's that if if your subclass requires something that the base doesn't then you know there's a good chance your code smells yeah yeah i listened to the uh the pearl site uh course on the solid and what he said is you have a base class a duck and then a subclass that is also a duck, but it requires batteries. Chances are you've violated this principle. Yeah, I'm trying to remember what his name was. Steve Smith.
Starting point is 00:34:37 And the reason I remember that is because there's an NBA player by the name of Steve Smith back in the day. So, you know, whatever works. I'll make sure to put that in the show notes. Yes. And I would also say that, would you say that casting is kind of a smell that you're violating the Liskov substitution principle? Probably, because you should be returning the interfaces, right?
Starting point is 00:34:56 And then you don't have to cast the things. Yeah, you should be able to deal with it at that level of abstraction, or else you should probably take the more specific type. So are we going back to a previous episode where you always wanted to convert your i-enumerable to list and your to list i-enumerable yep over and over and over again and if you don't know enough about interfaces right now now's a good point to uh pause this particular episode and go back to i think it was episode one, right? Yep. I is for interface. Yeah, I is for interface.
Starting point is 00:35:25 www.coningblocks.net slash episode one. Yeah, so we talked about interfaces ad nauseum there. But again, those are an extremely important part of this entire solid set of principles. But Joe brought up an excellent point. I've never really thought about it, though. Like, is the casting a violation of that it certainly it certainly feels like it would be yeah you're saying like i'm taking an object but
Starting point is 00:35:51 really what i need to do is something to this specific type so yeah but you're not interrogating it necessarily to say like what type are you you're just saying like i want you to work as this type but that means you're making assumptions right oh yeah i'm not saying it's good so but in in in the perfect world let's say you're not working with third-party apis or anything you would be able to just know that this is of a particular implementation you know it's a shape so this shape i should be able to call get area i shouldn't have to say okay cast this as a circle and get that type of area, you know? And if I've got a rectangle, I should be able to say set width to two and set length to four.
Starting point is 00:36:32 But if I've got a square that's also a rectangle, then, you know, do I throw an exception? What do I do? Well, no, at that point, you just, whatever the last one was, you set both of them to four, right? That works for me. That's an example of one of those headaches that, uh,
Starting point is 00:36:46 you know, we programmers love. Yeah. So I don't know the casting things that kind of up in the air, but I'm going to be thinking about that one all night. I had never considered that. So, all right.
Starting point is 00:36:55 So now we're going to move into number four, which is interface segregation principle. This is probably Joe's baby. These are the people that provide my internet connection, right?p isp that's it right there and which have been throttling our netflix by the way so yes yeah if we want to go down that road we can but i'm guessing we don't so this is my favorite of the the solid principles and that's because it results in more interfaces, more smaller interfaces, even more specific. And that's because basically if you've got a method that does something to an interface,
Starting point is 00:37:32 then it should only really know about the things that it needs to do or needs to touch. So we kind of talked about the car example. If I've got a class that does some braking and it takes in a car class and it'll tell the car to brake and give it whatever information it needs to do, then it doesn't really need to know about the whole car, right? What it really needs to know is about maybe what kind of brakes it has and when the last time the brakes were serviced maybe and some other type of stuff. And so what you kind of ought to have, according to this principle, is an interface that only specifies the information that is needed for that particular method, and then your car class can actually implement that interface.
Starting point is 00:38:19 So rather than just taking an iCar, it might take like an iCar brake information interface. Yeah. And the really key part about this is it allows you to use interfaces without having to implement a bunch of things that don't matter to what you need them for. One of the examples that Steve Smith gave in his Pluralsight course was the old membership provider in.NET. Apparently, it has like 60 things that you have to implement. And the problem is if you're just trying to do a login form you really only need two things username password and maybe a couple others but in order to use that now you have to implement 60 methods or however many there are and you have now broken the whole purpose of why you would use an interface in the first place so so i put my uh jeff foxworthy hat back on here
Starting point is 00:39:05 i wrote uh if your interface requires a lot of methods to be implemented that often aren't needed your code smells i like it very nice hey if you implement an interface and use throw new not implemented exceptions your code smells agreed yes um oh and another reason why we talked about interfaces being so important and and you ran on it earlier unit testing if you have little tiny interfaces that only have small things or or whatever's just required for that to work your unit tests are now very easy to write because you can throw in your own mocked-up classes to do what you need to do. So that is a huge benefit of that.
Starting point is 00:39:57 Yeah, agreed. So small is the way to go. Small and mini. Small is the new big. Now, the interesting thing, going back to our interfaces thing, we talked about in our first episode that one of your things that you didn't like about interfaces, they get all spread throughout the file system.
Starting point is 00:40:16 One thing that Steve Smith did mention in his Pluralsight course is he puts all his interfaces in another folder. Or he might put them in sub folders off his solution in various different places so that's one thing that you could do because technically speaking the interfaces don't really i mean so i like that but the problem is um then you have to decide whether you want your namespace to be different so that it matches that with the folder or if you want to violate the basically the tacit rule that your interface your that it matches that with the folder or if you want to violate the basically the tacit rule that your interface your name space matches up with your folder structure
Starting point is 00:40:49 right so i mean it can be done it doesn't hurt anything uh but just something to think about yeah i keep them close personally close to my heart sometimes I even put them in the same file. I know. It's dirty. It's not. But when you've got a bunch of little tiny classes and your classes are singly responsible and they're, you know, a bunch of 10 line classes, then suddenly it's not so bad to have it's truly an interface it's going to be implemented by a bunch of other things then it can get confusing as to where you're trying to find it right totally yeah i don't like that it's kind of weird to have two in this file and one somewhere else you know if if they are classes that i expect to be publicly available then um i like to keep them separate but there have been times
Starting point is 00:41:47 where if it's like uh you know a private internal class that i'm only wanting to use within some other class yeah and then i'll leave it in there because i'm kind of i guess in my mind whether or not the reader interprets it the same way i I'm trying to signify, like, I really only anticipate this to be used here. Yep. Although, I will say, if you're following these solid principles, you're probably going to end up with so many freaking classes that you can't really use the File Explorer much anyway. Yeah, that's a good point.
Starting point is 00:42:16 You're going to have to be doing some Googling on your hard drive. Yeah. You can do that through Studio. Yes, you can. Yep, Google through Visual Studio. All right, so I think we've pretty much exhausted interface. yeah you can do that through studio yes you can yeah google through visual studio all right so uh i think we've pretty much exhausted the interface are we ready for some dip let's let's go to the dip dip baby dip that's that's going back a few years right showing our age yeah a little bit or alan's age yeah my whatever
Starting point is 00:42:41 all right so uh yeah this is the uh dependency inversion principle and this is probably one that is probably the most uh i don't know confusing depending on which approach you take because there's so much involved um so it it seems like this is the this is the least solid description that's going to be given. I mean, the other ones are more simple. This one gets a little bit more complex, in my opinion. Well, the way I think if you follow through with the SOLI, the S-O-L-I, then you need some help managing this stuff because it gets big and it gets crazy. And so the actual kind of wiki definition here is that one should depend upon abstractions, not upon concretions.
Starting point is 00:43:30 Another way of saying that would be that not only do you take in interfaces for your methods and your properties, but also anything that you, anywhere where you create these classes that are actually the concrete manifestations of these interfaces should really be coming from somewhere that's outside the class that's using it so you know the new keyword suddenly becomes a smell yeah it's really frustrating too so there's there's a few ways to approach this and oh wow i guess i should get a little bit closer that's so weird um so you can either pass in your dependencies via constructors or you can do it through setters and there's actually another method that's not as frequently used and i can't remember what it is off top of my head but
Starting point is 00:44:14 so the thing is if you have a constructor you just pass in your you know whatever objects are or or dependencies that have been created you pass them in the constructor of another class, and then that class now knows exactly what it needs to use. The upside to this is that your class has all its dependencies as soon as it's nude up. It's ready to roll, and you know exactly what that class needs to have. You just don't know what nude it up. You don't know what nude it up. Yes, and we'll get into that in a minute too. We talked a little bit about kind of a car example, and this would be a little bit of an example of kind of a builder.
Starting point is 00:44:49 But someone's got to create that car and put that together with the brakes and the kind of the brakes. And whoever's putting that together. Ferrari. Yeah, Ferrari. Definition, by definition, has to know about those concrete classes. They have to say, you know, create new car, create new disc brakes, create new this kind of tire. And that's a class that I just described there basically violates every single one of these principles.
Starting point is 00:45:13 So that's where the dependency inversion comes in. Yeah, and if we're going to say that I can't use the new keyword, then in my link expressions, I can't do anonymous types, which are sometimes fun. Yeah, definitely. But, you know, solid is fun, too. If you don't have to get anything done. Right.
Starting point is 00:45:29 Just kidding. I kid. So now the downside to the constructor stuff is, first, is you can't swap out any of those dependencies at runtime. So if you have some sort of notification class that if something happens then it should be using a logger otherwise it should be using email then there's no way to swap that out you you basically have to pass in both a an email notifier and a log writer notifier or something like that so or different types potentially but that's what i'm saying single responsibility so so there's there's an issue with the constructor and and then uh the other going the setter route the um you're basically
Starting point is 00:46:12 after you knew up a class which you know we'll get into a little bit after you know up that class then you set the dependencies using you know property setters now the upside to that is you can swap out dependencies. Depending on whatever's going on in the class, you could say, okay, no, we want the notifier to be a logger, a file logger. Otherwise, we want it to be an email logger. So that's cool. The downside is when you new up that class now, the dependencies aren't there. So if things start happening and they're not there, then you could potentially get exceptions and see here's another example where i don't get to use one of
Starting point is 00:46:49 my favorite operators question question oh that's a good one yes i like question question yeah return it but if it's null let me set it first and with a new and then return it. Yeah, yeah. Question, question? Well, so let's also, there's two other things we need to get into here. One is, this is not all gravy. Like, when you do dependency inversion, the downside is you can have huge object graphs. So if you are passing in all your dependencies, they have to be there at the time that the other class is being used,
Starting point is 00:47:28 which means that if that class was never going to use that notifier, you still had to have that thing ready. It was already initiated and created and is being passed in as a dependency in standard programming practices, which probably most people use other than going through solid. You knew that thing up when you needed it. Right. standard programming practices, which probably most people use other than going through solid, you'd knew that thing up when you needed it, right? So now you've got this potentially large set of objects being passed in that are dependencies that could be eating up memory and never even be used, depending on what's going on in your code. So that's one real downside. You kind of have to weigh whether or not the upside's worth it.
Starting point is 00:48:04 Well, I'll say another downside is that you're literally adding a layer of complexity. So if your idea is to make something that's more resilient and more maintainable, then you're going to be adding some extra code. So this isn't something you're going to want to do if you're writing Fizzbuzz. But if you've got a large application then it's something you want to consider. And I'd also mention that you don't necessarily have to go off the deep end and replace every single new in your code, but it's something to kind of keep in mind,
Starting point is 00:48:33 just like all these other principles, and something to keep in mind when you're designing and creating your classes. Just in case if anybody got lost there, fizzbuzz is a common interview question. Oh, yeah. But I'll also say too though um i mean we've already just in the course of this conversation we've we've mentioned a couple examples of places where microsoft um maybe you could argue didn't adhere to some of these rules
Starting point is 00:49:00 so uh it i just using that as an example like it's difficult to adhere to all of them yes all of the time yes and that's why they say when it comes up you know more than once then it's time to start thinking about how to refactor your code although dependency inversion windows has come up a couple times yeah time to rewrite it all but dependency inversion is one of those things you actually want to do probably from the get-go yeah um a lot of these things are really better for like are easier to do in greenfield type applications yeah yeah the the part that i get hung up on with dependency inversion and there may not be a great answer to it i jo Joe and I spoke about this for a little while. If you're not using something like NINJECT and.NET or Spring and Java or, you know, any number of other frameworks that create your own IOC containers, this is going to be nearly impossible. Because where are you going to new up your classes?
Starting point is 00:50:00 You're going to be doing a lot of plumbing. Yeah. And that's, I mean, you pretty much have to use a framework if you want to go this route you're going to be looking at using a framework because it's mostly done through configuration files or settings or whatever and that is how they get that's how your classes get instantiated so well correct me if i'm wrong there, but wouldn't, like, in the.NET world at least, one of the earliest forms of this be in the config files where the culture and version and all that are specified for, you know, DLLs that you want to include. Probably.
Starting point is 00:50:39 You know, binaries that you want to include. I mean, that might not have been, maybe it was their intention initially, maybe not, or maybe it was just a cool side effect. But, you know, that was an early example. And also, because you're not doing any sort of newing up, if you're doing strict dependency inversion, it makes testing really easy. So rather than you actually, you know,
Starting point is 00:51:00 having a class that sends a physical email, it would take all the dependencies to send an email, physical email. Then it makes it much easier to test, and you don't have to worry about who you're going to send that test email to every time you hit RT. What does a physical email look like? Yeah, I keep saying that, physical email. Okay.
Starting point is 00:51:22 I'm going to have to go check my physical email. All right, so taking this one step further, and then I think we'll pretty much be done on the dip, is in the Pluralsight videos from Steve Smith also, he takes it away from the code. So typically when we talk about dependency inversion, we're talking about our code. He takes it a step further and says, well, you can do this at your solution level. And so if you think about a standard application, you have your view, your client interface, your UI. And then underneath that, you have some sort of, in some cases, called a controller. But that's where, you know, some of your logic takes place. And then you have your model, which is typically your database interaction. Well, the whole point of that MVC type thing is to
Starting point is 00:52:04 separate those. Well, in reality, though that MVC type thing is to separate those. Well, in reality though, they're typically tightly coupled to each other. Your view is highly dependent on the controller, which is highly dependent on the model, which means you can't really swap out that model. You're going to break a lot of things. And so he actually goes into the whole way of where you can abstract those things away, and so you invert the dependencies there so that if you needed to go from SQL Server to Oracle, then you could do that. Or if you wanted to go to a NoSQL solution,
Starting point is 00:52:33 you could do that without having those tightly coupled things. So was he suggesting that you just make them like nougat packages? No, I don't believe it was that. It was just adding other layers of abstraction in between them. Just different projects? I didn't get completely through the thing. Oh, sorry. Yeah, so thanks for calling me out.
Starting point is 00:52:57 But it basically boiled down to adding more abstractions. And one of the ways that he brought it up was back in the olden days, you know, he was trying to show that you could swap out databases or whatever. And the problem was is he might have his SQL server project there and then he would have his Oracle project, something along those lines. And then if he wanted to switch from one to the other, he basically had to go in and rename all his dependencies that were going from, you know, calling his SQL server project now to call his Oracle project dot whatever. Even if the methods were all the same, he was having to do this global replace. And so the whole goal was, okay, I shouldn't have to do all that stuff. I should be able to change this abstraction layer to say, okay, now this points to Oracle or now this points to SQL through some sort of configuration. So that's really what it boiled down to is creating that abstraction so that instead of him having to go through
Starting point is 00:53:50 and do a global replace on all his namespace stuff, he could, you know, more easily swap out pieces. And so that's interesting. But again, going back to what Joe said earlier, that whole three times thing, you know, you start going this route, you're going to spend a lot more time architecting and implementing these type of, you know, cross-cutting concerns and things in your application. That's really hard to do with brownfield applications and also, as Michael said, exploratory type coding. And pretty much a good percentage of what I do is either exploratory or maintenance on brownfield applications so I don't get a whole lot of time to you kind of to really try to do things the quote-unquote right way yeah it can be difficult and it's really challenging especially when you're under deadlines I mean you're always balancing the you know the extensibility and how
Starting point is 00:54:42 easy it'll be to do over time versus, you know, what's the trade off. What's the benefit. Is it ever going to be touched again? If not, then it's probably not worth doing if it is. And there's, and you know, there's going to be things and it's something you should probably visit and,
Starting point is 00:54:55 and try and take care of. So, yeah. So that pretty much wraps it up for the solid. Um, some additional resources we liked were the, we talked a lot about patterns in this episode. So there's a fantastic book, Design Patterns,
Starting point is 00:55:11 the famous Gang of Four book. We'll have that in the show notes. Also a book called Clean Code. There's a guy I really like. I'm not sure how to say his name, but we'll have links to his blog here. But he wrote a really great article and has a little talk on moving from stupid to solid. And he's got an acronym there, stupid to say, it's for kind of common anti-patterns and how to move those to like a more solid approach.
Starting point is 00:55:35 And he's also got something really cool here where he's got, he calls them object calisthenics, which are basically a set of nine rules for you to kind of try and build an application and i'll just give you a couple examples here like one of the rules is not having more than one level of indentation and like don't use the else no else no getter setters you know stuff like that so it's kind of stuff that's hard to do in your day job. But if you're doing a little... In your night job. In your night job, if you're doing a little tic-tac-toe app, then it's something that's kind of fun.
Starting point is 00:56:12 And actually, we'd love to see some examples of what you guys are doing in a solid way. So I was actually planning on doing a little tic-tac-toe example that was as solid as a rock. And we'd love to see what you guys could do too yep well along the resources uh alan's mentioned a uh plural site um video by steve smith called solid principles of object oriented to design that was another uh good good resource for information on that yeah excellent resource and he as mentioned, he even pointed out his follies in the past and how he got around those. So when he learned about dependency inversion, how he went and took that.
Starting point is 00:56:52 So you'll get a lot of tips of things to look at along the way when you're doing this kind of stuff. Yeah, we also mentioned Michael Feathers and Uncle Bob. And they write on the Object Mentor blog. And there is a wealth of information for just kind of principles and best practices around object-oriented programming,
Starting point is 00:57:08 and you can download some PDFs of papers they've written there. Yep. So now we're going to get into our tips of the week. So mine is in the new Visual Studio 2013, you now get the ability to modify code while you're debugging, even in 64-bit mode. That's something we've been missing forever. That's going to be dangerous.
Starting point is 00:57:33 That's beautiful. No more recompiling, reloading, especially if you're dealing with ASP.NET. Oh, my God, waiting for IIS to spin back up and all that. So, yeah, that's glorious. Yep. That would be a fantastic site. And also, my tip is basically what I just found out about, which is Control-Shift-S, which saves all of your modified files.
Starting point is 00:57:58 So you didn't know to save your documents? I am a religious saver. That explains so much. I save. I even commit ridiculously. I cannot go five seconds. Oh, we've talked about your ridiculous commits. Trust me. I like to save. But what this is really helpful for me for is saving solutions in project files. So sometimes if you delete or rename a project or something like that, the actual SLN file won't get written
Starting point is 00:58:23 to. And this is a problem if you go and you kind of do your if you're using source control and you do like a status or an update or commit or whatever a lot of times you're going to miss that sln file or csproj files because they weren't written to disk and so you do your commit um and the next day when you close your visual studio and you see that message saying like uh save changes to the sln file and you're like oh crap that pull request i put in yesterday is missing some stuff so control sift s whenever you make changes to um you know projects or properties on your solution is a big help so uh my tip for the week i found this really cool little project uh that i thought was a nice nice dovetail from our last show, which was about link.
Starting point is 00:59:08 And this is a project called Link to Twitter. And you can find it on CodePlex at linktotwitter.codeplex.com. And also on Twitter at, go figure, twitter.com slash link to Twitter. But the Twitter in that one, uh, doesn't have any vowels. So, um, it's a nice little, a cool little project where, uh, if you had a need to, uh, you know, go, go through, um, uh, various tweets and you wanted to do them in a link fashion, here's a link provider for Twitter now.
Starting point is 00:59:43 So we were talking about some of the crazy link providers that were out there i think um uh link to flicker flicker there you go that's the one i was looking for it came up and uh now we got linked to twitter and i thought that was just a really cool um little project and it's it's still it's very current there were some updates uh just this month to it and um yeah you could say something like from uh from tweet in context status where tweet type equals status type public select new tweet and uh you know get some neat little information from it so it was pretty neat and they have examples in there where you can integrate this into LinkPad, which is also another thing that we had discussed last week in our show. So I thought this was a great little tie-in to that.
Starting point is 01:00:32 Excellent. And speaking of Twitter, tweet us. Tell us what you're working on. Tell us what you like. Tell us what you hate and all that kind of stuff, at CodingBlocks. And we're very funny, too, very entertaining. Yes. And on topic.
Starting point is 01:00:47 Always. If you follow a lot of people on Twitter, you get a lot of noise. But we try to stick to the important stuff like coding and Icepocalypse. Yeah, I definitely had some Snowpocalypse in there. Yeah, that was a big deal. Yeah, yeah. That's why we're so late on getting this episode out, as a matter of fact. There was an inch of snow, guys, on the ground.
Starting point is 01:01:09 I mean, you say it was a big deal, but I mean, really, elsewhere in the country, it wasn't so much a big deal. But here in the South, we kind of like went overboard. Which there was a, for any Top Gear fans out there, they had a great thing recently where somebody had posted a sign. You know the signs that go over the freeway, the digital signs where they can replace the message and whatnot. And it said something along the lines of, oh my God, snow, we're all going to die. Hey, look, it was a big deal. We all had long commutes home. Again, it was a big deal we all had long commutes home again it was a big deal in the south yeah yeah so um yeah we do stay on topic but definitely hit us up at coding blocks uh you know we'd love to hear from you guys and interact with you uh and with that
Starting point is 01:01:59 i think that's a wrap we'll be putting the the links and the show notes up on the site uh and you'll be able to find that at www.codingblocks.net slash episode seven and uh and also make sure to subscribe to us on itunes and i've been really getting into the stitcher app lately uh which has been really cool so make sure you subscribe there and uh we also could desperately use your reviews on both stitcher and itunes um lets us know how we're doing and also kind of exposes us a little bit more, which is good for us. So also – Regardless of which app you prefer or what podcast source you prefer, we would appreciate some reviews and – It's highly motivating is what it is. Yep.
Starting point is 01:02:43 And also contact us if you have any questions or topics. Leave your name so we can get a hold of you and preferred method of contact. And also, shout out if you're okay with being mentioned on the podcast. Who wouldn't? And especially if you give us a review, you know, hint, hint. Yeah. You could even leave a website. We'll pimp it on the show.
Starting point is 01:03:03 Yep. So, yeah, even leave a website. We'll pimp it on the show. Yep. So, yeah, that's a wrap. What if it was a pimp who wrote in and wanted to pimp his pimping website? I'd pimp it. I'm fine with that. Yeah, I got no issues. Some legal questions might come in there. But I tell you what, you can provide your answers.
Starting point is 01:03:19 You can visit us at codingblocks.net where you can find our show notes and examples, discussion, and more. Send your feedback, question, and rants to comments at codingblocks.net where you can find our show notes and examples, discussion and more. Send your feedback, question and rants to comments at codingblocks.net and be sure to follow us on Twitter at Coding Blocks.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.