My father’s “man cave” was always covered in sawdust. He was a woodworker by nature. He had a normal day job, but I think in his ideal world he would have preferred if people had just paid him to stay in his wood shop all day, building things. He made things around the house, and he made things to sell. He even made a seven-foot long, three-story plantation dollhouse for a show once. It was incredibly detailed, down to the wooden roof shingles, individually cut by hand on the band saw.
My whole life growing up, I was surrounded by his tools. I cannot remember a time before that band saw was a fixture in the shop. Occasionally an older, cheaper tool that he’d started with would be replaced by a newer, better one because he’d earned it. The loud, portable Sears table saw that had moved with us through three states eventually made way for the shiny new Delta that was eerily quiet by comparison. Its motor didn’t scream electricity at you. The Delta just sounded like a powerful wind being thrown from the blade like the loudest whisper in the world. The old saw had a fence that you had to adjust by banging it around with your fist, and then tapping it with a mallet to get it as close to what you wanted as you could manage. The new one had a latch in two-parts with a thumbwheel between them that let you dial in the finer details with extreme precision. He used it to make things better and faster than he could before. Don’t get me wrong, as a true craftsman he achieved fine results no matter the tools, but it was much more enjoyable with better equipment and it let him try things he may not have attempted before.
Woodworking was more than a hobby, it was his zone. I think it just made sense to him, and maybe it’s why he didn’t understand why his son just wanted to “play on the computer” all the time. At some point in high school we had a talk one day where I tried to make him understand that I was making things too. I was just doing it with different tools and materials. He never really tried to talk me into leaving my room to build “real things” much after that, and I’ve always regretted that I may have hurt his feelings that day. I never really got the chance to clarify whether I’d simply turned him off of the idea that I’d be like him, or whether a light clicked on and he saw that we were already the same. I wish he was still around to talk to. I’d like to let him know that he had far more influence on me than he ever realized.
I started using the phrase “Fit and Finish” to describe my professional values a few years ago. I’ve worked for a lot of different companies, with widely varying cultures. I’ve worked for small companies that absolutely shared my values, and for large companies that maybe didn’t, but at least had a smaller division within them that did. I’ve been part of the screening process that determined whether a candidate was the right cultural fit for that division, and whether to keep someone on when they weren’t. I’ve had to remove myself from more than one company that did not share my values, or said they did on paper, but didn’t take them seriously. Some organizations say they share my core values, but they really only view them as marketing terms to be promised to clients, but never fully pursued and realized. Liberal use of the word “craftsmanship” makes it sound like you know what you’re doing, and the odds that the client will know the difference are vanishingly small, otherwise they wouldn’t need to hire you, right?
My upbringing makes it somehow impossible for me to just throw something out there that’s good enough to fool everyone else and move on. Like any artist, I know where every flaw is, and I can’t unsee them. Yes, I called myself an artist, and what I do “art”. That’s how I view it, and that’s how I treat it, otherwise what’s the point? If you’re just in this industry for the paycheck, then I can’t even relate to you. If your company consistently values short-term profits over long-term reputation, then we simply can’t work together. I have a need to feel proud of the work I do. I need it to be understandable and maintainable by the next member of the team.
Some companies only want to think as far as rough framing; what I consider carpentry. Me? I’m into fit and finish; what I consider cabinetry. They’re different. Just because it’s the shape of a house and keeps the rain out doesn’t make it a home. There is a ton of work that goes into “finishing” a house, and you can expect that all of that work will be inspected by someone whose job it is to find any mistakes in the plumbing or electrical work before they are sealed up behind the drywall. Then, someone is going to inspect the drywall before the trim goes up. Finally, someone’s going to inspect the trim.
That’s not to say that everything has to be perfect. One company that I left called me a perfectionist on a review, and that was somehow meant as a negative comment. Clearly this relationship was not going to work out. I am not a perfectionist, not by a long shot, but there is a minimum bar of quality and correctness that I won’t compromise, and I think it comes down to my definition of “good enough”.
Good enough to pass code review is not good enough. Good enough to pass QA is not good enough. Good enough that the client won’t notice the bugs and limitations during UAT, or during the warranty period is not good enough. Good enough to get the job done, however, IS good enough. My current project uses ASP.Net MVC’s built-in Inversion of Control (IoC) container. Why? Because it’s good enough. It does everything I need, and should continue to do so. If I run into a scenario that it can’t handle, then maybe I’ll swap it out for something more full-featured like StructureMap. Until then, it’s truly “good enough” because it’s all we need.
Maybe I should say it’s “good enough for now”, which is a subtly different concept. Did you choose a component because you aren’t exactly sure where a project is going to end up, and you don’t want to invest time in something you may not need? Then you’d be correct in going with “good enough for now”. If you chose a component because someone else, perhaps the client’s internal development team, will be taking over the project before it ever has a chance to become “your problem”, then that’s a bad choice, and a terrible attitude. If you justify it by smugly saying the word “agile” at me, I will kindly ask you to leave my team.
You can find a buzzword to justify anything you want. If you blurt out “yagni” because you simply can’t be bothered to draw on experience, or worse yet have insufficient experience to draw on, then you should go work on smaller things for a while and learn. When a more experienced developer says you’re going to need something, you’re probably going to need it. Why? Because they know enough to know that you always end up needing it. So go ahead and tell me why we don’t need to build logging into the system from day one, and you can have fun retrofitting it onto your other systems later on when you turn the corner. The voice of experience should be listened to. People know things.
One of the things I try to drive in every team I’m a part of is consistency. I don’t want five different ways of solving the same problem. That doesn’t just mean refactoring out repeated code. I’m talking about patterns. One of my pet peeve symptoms on an older system is observable strata in the code. Can you view your codebase like an archeological dig? Can you tell which controllers were written during the “Bob” era and easily tell them apart from the ones written in the “Fred” era? Are there old controllers or services that are written differently than the current ones? If so, why? If the old way was “good enough”, then why is there a new way? If it wasn’t good enough, then why wasn’t the old code updated?
Some teams are uncomfortable going back and messing with “finished” code because they’re afraid of breaking things. That’s what unit tests are for, my friend. If you’re not on board with the value of testing, then you’re just not on board with quality as a selling point in the first place, and that’s an entirely different conversation. I should be able to fearlessly change code patterns and have my confidence backed up by a wall of green lights telling me that I haven’t broken anything. I should use professional-grade refactoring tools to make certain kinds of changes for me, and have absolute confidence that the resulting code is functionally equivalent to the code I started with.
Approaches and patterns change. We grow, we learn, we adapt, and that’s fine. Don’t leave old code behind though. Upgrade it to the new pattern or don’t have a new pattern, you just have one more way of doing the same thing, and that’s bad.
Returning to the house metaphor, imagine the kitchen cabinets. You’d expect them to be installed consistently, right? You’d expect all of the knobs and hinges to be the same type, and installed at the same height, right? If, partway through the construction of your kitchen, one of the apprentice carpenters with something to prove discovered that mounting the hinges just one inch further toward the vertical center of the door relieved stresses on the hardware, and could be mathematically proven to increase the hinge’s lifespan by fifty percent, would you want him to hang the remaining doors with the hinges positioned differently than the ones he’d already finished?
If that apprentice decided that given the average height of your family members, moving the knobs on the cabinet fronts downward by two inches would result in a better, more ergonomic experience, would you want him to install the remaining half of the knobs in a different position than the first half? Of course not. The inconsistency would be right there, staring you in the face the entire time you live in that house. You’d never unsee it. It would irritate you every single time you look at the kitchen cabinets and see that half of the knobs are different.
It’s not that different when developing software. I don’t want to have to keep track of the difference between the “Bob era” and “Fred era” controller patterns. If Fred is unwilling to upgrade all of Bob’s older code to fit his new pattern, then Fred should just create an entry on his “to do” list until he either finds the time to upgrade everything, or starts on the next project where he can adopt the new pattern up front. If Fred truly needs to make a change because Bob’s pattern won’t allow him to do something that he absolutely needs to do, then we might be able to make an exception, but that’s different than establishing a new pattern. Never change how things are done “from now on”. Change how things are done… period.
You might be asking “why?” Is it just me being pedantic about things, or obsessive over consistency? No, there are reasons. When I bring a new developer onto the team, I want them to fall into the pit of success. When I assign them their first controller feature, I want the rest of the controllers to be examples of the way things are done on this project. I don’t want to have a conversation where I have to explain what the good examples are versus the bad ones. On top of everything else the new member has to learn, why should he or she need to learn the underlying archeological history and strata of the project, and remember which examples are current? I want them to find “current” at every turn. I want my projects to look like they were made by professionals.
If I hand this project off to someone else, how difficult will the knowledge transfer be? How much tribal knowledge is required to work on it? As a consultant, it is my job to leave. When that happens, I want the developers that take over the project to look around and say “that makes sense”, or at least “that’s consistent”. I don’t want them to find five different ways of solving the same problem with no objective way to figure out which one is “right”. What if they’re both right, and Bob and Fred simply have different opinions and styles? Can the new guy tell that by looking at the code? No, he can’t. All he can tell is that there are two different ways of accomplishing the same task.
“Fit and Finish” is about looking like you know what you’re doing. It’s about looking like a professional, and not someone who’s just winging it. In a previous post, I talked about how we, as an industry, are still trying to figure out what we’re doing, and that still applies. Everything we do will still be laughably out-of-date in two years time. It’s okay to not have all the answers, but you owe it to the clients that are paying you to do the best you can with the knowledge you have, and to pass that knowledge on as simply and easily as possible. Your code shouldn’t be a loose collection of clever hacks. It should be a purposeful, thoughtfully composed system of components designed to work with and compliment each other.
Take pride in your work. It matters. It shows.