Friday, February 13, 2015

It's All About Expectations Management

A few people in recent years have asked me how my wife and I manage to make things work when we both have so much going on in our lives.  It's a good question.  After all, my wife fills her schedule to the brim with client appointments, and any open holes get plugged up with social outings, shopping, cooking, housework, or some other diversion.  My schedule is no better -- it's currently bursting at the seams with teaching duties, curriculum development, Ph.D. studies, and a lot of time looking after my son.

If you've read any of my blogs at all, you know that the bulk of my life is firmly rooted in technology, so I'm certainly not accustomed to giving relationship advice.  However, I think that being a husband makes me qualified to share my experience as such.

So how does it work?  The answer is "expectations management."  It's an idea I picked up from my profession as a software engineer.  The primary purpose of managing expectations is to maintain a consensus between stakeholders regarding what can reasonably be expected from a project.  We aim to prevent disappointment by establishing what can realistically be delivered, and these expectations are periodically adjusted as details emerge and feasibility is assessed.

Some people place unreasonably heavy expectations on marriage.  For a time, I was one of those people.  Popular culture seems to suggest that we must marry someone who shares our interests, a companion who likes to do things together, a best friend that we can talk to about anything, a source of strength through life's challenges, someone to share a bed with on those cold nights, and a partner who will encourage and support us to reach our goals.  For some relationships, a subset of these expectations may be somewhat realistic.  For others, they are not.

In my marriage, for instance, not a single one of the above features is achievable on a large scale, but this does not necessarily imply a failed project.  Rather, the focus is shifted onto what can be done, and the expectations are set accordingly.  It's just a matter of accepting it for what it is and appreciating the good things.  For example, my wife is an outstanding chef.  (Check out her amazing cooking blog.)  She's also good at helping me take care of our son.  She does most of the grocery shopping and pays most of her own expenses.  She provides countless favors both large and small, like driving me to work when the weather is bad and helping me with various personal hygienic routines such as haircuts, shaving, and nail trimming.  I tremendously appreciate all of these things and more, and I take every opportunity to let her know.

So, to the question of how we make it work, the answer is a wise old classic: Focus on the positives, appreciate what you have, and maintain an attitude of gratitude.  Don't be overly obsessed with comparing yourselves to others, or to what is considered "normal" or "healthy".  Just be thankful for what you have and you may find that it's enough to get you by.

This is not just marriage advice, it's good advice for nearly all aspects of life (well, outside of software testing and risk management anyway -- it's terrible advice in those areas).  Accentuate the positives!


Saturday, February 7, 2015

Software Construction Fundamentals

As with all activities in software engineering, construction is based on a set of fundamental concepts which serve to establish goals and drive much of the work that is performed.  Following is a brief introduction to these concepts.

Minimizing Complexity

In construction, more than any other activity, minimizing complexity is utterly essential.  Fortunately, there are many guidelines to help us achieve this goal, including but not limited to the following:

  1. Code should be simple, readable, and understandable rather than clever or overly compact.
  2. Code should exhibit good “code hygiene.” This means it uses meaningful names, follows principles and best practices, contains sufficient and accurate comments, contains few or no public attributes, uses constants rather than hard-coded values, contains no unused variables or functions, minimizes code duplication, provides consistent interfaces to classes, and so on. 
  3. Code should be constructed using a modular design. 
  4. Programmers should follow a set of standards or conventions for the style of their code. Coding conventions can include guidelines such as capitalization, spacing and indentation, comment styles, names of different types or categories of variables, the organization of method parameters, and more.

Anticipating Change

Someone once said, “If a program is useful, it will have to be changed.”  This may seem backwards at first glance, but it is true that if your program is being used, people will eventually find problems with it, think of things it could do better, or encounter unexpected situations that the program was not designed to handle.  Therefore, programmers should always think ahead to what kinds of changes may be required in the future, and try to structure their code so that changes can be made with minimal disruption to the original design and functionality.

Constructing for Verification

Programmers should consider how difficult it will be to test the code, and try to structure it in such a way that it can be easily and conclusively tested.  Recommendations for accomplishing this goal include:

  • Follow coding standards that are specifically intended to support unit testing.  This usually implies a modular design and the Single Responsibility Principle.
  • Perform regular code reviews with a focus on testability.
  • Organize code to make it compatible with an automated testing tool.
  • Use the simplest possible programming language control structures.

Reuse

Reuse comes in two different forms:

Constructing for reuse means developing the code in such a way that it can be reused in new systems. Code for this purpose must be general, cohesive, and easily decoupled from its original context if necessary.  In other words, it should follow the same principles of design that were discussed in my posts on Fundamental Software Design Concepts and Software Design Principles.  Code constructed in this way provides a high return on investment, because once it is developed, it can be used again and again without repeating the development costs.

Constructing with reuse means integrating existing code with new code to create a new application.  Existing code could be something developed internally by your own organization, or it may come as part of a third-party library.  One advantage of this is the likelihood of increased reliability.  If code has been used successfully in previous projects, then it is likely that many of its defects have already been found and corrected.