Dear future-self, I meant well at least

Posted by : on

Category : coding


The other day a co-worker of mine asked me an interesting and difficult to answer question:

How do you determine whether to take the time to fully design and implement a robust and well-architected solution to a problem as compared to utilizing a solution that will handle the immediate issue/needs of the problem at hand?

I both love and hate questions like this. It shows a true concern for balancing doing things “right” as well as an understanding that it’s often easy to get carried away with what “right” means, but answers to questions like this are so situational and cultural that it’s difficult to respond to. So, I’d like to share some of my thoughts, as highly-opinionated and potentially incorrect as some may interpret them to be.

I’ve had numerous years of experience in software development and delivery, and I’ve seen some beautifully designed and implemented solutions that flex to meet unexpected future requirements, and I’ve seen those five-minute hacks that cripple production systems and make folks reach for their resumes. However, I’ve also seen robust architecture crack under its own complexity, or require such complex refactoring that it would be easier to start over. At the end of the day, past-self (That’s probably you today) always has a thankless job. If you do things right, it’s as if you’re never there, if you take the shortcuts, odds are future-self (The jerk you’re likely to see in the mirror in a few months) will be cursing at you later. I like to think of this relationship between past, current, and future self any time I have to make a decision regarding complexity and design, and try to treat my future self as kindly as possible.

The first thing I analyze when I’m worried about whether to spend time designing vs. implementing is: why am I even considering not taking the time? Typically I’m either being lazy, I’m pressed for time, or I’m not sufficiently familiar with what I’m working on if I am asking these questions. If I’m being lazy, future-self is sure to hate whatever code I write, and I’m likely to have to re-do this effort later because of it, and it’s a pretty easy decision (if I’m only going to bother myself, sometimes I stay lazy, but if it’s for work, a client, or something I care about, I’ll take the time needed). However, the other two cases are where I feel further thought is necessary.

If you’re working on a project without sufficient experience in its technology to design a robust solution, there’s a huge opportunity for learning, but spending a ton of time searching for best practices and how-to’s to write some theoretical code will often result in lots of time spent, and little to show for it. On the flip-side, diving in and trying to write code on something you’re not familiar with is a guarantee of low-quality, inefficient, and future-self-maddening code. My personal experience has found that the best results come from accepting that fact, and building re-factoring in to the process. Instead of spending hours researching the ‘ideal’ way to do something, start with something and do your best to get it working. Then, once it’s operational, don’t accept it as done. Refine it. Find a way to make it faster, cleaner, more flexible, or more conforming to a standardized style. Examine how your code differs from what you’re seeing in searches for similar solutions or examples, and make it that little bit better. Good, working better now? Stop and do it again! Maybe tackle a bit more of the project first, but don’t consider that “working” code to be acceptable. Keep comments that say “TODO: Make this future-friendly”, and get back to it immediately (Not “when the project is done I’ll clean this up”. We all know that doesn’t happen). You’ll learn what bad code looks like sooner by writing it, and then analyzing how it fails than by trying to search for perfect code on Google. Don’t be afraid of refactoring, of starting from scratch half-way through. Accept that working on a project as a learning experience is going to require triple the effort, and don’t get attached to your code. Remember: future-self doesn’t have any attachment to current-self’s code, and he can’t remember your excuse for why it was acceptable to take that shortcut.

The other circumstance I see a lot is the heavy hand of time-constraints. “We’ve got three days to get this working”, or “how soon can you get this done?” should be red flags that future-self will be cursing at you. If you’ve got a set amount of time to get something working, you’ve got a few options: Shortcut everything necessary to get there, and be ready to spend three times as long (Heh…if you’re lucky) fixing that mess down the road and trying to make sure your superiors understand the cost. Doing some parts well, and others poorly (still going to be just as messy to clean later, but you’ll forget what parts were good). Or doing things right, and either not delivering on-time or at all. There’s even the occasional (and advised against by future-self, trust me, we talked) herculean “do everything right within the time-box” approach which means stress and mistakes. Sometimes it will even end up that you were worried about nothing to begin with. The right answer should be: Do things right and adjust your expectations accordingly, but that’s not always an option. I’ve yet to find the solution to fixing management’s lack of understanding that last statement, but I’ll write a book on it if I ever succeed.

Along these lines, here are a few thoughts and some generally biased advice around writing code that rocks:

  • Take ownership of your code’s quality
    • Your job may be demanding, deadlines looming, bad past choices haunting, but at the end of the day the quality of any code you produce is yours alone. Take pride in what you’re putting out there in the world, it affects how you see yourself, how others see you, and quite possibly how you will be remembered. Don’t blame your circumstances for your failures, and when you see your own bad code, remember that by simply recognizing it as bad, you’ve already grown to be smarter/better than you once were, and cherish the journey.
  • Teach your environment to respect you and your needs
    • Take care of yourself and what you need to make your code good, and focus on eliminating what detracts from that. If that means you have to take twice as long to do your job right, then perhaps that needs to become your new operating pace. If your boss is making unobtainable demands, confront them, and if that doesn’t work, consider whether you need a better employer or boss. If distractions keep you from doing your best, write code in distraction-free environments. If your keyboard is bothersome, get a new one. This stuff is easy to fix when you identify it, and refuse to accept your status-quo from keeping you from being your best.
  • Balance your doing vs. planning vs. research time
    • It’s important to plan out work when it’s sufficiently complicated, and it’s also important to research topics you’re working on in order to do well at them, but if you’re not keeping tabs on how much time you’re spending doing vs. planning/researching, it’s very easy to let any one of the three spiral out of control. If you’re not doing any kind of planning or research, you may want to consider slowing down and making sure you aren’t burrowing down a hole that’s hard to back out of. If you’re spending more time planning out your work than doing it, perhaps you don’t understand what exactly you intend to do (or need better management in general). If you’re spending your days reading up on tech and not implementing anything it’s going to take you more effort to get rolling when the time comes. There’s no X% planning/research/doing that defines “in balance”, it’s a personal thing, but you’ll know when you’ve reached balance, because the frustrations and friction that each of these causes in imbalance disappear.
  • Trust yourself and embrace your mistakes
    • It’s easy to fall into a trap of doubting your capabilities, or the robustness of your solutions and to over-analyze or critique your own work to the point where your fear of doing things wrong keeps you from doing anything. You have to trust that (assuming you are taking the time to build in quality) you can do things well, and allow yourself to learn from mistakes to improve continually. You don’t become great by waiting around until you just have greatness, you become great by failing (a lot) and learning from your failures what it takes to be better. How many times do you think the great sculptors made sculptures with imperfections before they were recognized as amazing artists? How many of those same artist’s most renowned works are truly perfect?
  • Learn about coding dynamically
    • Software code is incredible in that every problem can be solved in innumerable ways, and frequently a good solution to one problem can be re-used to solve another. It’s a rare many-to-many relationship that should not be ignored. So I encourage you: When you encounter a problem, try to make your solution a bit less tied to the exact problem you’re solving, and more at the type of problem you’re solving. This doesn’t always apply, but I can’t tell you how happy you’ll make future-self when they can take some past-self solutions and use them to solve future problems. Learning how to think this way is an art, but it’s very rewarding in both time savings and satisfaction. Make your code dynamic enough to handle the problems you will solve later when you can.
  • Surround yourself with excellence
    • Learning from your own mistakes and experiences is invaluable, but there’s another fantastic way to accelerate this: learning from your peers’ experience. This can be attending conferences where folks that use the technologies you do explain what they are doing and how they’ve conquered their own problems, it could be sitting in an IRC channel seeing the problems others encounter and participating in finding solutions, or simply spending a few evenings a month in the company of thought leaders or co-workers idly chatting about the technologies you’re passionate about. You never know when an old co-worker will encounter an issue or tackle a problem that will save you hours of frustration down the line, or when you’ll do the same for someone else.
  • Remove the pedestals from your heroes
    • It’s very easy to treat the creators of your favorite tools/languages/etc… with the same kind of isolation and admiration that American culture places on our celebrities, setting them aside as somehow different or untouchable. (I’m guilty of this) But technology isn’t this way, and the people that wrote those tools are often just other passionate developers etc… out there sharing their own solutions (Mitchell Hashimoto‘s story is an inspiring example of this). Don’t be afraid to talk to the ‘heroes’ of technology, you’d be surprised sometimes how happy they are to interact with their communities (and worst-case, you’ll end up with an email in a ‘deleted’ box, no harm). Open pull requests, start conversations in IRC chats and Slack channels, comment on issues. You never know when you’re going to be the voice that reminds someone else why they love coding. I have recently learned this lesson, and it’s been incredibly empowering and energizing to realize how friendly and passionate the Puppet communities and thought leaders I admire are.

I hope my ramblings strike a chord and perhaps provoke some positive thoughts out there. There’s an unfathomably huge amount of code out there in the world, and I want to do my part to encourage more of it to be code that rocks, and to save us all (or maybe at least myself) from the wrath of future-self.


About Josh Souza
Josh Souza

A technologist and roller skater.

Email : development@codethat.rocks

Website : https://www.codethat.rocks

Categories
Useful Links