Episode 076 – Delivering Quality Software
What is Quality Software and how do we ensure we are Delivering Quality Software?
Clayton Hunt: This week we’re talking about quality and how we can deliver quality software.
Jon Ash: So quality software that’s what the QA departments for?
John Callaway: Quality is everyone’s responsibility. I heard … I think either on a podcast or on a YouTube video or maybe just on Twitter, I might’ve read that you’re not paid to deliver code. You’re paid to put code into production. I would take that a step further and say, you’re paid to deliver value. Whether that is a right code and produce some functionality and put that into production where it is being useful to someone or some process, or if it’s just a configuration setting or it’s a new manual process of Pencil and paper.
Clayton Hunt: Yeah, companies don’t want code they want or they think they want software because they think that it can solve a problem that they have or optimize a process that they already … That’s in existence. They don’t actually care about the code at all.
John Callaway: Stepping back for just a minute, what are we trying to do to find when we use the term quality?
Clayton Hunt: Well, the first thing that always comes to my mind is quality software. A software that does what the company needs with limited breakdown. So I mean, bugs happen, you can’t get rid of all the bugs. But five ninths worth of operation is really what we shoot for most of the time.
Jon Ash: And I would also add to that the ability to extend that code into new functionality that, that the business might need. So, you want the software to remain software and not just another form of hardware, even if it can stay running as hardware. Right.
John Callaway: So something that we’ll continue to deliver value as the needs of the business change?
Jon Ash: Correct.
John Callaway: So by that, do you mean that it’s something that’s easily maintainable and easily extendable or, what more do you mean by that?
Jon Ash: Yeah, I think the maintainability and extendability are where those two pieces are what I’m talking about. Yeah, I mean I think that you just … It needs to be able to be modified, right? So either add features to that or modify the way that, that system things that are integrated with it? There are definitely different ways of going about that, right? You don’t necessarily have to change the literal code that’s running. You could add … It could be a part of a system where you could extend it by adding other modules or other pieces of code, right? The way that you maintain it. But the code itself has to be able to be maintained and extended, and flex with whatever new requirements however the business changes, how the world changes, ’cause code really, once it’s written, the computer should be able to continue doing that exactly the same way for forever.
Jon Ash: I mean, assuming you don’t have things like, memory leaks and other issues, right? If it’s quality code that’s running well, it’ll run for forever. But if you can’t change it, then you’re going to have to go and stop that code to introduce a new system because the old one was too inflexible.
John Callaway: It sounds like you’ve been answering the question, of why Clean Code matters. Clean Code is a term that any followers of Uncle Bob would be familiar with, but it basically means code that is maintainable and flexible enough to change with the business needs. Are there any other reasons why Clean Code matters? So other than keeping up with the business, why would Clean Code matter?
Clayton Hunt: To Ash’s point? I think it, has to do with, the maintainability and extendability. I’ve written down a quote here to be sure to put in our show notes, attributed to Ben Franklin. “The bitterness of poor quality remains long after the sweetness of low prices is forgotten.” Clean Code and quality code is cheaper because it is maintainable and extendable. It is hopefully easily understood. It’s easy to get to fall in the rut or to fall in the mindset that I’m going to slap something together and push it out and then call my job done and then, leave for the day. Pitch it over the wall to do a QA department or just go ahead and ship it to production. Right?
Jon Ash: Yeah. So maintainable by others. After you’ve quit or retired or hopefully not been let go, the developers that come in behind you, would be able to work with that code without having to speak with you first.
Clayton Hunt: And even for future me. ‘Cause I mean there’s been multiple occasions where I’ve come in a day later, a week later, a year later and picked up some code and say, “Oh my goodness, what is this mess this previous jerk left for me?” Only to look at the commit history and see that the jerk was me. I want to make sure that I’m doing right by my future self or anybody that comes after me, that then I’m going to do the best I can from the beginning so that I don’t make a mess early on.
Jon Ash: Do the best for those that come after us, even if it’s ourselves, so that they don’t have to pay for the sins of their forebears.
Clayton Hunt: Right. A number of years ago in my first home back in Louisville, Kentucky. I wanted to build a double thick sound deadening wall to build a home studio, for musical recording guitar and drums and stuff. And a friend of mine offered to come over and help me because I really had no knowledge of how to go about constructing any wall. So, he came over and really took over the project for me and I thanked him immensely for this. We measured more than twice for a single cut. And he instilled in me that you want to start as precisely as possible, because the further along you go in the project, a little imperfection early on is going to cause just ripple effect of waves and waves of differences in the future. So be as precise and as clean as possible early on, so that you don’t cause yourself a massive headache and the in the future.
Jon Ash: Yeah. A 44 degree cut means that the whole wall is sideways.
Clayton Hunt: Or angled or something. Yeah.
Jon Ash: I think there’s also an element of quality. I mean we’re talking about Clean Code, but there is an element of the benefit of quality that comes from more of the bug side of things, is the application from the user’s perspective, what’s their experience? Anyone using a buggy application has a really bad user experience. They become very frustrated with the system, that doesn’t behave like they’re expecting it. Sometimes they’ll find what work arounds or ways, to deal with that, but that obviously is generally going to be bad for the business. And it doesn’t really matter what nice Ui or Clever Graphics and whatnot that you’ve pasted on that a bad buggy experience is going to be a bad thing and it’s going to ruin any of those things. So, Making sure that the application does what it says it can do and does that in a predictable and consistent manner. That’s an element of quality doesn’t impact us necessarily directly, but it is also really important. Which we already said we talked about it, but it’s why it’s so meaningful to the business.
Clayton Hunt: There’s another side effect of code that’s maybe not the best. And that is, something that any senior developer has probably experienced when trying to solve a new problem or understand a framework. I myself have gone into when I was trying to learn Angular 2 and understand its patterns that they needed to be worked with. I would do a small test in a certain part of the application. And very quickly there were 40 instances of a pattern that turned out to be a really bad pattern, because the other developers saw that and just Wet Wallace, he’s the senior or he’s the tech lead or he’s been here longer, we’re just going to copy that.
John Callaway: Or just that works right?
Clayton Hunt: Yeah, that must be the right way to do it or something. So that leads to one of our topics, which is bad code but gets bad code. And I think that there’s a flip side is that good code but gets good code. Whenever a developer enters a system, there’s a high chance that they’re going to copy the patterns of that system. Either for good or for bad.
Jon Ash: And just as a side note and in general with that I would say something that I would encourage people to do in general. I mean there is a point where you might need to … You’re trying to improve the system so you go against the grain. But you have to be very … You need to know when it’s appropriate to go against the grain and when it’s not going to be just cluttering up your system with a lot of different styles and format. So it would be much preferable for people to follow the patterns that have been in place.
Clayton Hunt: Yeah, and I agree to a certain extent I do feel like we should always be trying to right the ship.
Jon Ash: Absolutely.
Clayton Hunt: If you’re implementing a pattern because you’ve seen it in the system and you know that it’s already something that they’re doing, you should not blindly implement it. Maybe implement it and think about it and either ask the other developers if they think that it’s a good pattern or suggest something that might be different or depending on your team, maybe just make a slight tweak that you think will be better.
Clayton Hunt: I don’t think that we shouldn’t experiment in the codes, a little bit, especially when learning something new. But we should be careful about just blindly implementing whatever it is that we’ve seen. Legacy systems, Greenfield projects, like they’re all … Everyone should be, I would hope trying to get better all the time. So no code is ever going to be exactly the same. There’s a pattern that John and I have used for years the repository pattern and it’s probably been through at least 50 or 60 iterations where we’ve improved it or swapped out a piece because the framework changed.
Clayton Hunt: Lots of little changes along the way. And now John can go into a company and just drop that pattern in and instantly be productive. And that’s really what we should be shooting for. We shouldn’t be writing over and over and over the same exact code all the time.
John Callaway: Are any other issues with using the patterns that you’ve seen in the software? I mean, what are the side effects of that?
Jon Ash: Just to touch on that very briefly, the first half of my career, I was essentially a maintenance program here. So I would come in on an existing projects and pick up whatever had been developed before I got there and make modifications, make enhancements. So, I was wholly trained by existing code bases. Hopefully I was learning from those that were professional and did the very best that they could at the time. I think for the most part that is accurate. I think I saw a lot of quality projects and learned a lot of good practices and different patterns that I’d normally wouldn’t have learned. Making a good code base. We’ll help train your developers and help train future developers.
Jon Ash: Another aspect of bad code though, is that bad code can often hide bugs in the system. If you’re opening up a class or a file that’s 3 or 4,000 lines long, names are poorly chosen, it’s very difficult to get a grasp on what’s happening inside that particular file. That particular class.
Clayton Hunt: Yeah. What I’d like to add to that and that given the nature of software development, I think compared to other industries there is an exceedingly high turnover level for not only developers but also the business analysts and the project managers. So any job you go to the knowledge base of how the thing is supposed to work in the first place is pretty limited. And I’ve worked at several companies where a bug, like an actual bug in the software became a business rule that they depended on. So that’s another issue with, that bad code hiding the bugs is that nobody, whoever came up with a requirement in the first place didn’t realize that there was a bug there and the developers didn’t see the bug because it was hidden in some file. And then over time as people rotate it out, it just became the way the software worked.
Jon Ash: Yeah. Good or bad. that’s how it works. And if I’m coming on to a project looking into Legacy System, I’m expecting that it behaves the way it’s supposed to behave. So I would be very cautious about changing in the existing functionality.
Clayton Hunt: We’ve got an application at work right now and the users of the application are like, “This is terrible. We hate it. We need to change it.” So the developers go, “Okay, we’ll rewrite it.” And a particular developer that was working on it said, “Okay, you don’t like it as it is so I shall try to make the user experience better.” And they switched from like a chopped up, bootstrap plus custom. They tried to switch it over to material design and update the controls to be more user friendly and try to fix some of the Ui bugs that were happening. And the initial feedback was, “This doesn’t behave like the existing application. We want it to look and behave just like the existing application.”
Clayton Hunt: And another issue with bad code is it bad code costs money, whether that’s in maintenance or rounding off fractions of a penny and putting it in and do a bank account. I did in fact work on a project many years ago that a rebalanced monthly payments in a nightly transaction system and after months and months of it behaving badly, it turned into what we affectionately called the quarter billion dollar problem. Come to find out it was more than just a quarter of a million dollars was missing from their balance sheet as a result of badly behaving software, it ended up being over $1 million before we really tracked it all down.
Jon Ash: That is crazy. I want to extend that one though because I think that this particular one transcends simply the software. You could basically say bad insert word or word phrase costs money when you’re dealing with a company. So even if the word or a word phrase isn’t specifically the developers job, as a professional it’s still the responsibility to try and eliminate the bad.
Clayton Hunt: Whether it’s bad code or bad design or bad architecture or bad behavior?
Jon Ash: Right. If your architect tells you to do something that you actually think is a bad move than having discussion with them. If you’re a designer tells you to put Unicorns and pink rainbow’s all over the application. If you’re not in that kind of business, then you need to have a talk with them. And if the business analyst or a product owner, depending on your style of development, if they hand you a requirement and the requirement doesn’t make sense or you think is, not good for the business, then you should have a discussion with them about that. Same thing for bad code. Have a discussion with the developer or have a discussion with yourself if you’re the one about to write bad code.
John Callaway: Yeah, it’s all about professionalism at that point, right?
Jon Ash: Right.
John Callaway: So how do we ensure that we are delivering quality, whether it be quality software or just quality in general?
Clayton Hunt: That one’s kind of tough. There is certainly, and we talked about this a little bit in our, care and feeding of developers. There is a certain level of knowledge or wisdom or whatever you want to call it, that you will pick up over time. And without that knowledge or wisdom, it is difficult to know when you’ve crossed the quality boundary and gone over to the bad side, the dark side if you will. So you will have to develop that and that takes time. And if you have a mentor, great. Because that can shorten the amount of time. If not, then it’s a hard one battle. But there are other things that we can do that are pretty simple, like don’t rush through a problem. Is a simple one that anybody should be able to figure out. You know, it’s speed kills and faster kills faster.
Jon Ash: Yeah. I liked that one a lot because, I’ve worked with a number of developers recently. You say, “Wow, you code so quickly, you can solve a problem so fast and deliver on a feature very quickly I said, “No. I think about it for a day or two or for all night long, through on my commute, I’ll think about the problem that I’m trying to solve and once I’m sure that I understand the feature that I’m about to implement, then I’ll go about writing the code to implement that feature. Big proponent of test driven development. So I’ll start with the easiest test that I know that I must implement to make sure that I’m satisfying the criteria as I understand it. And then I just knock out those tests and then I write the code that I know that will satisfy the tests and then I’m delivering the feature.
Jon Ash: Once I start coding, that process happens very quickly because I’ve practiced that for a number of years. What isn’t often witnessed or isn’t as tangible is the hours and hours of forethought that I put into it to really make sure that I understand the problem that I’m about to do address.
Clayton Hunt: Right. And the tools and patterns that you have developed in the past and cap in your bag of tricks to solve certain classes of certain problems so that if you recognize that this problem can be solved with that pattern, you can just reach into the bag, pull out the solution for that pattern and you’re ready to go. But if you had to start from scratch without that pattern, then you’d be just as unfast as everyone else.
Jon Ash: Unfast I like it. I would extend that to even, things like names and having the time you’ve said and think about that. I mean, I don’t [inaudible 00:20:28] how many times I’ve written something and in that refactor set, “Hey, do I need to rename this?” Renamed it, and then to two iterations later, I’m naming it something else different because in the back of my mind, I’m so mauling over it, “Is there a better name here?”
Jon Ash: But then as you’ve been doing that for a while and he’s been working on that, incidents where you’re naming things, a lot of things get repeated and in our line of work. I mean you come across a similar situation and you’re like, “Oh what was the name that I used the last time? Okay this is going to be a similar name and it’s going to be very specific to those sorts of things.”
Clayton Hunt: I’ve been questioning some of that lately because I ended up with a lot of full service and bad service. And I’m like, “Services is not helping in this situation. I’ll just remove it.” But you know internally I formed that pattern a while ago and so my nature is to go straight back to calling something a service even though it’s not helping.
Jon Ash: It’s good to question that right? It’s good to follow those patterns. It’s like what we were talking about with the bad code, we get bad code, good code, we get good … Following those patterns or those were like internal patterns that we’ve set for ourselves. It’s good to follow those things, but don’t ever implement, a pattern even if it’s something that you’ve done yourself without questioning, “Hey, is this the right thing to do or can it be improved?” And if there’s opportunity to improve the drop service because this is not meaningful to me. This is not what this is doing. Right? Find a better name and use it.
John Callaway: Yeah, and in looking at the video feed here, sorry about that to those listening on the podcast, but feel free to watch it on YouTube as well. Just looking at the books behind you there Ash, and then my bookshelf over my shoulder here. There’s, also a fair amount of reading and studying that we all have continued to do, to continue to learn and grow and refine our craft. So, what other tips and tricks to ensure that we’re writing quality software?
Jon Ash: Well, I think I know you guys are all familiar with, the Boy Scout principle, which is ‘Make sure that you leave the code better than you found it.’ Is a really good way of cleaning up code. Doing the small incremental changes are much more impactful and a better approach almost in every situation than a massive rewrite or a massive fundamental shifting of the situation. It’s obviously better if you have some tests or something like that can make sure that whatever you’re changing, you’re not, removing functionality or whatever. But, I think that’s been a huge principle for me to take a system that doesn’t have quality and say, “How do we, move it towards the end of quality?”
Clayton Hunt: Or even systems that, had quality or have quality. Currently have quality, it’s just we did more reading or we had more discussions with the business, with the client, or we just thought about it and I think it needs a different name or this pattern needs to be implemented here or we just need to break up this monolithic class into something a little bit more manageable. It could have been the best code that we wrote yesterday and there’s probably still going to be room for improvement today.
Jon Ash: Yeah. There’s almost nothing in the world that can be improved in some fashion. I would say that the caveat is that the question you have to ask yourself is, “Is the effort that I’m putting in to making this better, delivering the value to make it worth it?” If the code is working and it’s fulfilling the business need, and let’s say it’s clean enough, but you think this name could be a little bit more expressive. If you’re already in that file and you’re making changes, by all means update the name. But if you’re just bored and it’s Sunday, don’t go in and start changing the code because you could confuse your team by doing that. But you do want your team to be in the mindset of while you’re in a space working, feel free to tweak the space to make it a little bit better than it was when you got there.
Clayton Hunt: Yeah, and I would say if you start down this rabbit hole and it becomes a little too daunting, if it’s going to be a larger body of work to implement the changes that you first started on, then maybe back that out. Maybe just add a task when you’re on your backlog and say, “This is the idea that I have, let’s discuss this and see if it’s worth the effort. Let’s come up with some ideas of how we might tackle this and make that improvement in the future.” Because we don’t want to start, particularly if we’re on a deadline or working inside a sprint, we don’t want to start on something that’s going to take us away from delivering the features that maybe might make the most sense to deliver the quality, to fulfill our commitments. We wanted to make sure that we’re focused more on that because that’s what we’ve committed to.
Jon Ash: Yeah. I’ve made the mistake of going into a legacy application and they want to be to make some minor change. And I like testing my code as well as the both of you. So I was like, “I’m going to make this class testable.” Three hours and the 30 files later I decided maybe it wasn’t the best idea and I should go and see if there was another way that I could work with that particular file. Ended up I created an external interface and I made the interface testable and then I could test. And that’s just the file became kind of [inaudible 00:26:27]. But it’s important to say, don’t leave the half done effort. Don’t, comment it out and leave it there, don’t leave it there in place half done.
John Callaway: So this is a little bit out of order and the notes that we have, but, is this an opportunity for to do comment here or what’s your thoughts now? ‘Cause I certainly have strong feelings.
Clayton Hunt: Why don’t you go ahead and say your strong feelings first and then we can respond.
John Callaway: Well I guess I would say that, I would say there’s never, I mean I wouldn’t say there’s opportunities for, to do comments if those are part of your planning for the work that you’re doing. But in this situation like this where you say, “Okay, well, I’ve gotten into something that’s too big, I want to implement this later. It’s not … I see a better thing here. Go make a note in your … So whatever your backlog is, whatever the work item where ever the work items are and bring that, put it in there and let it get scheduled for the rest and don’t clutter up the source code with to do, that would be my … I think I’m with Uncle Bob expunge all comments that aren’t absolutely necessary.
Jon Ash: Yeah comments or just a failure to convey the meaning that you were intended to convey. Right?
John Callaway: Yeah.
Jon Ash: But I think we’re more or less on the same page. I will leave myself a to do comment, if there’s something I’m going to address that day, I will leave a to do comment for myself. If there’s something that’s going to last more than a day, then I’ll have a hard time doing that. If it’s going to last more than, a couple of days or into another sprint, I might leave a to do comment. I will add an A, in item on the backlog. If it’s something that will not fit in this sprint but needs to be addressed in the next sprint then that’s probably where I would be doing that.
Jon Ash: These types of comments for me might be this is a larger feature that has been broken up into multiple stories, if I’m implementing part of the feature and come to a point where I know the next feature that needs to be implemented, here’s a hook into it or here is where I might put it. I’ll probably leave a comment to that effect there with a link back to the backlog item. But if it’s something that’s going to live more than us, sprint or a sprint and a half a to do comment is going to be useless because something else higher priority, we’ll come in and it’ll get knocked off the radar and it will be lost deep inside the code somewhere and then six years later that to do comment is a complete lie.
Clayton Hunt: Yeah, I would say that my opinion is somewhere in between the two. So I don’t use to do comments a whole lot, but when I do, it’s usually because I’ve got a story that, should have been broken down a little bit further. But for whatever reason I wasn’t … Maybe we didn’t think that it was going to be that big of a deal and then it turned out that it was, so I will leave a to do comment, more like a planning steps. So, I’ll comment here’s step 1, step 2, step 3, step 4 and then I’ll go slap it to do in front of all of them. And then as I write the test and the code to fulfill each step, I will wipe out that to do comment. And then from that aspect, I feel like for me at least to do comments are fine to commit, but they are not fine to merge. So I will not leave it to do comments in emerge. Not intentionally anyway.
John Callaway: That seems fair. Yeah, I mean it does keep, committing. Do you want to comment early in a quick early enough. I’m sure you isn’t get. I think that both of you guys, as much as I said I have strong feelings, I would say it seems reasonable.
John Callaway: One of the things I think that is a huge tip or trick or whatever, is really focused on naming. To me naming is like in cities trying to manage crime. They focus on the little tiny things. And the idea is like if we keep graffiti off the walls and we keep glass windows not broken and things up kept, it drives the amount of crime down because it leaves things out of place. And names I think are the broken windows of bad code. If you owe the graffiti of bad code. They’re really simple and easy to change most of the time and especially early, they’re easy to change when you’re near first working on them, but they’re really hard to get right. Sometimes they can be very difficult. And so if you’re focusing on the naming, you’ll want to improve the other things. But if you have sloppy bad names, it makes it really difficult to want to fix the other parts of the code.
Clayton Hunt: I feel like talking about naming gets into the Maslow’s hierarchy of needs for developers. Like you said, “Names are the broken windows, right?” So when you’re at the top of the hierarchy, then your code reviews are being picky about syntax and spacing and, “Oh, this name doesn’t make any sense.” But when you’re in the trenches at the bottom of the hierarchy, you’re just like, “This code doesn’t work.” If it ran, I would totally merge it. But it doesn’t run. I think we should actually put together, if it’s not already out there somewhere, we should put together a Maslow’s hierarchy of needs for developers. But that’s how I feel about naming. Naming is definitely one of those things that is great to focus on. But if the rest of your code is broken, then naming may not be the most important thing to think about right now. It definitely helps when you come back later or when the next developer comes in to that code and they’re trying to work with it. If the names make sense.
Jon Ash: Building on names I think code organization as well, putting classes in folders that make sense in SEG meeting up solutions out into different projects. Clayton, you had mentioned in a previous episode your rule of three to five or whatever that was. Maybe you can briefly explain that, but I think that goes a long way. The organization and the naming will go a long way that shows you care. So of course the system is going to at least compile and hopefully run and do the thing it’s supposed to do to where we’re focusing on what are seemingly small, minor things like naming and structure and organization. Because the larger things, the functionality, we’ve got that down pat now. We’re just making sure that everything is clean, neat and tidy.
Clayton Hunt: For anyone not familiar with I’ll, summarize the roll real quick. Basically, when you’re writing your application, if you do it incrementally, then when you have somewhere between three and five of anything, so three to five methods, three to five classes, three to five folders, it’s time to start thinking about breaking stuff out into the next level. If after folders would be projects and then after projects I guess you’re in multiple solutions, but somewhere between three and five is manageable, somewhere above five is unmanageable. And so it’s, a good idea to start thinking about breaking things out at that point.
Clayton Hunt: I want to throw something in that pairs with organization and it’s not in our outline, but there it’s a psychological thing where when you walk through a doorway, your brain dumps out on the floor and you get a fresh perspective. So literally leaving the room and coming back, you get a fresh perspective on whatever it is that you’re trying to solve. One trick that I have found useful in a writing better code is actually the Pomodoro technique. So you work for 25 minutes, you take a five minute break. When you come back from that break, your brain has been refreshed. So when you sit back down at your desk and you’re like, what is it that I was working on? You get to look at that code as if you didn’t write it and you realize how terrible it was, like right away, and then you can go refactor and so on.
Clayton Hunt: So that’s something that I would suggest, anybody who can manage it. It’s a really powerful technique. It also helps get a lot of work done in a day.
John Callaway: All right, so any final thoughts before we start to wrap up here?
Clayton Hunt: I would say the overarching suggestion here that we’ve made is always try to do better than you’re currently doing. I mean, that’s what all of those things are for. So if you focus on trying to be a little bit better and developer, little bit better person, little bit better whatever, every day then you should improve over time and people will really see the impact.
Jon Ash: Yeah, I will just say a little bit at a time, right? It goes along way the key thing seeking after that improvement. I think earlier we mentioned experience really helps if you don’t have the experience, you don’t have the wisdom already, then it’s going to be difficult to sometimes to be able to determine is this quality or is this not? You have to be seeking after that wisdom in order to get it. You can’t just … Life experience won’t just get it. You have to be open and ready to learn. So you have to be in the pursuit of those pieces. So you have to be, we’re working towards it, but then you also have to be doing a little bit adds up, a little bit at a time. Don’t, feel like you have to get at everything all at once and then that’s.
John Callaway: All right and we want to hear from you. If you out there in Radioland, have any tips and tricks for us or for the rest of our listeners. Then hit us up.
“Tempting Time” by Animals As Leaders used with permissions – All Rights Reserved