Posts

Don't Be Clever

Image
I was recently watching a talk by Dan North . At one point he briefly talks about a project he worked on. For this project, the Ant build script was generated with an XSLT transform, producing a build script about 2 million lines long. Even though that is clearly horrible, my first fleeting thought was, Huh, I would have never thought to do that. That's pretty clever. . Dan North's Simplicity, the Way of the Unusual Architect , at the time of the story That's pretty clever, is absolutely the wrong thought to have. I cannot fathom the monumental, wasted effort maintaining such a system. But I am also sure it started as someone's clever idea. There would be plenty out there who would say, Well, that project went wrong, but the idea itself isn't bad. It's pretty darn clever, really. "Cleverness" like that always seems promising at first. It is a novel view of a problem at hand. Because clever ideas are novel in completely unexpected ways, they h...

Stand Up Against Stand Ups

It's finally happening: your team is finally going Agile, whatever that means. The business has complained for too long. The team has complained for too long. You need to move faster and do more. Word comes down that you're going to try Scrum . This shouldn't be too bad. After all, Scrum can't be that hard to master . Well, turns out that there's a lot to Scrum, and your team can't just switch over in one day! Let's take this slowly, adding in the simple parts and going from there. Timeboxed iterations make sense. Your team already has a weekly meeting, so sprints are a week. That was pretty easy. What's next? Product owner, no; retrospectives, no; story points, no. Aha, stand-ups! Once every day, you stand up and talk about stuff. That's easy enough. Done. You are so Scrummy now! Or not so much. That all-too-common story of Agile Transformation highlights a number of pitfalls that derail real change. The most deceptive practice, though, is the d...

Exposing Dependencies: Getting Worse Before Getting Better

As software developers, our job is managing dependencies. We have to carefully construct balanced graphs of classes, objects, libraries, services, and more. Code needs to be encapsulated, reusable, and extensible, all while creating end-user value. We use techniques like composition, inheritance, and dependency injection to separate this from that, knowing that this or that could change in unknown ways at any moment. We don't always get to create the perfect system from the ground up though. Sometimes, we work on software developed long ago that could not anticipate today's needs. It hurts a little more when we see our name on all those commit messages. Regardless, we need to make the necessary adjustments for our system to meet the needs of today and tomorrow. To make code more flexible and adaptable, we often have to break it up into more singular and discrete responsibilities. We have to pull out and encapsulate the pieces that are at different levels of abstraction. We ha...

Inheritance as Polymorphism vs Inheritance as Code Sharing

We've all heard the mantra that we should favor composition over inheritance, and in most cases this is good advice. Occasionally, though, we really do need an inheritance relationship. Inheritance provides that useful “is-a” relationship that sometimes fits a situation so well. The pitfall we have to watch out for is using inheritance for code sharing between classes that should otherwise not be related, and not for polymorphism, that “is-a” relationship. What makes code sharing through inheritance so bad in the first place? An inheritance relationship is one of the tightest dependencies that could be made between two classes. It is hard-compiled in, and cannot be swapped out at runtime. It's an all-or-nothing relationship, and anything the parent wants to expose, the child must also expose. The child class may be able to override some of the parent behaviors, but the parent may finalize some methods and prevent this, locking the child class in even more tightly. This may be...

Trapped in the Purgatory of a Big Refactoring

Sometimes, it's not just a method that needs refactoring, or even a class. Sometimes it's several large packages with a spider web of dependents that just need a complete "rehacktoring." This can happen when years of legacy code build up in a system. It is complicated by the fact that the thing you want to change or delete or rename or move has tendrils of dependents spread all across the system, sometimes into classloaders and reflection and dynamic scripts that you cannot begin to search-and-replace all of. It is going to be a big, long slog into the swamp. We don't want our massive change to be a surprise to our team, though. We want to commit and merge the bits as we're going along. They don't represent complete refactorings. We might have pulled out a class just to put some code in a separate place, knowing that down the road we're going to merge it together with some other class and move that other method somewhere else. We're not quite su...

YAGNI vs Uncertainty

You're sitting there staring at the (pretty good if you say so yourself) code you just wrote. It solves a pretty tricky problem in a pretty elegant way. But something is worrying you: this code might need to change. You're not sure when and you're not sure how, but you just get this feeling tingling in the back of your neck that this code is going to have to change, and probably sooner rather than later. Somehow sensing your hesitation from across the room, that guy comes over. Yo, bro, looks like you got a problem. Just remember, bro, YAGNI! You ain't gonna need all that! You've heard it all before from that guy . You've even followed his advice a couple of times. Once, yeah, he was right, but that other time... oh, that other time. So much extra work that you just know you could have avoided, somehow. Maybe I exaggerate a bit, but we've all seen or heard of or (shudder) worked with someone who strictly follows the One True YAGNI. They never add any co...

#FOChaCo: Fear of Changing Code

In code, as in life, things are always changing, whether we want them to or not. (Focusing on the code part,) Operating systems, libraries, protocols, languages, standards, and best practices are changing on the regular underneath every bit of code we write. While many of these systems work hard to change in "backwards-compatible" ways, sometimes there are changes that break things. As software developers, our job is to write our code that is robust to change, so that it still works well when the future arrives. But sometimes there are those among us who suffer from #FOChaCo: the fear of changing code. Despite the inevitability of the future, they fight tooth and nail to keep things exactly as they were. They might insist that we cannot support anything later than version X of our platform, or that we should not update any libraries unless there is a dire need to do so. These developers are well-intentioned. They may have been bit in the past by a library update. They might...