Professional Values

by Jacob 7. February 2009 21:17

Dome Scratcher One of the things I am seeing less of lately is the understanding that reasonable people can and will disagree with one another—without either of them being any the less reasonable or intelligent for doing so. It seems to me that people become so invested with the “rightness” of their ideas that they deny the possibility that those who disagree with them may be equally intelligent and well-informed. You see it a lot in politics, but I think that this attitude has crept into development discussions as well.

I saw a manifestation of this in action after a recent Stack Overflow podcast wherein Joel had the temerity to question Robert Martin's SOLID principles (SOLID was the topic of a recent podcast with Scott Hanselman that Joel had apparently heard). I highly recommend both podcasts. It didn't take long for some bright stars in the Alt.Net universe to talk about Joel jumping the shark or the state of his imperial wardrobe. I'm not sure why the impulse to denigrate those who disagree with you is so strong, but it appears to be nearly universal. We go from the belief that somebody is wrong to the conclusion that they are incompetent or ignorant without taking time to draw breath, really.

I think this impulse is not only wrong, but damaging. It represents a voluntary limitation of our ability to engage in important dialog and stretch our understanding.

Education

One crutch of those who participate in this hidden hubris is the belief that people who disagree must be missing data. You can see this most commonly when someone tells you to “educate yourself” or its milder form “try it and you'll see”. The underlying message in those statements is that if you knew what they know, you'd do what they do.

And that may be correct. It really could be the case that someone is missing data and if they had that data they might agree. Since software development is so change-driven, much of development blogging is motivated by the desire to teach others things they might not have heard about before. You have to honor the often unrewarded efforts of those who take the time to put information out there for the benefit of those seeking education.

The problem is that telling someone who questions your tools or methods to educate themselves is arrogant, even if you are completely sincere and honestly well-meaning. You see, there are really only two possibilities for someone questioning you: they lack data or they have arrived at a different conclusion after weighing the data themselves.

In the first case, telling them to educate themselves notifies them of your superiority (you are in possession of data they lack) at the same time you deny access to yourself as a resource (you are directing them elsewhere for acquiring that data). It's a dismissive brush off. In the second case, telling them to educate themselves is a judgement of their experience and conclusion without the benefit of explanation or debate. In both cases you are saying that you are better than they are and that they shouldn't be allowed to participate in the discussion as a result.

If you honestly believe that someone disagrees with you due to lack of information, a better response would be a series of questions or even challenges geared towards examining their point better. “Have you considered” questions or “I disagree because” statements are more helpful; they give others the chance to respond and have the courtesy of taking someone seriously enough to invest in the discussion.

Weighty Matters

What if I'm already educated and I still disagree? What if I've done the recon, seen the scene, danced the dance, bought the souvenir and I still beg to differ with your Great Truth? How can two intelligent people look at the same data, having access to the same information, and arrive at two legitimately different conclusions?

Allow me to educate you. (heh)

You see, most decisions are complex and involve competing principles. Do I take the time to add an abstraction layer that will be useful later or do I YAGNI my way through with the simplest solution that works right now? Do I hassle with System.Data.Common to support multiple database providers or allow a strong dependency on SQL Server? Do I use test first to drive out my design or am I confident that my planned design is decoupled enough and tests ex-post-hackto will be adequate? All of these decisions break down into factors that we weight according to our experience and expectations.

I'll illustrate what I mean. Lets take, for example, deciding if Georgette Heyer is better than Meg Cabot. It can be argued (and I would, indeed, so argue) that they have comparable ability with characterization, prose, story, and plot. However, Meg Cabot sets her characters in modern settings and Georgette Heyer's books are chiefly set in Regency England. Two people could easily disagree over which author is best if one has a strong weight on “historical regency setting” without either being any the less intelligent or in need of education.

Back to software development. Consider some of the factors that might go into deciding to use TDD.

  • Force strongly decoupled design
  • Ensure a minimum level of test coverage
  • Early API exploration and (pseudo) documentation
  • Commit project to a test framework
  • Commit project to a mock framework
  • Commit project to automated testing infrastructure
  • Writing tests without the benefit of intellisense

How you weight each factor will determine your judgement of TDD. Someone who is not worried about forcing decoupled design (either because decoupling doesn't pay off in their environment or because they feel they can achieve decoupling without force) will be less likely to chose TDD for their project.

And it gets even more complicated when you realize that each factor can, in turn, be comprised of additional factors with their own weight and trade offs (you could easily break “decoupled design” down further, for example).

Learning to look for underlying principles and the weights that others may apply can be interesting as well as useful. More importantly, it opens up the gray areas and opportunities for honest disagreement (without denigration) that are vital when working with IRealWorld.

Educating Yourself

As software professionals, we owe it to ourselves, our employers, and our clients, to be educated in our craft. That's a not inconsiderable burden in a field that grows by leaps and bounds year after year with no sign of slowing any time soon. It is hard enough learning all the concepts, patterns, and practices (not to mention tools, environments, and platforms) that it is often tempting to find a core of experts that you rely on to make decisions for you (and there is some benefit in doing so initially as you come up to speed on the intricacies of our field).

But to be truly educated, you have to go beyond what your experts say and learn about the principles that exist underneath. That's extra work but more importantly it is extra responsibility. It may be that when you break a practice down into its constituent principles that you will find yourself in a situation where “Best Practices” aren't, in fact, best. To me, it is the ability to not only make that determination but to then act on it that truly makes a “professional”.

Tags: , , ,

Programming

Appreciating Alt.Net

by Jacob 22. January 2009 00:39

Appreciation I'm on record as dissenting from some of the planks of the Alt.Net bandwagon. I question design for testability and have extended that to questioning what I consider to be the over-use of Dependency Injection (though I've also talked about using it successfully in a project that I believe warranted its use). Further, in my last post, I asked if the Alt.Net folks couldn't expand their treatments of design principles to include contra-indications or fault points. I also decried those who actively stifle alternative viewpoints, though I left it vague about who I think might do so.

Given all of that, it's easy to see how some Alt.Net folks might see me as an antagonist and read my posts from an adversarial perspective.

For the Record

Realizing this, I thought I'd take a post to set the record straight. I'm glad that the Alt.Net movement exists and that there are so many quality .Net developers putting so much effort into that community. Software development is a non-trivial task with a huge range of concerns and diversity of environments. Having a group of people with an eye on broader software developments who then take the time to translate advances in other spheres into .Net is an invaluable service. Many folks in the Alt.Net crowd not only teach and explain software development advances, they work with awesome intensity to bring tools to the .Net environment that enable and promote these methods and practices.

Their passion and energy have advanced .Net development immensely and I would do nothing to take away from or diminish their achievements. We (as a .Net community) benefit from their work even if we don't implement the practices, tools or patterns they espouse. Not only do we gain from the visibility they give our platform, but we enjoy improvements that make it back into our development environment (whether through Microsoft or through tools vendors who incorporate and enable better designs).

Elitist?

So is the Alt.Net community elitist as they have been accused by some? I'd be careful about making such an accusation. Any group is going to be “elitist” if only from the simple fact that for a group designation to be useful you have to have people both inside and outside that group. Attributing a personality to Alt.Net is complicated, though, by it's amorphous definition. There's no official designation, no tribunal, no excommunication procedure—there's not even an official, endorsed doctrine. Alt.Net is a convenient designation to describe a general group of practices (and/or developers who favor or promote those practices) the details of which are in a more or less constant state of flux.

Generally speaking, those who identify themselves as a part of Alt.Net are some of the best and brightest in the .Net development community. They're smart and they have strong opinions (however loosely held) and they are willing, even eager, to express those opinions when given half a chance. Smart people expressing strong opinion can come across to others as elitist but I don't think that is an accurate description of Alt.Net as a rule. At worst, you can describe them as having high standards and the guts to promote the advantages of adhering to those high standards.

That's not to say that there aren't those in their ranks who sometimes behave arrogantly. As I described in my last post, I was stung by the public remarks of one prominent Alt.Netter and his casual disregard for my post and for me personally. I wouldn't, however, paint that incident as either representative of Alt.Net as a group, or even as representative of that specific person.

Painting the Alt.Net community as “elitist” can be simply an excuse to disregard them and their practices and I think doing so is a mistake. Even if they were a bunch of elitist jerkwads (which, again, I do not consider them to be), the fact remains that their ideas and principles are valuable and ignoring them will only hurt you. I may disagree with the broad applicability of Dependency Injection, for example, but I'm glad I learned the concept from them so that I was able to use it when I ran into a situation that was pretty much tailor-made for that pattern.

Transparency

One of the reasons Alt.Net suffers the slings and arrows of their detractors is that they take pains to be transparent. Their email list is open (and public), many of them are prolific bloggers, and they aren't afraid to speak up when they disagree with each other. This transparency can lead to unfavorable comparisons to organizations that are less open (like, say, the Patterns and Practices group at Microsoft). Such comparisons are misleading at best.

Laying your disputes out for public observation can make you look weaker than you really are because people will use those disputes as an excuse to ignore your strengths.  It's easy to miss the reverse side of that coin—being open allows your ideas to be broadly tested and honed. It takes a certain degree if intellectual fortitude to operate transparently, but being able to do so leads inevitably to stronger solutions, principles, and practices.

Those who are willing to put their ideas out there with warts and all deserve respect. I, for one, am happy to give them the respect they've earned (even as I remain willing to question individual applicability in my own development).

Tags: , , ,

Programming

Professional Development

by Jacob 14. January 2009 15:22

Baby Developer Many of the interesting .Net bloggers are part of the Alt.Net crowd; evangelizing Dependency Injection, Design for Testability, Test Driven Development, SOLID design and other development practices that they find useful in their work. It doesn't take long reading these blogs to pick up on what looks like an unforgiving attitude towards those who don't use the latest acronyms in their software development.

This acrimony is unfortunate because most often what is at the heart of those who question the standard Alt.Net toolset isn't so much principle as it is context.

A Fundamental Assumption

Unfortunately, discussing software development at all imposes an initial assumption that too often goes unexamined—the assumption that the software development you are doing is substantially similar. I'm afraid that this assumption is violated more often than we realize.

Most prominent development bloggers are consultants, conference speakers, tool vendors, or framework providers of one sort or another. As such, they are used to considering the problems of very large applications with many cross-cutting concerns. Is it any wonder, then, that they are strident about the importance of segregation and testing? For the majority of their hands-on development, everything that increases separation and independence is a benefit because isolating fail points and mitigating the cost of touching individual elements carries a heavy multiplying effect on overall complexity. No wonder they want to use a DI framework on every project and insist that other developers practice TDD. It's all up-side in such projects because the costs disappear in the noise and the benefits stand out.

Not all of us work in those kinds of environments and/or applications, however. Many of us work on projects that are wildly dissimilar. Our applications are narrowly focused, single use, and with limited distribution. For us, implementing solution-wide DI eats up half the project configuration overhead and delivers functionally zero chance of eventual benefit.

I'm unsure how many find themselves in similar (smaller) development shops. I suspect quite a few. We might even be a majority of actual, working developers. We're pretty much absent from the development blogger population, however.

A Problem

What that means for us small-shop developers is that we end up having to do a lot of on-the-fly translation. Up-scale bloggers have shown themselves averse to “thinking down” so we end up having to analyze the methods and techniques they discuss to see where the fail points are for our projects. If your QA team is the folks in the warehouse and your architecture a straight-on table insert, is TDD really going to pay off? What about bug tracking? Or continuous integration?

These translations are interesting and part of why I like smaller development. Our problem space is largely undiscovered country. We can't really trust anything labeled “best practice” and we have to do our own experiments to find what works and what doesn't and at what point it starts to make sense to engage different methodologies.

It'd be nice, though, if some of the gee-whiz bloggers would discuss the fail points of their methods and tools. Or point out the trade offs that various techniques are likely to entail. No technique or method is so useful that it is universally applicable, so where are the borders?

Worse, though, are those who actively stifle discussion of such fail points. Mention that you'd rather not use Dependency Injection, for example, and you can find your professionalism and/or intelligence questioned. Indeed, for many the very fact that you don't <insert favorite practice here> indicates that you must never have tried it. Or if you have you must have been doing it wrong.

This friction fosters resentment and shuts down discussion. Perhaps one reason we don't see more developers willing to discuss alternatives to the popular band wagons of today is a reluctance to enter what amounts to a hostile arena. As the troubles on Wall Street filter down to Main Street (where us small-shop developers live) the last thing we need is other developers calling us unprofessional in public. Particularly when those other developers are well-known and respected in their community.

I know this from personal experience. I'm pretty secure in my current position. My company is healthy and has a marked competitive advantage that I am key to delivering. My boss respects me as do the owners of the company. Even so, my gut clenched tight and my heart sank to my knees when I came across a twitter message from a luminary in our field (someone any informed .Net developer would recognize) dismissing me as unprofessional and my points as unworthy of consideration.

Seeing something like that will make you wonder if expressing your doubts is worth the risk, even when it isn't directed at you.

Tags: , , , ,

Programming

I'm a Lumberjack

by Jacob 13. November 2008 03:14

Lumberjack And I'm okay. Indeed, last week saw a payoff for one of those hygiene things you do because you know that you “should”.

A Logging Story

Allow me to share what happened (feel free to skip this section).

We receive orders from a number of different sources. In addition to EDI, we have spreadsheets, flat-files, and we even originate a few ourselves under Vendor Managed Inventory (VMI) agreements. One of the things we've done recently is create a single “process pipeline” such that once orders enter the pipeline, their processing from that point forward is uniform. Thus, a new client can send us whatever they want to (or can), and all we have to do is get the order details into a set of order import tables and away they go. i.e. we create a single customer-specific import routine to start their orders off instead of an entire order-processing process (yes, that was the previous solution when adding new customers—don't ask, it wasn't me).

So yeah. One entry point into the pipeline (it isn't fancy enough for the appellation “workflow”) is a set of order import tables. A simple console application is called by the import routine that created the entries. All it does is take the orders identified and create them in Dynamics GP. It is generally called by nightly import processes that run unattended.

This routine has been running for months now and frankly, I don't think about it much. That is, until last Thursday when I received an email with the subject “ImportOrders Log: Error”.

The cause of the error isn't really important (one of our customer records hadn't been updated with the new shipping method and GP Web Services choked). In a batch of 146 orders, the last 5 were skipped. It took me fifteen minutes to determine what had happened and why and another fifteen for our data guy to put together a fix—all before the rest of that order had been processed for the day.

Our internal order processors would never have caught this error so logging and notification saved us a couple of angry phone calls and pissed off store managers (and hence account managers and executives).

Chainsaws

So here's the rule:

Any process that will run unattended must have robust logging that will not only proactively notify you of any errors, but that also allows you to rebuild the circumstances and conditions surrounding errors encountered.

There are a number of good logging toolsets out there. I highly recommend finding and using one rather than “rolling your own”. A logging toolset will give you more flexibility and stability than you could give yourself and frankly, who needs the headache of slaying a dragon that has already been taken out so very thoroughly?

For this project I used the Enterprise Library Logging application block. Subtext uses Apache's log4net. I'm willing to bet that there are others of similar quality. Key features include being able to refine (through configuration) logging levels and logging details like where the log is kept and what form it will take.

Deforestation

As with any good general rule, there is a real temptation for over-application. A little logging saved a ton of aggravation so imagine the benefit I'd get if I logged everything! Yeah, well, don't forget your friend YAGNI when determining if and what to log. Pile up enough of these things and before you know it every little project can be so encrusted with “must haves” that you end up with huge unwieldy project frameworks.

Not that there is anything wrong with a good framework for enterprisey applications. But that's not what I had here. All I have is a simple console app that runs when needed to import orders into Dynamics GP. All the potentially enterprisey stuff happens later. I needed logging that kept track of events and notified me of errors. I didn't need much more than that.

Tags: , , , , ,

Programming

Too Much Quality

by Jacob 8. July 2008 21:22

deluxe doghouse The latest .Net Rocks podcast was from a panel at TechEd 2008 (that I sadly missed while there). Richard Campbell was the moderator and the topic was Software Quality. It was a good, if somewhat one-sided discussion and I recommend giving it a listen if you are so inclined.

I particularly liked Billy Hollis' perspective on quality because it was a perspective that was grounded in both reality and sound business principles. He kept bringing up quality in terms of trade-offs and the others kept trying to waltz around those comments with a more absolutist, almost dogmatic, vision of software quality. I think it was a real shame that Billy Hollis was so out numbered because his points are important if we are to gain the stature we desire as a profession.

The final comments completely got on my nerves. Which is fortunate because it helped crystallize my discomfort with the others.

Billy Hollis started off with this simple statement.

My key insight that I try to communicate is it’s all a matter of trade-offs. And getting to what the user needs is first and quality is defined within that context.

To which Neil Roodyn responded.

I’ll disagree. It’s about quality. You’ve got to get your quality as high as you possibly can. Always. The higher the quality of the software, the higher the quality the software will remain through the development life cycle. So right from iteration zero keep that quality as high as you possibly can.

And Jeffrey Palermo added.

The higher the quality the better. You can’t have too high of quality, you would just say you have too much behavior for the situation.

The thing is that Hollis is right and the other two are not only wrong, but dangerously wrong. Other members of the panel (David Platt and Neelesh Kamkolkar) didn’t support Hollis either, though they weren’t as overt as Roodyn and Palermo.

What Are You Trading?

The thing is that software quality, besides being pretty much impossible to measure, isn’t a first-order good in the first place—i.e. it isn’t valuable in and of itself and delivers what value it adds indirectly. You can make the reality of this simple business fact plain by pointing out how the deciding factor between two competing products is often not quality. Betamax anyone? Rolls-Royce? Sun Microsystems?

People choose software for a lot of different reasons and those reasons are very rarely explicitly the “quality” of the software. Price, availability, familiarity, and usability all play roles in the purchase (or use/approval if internal) of software and these factors need to be kept in mind. It could be that it is better for your company to have software that is harder to maintain but completed two months earlier. I do this all the time because I have lots of projects that are single-use and with a restricted domain.

Software development involves time, money, commitment, and concentration. Spending those valuable resources should be done carefully and be based on actual value to the company. Quality has a cost. Quality doesn’t always have a pay-off. Business people have a term for a cost that doesn’t return a pay-off. That term is usually “good bye”.

Dangerous?

So Palermo and Roodyn are wrong, but why are they dangerous? This comes back to my observations during the dot com bust. I observed the glee in putting IT back in its place. You see, during that whole tech bubble IT got arrogant. Technical folks were wagging the business dog, dictating strategy, policies, spending, and sometimes even remapping the boardroom to their liking. Which would have been fine if the business rules really had changed as some thought. Unfortunately, they hadn’t. This arrogance set the entire profession back because business leaders learned not only of our arrogance, but of our ignorance as well.

We don’t bother learning even basic business principles before we make important, even critical, business decisions. This discussion of quality is an example of just such thinking. Roodyn and Palermo are talking about dictating business resources without any concern for accommodating business realities. Worse, they don’t seem interested in even learning about or exploring the business realities they, of necessity, work under.

As much as we might like the universe to bend to our personal theories and values, the fact of the matter remains that there are a lot of reasons to compromise aesthetical purity when the rubber meets the road. Those reasons don’t simply go away just because they make us uncomfortable. Indeed, how we react to the inevitable trade-offs required will largely determine how much business leaders decide to trust us in the future.

Here’s a helpful exercise. Imagine you are a business leader evaluating which company to hire to solve some software need. As part of your vetting process, you ask two finalists their stance on software quality. The first one answers with “Getting you the things you need is our first priority and quality will be defined in that context.” The second one answers with “Quality is number one. Always. Quality cannot be too high though it could be that you want too much behavior for the situation.” Which would you hire? If you answered the second, it is because of ideological blindness. Actual business leaders will not only tend to go with the first, but will have confidence and trust in doing so.

Are You Agile?

A lot of the value in IT comes from giving businesses flexibility. Processes that used to take indoctrinating a new generation of workers can now turn on a software release. While this is both a blessing and a curse for businesses, it remains a key to our value in IT. Businesses have learned to be wary of our use of resources, however, and with some cause. It is unfortunate that they cannot trust IT, but until we let the needs of the business drive our development I’d say that their trust hasn’t yet been earned. If we really want to be masters of our own fate, we must learn to live in the messy world of business. We can only do so by proving that we will use the flexibility inherent in our profession wisely.

Tags: , , , ,

Programming

Putting Dependency Injection in its Place

by Jacob 13. June 2008 05:27

Careful Placement You might say that I’ve had issues with Dependency Injection in the past. Well, with all the things I’ve learned not to do, I thought I’d go into a case where I’m considering dependency injection because it looks like it might be a good fit.

Project Background

Like many (most?) developers, I’ve been involved for many years in a particular vertical market. Like most, my involvement in that vertical market includes acquiring a substantial amount of very specific domain knowledge. I’m sometimes reluctant to admit it, but I spent a good decade and more of my career writing software designed for Multi-level Marketing companies. Specifically, I wrote programs that calculate the commission payments to their distributors. If you are familiar with that domain, my condolences. If you are considering entering that domain, talk to me (it’s not all bad).

Now, many accounting software packages deal with paying commissions, but compared to even the simplest MLM, their capabilities are pretty primitive. I won’t go into the full complexity of walking a tree with money on the line, but here’s what’s important for this post:

  • The data you have to process is well contained, finite, and known in advance.
  • Data concurrency tends not to be an issue (you read distributor information at the beginning and you write payout and promotion information as you go or at the end).
  • Every company has their own, unique twist for qualifications, promotions, and payouts—indeed, commission plan differentiation is a key business differentiation.
  • The only thing absolutely common to every commission plan is that you walk a tree of distributor nodes, processing orders at those nodes, and calculating payouts and/or promotions on them.

Most programmers working in that domain spend time designing their dream "bonus engine". One that can encapsulate the common elements so that their programming only has to deal with the payout and promotion logic. This turns out to be harder than you’d think to do right (if only due to the temptation to put more in the engine than really belongs there).

My Bonus Engine

Since I’m still getting occasional contract work programming commission payouts (and because I’ve seen a bonus engine or two and know what works and what doesn’t), I went and created an OSS bonus engine. Those of you dying to critique my code-fu to bring me up for well-deserved mockery, here’s your chance. So far I’m the only dev on the project, but that’s only because I don’t know anybody else masochistic enough to join me (hey, if you’re that nuts, let me know).

Right now, this engine is still pretty raw, but it works. Mostly. There are INode and IVolume interfaces for distributors and orders respectively. There’s a NodeBase object that implements INode with nifty events already implemented for easy inheritance and feedback and there’s a BonusManager object used to kick off a bonus run.

The tricky bit for this post is the data access. You see, when programming commission payouts, I seriously don’t care where the data comes from or where it is going. My clients all have their own tricky little data schemas and I’d just as soon not deal with the ins and outs of their systems. Abstracting that part out is beneficial all round.

In my initial design, I figured that something like that is a classic call for an Asp.Net-like provider model. This works well because the client can implement a provider (or have me create one for him) that we can drop in and we’re golden. That means that my eventual Distributor objects can be ignorant of all data implementation details and make a call to MLMBonus.DataProvider.BonusData.Promote() to notify of a promotion (for example).

Making the method references static seems like a good call because the distributor object has no other contextual information available. The engine is walking a tree and calling interface methods so the distributor and volume objects don’t really know much more about the outside world than their relationships to each other.

Because this is my first ever implementation of a "Provider Framework", I went digging for some sense of what kinds of things to look out for. While I initially went with an interface structure, I eventually decided to use Joel Ross' well written guideline for creating your own .Net providers.

There’s Always One

Unfortunately, I got some push-back when talking with my favorite client. You see, he’s chafing at the static nature of my provider model. He wants to make a grab for the holy grail of bonus commissions—executing mini-commission runs on-demand (most likely for partial distributor trees)—and the static provider just isn’t cutting it for him. mini-commission runs allow you to provide some interesting features to your distributors and that’s never a bad thing.

To support his functionality, he would need to be able to alter the data provider "on the fly" and/or be able to initiate multiple runs in the same application space without allowing them to step on each other. There’s just no way that static providers are going to work for that functionality. Naturally, I’ve been thinking about how best to work out meeting his need (mainly because I can see this feature will be something others will like but also because he’s my favorite client). Fortunately, my engine isn’t widely disseminated so it’s a good time for wholesale architectural alterations if we want to make them.

I’ve considered a number of ways to tackle the problem, playing with things like anonymous methods and context managers. They all turned ugly fast so it’s time that I face the fact that this functionality is pretty much tailor made for Dependency Injection.

Where To Inject

So where’s the best place to inject this little dependency? There are four options as far as I can tell.

  • constructor injection
  • property (or setter method) injection
  • method parameter injection (since the number of methods affected will be very small).
  • framework injection (Spring.Net or Castle Windsor for example)

Constructor and property injection are both object level references carried by the dependant object and have little to distinguish them in effect. Conceptually, I’ve heard that constructor injection is best for dependencies that are crucial to an object—something the object simply cannot do without. I think I agree with that guideline but I also like the convenience of being able to do grunt-work things in constructors, so if I were in charge of the objects, I’d include both a base constructor and one that includes the dependency as well as a setter method of some kind.

Method parameter injection is tempting, though. With method parameter injection, a client can set the dependency on BonusManager and rely on BonusManager to send the dependency to the Pay and Promote methods on INode. That way the reference to the data provider is short lived inside INode and IVolume objects. Thinking it over, though, I’m not sure why I’m so worried about carrying a bunch of references when garbage collection isn’t going to happen mid-run anyway. Yeah, there’s some overhead involved in tracking the reference on each INode object, but it’s negligible (are pointers in a 64 bit environment 64 bits long? They’d pretty much have to be right? I’ve never bothered to find that out—it’s never been significant before).

Framework injection simply isn’t going to be helpful in this case, I don’t think. For one, I’m not familiar enough with any DI Frameworks to make it worthwhile. For another, I don’t want to introduce a framework dependency on the project. And finally, I don’t want to commit future clients to a DI Framework that may be an issue in their environment.

Injecting

So my next task for the engine will be to muck around with the EngineInterfaces library. I’m thinking I’ll leave the provider object as-is (the BonusDataProvider abstract class) and simply add a property to INode to inject that sucker. In addition, I’ll update NodeBase to have an appropriate property and a new constructor that allows you to set the provider property on object creation.

Since I have the provider stuff already in place and no changes are needed to make this work, I’ll likely leave it alone. That way I won’t break anything currently working.

The only thing left is to decide if I want the IVolume dependency injected via a field or a method parameter on Pay. I’m pretty sure I don’t need the fine-grained control of allowing different orders for a single node to pay down a different path, but do I really want to commit to that? My arguments above against method parameter injection seem pretty solid for the IVolume object as well, but I haven’t completely convinced myself that they apply as strongly.

Tags: , , , , , ,

MLMBonus | Programming

The Technical Manager

by Jacob 23. April 2008 01:20

Small Manager Aaron Lerch talks a bit about what it takes to be a technical manager. He enumerates five characteristics that he feels are essential for a technical manager (personally, I think that they are better classified as skills because they’re learnable and improvable). Here’s his five:

  1. Communication
  2. Technical Savvy
  3. Organizational Skills
  4. Priorities
  5. Humility

It’s a good list for the good times, I think. As long as things run more or less smoothly, a manager with those traits will be in good shape. As you can probably tell by my qualifiers, I think that he’s missing something.

Tough Choices

Unfortunately, managers (technical or not) often find themselves in a position where a decision has to be made and where the choices are all distasteful. What do you do when it turns out that someone doesn’t live up to your expectations or, more importantly, their job description? Or they simply don’t get along with the other developers on the team? Or, heaven forbid, the company has decided that less overhead in the development department is needed?

Firing someone is, by far, the hardest thing I’ve ever done as a manager. Firing someone is both an admission of failure and one of the harshest things a person can legally do to another. So a manager who fires somebody is pretty much a big, mean failure.

It’s a real shame that sometimes, people simply need firing. If you’ve ever been on a team with someone who couldn’t (or wouldn’t) pull their own weight, you’ll understand what I mean. Not firing someone who needs it can have a larger impact on team productivity than just about anything else I’ve encountered. I know because I’ve been a team member when someone needed to be let go and the manager couldn’t bring himself to pull the trigger. The hit to both productivity and morale is huge and grows geometrically over time.

Firing someone is the extreme case of an important skill. Management is all about the hard decisions. Yes, communication is important. And making irrevocable technical decisions without team input is suicide. But consensus is the one sure path to mediocrity and, frankly, mediocrity doesn’t do that well in the marketplace. It’d be nice if everything would shake out into rational lines with obvious choices, but real life (and real development) doesn’t work that way.

Decisive Humility

To make things harder, Aaron’s point about humility is still a good one. Technical managers should do their very best to surround themselves with people who are smarter than they are. Being surrounded by smart folks can be hard on you if you wear your ego on your sleeve, though. Also, smart people are incredibly difficult to control.

Being able to make compromises and solicit (and listen to) advice from your team is important for both you and them. But eventually, you will find yourself in a situation where the alternatives are as known as they are going to be and it is time to make that tough call. Making that call (and sticking to it) is your job. Managers who waffle or leave it up to a vote (whether formal or not) or who weasel out of responsibility later compromise the integrity of their team.

Balancing humility with the power and ability to decide is tough. It is, nonetheless, necessary.

Top Skills

So how would I re-order Aaron’s top five?

  1. Communication
  2. Technical Savvy
  3. Responsible Decision Making
  4. Humility
  5. Priorities
  6. Organizational Skills

While this is a general ranking, situations will arise where any one can become paramount—meaning that none are optional. All of them should be as strong as you can make them and the better you do, the better manager you will be.

Tags: , ,

Testy Development

by Jacob 21. February 2008 21:16

Peeved One of the things that irks me when discussing certain technical topics is a tendency towards boosterism that can hinder, or even halt, deeper evaluation and discussion. Some topics, tools, or practices arrive with a divine imprimatur of authority that is hard to resist. Since I believe in being personally responsible for the software development I undertake, I sometimes find myself exploring murky territory that seems like it should be better mapped. The latest of these pre-hallowed principles is Test-driven Development.

What comes across as a casual assumption of superiority gets my hackles up. I’ll show what I mean using a recent post by Derik Whittaker titled Sound of One Man Testing. I want to be careful up front, though, because my purpose isn’t to pick on Derik. Indeed, I really liked a previous post of his describing his love of being a software developer. I suspect that I’d like him if I knew him personally. I’m just using his post so that I have concrete illustrative examples for what I’m reacting to. His post is in good (and numerous) company.

TDD or A Poke in the Eye with a Sharp Stick

I mentioned this before, but it keeps happening. The comparison to TDD seems to always be a complete lack of testing. This is always a flawed comparison. It doesn’t matter if you’re addressing heathens or saints, it simply carries no useful information. It promotes sloppy thinking and lazy arguments because you set such a low hurdle to beat. It’s worse than unconvincing because it irritates people who disagree with you and thus erects barriers to communication.

It is a textbook case of the Straw Man logical fallacy. Defeating a straw man isn’t really much of an achievement and pretending that it is doesn’t make it so. Skipping straight to 50 when counting out pushups is only impressive to someone who didn’t notice. It doesn’t actually do you any good and will certainly never result in those ripped abs your SO goes on about.

Going Mental

Derik says "Following TDD is more about your mind set and attitude [than] it is about the process in my opinion." David Tchepak recently made a similar point (admittedly tangential to his post) in his generous response to my earlier comments, "I feel TDD has the potential to change the way you think about coding."

I get their sentiment and I’m not trying to dismiss these statements out of hand. Attitude, mind set, and perspective matter, and things that keep you focused or have other purely mental benefits have a place in software development.

It’s just that these benefits are highly personal and hard to make relevant. If you include them, it is helpful if you can make sure that they are an important part of your point and that you develop them in a way that stands a good chance of connecting with others. Failing to connect them to your larger point makes them stand out, weakening the whole.

Clique Here

Many posts about TDD are aimed at those who are already convinced. Derik’s post is one such—he is clearly addressing those who already believe in TDD who want arguments to help them bring TDD into non-TDD environments.

Which would be fine in a discussion group or forum, but is more problematic in a blog post. Blogs are, by nature, public (I’ve seen private blogs but I really don’t see their point). Blog posts are likely to be read by people who don’t share your basic assumptions. It is wise to bear this in mind when discussing potentially controversial topics.

Addressing an in-crowd comes across very poorly for those who don’t consider themselves part of your community. It’s like those jerks in High School who talk about others in public as if they weren’t there—which is essentially what you are doing.

Take this section of Derik’s post, for example:

Benefits the project will gain

  • Better code coverage
    Even if you only can cover 5% of the code in your tests, that is 5% less code to worry about
  • Increased code quality
    Do I really need to explain this?
  • Increased code reliability
    Do I really need to explain this?
  • As foundation to grow on
    Because you have [taken the initiative] to create the test plumbing (i.e. configuration, db setup, logging setup, etc) you have reduced the barrier of entry for other developers. I have found that this barrier of entry is a common reason people don’t want to start testing.  I know it is lame, but I have heard it.

Someone not already convinced of the superiority of TDD can take what looks like a casual disregard for their perspective poorly. My inner spite-demon pops up like a jack-in-the-box and says things like "Yes Derik, you do really need to explain this." or "Do you really mean to say that covered code == code you don’t have to worry about?" or "Taking the initiative to provide infrastructure only you use sounds a lot like wasting time and resources to me."

While I got over myself (and reminded myself again that I liked his previous post), the reminder that I’m not in Derik’s clique is off-putting. If you don’t want to re-hash arguments that you feel have been established elsewhere (a perfectly reasonable impulse), give a link (or at least a reference). Bear in mind that there are reasonable people out there who don’t share your convictions and if they show up you would probably like it if they would hear you out.

Remembering that Reasonable People Disagree

There is an unfortunate human tendency to believe that all smart people agree with you. The corollary is that anyone who disagrees with you is stupid. The thing is that even if you are right, communicating from that perspective doesn’t work out very well. Reminding yourself from time to time that people disagree with you and some of them might be worth reaching out to is a good habit to cultivate. I know that I’d personally take it as a kindness.

Technorati Tags: ,,

Tags: , ,

Programming

Post Comments

by Jacob 29. January 2008 12:58

BlahBlah The discussion spawned from my TDD post has been interesting to me. I’ve enjoyed the comments by Phil on his post and by him and others on my own. I’m particularly flattered that one of the authors of the original study dropped by. I disagree with some of his points, but this isn’t where I want to address them. Instead, I want to examine the discussion itself because this is definitely something that we as a software development community could be better at.

The Report

First, I want to emphasize something that I could have made clearer in my original post. The original study was extremely well designed and I have no issues with how it was conducted or how it was structured. I described the report in my prior post but neglected to give my opinion of the setup. Let me correct that now: this is an exceptionally well-designed, well-executed, and well-written study. And I’ll point out that my criticisms were not with the data collection or design. If you go back over what I said, you’ll see that my concerns are with presentation and interpretation.

On Commenting

As I said, I enjoyed most of the comments posted both on my post and on Phil’s. That said, here’s some advice for those expressing opinions online.

First off, if you are going to criticize something, it’d probably be best if you actually read it. Or at the very least, read what is said about it very carefully. I can tell that many of those supporting or criticizing the report hadn’t bothered to get to know the study at all because of little misrepresentations they made (like assuming that two teams from a group of 24 must be split evenly—they weren’t). Here’s the thing, if you make little errors of fact, it becomes hard to take the rest of your points seriously.

Second, if you are going to criticize the way a study is put together, it’d help if you know what you are talking about. Take sample size, for example. While 24 seems like a small sample size to end up with, there are very detailed and specific methods to adjust for sample size in statistical mathematics. This fact is at the heart of the authors' use of the term "statistically significant". In essence (and strongly backed by decades of research) if a bias is strong enough, sample sizes don’t have to be very big to be representative enough to be useful. A little cross-discipline humility goes a long way here.

Now, I have no problem with someone who might say "that seems like an awful small sample size" because that allows you to express your doubt but also leaves room for further enlightenment and avoids making an unsupportable assertion of failure. The thing is that this study wasn’t put together by amateurs. This is an academic paper presented to the IEEE. Like all good academic papers, it includes an entire section titled "Threats to Validity". Reading it, you’ll notice that sample size is not listed in this section. Asking (yourself or in general) why a sample size of 24 isn’t considered a threat to validity is a good idea and potentially interesting in a geeky kind of way.

Third, the force of your conviction doesn’t ameliorate the burden of making your point clearly and rationally if you want to convince someone else. Too often, advocates will substitute emotion for reason when discussing their Great New Thing™. That’s a perfectly human thing to do. It is also perfectly human to reject overwrought arguments out of hand. Seriously, you do your cause no good if you cannot be bothered to make your case in clear and rational terms.

Finally, if you don’t know people you can simultaneously respect and disagree with, the problem isn’t that people who disagree with you are all stupid jerks. The limits of a system isn’t in the brilliance of those arguing for it, it’s the brilliance of those arguing against it. Untested theories and unquestioned understanding are as useful as untested code. Personally, for any given topic, I want the best arguments that I can find. It’s not enough to examine both sides of some new thing, I want the very best arguments that both sides have to make.

Which is why I appreciate the efforts of people like the authors of this study. And why I appreciate guys like Phil who take the time to discuss their theories and to explain and expound them when challenged. None of this stuff is a no-brainer. If it were, people wouldn’t pay us to do it.

Technorati Tags: ,,

Tags: , ,

Observations

TDD or POUT

by Jacob 26. January 2008 10:41

pouty boy Because Unit Testing is the plain-Jane progenitor of Test Driven Development, it’s kind of unfair that it doesn’t have an acronym of its own. After all, it’s hard to get programmer types to pay attention if they don’t have some obscure jargon to bandy about. UT is too awkward, besides being a state abbreviation in the U.S., so for this post (and, if it catches on, future posts as well) I’ll borrow from the telco folks and call unit testing Plain Old Unit Testing.

The Best of all Possible Worlds

Part of my problem with TDD has been that it claims to provide complete testing. You see, even if this is true, it runs up against my gut feeling that worse is better when it comes to unit testing. Or, to throw in yet another development aphorism, it is my suspicion that unit testing lies squarely in the realm of the 80/20 rule—80% of the value of unit testing comes from 20% of your unit tests.

While it is functionally impossible to know in advance exactly which 20% of your unit tests will be important later on down the line, that doesn’t mean that we’re throwing darts at a board. Experienced developers can make pretty good guesses about what the problem areas are likely to be. And they’re pretty good about developing unit tests that cover those problem areas.

Which is my way of saying (or restating, really) that number of tests is no more important to me than number of lines of code as a measurement of value in programming.

Crossing the Beams

I think some of the confusion with TDD discussions is that TDD is an intensified version of POUT. Both POUT and TDD use unit tests. Both do so as part of a process. Both are concerned with future maintenance and functionality. The primary substantive difference is that TDD writes the unit tests before developing anything else.

Unfortunately, the popularity of TDD followed the widespread use of POUT very closely. This hurts because we never had a chance to get comfortable with POUT on its own before TDD appeared on the scene. Indeed, many people went from no POUT (or just beginning to learn) straight into TDD.

What that means in practical terms is that we have a tough time separating the value of POUT from the value of TDD. Few people have done both thoroughly enough to judge them based on this relatively singular point of differentiation. The inability to distinguish or track the value of each separately lies at the heart of much of the cross-talk surrounding TDD and TDD evangelism. Indeed, many of the testimonials I’ve seen (including many comments on a prior post) seem to assume that without TDD, no testing is done at all.

Those of us who are happy with POUT (and looking at the extra effort needed for TDD with some distaste) are left wondering what TDD offers us that we don’t already have. We don’t want some hogwash about forcing us to do our job. We see the value of testing and have learned to take time out for POUT (Oh. There’s a slogan that you can paste up on your very own office wall "Time out for POUT!" Remember you read it here first.). Frankly, it seems to me that we’re getting the goodies the TDD folk go on about just fine and without having to retrain how we develop.

A Call for Differentiation

So here’s my request for those of you who are using and enjoying TDD who want to invite us all to partake of its superior benefits: please couch your arguments in the assumption that I am already POUTing, that my POUTing already delivers substantial benefit, and that adopting TDD is a non-trivial training and practice burden. Thank you.

Technorati Tags: ,,,

Tags: , , ,

Programming

scruffylookingcatherder.com

Information

    Recent Posts

    Calendar

    <<  September 2010  >>
    MoTuWeThFrSaSu
    303112345
    6789101112
    13141516171819
    20212223242526
    27282930123
    45678910

    View posts in large calendar
    Disclaimer
    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2010 Scruffy-looking Cat Herder