Anonymous Listener Question: Cowboy Coders
Published 6/2/2017
In today's episode, we talk about cowboy coding, and how to deal with a legacy project primarily managed by cowboy coders.
Today's episode is sponsored by Fuse! Build native iOS and Android apps with less code and better collaboration. Head over to spec.fm/fuse to learn more today!
Transcript (Generated by OpenAI Whisper)
How do you deal with a project that was handed to you in a terrible, terrible state? That's exactly what we're talking about in today's episode. My name is Jonathan Cutrell, you're listening to Developer Tea. My job on this show is to provide you with the insights and the information, the conversations, the inspiration and the interviews, all of these things to help you become a better developer, to help you level up in your career. That's our motto at spec. And that's true for designers and developers and anyone else who's listening to this show, you know, a lot of the things we talk about on the show really apply across the board. They're not limited to only developers certainly. And I believe that they're also not just limited to digital people working in the digital sphere either. I think there is a ton of value in some of the discussions we have on the show, some of the people who come on the show, some of the methods, these are not things that I've made up. It's stuff that I've learned and that others have learned and I've learned from others and experience and data and research and all of these things I bring to this show because I believe that it really can help you in your career. I wouldn't do this for this long if I didn't believe in it. So hopefully you have, many of you have reached out and told me that this show has helped you. Hopefully you will experience this too if you're listening to this show and you're not finding it valuable. First of all, I'd love to hear why you can email me at developerateatgmail.com. But also I don't want you to stay and waste your time. I really only want people who are getting value out of this show to spend their time listening. I don't want you to stay and waste your time listening. So certainly if you are getting value out of this show though, I would love to hear from you and I'd love to hear your questions. Like today's question, today's question comes from a listener who wanted to remain anonymous because the sensitivity of the subject that they're asking about. So I'm going to go ahead and read this whole email because the entire thing has a lot of really interesting context and perhaps we'll strike a few chords from those of you who may find yourself in similar situations. Our anonymous listener writes in and says, love your podcast. Listening to it helps keep me sane. I have a question for you to cover which would rather be anonymous for obvious reasons. What can you do as a new developer when receiving a project being handed over from a company contracted to develop a project for your employer? When they have no handover documentation, no inclination even try to write some, a lack of standards and by this, I mean no coding standards, no data dictionary, table names and field names and a database switch from the plural to the singular. If you're lucky, if you can see any relevance between them, they use magic numbers instead of meaningful constants, etc., etc. No unit tests, no diagrams, except for what I can generate for myself, nothing. Up the creek. I could go on, but essentially they appear to be the absolute epitome of cowboy coders made real. They do appear to use version control as there's a dot get directory present, but commit messages range from dot dot dot to meet meet. One of them is probably a road runner fan, perhaps. Anyway, I have run analysis tools like PHP, Doc, Java, Doc, JS, Doc, etc. over the code base, which does help to some degree, but as you might expect, this can only be of use if the Doc blocks are kept up to date or even written in the first place. So I can't really place much faith into that either. Static analysis tools show way too much duplicate code, dead code and technical debt. For example, there is a 1000 line method inside of one of the controllers. UML diagram generation tools kind of help, but only so far because of the disparity between table and field names and what they, the tables, etc., are actually used for. I fear they just add to the confusion rather than help figure out how their code and their database actually works. As I'm new to the company and honestly, even if I wasn't, I want to prove that I'm everything these guys aren't, but aside from telling my employers that we should really just rewrite everything, what would you do? And what can others do to not go through this? What I mean is when contracting software development out to a third party, how should a company ensure what is developed by that third party is top notch with good documentation and processes? I am aware of source code escrow, but I'm not sure if that applies in this situation. Don't get me wrong. What they've delivered as a product is exceptional. It works and has a nice, shiny UI. Under the covers though, it's a completely different thing. Thanks for reading this and I apologize. This scenario gives anybody nightmares. I'm sure you can understand why I want this raised as an anonymous question. For the sake of today's episode, I'm going to call our guest Max or our question asker today. And your name is Max. Thank you so much for writing in to Developer Teafirst of all. These kinds of questions are real life experiences that many developers who are listening to this show. They have had these experiences and I myself, I've had very similar experiences. This is a legacy code, a very common legacy code scenario and you're right. It is a cowboy coder's scenario. And let's be very clear about something. This is not an easy problem to solve. There's not a one shot solution that's going to answer every single one of these questions. But I do have a plan for you, Max, that I think will provide at least some clarity and some direction and give you ways of answering some of your questions. I don't want to give you that right after we talk about today's sponsor, Fuse. If you have ever done app development in a normal environment, meaning if you've done iOS or Android development or even macOS development, you probably have seen basically the same tools even for decades. If you've been in the industry for a long time, you haven't seen those tools change very much in decades. And the tools that we have are good, but they could be better. We could evolve our tool set. If you've ever worked in game development and you've used an app called Unity, you know this to be true. If you've ever worked in a highly integrated development system, then you know this to be true as well. There's a lot left in the space of developing new tools for app development. Well, that's exactly what Fuse has done. They've created a one-stop solution that installs on a Mac or installs on a PC. If you build apps with Fuse, that can then be deployed to iOS or Android. It's all in one solution that allows you to write a little bit less code and focus on the product a little bit more. Go and check out what Fuse has to offer to Developer Tealisteners by going to spec.fm slash Fuse. That's spec.fm slash Fuse. Thank you again to Fuse for sponsoring today's episode of Developer Tea. So we're answering anonymous listener who we're calling Macs today. We're answering many questions that were raised about legacy projects. And I'm going to attack a few of the questions. I'm going to kind of reformat these questions so that we can kind of break apart the different problems that we're really trying to solve here. Because we could end up with a code based like this ourselves. If you've ever worked on a project where you yourself left the project for a while and then came back and it was in a similar state. In other words, you had no tests, no documentation. All of your static analysis tools are revealing problems. But the final product is still relatively good looking from the outside in. This kind of scenario is not only when you are receiving a handoff. This can also happen over time inside of a company, especially when you haven't learned best practices if you're a relatively young developer and your company has relatively young developers in it. And you don't have a lot of mentorship and you weren't raised so to speak to perform the documentation practices and the writing correct commit messages, those kinds of practices. Then you probably will end up in the scenario. This was my scenario as well. And the company that I work for now in our very early days, a lot of the work that we did ultimately, we didn't really think about transferring that work. We didn't really think about the possibility that another person may work on this project or that I'm going to work on it at a date that is late enough into the future that I won't remember what I was even doing. So our sole focus is on this one thing, this outcome, right? The final product that I can see from the outside looking in and not on the business, right? And the reason for that, let me walk that out for a second, for those of you who don't totally connect with that. If your focus is on the business, then you can recognize the threats that writing bag code poses to the business. So think about it this way. If your code poses a threat that is realized in three months from now, even if your UI is beautiful, then bag code eventually is going to become as big of a business problem as bad UI. Hopefully, we can all connect with this and usually developers agree with this that solid code isn't as nearly as important or as important as any other part of the project is making any other part of the project high quality. So we're dealing with bridging that gap, at least from an operational standpoint, to make good code a priority. And Max, it sounds like you have this as a priority for yourself and that you are communicating this priority to other people. And it also sounds like your superiors, your bosses, whoever they are, are also, they will appreciate the good code as well. So that's a hurdle that a lot of people are facing. It doesn't sound like you're facing that hurdle, Max. But the other hurdles that you are facing really is a very common scenario. And I want to kind of tackle a few of them head on and then give you a roadmap to get out of this situation. First of all, a lack of documentation. This is a big and difficult problem because creating and maintaining documentation is expensive. It is very expensive. It's an investment. And as many people have found out, sometimes bad documentation is even worse than no documentation. Because if you have bad documentation, then you're trusting a source that shouldn't really be trusted. Those updated Doc blocks, as you mentioned, Max and your email, those are incredibly important. Once you start maintaining a documentation. So lack of documentation is a common problem and sometimes is going to continue into the future until the project becomes of such a size that documentation at a detailed level is warranted. What I would recommend for an initial documentation effort is not to create extremely specific documentation on what the code is, but rather to explain the purpose for the code. So for example, you mentioned controller in your email. It's likely that you're using some kind of MVC structure, so it would make sense for you to provide some general kind of architectural documentation to begin with. Now this isn't the roadmap. We'll get to when you would actually start doing that documentation, which is not on day one. I want to be very clear about that, not on day one. But eventually, you may get to the place where documentation is warranted, but not at a specific method to method level. A lot of times, that's overkill, first of all. And secondly, because of the risk of that documentation going out of date, and because of the cost of keeping it up to date, it may be prohibitively expensive to do that. So a lot of people, instead, like I said, they'll do a higher level documentation. Another reasonable way of handling this is to provide very good commit messages. You've already identified that this is a problem in the project. So really, we're going to essentially ignore a lot of the previous commit messages, unless you can find ones that were particularly useful. And instead, moving forward, use commit messages as a reasonable starting point for when that project is starting to gain some documentation and meta information to explain why things are the way they are. Another problem that you mentioned here has nothing to do with documentation at all, and rather it has to do with consistency, consistency in table names specifically is something that you mentioned in your email max. And this sounds like this is a switch in methodology. So what you will likely see is a mirrored methodology in the code base. This is kind of a sign that wherever those table names are referenced, you might see, for example, a different database connector. For using PHP, you may see a PDO versus an older, you know, direct my SQL connection or something like that. So differences in the database, it usually means that there's two different opinions and also very often two different structures or two different tool sets. So you may see both of those two or more, but you may see two different tool sets being active. So a lot of times in older projects, especially on the web, we would see two ways of doing JavaScript. You'd have maybe jQuery and then also MooTools. This is a very common accident or perhaps a very common bad practice that web developers would use because it was a tool set they knew and they weren't thinking about the implications of using overlapping tool sets. So look for that as you start cleaning up the code. But let's go ahead and dive into this roadmap that I'm mentioning a few times here. Because there's still a lot of questions that are being asked in this email. For example, there's no tests. There's nothing to verify the code, right? There's all of this information is around the code and also in the code. So that's really the two categorical things that are being asked here. The code quality itself is not very good. It's not very consistent. But then secondarily, the surrounding information to tell you about the code is also not very good. However, there is one thing that you identify as very good. That is the product itself, the outcome. This brings up a very good point. We aren't going to stick on it for very long because I do want to get into a roadmap to get you out of this situation, Max. But I want to drive this home here because I think it's incredibly important to understand. The quality of the end product is almost agnostic to the quality of the code because code is a communication mechanism. Code is a communication mechanism. You are communicating as a human to a machine, but you're also, perhaps more importantly, communicating to other developers. So the machine doesn't care about variable names. The machine doesn't care if you are using magic numbers or if you're using constants. The machine doesn't read documentation. For those reasons, very poor coding practices, assuming they aren't greatly affecting performance, very poor coding practices can absolutely function to the effect of a good outcome. We have to learn as Developer To separate those two concepts so that we can instead talk about what good code does actually provide. Good code does not equal a good product. This is a fallacy. Good tech, solid, maintainable code does not mean a good product. But what it does mean is mitigating risk for the business, mitigating difficulty in developing a good product. This is a hugely important distinction because you will run into situations where your client is asking you to do the minimum thing that is necessary or to do the thing that is quickest path to the effect, the final solution. And you as a developer have to be able to weigh the cost versus the benefit. If you adopt new technical debt, which is what this term really comes from, you're buying into the quick solution so that you can get to that effect, but ultimately building those maintainable pieces of code and building communication mechanisms like documentation, these are all in order to make the development process more stable and ultimately more predictable. And hopefully in the long run, actually a faster pace seems counterintuitive, but in the long run, if you take into account all of the bugs that you will experience, if your code is difficult to read or if it is difficult to maintain, you're going to experience more bugs because you're going to be more prone to errors. Okay, Max, you already know all this. This is why you're wanting to go into a different direction. So I want to give you a roadmap out of this scenario because it sounds like you're in a doom scenario and very often as developers, we have the tendency to think that rewriting is actually the best answer. And a lot of research has actually shown that refactoring is a much better answer nine times out of 10. And in this scenario, I think that's true as well. And here's why. The stuff that you have in front of you, Max, the code that you have in front of you, despite all of the negative pieces of that code, despite the lack of documentation and the poor naming of the database tables and the constants, the magic numbers, all of this is information. It's raw learning. It's things that the developers, regardless of their cowboyish nature, coming before you, those people, they learned things that if you were to start from zero, you would have to relearn from zero. You would probably have to learn with a lot of trial and error. Now don't misunderstand me. I'm not saying that the code in front of you has everything learned, right? Not all of the knowledge is necessarily good. And perhaps there's quite a few errors in their knowledge, right? But nonetheless, someone has come before you and they've learned something and you can learn something from what they have provided you. It's very similar to, let's say, raw notes for a movie script. Even though there doesn't seem to be any direction or organization in the notes and even if there's grammar errors, maybe there's random sketches here and there. If the product would end up being good, right? If they were a talented writer, they had a good story, but it was hard to see it. It was hard to conceptualize what was going on in those notes. It wouldn't really benefit you to just take the notes and throw them away, right? It would benefit you more to try to understand what's going on in the notes and then try to create structure and take advantage of the good parts of those notes. So that's exactly what we're going to do with your existing code base. So here's step one. This is your day one starting goal. I want you to identify the number one critical path. All right? This is this is very first step and this is going to be a recursive process. Let's go ahead and prime your brain for that. But identify the number one most critical path, whether it's from a user or from a computer running a script, whatever it is, identify that critical path and then do everything you can to understand exactly what pieces of code that critical path is running through. All right? Once you have that figured out, then I want you to refactor along that path. That sounds simple. It sounds maybe overly simple. But what this is going to do is it's going to provide you the context you need to be able to rebuild the code one piece at a time or perhaps a better way of saying that is refactor the code one piece at a time. This is effectively an agile method, right? It is taking the most important things and moving them to the very front of what you plan on doing. I don't want you to make a wide sweeping code changes. I certainly don't want you changing massive parts of the code or deleting massive parts of the code until you understand exactly what that code was intended to do. Now as you go along, as you find things on the critical pathway that shouldn't be there, right? That is indeed dead code and you can verify it, then remove that dead code. But this is how we begin a refactoring process, build those critical pathways. The most important, the highest value pathways, rebuild those one at a time. The most likely outcome to this is that you're going to start becoming more fluent with the code base. In other words, you're going to start to understand and gain some level of intuition for what the cowboy coders were thinking, right? So you'll start understanding what objects are in the system. Perhaps you'll start understanding the naming structures that one or two developers were using and you'll be able to gain intuition to know where to look for the next thing. As you go through this refactoring process, a few things that I want you to do. Number one, I want you to version control and manage each refactoring in its own branch. This is a very simple feature branch. You can Google feature branch workflow, a very common way of doing work. But basically, the concept is to keep things sequestered, keep things contained in their own branch and you can use this concept anyway, really. But keep things contained based on the refactor that you're doing, based on that wine critical pathway. The second thing I want you to do is I want you to write in plain English or whatever your native languages, write out the method or the pathway, write it out in plain English. What is doing? What are the involved pieces of information? When does it happen? What is the life cycle of the application when this particular thing happens? As you build other critical pathways and as you create documentation between these, you're going to also start seeing places where duplication may be best resolved with some level of abstraction. This is how refactoring occurs. I highly recommend you go and check out refactoring patterns. There's tons of great resources out there. We've talked about some of the refactoring patterns, some of the design smells and the anti-patterns, that kind of stuff on the show before. Perhaps my favorite site for this is sourcemaking.com. They have some really good information there, very thorough walking you through some of the most common refactoring and anti-patterns and that kind of thing. Go and check that resource out. It's very detailed and incredibly educational. As you're going through the process of refactoring, you will be able to apply these well-tested and proven ways of doing that refactoring. These things are very specific. They have very specific shapes to them. As you go through the app, you're going to identify every critical pathway. The first most critical and then the second most critical. As I said, this is a recursive process. Once you get to the end of all of the critical pathways, most of your code should be refactored. You should have identified places that seem to be completely out of left field. Maybe they're totally unused or dead code entirely. You should be able to identify duplicate libraries and dependencies that really shouldn't be in there. All of this stuff should come through you getting more familiar with the critical pathways in the application. Thank you so much for listening to today's episode of Developer Tee. Thank you to our anonymous listener who we've referred to as Max. For sending in this fantastic question, such a lot of things going on in that that I think so many people are going to identify with. I will probably continue to talk about some of these ideas in future episodes. Certainly, I've talked about them in previous episodes as well. You can find all of that stuff at SPECT.FM. Every episode of Developer Tee is on SPECT.FM. There's tons of other great content on there for you as well. Thank you so much for listening. Thank you again to Fuse for sponsoring today's episode of Developer Tee. If you have been doing app development the same way for years, specifically for mobile app development, go and check out Fuse, SPECT.FM slash Fuse. They have created a tool for you to use. It's incredibly easy to install on Mac OS and on Windows. It allows you to develop all in one place. It's like Unity if you've very used Unity for game development. It's like that for app development. Go and check it out SPECT.FM slash Fuse. Thank you so much for listening to today's episode. Don't forget, if you don't want to miss out on future episodes of Developer Tee, which you almost certainly will, go and subscribe in whatever podcasting app you use. Thanks again and until next time, enjoy your tea.