The Complete Team
I think it’s safe to assume that any software development project has developers participating. In a team environment, the better a developer is at collaborating and working with others, the better the project will turn out. This includes not only interpersonal interaction, but also manging things like overlapping work and code conflicts. It sometimes works to segregate developers or groups of developers on slices of projects, and shuttle the work between the groups via APIs and interfaces, much like the software ultimately will.
It also works well to have collaborative code ownership, where all developers get their keyboards into all of the source and apply their special talents to each part of the project. Fostering this kind of collaboration will ultimately bring the strengths of the entire team of developers to all of the parts of the project. When projects are sliced up and developers are brick-walled from each other, opportunities to have brilliance throughout are lost.
Good Developers All
All software developers are good at it. At least good enough to get jobs. It’s not an easy thing to bluff for very long. It’s important to try to keep them that way.
In many domains, including game shows, the phrase “weakest link” is used to describe a likely point of failure of a system. In software consulting, there are occasionally “developers that shouldn’t be.” We’ve all run into them. They’ve taken the classes, and even done some work, but there’s something off. Perhaps it’s the pace they can’t maintain. They might have a comfort zone, a favorite type of software or tools or product, that once they leave that realm they become…less good. Maybe they have a problem grasping things out of context or without so much understanding that everyone else could have already written the software already!
It’s important to recognize these trouble spots early, and wed them out. I’m not suggesting anyone should be lose their job over weaknesses, but everyone should know if there’s a place they’re good and where they’re not good. Having developers work on things they’re not familiar with or comfortable with is a good way to get them to learn, but it’s also a likely spot for schedule slips, performance dips, and bugs. When someone is stepping into a new technology or programming paradigm, give them some training, and not always on their own, or pair them with someone who’s done it or something like it.
It is often the case that the weakest link may not be an issue of skill, but one of utilization. If a project is segmented, it can very well happen that one developer on one project is overwhelmed with work queuing up, while others are idle. This happens for a variety of reasons. It sometimes waxes and wanes in cycles that are impractical to try to predict.
When someone can’t get the hang of it or when someone is underutilized, try finding a place on the project they can succeed and add value. In a divided software project, there may be developers who aren’t contributing fully to their vertical bit for whatever reason. It may very well be the case that a gap exists elsewhere on the project that this developer could provide much value. In a collaborative environment, the developer who’s lost or idle can find tasks that suit their skills and time and the project can be better for it.
Ideally, everyone working on a project should be able to add their bit to every bit.
Stickler for Standards and Patterns
It’s easy to get carried away, but it’s important to have some members of a complete team that encourage and enforce following standards and recognizable patterns.
However, anyone who’s had to adapt or maintain someone else’s code recognizes the time saved when the not-obfuscated code is properly adorned with a standard or guideline-compliant set of names. Having someone (or a few) on a team who enforces even simple things like naming standards can add incredible value and time savings during development and later maintenance of any project. Done right, their influence and encouragement will bring everyone on the team to embrace and follow whatever guidelines have been agreed to.
The same thing goes for following common software patterns. By and large, I’m all for patterns as a way to communicate and provide direction, but I’ve run into a few extremists who insist on wrapping every little thing in some kind of pattern label. Sometimes it can’t be done, so relax a little. At the same time, having everyone familiar with the frequently used and sometimes necessary patterns is essential. Everyone should be able to use Singelton, Fly-weight, Factory, and Visitor patterns; and probably has done so without even knowing it. Anti-patterns, too, should be known and shared, and avoided…surely we’ve all been on projects that have been one big “ball of mud” or faced “interface bloat.”
Ideally, what will happen is that the Sticklers for Standards and Patterns will be cruising through the code working on their bits, and either see and correct a non-compliant bit of code, or point it out to the individuals or group at large. When near-misses occur and are corrected just through collaborative code ownership, all of the software gets better for the effort.
Also, the more standard following and pattern recognition the team can do is better for development overall. Each developer improved with standards and patterns is a little bit better for it.
In a large project, it’s important to test the software as it is developed. This includes sitting in front of a running version of the software as well as writing unit test software on the software base itself.
Some developers don’t agree in the value of writing tests on software. Some developers dig writing the tests on software as much as writing the software itself. A balance needs to be met to ensure that all of the time isn’t spent writing tests, or that software isn’t getting written just because it satisfies a test. Balance needs to include the usefulness and necessity of having the software.
On a large project, especially one where every developer is free and comfortable to change any of the software, unit tests are measurably necessary. Some disciplines call for “Test Driven Development,” but I contend that it’s really often more about “Test Defended Development.” In a proper unit test, the implementation inside a method isn’t necessarily what’s being tested. Sometimes that’ll happen in order to deal with that blurry line between unit test and integration test. In the end, though, a test should prep for a method call, call a method, and evaluate the results, ensuring that the desired and expected changes or events happen. Once a method is so protected by a test, changing the method appreciably should affect and break a test; this will encourage the developer making the change to ensure that the change is worthwhile and necessary. The dread of breaking tests should keep nitpicking to a minimum. Conversely, correcting broken tests when necessary changes are made will further strengthen the software.
The relentless testers will ensure that the tests add value to the project, weeding out the useless tests added just for “coverage numbers.” I loathe the test wrapped in a try/catch block that allows the test to pass regardless of the actual outcome of the method, neither preparing or evaluating results, and often not really testing anything; just getting the count up on the number of tested methods.
Ideally, some of the developers on the team will be the sort that does unit testing right. As they do their parts on collaborative projects, they may encounter weakly covered software or tests that aren’t efficient or valuable. They’ll take their moment to shine and correct the tests, or even help the other developers improve their testing skills. As these developers relentlessly add to the coverage and improve the defense and definition of the software through testing, the project as a whole gets stronger and defects are greatly reduced.
Master of Performance and Brevity
Similar to the Stickers for Standards and Patterns, the Masters of Performance and Brevity will be those developers with eyes and knacks for identifying software that can be improved or made ore concise or both. We affectionately call them “tweakers,” but they add value in all kinds of ways.
Sure, we’ve all written hasty loops and methods that inefficiently step through collections and whatnot. A second pass is often used to clean up that “get it done” initial effort. The tweakers will take it a step extra and optimize the code, for both performance and brevity. Extra temporary declarations and casts will be removed. Inefficient and clumsy code will be streamlined and refined to be elegant. Elegant and clean code is easier to maintain.
Sometimes the tweakers need to be reigned in as they’ll spend large and quantifiable time working to improve processes that will result in shaving machine cycles from software that can result in immeasurably small gains such that the input will never equal the output.
Ideally, all of the developers on a project will write efficient code, at least by the time it gets committed to the team repository. The tweakers will then further clean the code when they encounter it, improving the project as a whole. When these developers are on segmented projects, only some of the parts get optimized. Also, as the not-quite-tweaker developers return to those parts of the code, they’ll get exposed to the tighter and cleaner code, and hopefully begin to incorporate that.
Wizard of Tools and Environments
Unless you’re a total die-hard, editing code with the most bare of text editors, compiling, linking, and otherwise packaging from command-line interfaces, you’ll be using an IDE. Sometimes it doesn’t matter which IDE is used; the code should be compliant to the language in which it’s written, not the editor used to write it. Some bits of the environment leak in, however, and influence the project structure, if nothing else. Sometimes the combination of tools used (e.g., Eclipse, Subversion, and Maven) have myriad options and combinations of configuration. It helps to have someone familiar with the ideal development environment.
Likewise, the targeted testing or deployment environments can have an impact. If the team uses a continuous integration tool (as they should) to do an out-of-the-IDE and off-the-desktop build and run of the tests, this will add complexity as there needs to be an additional build tool (like Ant or Maven or make) that might do things differently than the IDE does. And whether deploying a stand-alone application or some kind of container-deployed application, there are additional considerations to have regarding the end of the development stream, when the deployable is made. If a web-application, for example, is being developed, separate packages may need to be built and tested for the different application servers; a simple WAR file gets a little complicated when deploying to Jetty or Tomcat or JBoss or Glassfish as each may include different bits in their default classpath or may work differently with the classes and archives provided in the WAR as they implement their classloaders differently. And let’s not forget the differences between deploying on a Windows and non-Windows environment, or even the occasional nuances and inconveniences of the differences between the non-Windows (and heck different varieties of Windows) environments.
Ideally, the Wizards on the team will help ensure that the tools used combine to make a harmonious, not conflicting environment. Sometimes this can include moving files around to correct a multiple-platform build consideration, or to correct a version or dependency conflict. A developer may add a Maven dependency, for example, that is already resolved by another dependency, so the Wizards will remove the unnecessary one, or correct the version of the other, to be sure the tree is neat and clean, and easier to maintain.
Regulator of Plans and Tasks
Many of us dread the endless meetings to hash and rehash project specifics. Some of us live for those meetings. In moderation, there’s value in collaborating together, if for nothing else than disseminating information quickly.
As a project cycles along, things will need to be tracked and changed. Velocity is hard to maintain otherwise. It is imperative that a list of some sort be maintained that allows developers to identify, and possibly define, work to be done, and for their managers and peers to know what work has been done. Efficiently tracking tasks, more importantly than time (sorry, bosses), ensures that dependencies are fulfilled and identified as the project stretches through the development cycles. Following a Getting Things Done habit of just doing what can be done quickly and noting what must be postponed ensures that nothing is missed.
Additionally, if a developer in the middle of a task notices something that needs to be done, either to meet some missing or improved requirement or process, then another developer who may be between things to do, or even working on the same or similar tasks, can do that and perhaps be done before the developer who noticed it has finished their initial task.
Ideally, the regulators will help keep things flowing smoothly. They’ll recognize duplicate or similar tasks and eliminate or relate them, keeping task lists from getting overwhelming. If everyone participates in the management of plans and tasks, at least insofar as they take tasks off the queue that they can do, and add tasks to the queue that they cannot do (for time or skill reasons), it works out that projects can actually kind of self-manage.
Of course, it helps to have someone who knows about the software being written. It’s quite possible to have developers who don’t know all of the specifics of the project. Certainly to some degree they should all know something about the project, but that can still be at a pretty high level.
Arguably, most business software is some kind of interface-to-database-and-back-again. That interface can be a stand-alone application or a series of web pages, or maybe even just some web service or RSS feed kind of thing. The database could be a bunch of in-memory data, files, or an actual database. It could be complex and send information to other applications in a cloud, or simple and just run on its own.
Knowing that to some degree, some parts of all software are frankly just software, it’s possible to have developers writing software without knowing about the stuff they’re writing.
Someone should, though.
Ideally, there would be some developers who are experts to some degree on the subjects that make up the project. This could mean all about the finances of the banking application, or just about the security technologies used in it. In a segmented environment, these experts get blocked from sharing their expertise with the other parts of a bigger project, but in a collaborative environment, they get to help everyone fill in knowledge gaps.
Jacks of All Trades
Having people that have more than one of these skills is a bonus. Further improving a complete team is having multiple people with multiple skills that aren’t all the same sets, overlapping to provide multiple coverage in all of the collaborative tools and disciplines.
Certainly, some shining stars can do some or a lot of all of these things. It happens sometimes that when one focuses too hard on one area they suffer in others. Conversely when they focus on all areas, it happens that all areas suffer. A balance must be struck, but breaking out of the “one-developer, one-task” will strengthen everyone working on the team, and strengthen the project overall.