Critical Development

Language design, framework development, UI design, robotics and more.

Archive for February, 2008

Important Professional Skills for Software Architects

Posted by Dan Vanderboom on February 2, 2008

I was recently asked which professional skills were most important for a software architect, and the answers I came up with, I believe, apply to professionals in general.  Some of the following descriptions are slanted toward the software architect, but can be applied quite easily to other professions.

Customer advocacy.  First and foremost, we have an ethical obligation to our clients to discover and represent their best interests.  There are unscrupulous consultants who will milk contracts for as long as they can for their own financial survival, and this is a serious problem because it creates mistrust in our industry and problems for those who are honest.  As this problem may be outside of our immediate sphere of influence, I would also point out that even with the best intentions, those who are honest may not be serving the customer’s real needs due to hyperfocus on the detail and technology, and unfamiliarity with the requirements or lack of focus on business needs.  Some of this can only come with experience, but I believe we can all learn what our limitations are and to admit when we aren’t seeing enough of the big picture to make a confident recommendation.  This is an important focus of systems architecture organizations such as IASA and WWISA.  Dan Appleman in a recent Hanselminutes podcast episode covers this responsibility of the Software Architect very well.  I had the opportunity to meet Dan briefly at DevConnections, and consider him to be a great role model.

Articulate and organized written and verbal communication skills.  Communication skills are the glue that hold teams together and allow a single coherent vision of a project or product to be shared.  The most important of these skills is listening, or observation in general, as decisions can only be as good as the information they’re based on.  Communication skills can be further broken down for more intense self-examination and improvement: the ability to compose meaningful and relevant messages; delivery of those messages via writing, impromptu speaking, and prepared presentations all require different skills; and observance of social protocol to appear responsive, considerate, etc.  When I hear people saying that someone has “poor communication skills”, they are most often referring to a failure to observe social protocol, not that the person isn’t capable of composing and articulating their thoughts well.

Negotiation and conflict resolution.  Everything that involves communication contains the potential for conflict.  Knowing how to negotiate can prevent daily micro-conflcits from escalating out of control.  When we understand that conflict is normal and comes from the interaction of different perspectives, requiring a dynamic, shifting dance of give and take, we can embrace and work with it, using that energy and the diverse perspectives involved to our advantage, fueling our creative processes instead of letting them degenerate into unhealthy ego battles.

Problem-space modeling and creative problem solving.  The effectiveness of the solutions we put in place depend primarily on the way we view the problem.  Modeling a problem (seeing) is a very creative process, and the ability to be flexible and think outside the box when looking at a situation can lead to much simpler and more effective solutions.  Too often, designers assume the first model they imagine “is” the problem, instead of one of many ways to view it, and build their systems with this limiting and often dangerous assumption.  A willingness to play and refactor ideas, coming up with alternatives through brainstorming, and synthesizing conflicting approaches, all add to one’s repertoire of visualization techniques, and therefore problem-solving skills.

Risk identification and management.  Software development (as with business in general) involves a great deal of risk, with pitfalls around every corner.  Incorporating new tools, processes, and team members, solving problems in unfamiliar domains, company acquisitions, etc., can make a project miss schedule and budget targets.  Identifying the risks involved requires project experience and good observation skills.  Managing them requires organization and a proactive, prioritized approach, as well as planning for several alternatives and mitigations.  We start with awareness, then we identify, and finally we can manage and plan around them.

Critical thinking and analysis.  Complex software systems are designed and developed too frequently with a casual, shoot-from-the-hip mentality that endangers projects.  By thinking through issues with a critical and analytical approach, we can reduce risk substantially and ensure success.  The greatest barrier to proper critical thinking is impatience, the urge to jump to conclusions to avoid thought.  As David Allen says in Getting Things Done, “You have to think about your things more than you realize, but not as much as you’re afraid you might.”

Strategic (long-term) and tactical (short-term) project planning.  Short-sighted design and development, and lack of planning, leads to systems that are incapable of growing with or adapting to changing business needs.  Keeping long-term goals in mind ensures longevity and relevance.  This depends, of course, upon the resources and leadership of the company you’re working for.  You may be working on a project with a short lifetime, or your boss may not be persuaded to invest in strategic moves now to save time and money later.  But for most projects, development costs are too great to be wasted on short-sighted expediency.  In any case, long-term and short-term priorities and forces must be balanced against one another along the way.  Every decision and trade-off will have consequences down the line.

Continuous research on trends and technologies.  Long-term strategic planning can’t be effective without knowing the future state of the industry or its many technologies.  This is all about “knowing the territory” as Sun-Tzu has described in The Art of War.  We must often plan the future state of our software systems to take advantage of technologies that aren’t yet available.  This requires keeping ourselves in the loop and on top of our game at all times.  This is difficult in a world that is expanding exponentially, and often requires that we find a niche specialization both to differentiate ourselves and to provide more focused value.

Whereas a developer is concerned with doing things right and being efficient, an architect must focus on doing the right thing from a larger point of view.  As Peter Drucker writes, “Efficiency is doing things right; effectiveness is doing the right things.”  An architect must be effective.

Or as paraphrased by the VisualSVN tag line (quite brilliantly): “Right thing.  Done right.”

Couldn’t have said it better myself.

Posted in Goal Setting, Problem Modeling, Software Architecture | 1 Comment »

Code Clarity, Commenting, and Documentation for a Specific Purpose

Posted by Dan Vanderboom on February 2, 2008

I am currently transitioning from one job to another.  As such, I find myself looking through three and a half years of source code, and analyzing it from a perspective of needing to make sure that it’s maintainable for those who follow me.  One trend that I observe is the gradual decline of comments I’ve written over the years.  Not because I feel they are less important now than in the past, and certainly not because of laziness (I am very consistent and meticulous about my code).  As I will explain, the slimming down of comments isn’t necessarily a bad thing, and the number of comments isn’t directly related to the clarity of code.

It has to do with the mind set and skill level of the developer.  When I started my current job, I had been doing VB.NET development for a few years (after a succession of other languages), and C#—other than what I’d experimented with in MSDN magazines, and despite my experience with C and C++—was basically new to me.  I found myself commenting anything that was different from past language experiences, such as delegates and events (different syntactical style in VB.NET versus C#), or new design patterns or idioms that I learned or created.

Over time, familiarity with the language, the patterns being used, and the framework caused many of those comments to seem superfluous and redundant.  Things that once seemed odd—delegates, reflection, use of nested dictionaries, exception-handling patterns—have become so second-nature that comments describing them decreased in perceived value dramatically.  Add to that the fact that comments themselves are assets that need to be updated along with the code they reference, and the creation of unessential comments becomes something of a small burden to add to a rapidly-growing pile.

Up until now, when deciding whether to add a comment to a section of code, I’ve asked myself this question: if I were going to look at this code several months or years from now, what about it would be confusing at first glance?  This has led me to write clearer code, breaking operations that could appear on one line into several, and naming variables in the clearest way possible to indicate their role in whatever algorithm they appear.  This, I find, precludes the need for some of the comments I may have otherwise felt the need to write.  If we can write code in a way that is self-describing—making the best use of identifiers to do their job and identify purpose—then comments will often seem redundant.  (The purpose of a good comment is to clarify code, not to instruct a beginner on “how to program 101”.)

Coming up with good, accurate identifiers is an art in itself, and comes only through a great deal of experience, learning to describe the entity’s purpose instead of the implementation details whenever possible, being very specific instead of defining ambiguous methods like Process or DoWork.  Naming things consistently according to a unifying metaphor (or set of metaphors) also helps to clarify how all of the pieces fit into a coherent whole.  Above all, one must be willing to refactor and rename whenever it will enhance code clarity.

Not all comments can be obviated in this way, however.  Sometimes, algorithms are just plain hard, or the entities you’re working with are so abstract (such as manifests full of collections of cached reflection metadata) that comments are critical.  The need for comments in situations like this may be an indication that there is still an opportunity to refactor and make the purpose more clear, but since unoptimal solutions will always exist, and our opportunities to refactor are often limited by time, resources, and therefore other priorities, comments in these situations do serve a very useful purpose.

So without being irresponsible and leaving those who follow us with an undecipherable mess, while at the same time minimizing redundancy and unnecessary work, how can we come up with a code documentation strategy that makes sense?

First, I would consider the level at which code is commented.  There are comments we place above or to the right of a single statement, comments that describe a following block of code, and comments that appear on larger entities (such as methods and classes).  Method comments, whether XML or not, are a good place for defining the purpose and describing the strategy used.  If you feel that comments for every few lines of code creates unnecessary clutter, this may be a good place to provide some guidance.  With a little bit of contextual information, it is much easier to figure out how each line participates in the method’s strategy, and class-level comments can describe how that class fits within a larger design pattern.

Second, if you find yourself continuously copying and pasting comments because you keep reusing the same pattern or idiom that would, perhaps, be unobvious to outsiders, then you have an opportunity to consolidate those comments into your software solution’s design documentation.  I have discovered and identified fourty- or fifty-some patterns that I’ve used consistently throughout my current software system; and this list, along with descriptions, should serve as good prerequisite reading and background information for future developers, along with several diagrams of complicated interactions and dependencies.  If we as object-oriented developers value code reuse, then we should embrace comment reuse as well, and consolidate this knowledge in a place outside of our code base.  Having and updating this list can also serve as a reminder of the strategic level of your coding patterns, and give your software a more tangible form of stylistic identity.

Third, identify the purpose of comments and your target audience.  If you’re developing a system in-house, working on a commercial software system, or building a development library that you deliver with source code (or XML comments supplied for Intellisense), you will have different sets of eyes and different perspectives to consider.  Is the project huge and convoluted, or small and simple?  Sometimes the simple question of “could I understand it later?” is too short-sighted.  Coming up with a set of principles to follow will make all of your individual documentation decisions much easier.  Just as comments are used to indicate the purpose of your code, identifying the purpose of your comments is the surest way to a sensible documentation strategy.

Posted in Documentation, Object Oriented Design, Software Architecture | 1 Comment »