DaedTech

Stories about Software

By

Abstractions are Important 4 – Personal Interactions

An Announcement

I’ve enlisted the help of freelance editor Amanda Muledy to copy edit this blog. The content will not be altered in terms of substance; rather, she’ll be correcting grammar and spelling mistakes and the like. She’ll even know whether or not the semi-colon I just used was some kind of faux pas.

She has started on my oldest posts and will be working her way toward the newest ones and we’ll eventually probably work to a state where I send them to her prior to publication. So, if you see mild edits to content here and there, that’s the reason for it. If you’re interested in her services or more information along these lines, she has contact info on her blog.

And now back to your regularly schedule post…

Beyond the Code

In the second post in this series, I described in detail an abstraction that had nothing to do with programming: the pizza parlor with delivery service. Today I’d like to revisit abstractions in the real world, but not focus on static institutions. Instead, I’d like to talk about the ad-hoc abstractions that we form in one another’s lives as we work collaboratively.

Huh?

When we work with other people, what we generally do is offer abstractions to one another for the purpose of getting things done more efficiently. Have you ever said something like “you prep the chicken, and I’ll start the grill”? This is an ad-hoc, process-based abstraction. What does prepping the chicken entail? Maybe a dry drub, chopping it into chunks, etc. But, the interesting thing is that the person starting the grill doesn’t care at all, as long as it’s taken care of. Likewise with the starting of the grill. Is it a charcoal grill? What kind of charcoal to use? None of that matters to the person prepping the chicken.

This is an example of a good process abstraction, and these types of abstractions are the basis for the concept of effective teamwork. They allow people to work in parallel and to be more efficient than they would be working on their own, assuming that the tasks are not temporally dependent. Sure, one person could prep the chicken and also start the grill, but two people doing it simultaneously will go faster. It would be a different story if the two tasks were interdependent or mutually exclusive. “Hey, you clean the bottom of the grill while I start it” wouldn’t work very well.

So efficient teamwork requires tasks that are relatively orthogonal and participants providing abstractions to one another. (It is certainly possible to have abstraction in sequential tasks, but that’s not nearly as interesting). Without orthogonality, the team members would step on one another’s toes while completing their tasks, and without abstractions there wouldn’t be any productivity boost.

For Example

Last week, I wanted to order a server and confirm that our MSDN licensing covered the server software that I wanted to install. Management paired me with someone whose job it was to worry about these things so that I could focus on my job of being a programmer. Things started to go a bit off the rail at this point, though. I got an email about computer wholesalers and the names of salespeople at these wholesalers, distrust of Microsoft and its licensing and any number of other things that weren’t of interest to me — things that should have been abstracted away from me. My goal was simple — get a computer and install server software on that computer.

I responded to this email by saying that I appreciated all of the information, but I didn’t really want to worry about all that stuff. I just wanted the computer. I did ask if it made sense for me to call one of these wholesaler employees directly, which I would have been happy to do, since this would have provided me with an actual abstraction. The response to this email was another torrent of information that was tangentially related at best (overseas latency issues, server hard drive configuration snags, etc) , but no servers ordered and no contact information provided. This went on for several emails more emails in the same fashion (the situation is now on hold for other reasons, so there is no resolution, either).

What I had was a consistent failure to provide an abstraction, and thus I had no actual help with anything. If I have to stop working at my assignment (being a programmer) to deal with an IT assignment (ordering a server) than the person whose responsibility is the latter is providing no abstraction and thus, functionally useless to me. In this example, the time I spend reading and responding to emails could better have been spent calling Microsoft and/or the wholesaler directly. Either way, I couldn’t focus on my job, so at least something productive could have come out of it.

Why Does This Happen?

As you read through this, you’re probably both asking yourself why anyone would do this and also thinking of people who have provided a bad abstraction to you in the past. That is to say, it’s often incomprehensible to a problem solver not really mired in office politics, but it’s also a common behavior. I posit that there are three reasons someone will provide a bad ad-hoc personal abstraction:

  1. Passive-aggressive desire to sabotage an initiative
  2. Earnest over-exuberance or over-inquisitiveness
  3. Simple incompetence

The last of these is the simplest and least interesting. If someone is simply incompetent at a task, they will serve poorly as an abstraction. If you were to ask me to ask someone for the time of day in Mandarin, I would respond with either “how do you ask someone the time of day in Mandarin?” or “will you do it for me?”. I am simply ill-suited for this task since I don’t speak that language.

The second of these is what results from people who are nervous about responsibility or perhaps overly excited about it, but are willing to put in a good faith effort. Perhaps you ask me to cook you an omelette, and I respond by saying, “how much pepper would you like in it; do you care if the eggs are whisked for 20 seconds or do you want 30; these are those brown eggs – is that alright; do you want me to use PAM or oil; etc?” I mean well, but I’m defeating the purpose of what you asked of me. By bogging you down in these details, I’m forcing you to spend more time helping me than was your intent and I might well be annoying you. This sort of behavior might result from me really wanting you to enjoy the omelette or me being afraid that you’ll yell at me if I mess something up, but there’s no ill intent.

The first item in the list is probably the most interesting from a realpolitik perspective in a collaborative setting, though it isn’t because it’s a sophisticated technique. Children learn to do this at an early age and employ it without any subtlety. Ask a child to clean his room and, after some initial whining and the gears start turning:

Child: Where does this go?
Parent: In the drawer over there.
Child: But I can’t reach!
Parent: Get a stool.
Child: Where are the stools?
Parent: There’s one on the other side of your bed.
Child: It’s heavy!

The goal here is to feign simple incompetence to get out of the task, which is a rather natural thing for a child to do since parent-child relationship often doubles as teacher-student. The child banks on the parent becoming so exasperated that he or she finally exclaims “Oh, for the love of… I’ll just do it!” This gets interesting in adult interaction dynamics since it necessarily involves a sacrifice of perceived status. Whoever does this must be willing to accept a role of subordinate status and often to move down the path toward learned helplessness. If you work with me, and I respond to all of your requests by saying that I don’t know how to do things, it’s only a matter of time before you and others begin to question my competence and value in my role.

As a result, the best way to get out of work (or sabotage an initiative in general if the motivation is something other than laziness) is not to offer oneself sacrificially as a buffoon, but instead to exaggerate the difficulty of the task with which one is presented:

Oh, sure, I’ll make you an omelette, but there’s really a lot to think about here. You have to consider what kind of pan you want, what size and color of egg, the quanity of pepper involved… I mean, there are a lot of variables here. Don’t worry, though — I’ll make some inquiries as to what the best kind of ingredients are and get back to you tomorrow.

Notice that it’s very similar to the over-exuberant explanation, but with a bit more of an air of authority. It also subtly implies that the earliest possible completion of the task renders it not worth doing — who wants to wait 24 hours for their breakfast? This shift from excited questioning to authoritative is often a giveaway, but sometimes these motivations may even come off as identical. They’ll certainly be similar and it would be a shame to accuse someone of some sort of malfeasance when the explanation is benign. It’s genuinely hard to distinguish items (1) and (2) in someone else in a vacuum without track records and understanding of possible ulterior motives.

Avoiding All Of It

And, most diplomatic people will avoid this sort of accusation because it is rude and assuming. They’ll act on the surface as though you’re simply excitable. But, here’s the catch — they’ll assume that you’re passive-aggressive if it happens too often and if it’s a regular source of impediment. So really, this type of behavior, even when benign has at best a short term benefit with a long term cost. People will probably assume that you deliberately make yourself an obstacle, but even if you’re fortunate enough to avoid that, they will assume that you are incompetent and/or annoying.

Do you really want any of those labels? I don’t, myself. So, I’d stress that you make sure to be a good abstraction for others when asked. Make sure that your work makes things simpler for other people and removes obstacles from their path, rather than adding them. And, if you really are ill-suited for a task, explain why and try to think of something you can offer instead to be helpful. It really does parallel code in a lot of ways — you should hide complexity from others and present them with simple but meaningful choices.

Good abstractions in code, good abstractions in life — a good way to live.

By

Beware the Bloated Constructor

What’s a Bloated Constructor?

Yesterday, I was going through the version history of a file in some code base (from earliest to most recent) and I saw the following:

This made me sad and tired but no worries, I figured, there were a lot more revisions I hadn’t yet seen. Surely somebody did something about this later. And then, happiness:

Sweet! That’s much easier on the eyes. Let’s see just see what Initialize does and call it a day:

Oh, the humanity… looks like someone sprayed a bit of cologne here and nothing more.

So, what’s the problem?

I contend that this is a fundamental design failure. Forget throwing an exception from within a try block as some kind of goto. Forget all of the static stuff like the logging and exception handling and general global state. Forget the singletons. Forget all of the other ancillary problems. The design failure is how complicated (convoluted) this constructor is. I see this enough that I think some people would call it a development pattern (I don’t think any would claim it rises to the level of “Design Pattern”), but I firmly believe that it is an anti-pattern.

This style of code is the product of procedural, command and control thinking that I blogged about some time back. It makes no distinction between creation/initialization of an object and operations of the object. These distinct activities are blurred as the bloated constructor generates logger messages, talks to singletons, instantiates other objects, etc.

From the perspective of the procedural programmer, the constructor should take the role of making sure the object wants for nothing, having all of its creature comforts and having its every desire and whim satisfied. In the object oriented style, where dependencies tend to be inverted, the constructor has a different and more Spartan role. Its only job is to make sure that object initializes into a state where it satisfies its basic invariants (in other words, it makes sure that the object instance starts off in a valid state and nothing more).

Let’s consider why the latter, object-oriented approach tends to be a better fit in object oriented languages (and, I would argue, in any state-based paradigm, but I’ll focus on OOP here).

1. Violating Developer Expectations

Imagine that you’re newly assigned to a code base and you want to start understanding how it works. An excellent way to do this is to write a few unit tests (perhaps to keep or perhaps just for throw-away experimentation). You pick some class that you’d like to test and figure you’ll experiment with its API before digging into its code. So, you create a new instance of that class and…

Oops. Your continuous testing tool crashes. Huh. Guess you’ll have to look in the code now (this is never a promising sign — if you have to inspect a class’s code to understand why it’s crashing, it’s probably not a good abstraction, especially if this is true of the constructor.) So, you look in the code and see that there’s a reference to a lazy-loading singleton that lazy-loads a few other singletons and one of those singletons is trying to read files off of a network somewhere and….

Alright, forget it. Let’s move onto another class. You instantiate that class and your testing tool doesn’t crash, but it does turn red. Huh. Back into the code. Ah, this time the class under test doesn’t touch any static stuff or singletons, but it instantiates another class that does. The exception handling is a little better here, so you just turn the testing tool red rather than completely crashing it, but this class is hosed for testing as well.

As a new developer, you’re instantiating classes and expecting that they’ll be instantiated. What’s happening instead is weird, bad, unpredictable things that force you to open the source code to figure out what on Earth is going on. You’re badly betraying a trust other developers put in you to do what you advertise (i.e. putting together the minimum invariants of the class).

2. Testability Nightmare

And, looking back at the narrative from the previous section, another problem makes itself pretty obvious as well. Constructors that do real work instantiating other things (especially global state) make classes impossible to test in isolation. Even if you don’t use global state and instead have classes all instantiate their collaborators, it’s still tough to test things in isolation.

Imagine that your code works like this: main tells a car to build itself, the car tells its engine and chassis to build themselves, the engine tells the alternator and transmission to build themselves, etc. Now, let’s say that you want to write a test of the car to see what happens when its engine starts out invalid. Just how will that be accomplished? You have no control over its engine — it controls that in its constructor. Even if it exposes engine via an accessor, too little, too late.

3. Casts Dependencies And Assumptions in Stone

If the constructor is busy, it’s likely that it’s talking to global state/and or instantiating things. If it takes arguments, it may be mutating those or paring them or coupling itself to them. But, whatever it’s doing, you have no control over it as a client. So, if you want this object at all, you’re getting it with whatever the constructor decides to foist on you.

Contrast this with any non-constructor method. Any non-constructor method you have the option to call or not, so you have the control. If you want a Car that isn’t started, you can simply not call Car.Start(). However, if the author of Car decides to start it in the constructor, you’re hosed. Not having a started car is not an option for you, buddy. Likewise, if Car instantiates a new SixCylinder() engine and you want a more fuel economical four cylinder, you’re SOL.

4. Performance Problems

Let’s say that I have some class, Critical, that I can’t live without in the application. I need to instantiate a Critical and access some property on it in response to a user request. Let’s say that Critical has a busy constructor that chugs and hums and does all manner of things, taking 5 or 10 seconds at times. Not all of this stuff has anything to do with the property that I want to access in response to the user request.

What are my choices here? Well, I don’t have any. I can like it or lump it. I need new Critical() and the user therefore needs to wait 5 or 10 seconds even though his request should take that number of microseconds. Sure, I can cache my Critical for next time or I can implement a flyweight, but that first time, I’m still needlessly forcing a wait on the user.

So, What Should a Constructor Look Like?

Given all of these arguments against bloated constructors, it should be fairly obvious what I think a constructor ought to look like. It ought to contain very little code. If the class has no dependencies, then it ought to contain no code (or not exist). After all, what are you going to do in the constructor that you can’t do in a field initializer? You’re not reaching into global state somewhere, are you?! Tsk tsk.

If a constructor has parameters, it ought to do nothing but set local fields according to those parameters, and perhaps perform some sort of validation on the parameters to ensure that its invariants can be satisfied with these values. That’s really it. The constructor’s only responsibility is to put the object into a valid state as far as its invariants are concerned, while doing the minimum amount of configuration possible. After all, you want objects where clients can explicitly tell them what to do. Even simple things like hooking to events should be triggered by a client method and not the constructor, ideally. It may seem a bit more cumbersome, but it’s also expressive and clear. Constructors hide side effects where well-named methods promote them from side effects to deliberate effects.

So What About that Constructor We Looked At?

How about this:

Wow, isn’t that like a ray of sunshine on an otherwise cloudy day? No Initialize() method hiding untold horrors. No nested, contradictory exception handling logic. No logging, no singletons, no static state — simple, minimal and easy to reason about. So, what to be done with all of these things that formerly resided in this constructor?

Well, a number of them were simply initializing properties or backing stores. This can be done with class initializers for sensible defaults and should otherwise be left to clients. After all, we’re here to serve them — not force settings on them. The logging makes no sense — do that somewhere else. If you’re writing a class and you want to know how long the constructor takes (which is a huge warning flag, by the way), write that code where you instantiate it — don’t force this on every conceivable client of your class.

The event wireup can be moved into some kind of “Hookup()” method to allow clients specifically to request this. You could also make it more granular if you like, allowing them to hook up ala carte instead of all at once. As for the singeltons and static state, leave that up to the instantiating client if it wants that done. We might as well leverage the thing that makes static state a design nightmare — the fact that anyone can do anything from anywhere — to move the stink away from us with some “Not in my backyard” attitude. If everyone does this, eventually the global state will be bubbled to some common location where singletons can be slain and static classes converted to instances.

Are You a Lone Crackpot, Erik?

As it turns out, no. Here is what others have to say on the subject:

Microsoft agrees with this take, citing performance:

Do minimal work in the constructor. Constructors should not do much work other than to capture the constructor parameters. The cost of any other processing should be delayed until required.

Misko Hevery agrees, citing problems finding seams for testing:

When your constructor has to instantiate and initialize its collaborators, the result tends to be an inflexible and prematurely coupled design. Such constructors shut off the ability to inject test collaborators when testing.

John Wigger cautions against putting too much code in a constructor:

In dealing with a more complicated OO design, it can be a mistake to put too much initialization logic into constructors. This is especially important for an OO design that uses inheritance significantly.

Gilad Bracha even goes so far as to hypothesize that constructors are harmful:

Constructors come with a host of special rules and regulations: they cannot be overridden like instance methods; they need to call another constructor, or a superclass constructor etc. Try defining mixins in the presence of constructors – it’s tricky because the interface for creating instances gets bundled with the interface of the instances themselves.

By

C# Tips for Compacting Code

This is a little series of things that I’ve picked up over the course of time and use in situations to make my code more compact, and, in my opinion readable. Your mileage may vary on liking any or all of these, but I figured I’d share them.

To me, compacting code is very important. When I look at a method or a series of methods, I like to be able to tell what they do at a glance and drill into them only if it’s important to me. I think I naturally perceive code the way I do an outline in a Word document or something. I look on the left for brief, salient points, and then in the smaller text that goes further right only if I want to fill in the details. This allows me to variable skim over or delve into methods.

If methods are very vertically verbose, I lose this perspective. If I have two or even one method taking up all of the real estate in my IDE vertically, I don’t know what’s going on in the class because I’m lost in some confusing method that forces me to think about too many things at once. I don’t ever use that little drop down in Visual Studio with the alphabetized method list for navigation. If I have to use that to navigate, I consider the class a cohesion disaster.

So, given this line of thought, here are some little tips I have for making methods and code in general more compact without sacrificing (in my opinion) readability.

Null coalescing in foreach

Consider the following method:

We’re going to take a collection of commands and iterate over them in this method, invoking an individual method to do the individual dirty work. So, the first thing that we do is guard against null so we’re not tripping over an exception. We could throw an exception on null argument, which might be preferable depending on context, but let’s forget about that possibility and assume that failing quietly is actually what we want here. Once we’ve finished with the early return bit, we do the actual, meaningful work of the method.

Let’s compact that a bit:

Now, we’re using the null object pattern and null coalescing operator to take care of the null handling, instead of an early return with an ugly guard condition. We can compact this even more, if so desired:

Now, we’ve eliminated the extra code altogether and gotten this method down to its real meat and potatoes — iterating over the collection of commands. The fact that a corner case in which this collection might be null exists is an annoying detail, and we’ve relegated it to such status by not devoting 50% of the method’s real estate to handling it. The syntax here may look a little funny at first if you aren’t used to it, but it’s not double-take inducing. We iterate over a collection and do something. The target of our iteration looks a little more involved, but in my opinion, this is a small price to pay for compacting the method and not devoting half of the method to a corner case.

Using params

Speaking of params, let’s use params! In the method above, let’s consider the code that I was replacing:

Client code of this then looks like:

As an aside, ignore the fact that it’s obtuse to bind a bunch of different commands to the same window and key gesture. In the actual code, there’s a lot more going on than I’m displaying here, and I’m trying to include nothing that will distract from my points. If you look at the params version above, consider what the client code of that looks like:

Now, I personally have a strong preference for that. A bunch of lines of the same thing over and over again drives me batty, even if the things in question need to be parameterized somewhere and this is the place it has to happen. There just seems something incredibly vacuous about code like the pre-example and I always favor more vertically compact code because I can process more of the details. By SomeCommand12, I’ve probably figured out what’s going on even on my slowest day — I don’t need another 50 lines besides. If we have to do things like this, let’s at least condense them so they take up as little mindshare in a method as possible.

Optional Parameters

If you haven’t gotten on board this train since C# 4.0, I’d say it’s time. If you have a bunch of code like this:

… it’s time to turn it into this:

Omit brackets when you have a single line following a branch or loop condition

I used to be a stickler for this:

I reasoned that omitting the brackets was just begging for downstream maintenance problems, and that’d I’d be a good citizen, not taking shortcuts. I persisted in that way of doing things until quite recently. I was watching an Uncle Bob video where he said in passing, “I think that there should only be one line of code after an if or else or for, and I’m not going to make it easier on anyone that comes along to mess that up.” (can’t find the video, so I’m paraphrasing).

I blew this off at first, but for some reason, it stuck in my head and would occur to me from time to time. Finally, one day, I simply had a 180. I was now continuing to do it out of stubbornness, I realized, having long since decided Bob was right while barely realizing it. This practice made my code more compact, and it encouraged me to factor everything following a control flow statement into its own method, leading to much more readable code. I think the bigger benefit comes from the practice of “1 line per control flow statement” than the two lines you save from omitting the brackets, but nevertheless, both are adding up to create methods that are much more compact:

So, I’m out of tips for the day. If people like this, let me know, and perhaps I’ll put together another little post with a few more compactness tips, though it might take me longer to think of ones. These were low hanging fruit that I find myself doing often.

By

Abstractions are Important 3 – “What?” Before “How?”

So, I’m back from my two weeks overseas, refreshed, enriched, and generally wiser, I suppose. We traveled to Spain and Portugal, visiting a ton of historic sites, eating good food and having fun. For my first post back, I’d like to make a third post in my series on abstractions.

Methods as Recipes

I was looking at some code yesterday. It was some long method, probably 60 or 70 lines long, and I sighed as scrolled disinterestedly through it. At the moment, I couldn’t muster the energy to try to figure out what the author thought it did or probably wanted it to do, so I started ruminating about what leads to methods like this. And, I think I understand it. It’s the idea of a method as a recipe.

By way of homage to Spain, let’s write a “CookPaella()” method. When writing methods, do you ever start by doing the following?

(recipe compliments of All Recipes).

This is a sane approach. Much like making an outline for an essay in English class, you list out the basic procedure that you want to follow, and you fill in the details:

This is great because rather than starting without any kind of gameplan, we’ve stubbed everything out that needs to happen, and now we’re in the process of filling in the template. Whether you’re cooking or assembling a piece of furniture or anything else, there is a tendency to read through (or skip) to the end so that the actual following of the instructions reveals no mysteries. We take the same approach here.

Once this is complete, you’re going to have a large method, so some refactoring is probably in order. At the very least, our numbered bullets provide some logical methods to create:

There, look at that. We’re going to have this reduced to a nice 13 line method and, we could probably even group the calls further from there, resulting in a CookPaella() method that had three instructions: Prep(), CookRice(), CookMeat(). Those methods would consist of three or four lines themselves, and things would spread on out from there like a tree. This is a series of well factored methods that are probably clean and reasonable (discounting the fact that we’re instantiating what we need with Bowl, rather than having variables passed in — that’s for example purposes and not a weakness of the approach).

So where do these long methods come from? Well, I would argue that they come from people thinking in terms of recipe, but not creating or factoring to the outline. That is, they sit down to write the method and simply start banging out code line by line until they’re done. They think in terms of a recipe — a procedure — and methods are simply containers for procedures. So, when they start out, they don’t know what all a method is going to do; rather, the method twists and winds and meanders its way toward some eventual end in ad-hoc fashion.

In a less contrived case than this one, a method will probably start out as just a jump point for a series of instructions. The instructions are coded sequentially until there are no more instructions and then the method is at an end. The “how” is defined, and then the author looks at the “how” and decides what to name the method. He describes “how” and then, based on “how”, decides “what”. Ah, I see that I’ve assembled a series of instructions that seems to cook a paella, so “CookPaella” is probably a good thing to call this.

Methods as Abstractions

So, is there another way to do this? Absolutely. You can flip the script and decide “what” without worrying about “how”. With this approach, we completely discard the procedural/sequential concept and focus instead on creating meaningful abstractions. Procedural/sequential programming is good for, say, batch scripts, but object oriented programmers need to think in abstractions. I don’t want a specific, blow-by-blow recipe for cooking paella to become the ‘architecture’ of my code. I want to write code that a cook can use to get things done. That’s an important distinction.

Let’s think of our paella cooking a little differently. Let’s just think of it as cooking. In this fashion, we can define implements like pots and pans, ingredients like paprika and meat, and actions, like sear or boil. From there, we can start thinking about an object model. What is a “bowl” and what should it do? A bowl does things other than mix ingredients for paella — it has properties and, depending on the object model, may have some actions. Let’s decide what those properties and actions are without worrying about how they work.

For example, let’s define a bowl, along with concepts called “ingredient” and “quantity”:

Notice that we have a Bowl interface, rather than any kind of implementation. How do these methods work? Who cares. We don’t need to know that to make our paella. From here, we might define a paella pan interface as well, and perhaps various inheritors of ingredient and quantity, depending on their implementations. The point is, we’ll reason about each individual object and how it should behave. After we do enough of this, we can start to create larger constructs, such as some MeatCooker class that takes an arbitrary number of meats and a pan and cooks them. A few classes like this, and before you know it, your CookPaella() method will write itself.

Notice that the “start at the beginning and sequentially do everything” scripting style approach is gone, but so too is the structured, outline approach. With this abstraction-based approach, we’re defining objects with properties and behaviors that make sense in our domain model. This is what allows easy assembly. But, the important thing to understand is we’re defining abstractions rather than procedures. These are going to be easier to reason about, and they’re also going to be more flexible. We can use our meat cooker and pan and bowl to cook lasagnas as well as paellas.

So, the overriding message here is to think sequentially and abstractly when considering how to model a problem in an object oriented language. Don’t think about “how” until the very end. Instead, think about “what”. What objects should you have? What properties should they have? What actions? What interactions do you foresee for them. As you answer these questions, the specifics will become much easier. The longer you defer those specifics, the more flexible the design. You’re using an object oriented language, so leverage that language. Don’t code like you’re batch scripting. Don’t model your application by writing recipes even when you’re modeling, well, cooking a recipe.