Archive – Page 6

Just Say No to GDD: Guilt-Driven Development

When I finally decided to ditch PHP back in 2006 and learn Ruby on Rails, one of the main reasons was that PHP just wasn’t fun anymore. I’d previously built my own custom web framework using the latest hotness of PHP 5 soon after it was first released. But then Zend announced their official web framework, and I figured my little project didn’t stand a chance. (Interestingly, Zend Framework didn’t end up being that huge of a deal and a lot of PHP programmers are using other frameworks. But I digress.)

I didn’t like how Zend was doing things when I looked over the initial docs, so I decided just to jump ship and try RoR. My own framework was already somewhat influenced by Rails, so I figured the learning curve wouldn’t be too high once I got the hang of writing Ruby code.

Boy oh boy, did I fall in love with both Ruby & Rails. I’d never had so much fun programming in my life. Finally a language and a methodology of writing websites and webapps that felt simple, clean, fast, and maintainable.

But then a few years went by. New updates to Rails. New tools. New gems. New philosophies. New testing frameworks. New client-side Javascript frameworks. New server deployment best practices. New things to learn Every. Darn. Minute.

Suddenly, writing Rails apps didn’t feel so much fun anymore. It felt difficult. And I felt guilty. Guilty I’m not writing enough tests (and not using the right testing gem). Guilty I’m not setting up my servers right. (Darn it all, why even set up servers? Use Heroku, right? That’s what all the cool kids use.) Guilty I’m relying on server-backed HTML views. Shouldn’t I learn HAML anyway? Skip that, just use JSON on the frontend and Handlebars on the front end. Actually, why even use Rails for a simple JSON API? Just use Node.js and be done with it. Bye-bye Ruby.

What?!?! This is madness! I left the world of PHP and learned Ruby (and Rails) for specific and valid reasons, reasons that simply hadn’t stopped being relevant for producing web software. Certainly competiting technologies might have an edge in one area or another. But my criteria for evaluating languages and frameworks hadn’t changed.

Is it fun to read, fun to write? Is it concise and easy to understand? Does it embrace the way the web works or does it try to do something weird or non-standard? Does the community and the tooling/best practices/packages/etc. seem to be top-notch?

In all of those areas, I remain quite pleased with Ruby on Rails, and in one particular area (client-side interactivity or “rich UI” instances), I have found an amazing tool in Opal, a Ruby-to-JS transpiler with which I have developed (what, again?) my own custom front-end framework. Actually, it’s barely a framework…more a straightforward way to organzine code and objects in an MVC pattern suitable for client-side development. YMMV. If you want to stick with popular JS client frameworks, knock your socks off.

Editor’s Note: Since I wrote this article, ES6+ took off along with Webpack, Stimulus, and LitElement, so I no longer use Opal. But hat’s off to you if you do!

My point is this: after a period of falling prey to that terrible practice known as GDD: Guilt-Driven-Development, I finally snapped out of it and realized that the only person forcing me to look at tools and technologies I simply don’t want or need was myself. As long as there’s a job open somewhere for a Rails developer, I’m good to go. And I don’t need to learn every single darn gem on the planet. All I need to learn is what I need to learn to do a good job building exactly what I need to build and no more.

So, I’m thankful I was able to leave GDD behind and embrace a better practice, which I call HDD: Happiness-Driven-Development. When I’m happy, I write better code. I care more about why I’m writing it and what’s it’s supposed to be. And, in the long run, I believe all developers should strive to follow the HDD philosophy. After all, that’s why we have Ruby in the first place!

“I hope to see Ruby help every programmer in the world to be productive, and to enjoy programming, and to be happy. That is the primary purpose of Ruby language.”

Thanks Matz. I almost forgot.



The Best Code is the Code Nobody Writes

There are many metrics that people use for determining what is good code vs. bad code. Things like:

There are many more I’m sure you could think of to add to the list. Here’s another metric I think is very important to consider for judging code quality:

Think about it. Code that doesn’t exist is the most readable code, because nobody has to read it. Code that doesn’t exist is the most maintainable code, because nobody has to maintain it. Code that doesn’t exist is the most easily tested, because nobody has to write and maintain test suites to validate that code. And so forth.

You may think I’m being flippant, but heed my words, young padawan: I have worked on many a software project in my day that was full of spaghetti code, deadends (aka code that wasn’t in active use but still in the codebase), untested code, and even semi-duplicated code because multiple people implemented similar functionality more than once. And, I regret to say, many of those mistakes were ones I made as well.

If you build it, you are stuck with it. #

One of the major challenges I’ve run into is dealing with clients who are unfamiliar with programming best practices and the concept of technical debt. In their minds, building a new software feature is just like painting a picture or constructing a chair. You work on some stuff, and then it’s done, and then you look at it and see if you like it.

But as we all know, software doesn’t work like that. Nearly every single line of code you write ends up with a lifecycle and an impact that goes far beyond the one feature you’re working on.

And then, after adding new methods to User and creating new controllers and placing yet another service object in a growing folder of modules and including those three new gems in your Gemfile (not to mention adding new database tables and columns on existing tables), the client decides to delay the feature and work on another feature. Is this a temporary delay or a permanent one? Who knows!

Now you have a ton of code strewn all over your codebase, gems you don’t need, and a bloated database. What do you do? Spend hours to carefully remove all of the changes you made? Sorry, clients don’t really like spending money for you to do things that don’t result in another fancy demo at the next executive meeting. So you do what a lot of programmers (myself included) typically do: leave it. Sure, you might comment out a route or remove a button in a view, but that’s it. The “feature” remains, lurking beneath the surface like a hideous creature, just waiting to leap out and bite a chunk out of you or another programmer when you later come along refactoring code and cleaning up cruft.

Just Say No. #

If you’re lucky enough to work in a company with a culture of software engineering excellence, these issues may be relatively rare because everyone is aware of them and the business side understands and respects the concerns of the software team. But if you are a contractor working with a variety of clients—some of whom may know next to nothing about the discipline of programming—you simply don’t have that luxury. This means you are going to have to be very careful to set expectations up front.

Clients need to be aware that your job as a programmer isn’t simply to build what they say they want. Your job is to create a healthy codebase and grow it slowly and deliberately, always being mindful that at some point in the future, you might, God forbid, be hit by a bus (or fired, or leave for greener pastures…) and someone else is going to have to figure out what in tarnation is going on with your code. Your job, in many cases, is to tell the client no.

If you do need to write code (shock! horror!), keep it as self-contained as possible. #

There’s a concept in software security to keep the “surface area” of a possible attack vector as minimal as possible. The less accessible a portion of code is to the “outside world”, the less likely it can be used for a malicious act.

We need to be vigilant to reduce the surface area of new features. When you’re figuring out how to go about writing code to support new development, think in terms of small, modular components that are easily changed or removed in the future if the feature is no longer required or if the requirements change drastically.

Nobody can blame you for code that doesn’t work if the code doesn’t exist. #

I’ll close on a somewhat cynical note, but it’s absolutely true. Code that doesn’t exist is bug-free and never causes any problems. Now it’s true that bugs in existing code can be due to “missing” code (aka the code to validate that input value is missing). But missing code and non-existing code are slightly different. Missing code in those instances is usually just existing code that was badly written. Avoid writing object.value + 1 or object.title.upcase when you can write object.value.to_i + 1 or object.title.try(:upcase) (unless of course you’ve already vetted your variables in some way).

Non-existing code is the code you’ve chosen not to write. Far too many programmers lack the foresight or the courage to chose not to write code. Or maybe their ego is tied up in the clever solutions they can come up with or the lines of code they commit to GitHub every day. Resist these temptations! And always remember this:

The best code, next to the code nobody writes, is the code written carefully and deliberately, with humility. The client could be wrong. You could be wrong. The project could end up completely different in the near future. So don’t waste time and effort building stuff that’s easy to break and hard to remove. Go the extra mile and get it done right.


Additional reading: The Best Code is No Code At All.

Newer Posts
Skip to content