DaedTech

Stories about Software

By

Flexibility vs Simplicity? Why Not Both?

Don’t hard code file paths in your application. If you have some log file that it’s writing to or some XML file that it’s reading, there’s a well established pattern for how to keep track of the paths of those files: an external configuration scheme. This might be a .config file or a settings.xml file or even a yourapp.ini file if you’re gray enough in the beard. Or, perhaps it’s something more exotic like a database table or web service that stores key value configuration pairs. Maybe it’s something as simple as command line parameters that specify the path. Whatever the case may be, everyone knows that you don’t hard code — you don’t store the file path right in the source code. That’s amateur hour.

You can imagine how this began. Maybe a long time ago someone said, “hey, let’s log critical application events to a file so that we can review and troubleshoot if things go wrong.” They shipped this for some machine running Windows 3.1 or something, and were logging to C:\temp, which was fine unless users didn’t have a C:\temp directory. In that case, it blew up spectacularly and they were flooded with support calls at which point, they could tell their users to create the directory or they could ship a new set of floppy disks with the new source code, amended to log to a directory guaranteed to exist. Or something like that, anyway.

The lesson couldn’t be more obvious. If they had just thought ahead, they would have realized their choice for the path of the log file, which isn’t even critical anyway, was a poor one. It would have been good if they had chosen better, but it would have been almost as good if they’d just made this configurable somehow so that it needn’t be a disaster. They could have made the path configurable or they could have just made it a configurable option to create C:\temp if it didn’t exist. Next time, they’d do better by building flexibility into the application. They’d create a scheme where the application was flexible and thus the cost of not getting configuration settings right up-front was dramatically reduced.

This approach made sense and it became the norm. User settings and preferences would be treated as data, which would make it easy to create a default experience but to allow users to customize it if they were sufficiently sophisticated. And the predecessor to the “Advanced” menu tab was born. But the other thing that was born was subtle complexity, both for the users and for the programmers. Application configurability is second nature to us now (e.g. the .NET .config file), but make no mistake — it is a source of complexity even if you’re completely used to it. Think of paying $300 per month for all of your different telco concerns — the fact that you’ve been doing this for years does’t mean you’re not shelling out a ton of money.

What’s even more insidious is how this mentality has crept into application development in other ways. Notice that I called this practice “preferences as data” rather than “future-proofing,” but “future-proofing” is the lesson that many took away. If you design your application to be flexible enough, you can insulate yourself against bad initial guesses about user preferences or usage scenarios and you can ensure that the right set of tweaks, configuration alterations, and hacks will allow users to achieve what they want without you needing to re-deploy.

So, what’s the problem, apart from a huge growth in the number of available settings in a config file? I’d argue that the problem is the subtle one of striving for configurability as a first class goal. Rather than express this in general, definition-oriented terms, consider an example that may be the logical conclusion to take this thinking as far as it will go. You have some method that you expose publicly, called, ProcessOrder and it takes a parameter. Contrary to what you might think, the parameter isn’t an order ID and it isn’t an order: it’s an object. Why? Because this API is endlessly flexible. The method signature will suffice even if the entire order processing mechanism changes and even if the structure of the order itself changes. Heck, it won’t need to be altered if you decide to alter ProcessOrder(object order) to send emails. Just pass in an “Email” object and add a check for typeof(Email) to ProcessOrder. Awesome, right?

SwissArmy

Yeah, ugh. Flexibility run amok. It’d be easy to interpret my point thus far as “you need to find the balance between inflexibility/simplicity on one end and flexibility/complexity on the other.” But that’s a consultant answer at best, and a non-point at worst. It’s no great revelation that these tradeoffs exist or that it’d be ideal if you could understand which trait was more valuable in a given moment.

The interesting thing here is to consider the original problem — the one we’ve long since file away as settled. We shipped a piece of software with a setting that turned out to be a mistake, so what lesson do we take away from that? The lesson we did take away was that we should make mistakes less costly by adding a configurability out. But what if we made the mistake less costly by making rollouts of the software trivial and inexpensive? Imagine a hypothetical world where rollout didn’t mean shipping a bunch of shrink-wrapped boxes with floppy disks in them but rather a single mouse click and high confidence that everything would go well. If this were a reality, hard-coding a log file path wouldn’t really be a big deal because if that path turned out to be a problem, you could just alter that source code file, click a button, and correct the mistake. By introducing and adjusting a previously unconsidered variable, you’ve managed to achieve both simplicity and flexibility without having to trade one for the other.

The danger for software decision makers comes from creating designs with the goal of satisfying principles or interim goals rather than the goal of solving immediate business problems. For instance, the problem of hard-coding tends to arise from (generally inexperienced) software developers optimizing for their own understanding and making code as procedurally simple as possible — “hardcoding is good because I can see right where the file is going when I look at my code.” That’s not a reasonable business goal for the software. But the same problem occurs with developers automatically creating a config file for application settings — they’re following the principle of “flexibility” rather than thinking of what might make the most sense for their customers or their situation. And, of course, this also applies to the designer of the aforementioned “ProcessOrder(object)” API. Here the goal is “flexibility” rather than something tangible like “our users have expressed an interest in changing the structure of the Order object and we think this is a good idea and want to support them.”

Getting caught up in making your code conform to principles will not only result in potentially suboptimal design decisions — it will also stop you from considering previously unconsidered variables or situations. If you abide the principle “hard-coding is bad,” without ever revisiting it, you’re not likely to consider “what if we just made it not matter by making deployments trivial?” There is nothing wrong with principles; they make it easy to communicate concepts and lay the groundwork for making good decisions. But use them as tools to help you achieve your goals and not as your actual goals. Your goals should always be expressible as humans interacting with your software — not characteristics of the software.

By

RIP, RTFM

There’s no doubt about it: I’m locked in a mortal standoff with verbosity, and I’m not winning. Every now and then I go meta with this and vow to make some smaller posts to keep the cadence at around 3 per week, and mostly I don’t. But I like to think that these travel sized posts are coming at least slightly more often.

I was poking around for some OCR software that would take scanned PDFs and spit out text, so I took to google. I wound up here. Ugh, next. Then I found this, which I downloaded. The code sample wasn’t helpful, but I poked around with Intellisense until I had something that should have worked. I got a weird exception, which turned out to be because I need to target x64 (jeez, my .NET is getting rusty), and then I got another exception because I needed a license, which required going to their site, filling out a… ugh, screw it, uninstall, next. Then I wound up here, got what I wanted in the small, and decided to call it a night.

Now, I’d been looking for an API that I could hit and preferably control (i.e. as a compiled library and not a service), but you know what? The first thing I’m going to research if I pick this up again is whether I could pay the good folks at that last site for an API somewhere, even as a web service. That’s how powerful it is to offer simplicity. They’re not even offering what I want, exactly, but they’re offering it in such dead simple fashion that I get a win in 30 seconds.

The RTFM mentality is simply dead. You can stamp your foot and scream that at me all you want.

CryingDev

My response will be to blink at you in amusement, shrug, and walk away to look for someone that wants my money and my business.

By

The Dominant Leader Fallacy

There’s nothing quite like the pressure of assuming organizational leadership for the first time in a professional capacity. And, seriously, I mean in a professional capacity — I’m not talking about being voted captain of the freshman basketball team or student government something. Non-professional leadership scenarios are akin to poker games played at the kids’ table for chips only in that they’re artificial scenarios designed to build character by simulating the real thing. In these scenarios, a wrong decision can cost you a soda machine in the cafeteria whereas in a professional capacity wrong decisions can alter careers and livelihoods (and, in higher pressure gigs than I’ve ever had, sometimes even human lives).

I can’t speak across the board, but I can speak to organizational leadership against the backdrop of knowledge work (and in this case, I mean official leadership, as opposed to ad-hoc or thought leadership). In this field, you often have a good bit of “paying your dues” before you’re deemed ready for leadership. Sadly, the gatekeeper factors here are often duration of tenure or having been a leader before (the entry level Catch-22 all over again, wherein you need leadership experience to be given a leadership role and a leadership role to gain leadership experience). Thus, the waiting period might be years or even decades, in some cases, so if you’re ambitious, you’re probably chomping at your bit for a long time before it comes. And then it comes…

…and you’d better not screw it up! The very people that gave you the nod have you on quite the short leash, and they’re ready to yank you off the stage with a cane should you show the slightest hint of weakness. Whatever you do, never admit to ignorance of any sort. If it’s an acronym you’ve never heard or a technology you haven’t used, grit your teeth, fake your way through it and study up until 4 in the morning so that you can stay perfect in everyone’s eyes. And don’t think that this only applies to your superiors. Those you’re leading are also waiting for any excuse to dethrone you and lay their own claim, so don’t sleep on them, either.

TimeLearning

Heh. I don’t know that I ever thought these things, consciously, but I certainly did to some degree on a subconscious level. And, while I’ve never been the sort to try to bluff at having knowledge I don’t, the part about staying up ’til 4 AM studying was (and still kind of is) definitely my style. I didn’t want to blow the whole leadership thing, so I broke my back trying to be perfect. But these days… not so much. I now break my back trying to do other things.

At some point, I figured out that trying to know more than 5 or 10 or however many people doesn’t scale very well and, even if it did, would winning knowledge trivia duels be the best use of your time as a leader? Maybe if you’re running a gang or a pack of wolves this makes sense — your cred is tied up in your ability to dominate any challengers. But I like to think that we have a bit more organizational sophistication in our approach. In knowledge worker professions, the best use of a leader’s time is removing obstacles that are stopping the team from excelling and figuring out how to create an environment that gives rise to good ideas.

If you’re a leader and you don’t know some finer point of the language that your team is using or you’re less familiar with a deployment tool than someone on your team, don’t hide that fact — embrace it! You’ve found a skill and there’s probably a need. Good leaders play match-maker in these situations. “Hey, you seem like you really know your Python and I know there’s some nasty code over in that particular module, so maybe you could get it sorted where the rest of us failed.” If you think back to the best leaders/bosses/managers/whatevers that you had in your career, did you appreciate them because they were better at everything than you were? Or did you maybe appreciate them because they got out of your way, trusted you, and guided the team toward playing to your strengths?

So if you’re new to leadership, relax and take a deep breath. You’re not playing a game of “king of the hill” and the team members aren’t adversaries looking for a crack in your armor. You’re playing a team sport and you’re more like the coach — they expect you to put them in a position to succeed rather than to push them out of the way and single-handedly win the game for them. So go in, cop to what you don’t know, and solicit volunteers for people to get the job done and maybe even teach you a thing or two along the way. Leadership is a matter of trust — not dominance.