Working Life

You are currently browsing the archive for the Working Life category.

I’ve found that putting together a very rough architectural sketch is the best way to start when you’re building an application from scratch. While it’s a lot more fun to write code and see it executed, you save yourself a lot of grief, and create a more robust and flexible system, if you think things through up front and draw some boxes and arrows.

For this project, I knew that I would have at least three tiers: the user interface, which would initially run on WebSphere Application Server but should be portable to WebSphere Portal Server; the business logic layer, which would do the heavy lifting of taking the user’s input and sending it to the right back end screens; and the back end screen interface itself, built on an existing Java bean architecture.

I also knew, from painful previous experience, that keeping those tiers separated was critical. Java makes n-tiered development easy, with the ability to control scope and encapsulate functions, but it also makes breaking a clean separation of tiers very easy, too. Sloppiness early on, in making too many methods public rather than protected or giving one class too much access to things outside its logical scope, can doom your application. So that initial architectural sketch should include an attempt to block out the domains of interest and identify what limited interfaces should exist between different parts of the application.

I ended up with something roughly like this:

4GL Service Layer

Back Office Beans
Business Logic
Configuration Logic
Services (JAX-RPC)
Client Layer

Service Client
Controller
Business Logic (limited to validation rules)
Configuration Logic
User Interface (JSP, CSS, JavaScript)
User’s browser

The service and client layers are implemented as separate web applications: though they are packaged in the same enterprise application for ease of deployment, they are independent of each other and could be deployed as individual WAR files. Each domain surrounded by dashed lines in the table above represents at least one Java package, with most methods set to protected rather than public: this limits the points where changes in one layer can affect the code in another, and makes swapping out different services (caching, configuration, etc.) relatively easy. Building clear walls between application layers in the beginning will help you in building out and maintaining the application in the future.

In the original version of the application, developed on Eclipse and running on Tomcat (I didn’t yet have access to the licensed versions of IBM’s tools), the interaction between the service and client was handled through Axis, a Jakarta web service infrastructure. In the final version, running on WebSphere, the interface is handled through JAX-RPC, the default mode for WebSphere. My first attempt to deploy the application to WebSphere was, in fact, botched by the use of Axis: WebSphere wants to do JAX-RPC when it does web services between WebSphere servers, and was very unhappy about Axis. Luckily, both Eclipse and Rational (IBM’s version of Eclipse) have handy wizards for generating the web service bindings, so switching the web service layer was relatively painless and, since I started with the practice of separating the application into distinct domains, required no code changes.

In developing a SOA application, a lot of attention should be paid up front to designing your service interfaces. Keeping your changes to the service interfaces to a minimum will make your development a lot smoother–no need to re-generate the service and client bindings if you keep method signatures in place from version to version–so it pays to do as much analysis up front as possible.

For this application, I knew that I would be passing a user-generated data bean from the client layer to the service, sending that bean through various permutations in the service layer to do all of the back office work, and then sending that bean back up to the client to show the user the fruits of their labor (and any error messages that might have been picked up along the way). So the first order of business was designing the data bean, which would act as the primary transfer object, and the methods that would accept it.

The data object had to be very flexible, since the back end system is so denormalized: multiple fields and value types would have to be carried by the bean, not all of them well known at design time. The solution was to make that bean into the carrier of a collection of field objects, which have name, value, and type (since passing raw Objects over web services is forbidden) attributes. This allows the bean to pick up whatever fields it needs to feed the back office system, without having to change the code any time a new field is discovered. With simple getField(String fieldName) and setField(FieldObject field) methods, any value can be put on the bean.

Another consideration in developing your service interfaces is data typing. As noted, you can’t send a plain Object over the wire and expect to be able to cast it to the specific type you want. Any object that is transferred over the service needs to be mapped through XML, and so should consist of serializable or primitive members. I’ve found that sticking to Strings, ints, longs, decimals, and such is by far the safest way to work with web services; more complex objects can be generated from the primitive transfer objects after they’ve reached their destination.

Once the service interfaces were in place, and the demarcations within each application were defined, it was time to start wiring things together. And that’s the fun part!

Tags: , , ,

Since September, I’ve been developing a Java application for a client in St. Paul. As noted in an earlier post, this has been a very successful project; I’m quite proud of the application, and with the quality of the work that we’ve done as a team. It’s unusual for a corporate IT project to be on time, under budget, and to deliver real functionality, so being involved in a project that hits all three is quite a treat.

The code in this project was bought and paid for by the client, for use in an application that runs behind the firewall, so I won’t be sharing any of the source here. But I think there’s value in sharing some of the patterns and principals, the architectural strategies, and the methodologies that have led to our success, and also in calling out some of the open source projects from which we’ve borrowed. In this series of posts, I’ll provide highlights of the project that have made it especially fun.

My role on the project is winding down at the end of the month, and I’ve started searching for a new gig. I can only hope that my next project will be half as enjoyable and successful as this one has been.

The Problem: So Many Screens, So Little Time

The application is used by a business unit responsible for setting up the licensing, maintenance agreements, and billing for customers. Before this application went into production, they used a series of browser screens that expose a 4GL application (extended, I believe, from a terminal screen application). To set up a customer order, the users would have to visit a dozen or more screens, often entering the same information into each one. Behind the screens is a highly de-normalized database.

Though the 4GL application contains some validation rules, there are other business rules that were really more like uncodified traditions: the users could very easily enter “incorrect” data into the screens, because there were no program controls in place to control their input. Data entered in one screen is dependent on data entered in other screens, resulting in a lot of back-and-forth in the system to gather up all the information that needs to be submitted. Training in a new user on the Byzantine ways of the process was difficult, and errors were frequent and painful to correct.

The primary goal for the application I’ve been working on, then, is to increase the users’ productivity and accuracy by giving them one form to complete. All of the manual lookup steps, all of the rules for deriving certain values and codes, needed to be automated to simplify and streamline the process.

Despite its limitations, though, the 4GL system is of great value to the business processes surrounding the data entry. It’s used to generate reports and billing, it serves as a repository of customer contact and relationship information, and it feeds into the business’s bottom line. Replacing it was not an option; the new solution would have to work with the 4GL layer, and be compatible with the rest of the business processes.

Another requirement going into the project was the separation of the business logic and UI layers. There was a strong interest in eventually using WebSphere Portal Server as the front end (not yet implemented, alas), but in the interest of meeting the schedule the first version of the application would be delivered as a stand-alone web application running on WebSphere Application Server. To avoid reinventing the wheel and introducing a lot of regression errors, we started off with a service-oriented architecture: the business logic would be implemented as a web service, with the front-end web application driven entirely by the web service layer.

The biggest challenge in getting this application started–the communication with the 4GL layer–had luckily been handled in a different project, so I was able to build on a successful set of APIs instead of developing my own methods for interacting with the back end screens. The 4GL programs expressed by the screens have an XML-over-HTTP interface, and a developer had already built a very nice tool for converting the XML into Java beans. The challenge of wiring together all of those screens, then, fell to me. And that’s the real heart of this application: marshalling a collection of disparate Java beans into an orchestrated process that does complex things using simple tools.

Tags: , , , , ,

Pardon our improvements? by John MortonI’ve worked on a variety of projects in my IT career, from small Lotus Notes applications where I’ve been the business analyst, developer, tester, system administrator, and support engineer, to multi-year enterprise initiatives with far-flung teams and huge project management systems where my role has been very narrowly defined. I’ll admit to a preference for the former–I like to write code, and waiting weeks or months for the first solid requirements to trickle in is painfully dull. But all of the projects, like most IT projects, have been plagued by the usual disconnects, missed opportunities, and frustrations with delivering what the users really want on time and on budget.

My current project, though, has been surprisingly successul. We released our first version in November, after two months of development and testing on top of about six months of thorough analysis (most of which happened before I joined the project), and since then we’ve released new and improved versions on a monthly schedule. The customer has been pleased, the application has been solid, and we continue to meet the users’ expectations.

What’s the secret?

To a great extent, it’s due to a very talented team of developers, testers, project managers, analysts, and business users. We work together well, have open and honest communication, and set up realistic and reachable goals for each release. The problem with talent, though, is that it’s not necessarily reproducible; you can’t bank on having good people in every role, or even on having good people at the top of their game most days. A project that relies on talent alone is bound to fail eventually.

What has really worked for this project is a philosophy of continual improvement. Our driving principal has been, to borrow a line from Jeff Atwood, version 1 sucks; ship it anyway.

My current workplace doesn’t have a formal “methodology” for development, no waterfall gate-checks or SCRUM masters, at least that I’ve encountered. There are rudimentary project controls and such to meet corporate governance requirements, but development teams are left largely to organize their own efforts. As a result, we’ve landed on some practices that borrow heavily from various flavors of “agile” development without professing the full “agile” theology; the guidelines that I’ve found work best on this project, and that may be reproducible on other projects, are pragmatic and contingent, flexibly implemented within a loose framework. This may not work everyplace, on every project, and it doubtless has some scalability issues, but for a mid-sized project with an aggressive schedule, these are some practices that have worked for us:

Manage the requirements to the schedule: hit the dates by containing the enhancements

We have a huge list of things we’d like the application to do, ranging from simple tweaks to pipe-dream fantasies. They’re all good requirements, all worth meeting because they represent what the users really want. But they’re not all going to go into the first, second, or third release.

Instead, we’ve promised a monthly release with at least one major system enhancement, and as many smaller enhancements as can be realistically squeezed into the time frame. Like the big rocks fable suggests, we focus on the one big thing first, and then categorize the other requirements as hard, challenging, or low-hanging fruit. Once the big requirement for the next release is ready, we knock off the smaller requirements as time permits, always mindful that no small enhancement should jeopardize the big one. It sucks to leave low fruit on the branch, but we keep our spirits up in the knowledge that we’ll have a long harvest season if we keep the customer happy.

A little spice and sizzle helps, though

The “one big rock” is usually a meat-and-potatoes affair, and it’s always filling and nutritious. But we’re also sure to include a little spice among the smaller enhancements. Refreshing the style sheet, adding a more attractive screen layout, or providing an extra screen of administrative information on the application’s performance is often cheap, easy, and low risk, but it’s very useul for maintaining customer satisfaction. The users may not notice that you’ve shaved an average two seconds off the web service response time and implemented a really nifty sorting algorithm–indeed, you’d better hope they don’t notice those things, because their only evidence should be when they fail–but they’ll ooh and ahh over a nicer interface.

Track every requirement, no matter how small

Indeed, make your requirement-tracking as granular as possible. Break the big requirements up into bite-sized chunks, and build good estimates for them (this is where something like the Pomodoro Technique can really shine). You don’t know which rocks are big and which are small unless you track them, and you don’t know if you need to scale back your release features unless you do estimates.

Open up the black box and let everyone see the work list

Having a good requirements and bug-tracking system is critical to managing in a progressive-enhancement environment. We’re using FogBugz, but other tools–Roundup and Bugzilla come to mind–are also useful. Even a shared spreadsheet is better than nothing. The key requirement is that everything is on the table and visible to the entire project team; having the project progress available at a glance, and maintained in real time, is the only way to keep everyone honest and ensure that releases happen on schedule.

Build plenty of testing time into the schedule

I’ve known thin-skinned developers who don’t like testers. Personally, I’d rather have someone on my team find my bugs before a customer does: it’s easier and cheaper to fix problems before your release date, and a good, thorough tester can be the difference between a product that people love and one that makes their jobs harder. In our current project schedule, we have a code cut-off date a week before the release date, after about three weeks of development; this should be adjusted for larger and more complicated projects, with even more time dedicated to serious testing.

Release early and often

That “three weeks of development” in our project is really three weeks of development and testing. As soon as you have something to show, even if you know it’s not ready for release, get it out there for your testing team to break. If you’ve got users who can spend time looking at things that are in development, so much the better: unvarnished responses to early iterations can flesh out requirements and ensure that you’re meeting the customer’s needs. There’s nothing worse than releasing something that’s been carefully developed, thoroughly tested, and still misses the customer’s core requirements. During the last two weeks of development on my current project, I’m deploying something to the shared development environment nearly every day (and if I had an automated build and deploy system, I’d be checking in updates even more often).

Build a solid architecure in the beginning, and build out modularly

My current project lends itself well to continual improvement, because it was architected from the beginning to be modular. It’s a service-oriented architecture that uses the Apache Commons Configuration framework to abstract the business logic into XML documents. It’s developed to Java interfaces and abstract classes as much as possible, with an eye toward identifiying and reusing patterns; if something can be accomplished through XML rather than code, that’s the direction we go.

SOA is a good fit for continual enhancements because the application layers can be clearly separated from each other; you’re less likely to break something if you don’t have to touch it. But the same principals apply to any development platform: make code small, abstract, and reusable, and avoid great big tangles of spaghetti. If you can’t see the whole method on your screen without scrolling, don’t adjust your monitor resolution: break the code up and look for the patterns.

The next release will be better

Whether the customer is pleased as punch, or grinding their teeth in angst, that’s the appropriate response: the next release will be better. The requirements we missed in this release are first on the docket for the next; the new requirements that have emerged from the testing rounds have been captured and scheduled for future deployments; there’s nowhere to go but up.

Provided that you set a pattern of actually delivering on this promise, the customer will be willing to accept that they won’t have the perfect system out of the gate. And if the customer is involved at every stage, and has a hand in the requirements triage and testing, they’ll be happy to play along with incremental enhancements. Something is almost always better than nothing, and unless they’ve got the self-control of toddlers they’ll be willing to defer some of their gratification, especially if they get a little taste of real improvement at each release.

I can imagine projects where these guidelines would fail to deliver: big enterprise initiatives with lots of interrelated parts are hard to release quickly in small pieces. At the same time, though, this may be as much a matter of perspective as of scale: if the project is too big for continual enhancement, maybe it’s really two or three or ten projects that need to be broken up and managed independently, with a longer test and integration period set aside to mesh the components. If it’s possible to deliver a little bit more often, rather than a lot after a really long time, my bias is toward the former: it keeps everyone working, ensures that real requirements are identified early, and shines some light into IT’s darkest boxes.

Tags: , , , , ,

Scout SaluteEvery Scout in the United States learns the legend of the “Unknown Scout.” In 1909, an American businessman, William Boyce, was lost in the fog in London (this was before the Clean Airs Act restricted the burning of coal, and London’s fogs were really more a noxious smog than a quaint low-lying cloud). A boy emerged from the fog and helped Boyce get back to his hotel. When Boyce offered a tip, the boy refused, explaining that he was a Scout and simply doing his daily Good Turn before disappearing back into the fog. Boyce was so impressed with the Scout ethic that he brought Baden-Powell’s “Scouting for Boys” back to the United States, thus launching the Scout movement in North America.

Like most good legends, this one has some holes in it. Apparently there wasn’t really a fog that day, and the boy just helped Boyce get across a busy street. A nascent Scouting culture already existed in the United States and Canada, founded by Dan Beard and Ernest Seaton, and in fact the Woodcraft Indians and Sons of Daniel Boone greatly inspired Baden-Powell; B-P’s version of Scouting would probably have made its way over the Atlantic without that helpful Scout. But like most good legends, it’s a useful one, and illustrative of the Scout spirit.

A SCOUT’S DUTY IS TO BE USEFUL AND TO HELP OTHERS. And he is to do his duty before anything else, even though he gives up his own pleasure, or comfort, or safety to do it. When in difficulty to know which of two things to do, he must ask himself, “Which is my duty?” that is, “Which is best for other people?”—and do that one. He must Be Prepared at any time to save life, or to help injured persons. And he must do a good turn to somebody every day.

Scouting for Boys, Robert Baden-Powell, 1908

Helpfulness involves offering up something that we have to someone who lacks it. In information technology, the thing that we have an abundance of is, of course, information. We have access to tons of data, and our daily bread is extracting, manipulating, and distributing that information in useful ways.

Simply providing information, though, isn’t helpful. Helpful information is specific, timely, and relevant. The Scout who helped Boyce (in the fog version of the legend) could have given a lot of information to the befuddled businessman. He could have told him that they were standing in the city of London, and that the fog was especially thick that day; a certain kind of Scout could also have told him the temperature and dew point, explained the effect of prevailing winds on the fog, and suggested that the composition of the fog was largely coal smoke and a North Sea low pressure system. All good, true information, but all horribly useless: the Scout would not have been helpful at all by giving those facts. Boyce needed task-specific information–how do I get to my hotel?–and that’s what the Scout provided.

As programmers, we need to be in the habit of providing the same kind of targeted information: to our managers, our business partners, and each other. A good place to start practicing that habit is in the code we generate:

Comment only what requires a comment, and strive for readability in your code.

We’ve all seen, and been guilty of, unhelpful comments in our code. An unhelpful comment isn’t necessarily a false comment; it’s just one that doesn’t aid in understanding the task the code is trying to accomplish. For example, a lengthy comment on the inner workings of SOAP and the implementation of a Jakarta HTTP client to negotiate an XML-RPC connection might be fascinating, but it has no place in the code itself. Tell me what you’re getting from that SOAP source, not how you’re getting it; if your code is clean, I can figure out how it works.

Commenting the obvious but skipping the difficult is another sign of unhelpful code. When I see source code where simple iterator loops and string parsing functions are heavily commented, but an obscure and obtuse method has no comments at all, I’m nervous; I suspect that the person who wrote (or copied and pasted) the code doesn’t really know how it works, either, and I start to wonder if those other comments hold water, either.

You can cut down your need for comments by writing readable code to begin with. One of the first places to start is with variable names. It’s all well and good to use throwaway names for purely instrumental variables–iterating over an integer called “i”, doing transient string manipulations on “s”. But if it’s going to persist for more than the scope of one method, or if it represents a business object, or especially if it’s going to be exposed in an API function someone else will use, then give it a real name. “Foo,” incidentally, is not a real name; nor is “bar” nor (as one of my Lotus Notes colleagues tended to name things) “chucky.” Since most modern IDEs offer type-ahead, and most modern languages don’t have onerous limits on variable name length, you can be verbose without wearing out your fingers.

I’m a fan of the much-maligned Hungarian notation system, at least in untyped, late-binding languages. It may be overkill in an IDE that lets you inspect an object’s type by hovering the mouse over it, or with tools that aggressively do type checking as you go, but in other cases–I’m thinking in particular of JavaScript, PHP, and LotusScript–encoding the object’s type into its variable name can save you grief down the road. Though one of the benefits of loosely-typed languages is that you can let things be a little slippery, it’s also one of the downfalls when developing in such a language across a team or over time; “strName” is a helpful hint, to your co-workers or to yourself in a week or two, what to expect of an object, so you don’t expect it to behave in a way that it can’t.

As one who has both developed and maintained a lot of code, I’ve learned to see myself like the Tralfamadorians in Slaughterhouse-Five: a four-dimensional being stretching off into the future. When I make my code clear and well-commented, I’m not only helping my teammates now, I’m helping the future me who will forget the nuances of the code almost as fast as it was compiled.

Tags: , , , ,

Scout Salute

A SCOUT IS LOYAL to the King, and to his officers, and to his country, and to his employers. He must stick to them through thick and thin against anyone who is their enemy, or who even talks badly of them.

Robert Baden-Powell, Scouting for Boys, 1908

Loyalty is another of the Scout values that is in short supply these days. Employees and managers look on each other with mutual suspicion, if not downright paranoia, and we are all quick to cut the human nexus for short-term gain. A narrow instrumentalism defines our work relations, and threatens to bleed over into our personal lives as well.

While blind loyalty is certainly as much to be avoided as extreme self-interest, the Scout recognizes that a lack of loyalty is a huge risk. Loyalty is a corollary of trustworthiness; it is trustworthiness over time: someone who can be trusted tomorrow as well as today is someone who exhibits the brand of loyalty Baden-Powell expounded in 1908.

Programming by the Scout Law is unlikely to cause big changes in our work culture, but it can at least get us into the habit of thinking about how loyalty can be a value in information technology. We may not be able to inspire loyalty in our managers or our co-workers, but we can encourage loyalty in our code.

Loyal code is both backwards-compatible and future-proof; it recognizes that other code depends on it, and keeps the contract intact.

In enterprise development, dependencies build up quickly. A sign of a successful component is that it is reused widely, often in ways not known nor ever imagined by the original developer. This can be a benefit–if you already have a good wheel, you don’t have to spend a lot of time making something else round–but it can also introduce a significant risk, especially if the reused component is changed capriciously.

There are practices in programming that strive to reduce this risk. One approach is Contract Programming, where the relationships between code components are defined formally and the “contract” is strictly enforced at run-time. This is especially useful in a distributed, service-oriented environment, where code components are developed by different teams, and even different companies. It also requires significant discipline to define the preconditions, post-conditions, and class invariants at design-time.

Perhaps requiring a little less rigor, but still a good way to ensure that changes in code don’t break the relationships between modules, is test-driven development. In this methodology, tests are written before the code, and the tests are executed often in the development iterations. If tests are written explicitly to ensure that the integration points are functioning, problems in the implicit contract can be uncovered before they become serious.

Of course, it’s still possible for us to be careless about our obligations even if we’re defining contracts or running frequent tests. This is where a loyalty-oriented approach to writing shared components comes into play. A loyal mindset encourages these practices:

  • Make as few methods public as possible; the fewer functions you expose, the fewer chances you have to break the contract.
  • Keep your parameters and return values simple; passing a very simple bean with primitive or core getters and setters will simplify your interface and make it easier to extend, than if you have multiple parameters that can change over time and break dependencies.
  • Do good design up front; understand how your methods are likely to be used, and then imagine how they might be used in the future: will your code scale if someone comes up with a novel use for your modules?
  • Use deprecation when you’re planning to retire a function, rather than simply yank the rug out from under a client; provide fair warning that a method signature is going to change, and continue to support older interfaces for as long as is feasible. Code isn’t, and shouldn’t be, forever, but it should be dependable.

And if you’re on the other side of the equation, making use of a shared API or service, respect the obligation to use the service wisely. Make sure you’re using the service in a reasonable way, without over-taxing it; if you require additional scalability, try to work with the service’s owner before you start to make extreme use of it. I’ve had web services die because they were forced to respond to a multi-threaded, distributed system when they were originally designed to handle a simple queue; it’s not much fun to fix that sort of problem after the client has already gone into production.

If you’ve already built your applications to be trustworthy, the next obvious step is to extend that trustworthiness over time into code that earns the loyalty of other applications. Respect the implicit contracts between components, and perhaps you’ll help to nudge us toward respecting the implicit contracts between people, too.

Additional reading:

Tags: , , ,

Scout SaluteOne of the hats I wear besides “programmer” is “Scout leader.” I’ve got a Cub Scout den of a dozen Wolf Scouts, and I serve as our Pack’s Assistant Cubmaster. It’s a side job I do because (a) I love my sons, who are enthusiastic Cub Scouts, and (b) I came up through Scouting myself: my father and grandfather were both Cubmasters, and I earned my Eagle in 1984. The basic life lessons of Scouting, especially the twelve points of the Scout Law, are about as succinct and universal a code of ethics as you could ask for. 1

This is the first of a series of posts exploring how the twelve points of the Scout Law–a Scout is trustworthy, loyal, helpful, friendly, courteous, kind, obedient, cheerful, thrifty, brave, clean, and reverent–can be applied to information technology in general, and programming in particular. It will likely be a somewhat irreverent look–I also subscribe to the notion that a Scout has fun–and, I hope, useful, whether you’re a Boy Scout Programmer or not.

If a scout says “On my honour it is so,” that means it is so, just as if he had taken a most solemn oath. Similarly, if a scout officer says to a scout, “I trust you on your honour to do this,” the Scout is bound to carry out the order to the very best of his ability, and to let nothing interfere with his doing so. If a scout were to break his honour by telling a lie, or by not carrying out an order exactly when trusted on his honour to do so, he would cease to be a scout, and must hand over his scout badge and never be allowed to wear it again.

Robert Baden-Powell, Scouting for Boys, 1908

Trust is generally hard to come by these days, especially in the business world. Every word that comes from management or analysts or consultants has to be parsed and weighed and heavily salted; plain talk and honest dealing are quaint notions in these brutal times.

While I think that much of our current discontent could have been avoided if there had been a few more Boy Scouts in MBA programs, there’s not much that we programmers can do to affect the moral compass of a system that’s trying to navigate without a needle. But maybe we can look inward a bit, and consider ways in which we could be a bit more trustworthy ourselves. I’ve got one small suggestion that may not shift the economy back onto a moral footing, but might help developers sleep better at night.

Do in your code exactly what your code says it will do; no more, no less.

Not long ago, I was refactoring some old (circa 2001) code. It was a Lotus Notes application with a web interface that used the Sun LDAP APIs to manage some LDAP nodes. It was one of my first Java applications–at the time, Java was the only option if you wanted Notes and LDAP to communicate–and it showed in more than just the way I handled string buffers.

The object model was a little over-complex, but workable; the encapsulation was pretty awful, exposing the application to a little too much of the specific LDAP implementation to make it very portable. But the worst thing by far were the side effects.

I had the basic understanding of “getters” and “setters” from my Java crash course, but I didn’t understand how to keep them away from each other. Too many of my “getter” methods inadvertently called a “setter” method (or, worse, manipulated data internally, in great big blocks of unreadable nested “if” statements). You’d think you were innocently asking for a piece of data from LDAP, when unbeknownst to the calling method you were actually writing a whole tree of nodes. Yuck!

The error handling was pretty awful, too. The methods either threw esoteric LDAP exceptions, or caught generic java.lang.Exception objects, or swallowed their errors and just kept chugging. From the outside, you really had no way of knowing if something worked (even if you could figure out what that something really was).

The first thing I did was pry the read/write functionality apart. The new public “get” methods did just that–they “got” data out of LDAP and returned it, either as primitives or simple objects, or as bean-like structures that were easy to understand. The public “set” methods prepared a bean that could be written, and the only methods that could actually modify data were named, surprisingly enough, “save” or “delete.” The side-effects were removed, so no one using the API could accidentally modify LDAP.

Cleaning up the error handling went a long way toward making the changes trustworthy. Note that Baden-Powell says that a Scout does his task “to the very best of his ability,” not that he succeeds every time. There are vagaries–network, memory, fire, flood–that even the best application can’t handle, and plenty of contingencies that any application can predict. Rather than trying to soldier on when things fail, know when to report back a useful error and stop the application from damaging your data. Subclassing the correct exceptions, setting useful error messages, and warning the API user what kinds of problems might arise so they can handle them appropriately makes your code worthy of trust.

The interesting thing about this exercise was that the trustworthy code–the code that did just what it said it would do, no more and no less–was lighter, simpler, and more portable than the overly complex code that I started with. It ran faster, too. One could say that this was because of better OO design and six or seven years of hard-won experience, but I think it was because it adhered first to B-P’s core principals.


1By universal, I really do mean universal. I disagree strongly with the current BSA policies excluding gay and atheist/agnostic Scouts and Scouters. If you’ve got a passion for working with kids, a willingness to spend hours sanding Pinewood Derby cars or tying knots, and an enthusiasm for helping boys grow, then I want you to be a Scout leader. If a kid is prone to questioning things, exploring the meaning of life, and honestly grappling with the path to adulthood, then I think Scouting is a safe, supportive, and fulfilling place for him to do it. Questions of doctrinal belief and sexuality simply don’t enter into the day-to-day efforts of running a successful Pack or Troop. Scouting in America survived for almost a hundred years without such tests and exclusions, and I’m confident that in time we’ll move past the current policies.

I’d also note that I simply can’t square the BSA’s policies with the spirit of the Scout Oath and Law. In Baden-Powell’s original formulation, “a Scout is a friend to all, and a brother to every other Scout.” That doesn’t leave a lot of wiggle room for discrimination.

Back to top

Tags: , , , , , ,

Social CapitalThe programmer needs lots of tools to succeed: IDEs, compilers, text editors, debuggers, and various other software geegaws and doodads.  We’ll talk about some of these in upcoming posts.  But the most important tool, and the one too often overlooked, is social capital.

This is a challenge for many of us: let’s be honest, there’s a lot of truth to the stereotype of the soically-awkward computer geek.  Most of us, if given the choice, would love to spend our days heads down, working on code,w ithout the messiness of human interaction.  Unfortunately, that’s not a choice that many of us have.  Whether in a large shop or small, we need to interact with a wide array of people to get our work done.  Customers, testers, DBAs, system administrators, managers … Our code goes nowhere, and does not good, unless we’re able to work across all the IT and business disciplines.

There are good ways to work with people, and bad ways.  Most of us are good at the bad ways: standoffishness, obtuseness, and one-upmanship come naturally.  These are all good ways to burn social capital to no good end.  So here are a few ways I’ve found of building social capital instead, which you can then spend in more useful ways.

Offer to Help

Do you know something your co-workers don’t, that might help them with their projects?  Share it.  Even if their problem has nothing to do with your project, the insight will be appreciated if offered humbly and with no quid pro quo.  You’ll build a reputation as an expert, and generate goodwill, with even the smallest bits of help.

Ask for Help

More even than offering to help, asking for help builds social capital.  People like to feel smart, and like to be helpful, even the curmudgeons.  This can be a great way to mentor junior colleagues: rather than pontificating on your way of doing something, involve them in the solution process and ask for their insights.  They’ll learn by teaching, feel like an equal member of the team, and may surprise you with their skills.

Share the Credit

Give credit where credit is due. In most IT operations, many hands go into creating success; when the spotlight lands on you, acknowledge the help you received. Sharing credit is a good way to bring a new team member on board, and to repair the bridges that often become a little rickety between IT teams.

Take the Blame

“I didn’t do it. Nobody saw me do it. You can’t prove anything.” It’s funny coming from Bart Simpson, but not so funny from an IT professional. Odds are that someone did see you do it, or can prove it, unless you’re especially good at covering your tracks. So your best bet when you screw up is to take the blame and make amends.

One of my biggest screw-ups happened about three weeks into my job as a Lotus Notes developer. I made some changes to our mail purge agent to support calendering and scheduling when we upgraded to Notes 4.6; I didn’t have any test data older than the purge window, so I commented out the “purgeDays=90″ line and replaced it with “purgeDays=14″. Of course, I failed to switch back before the change went into production, and the hungry agent began chewing up an extra 76-days worth of e-mail. I had quite a welcoming committee waiting for me in the morning…

By admitting to this colossal blunder, I was able to salvage a little bit of my pride and also got the opportunity to learn, over the next week, a lot of things about tape backups, Notes replication, and mail server administration, and had the lessons of code review and good testing practices drummed into my head. Had I tried to dodge the blame, I would have ruined my relationship with the Notes administrators and, no doubt, I’d have started on a new job search.

Not every work environment is so forgiving of screw-ups; ‘fessing up may be a quick route to an exit interview. But that may not be so bad, either, even in economically grim times; do you really want to work someplace where honesty is so badly rewarded?

Tags: , , ,

Switch to our mobile site