Thursday, November 26, 2015

Thanksgiving 2015

Happy Thanksgiving, everyone!

As I do almost every year at Thanksgiving, I sat down to ponder all of the things for which I am thankful. It started to feel extremely familiar, and I realized that this year's list is nearly identical to last year's.

We have a bulletin board at work where colleagues were asked to post a note about something they are thankful for.  I wrote:  "A job that I like (most of the time) that pays well enough (most of the time) with coworkers that I love (most of the time)."

But in addition to that, the things for which I am thankful this year are much the same as what I wrote about last year.  I was and still am thankful for:

My family.  My son is still great, and my wife has done better this year in general.  I'm sad that I can't see my relatives today, but I will enjoy the day with my immediate family anyway.

My career.  I am thankful to have a steady job that pays the bills (as long as I keep a tight rein on my spending, anyway).  It's difficult to say whether it has improved this year or not.  On one hand, I did get nominated to the position of Faculty Chair.  On the other hand, this move has required sacrifices beyond my expectations.  Nevertheless, I appreciate the confidence that my coworkers have in me, and am certainly thankful for the upgrade to my resume.

My students.  Now that I am Faculty Chair, the way I work with them is much different than it used to be, but I am thankful that I've had very few truly difficult ones to deal with. Most of them are very grateful and appreciative of the help I provide to them.

My colleagues.  I now work more closely with them than ever, and they're still as great as ever.  We tend to pile a lot of work onto each other, but we also assist each other whenever possible, and that's the kind of teamwork that I love.

My friends.  I still carry a perpetual burden of guilt regarding the lack of contact I have with my friends, but I have improved this year, at least with a select few close ones. I am extremely thankful for those who have helped me to improve the frequency of my contact with them.

My education.  I am thankful for the opportunity to pursue my doctorate degree, the financial support provided by my employer, and the fantastic experiences I've had so far in this program.  It's perhaps the most exciting thing I have going on right now.  The pressure has increased and my level of comfort with the tasks has dropped sharply recently, but venturing outside of our comfort zone is how we grow.  I am thankful for the chance to do so.

My house.  I complain all the time because my current house is twice as expensive but half as good as my old house, but I have to admit that it's far from being the worst thing people live in.  I'm thankful that it's adequately comfortable and functional, that it's in a good location, and that I have a home at all.  Not everybody does.

Happy Thanksgiving!

Tuesday, June 9, 2015

Why I Love My 2014 Mitsubishi i-MiEV


I recently bought my first electric vehicle -- a 2014 Mitsubishi i-MiEV.  I absolutely love it!  However, I have discovered that not everyone can understand why I love it.  So the purpose of this post is to lay out some of the reasons why this may be my very favorite car ever -- and I've had quite a few.

First, I love the way it feels to drive it.  It handles extremely well, with perfectly smooth acceleration and an impressively tight turning radius.

The steering wheel feels great in my hands, too.  Though it isn't adjustable, its size and position are perfect just the way they are.

It is distinctly different from any other vehicle on the road.  It has been quite a conversation piece with strangers, a number of whom have taken notice and asked a lot of questions.  I also catch a lot of people staring at me.  I can't tell if it's curiosity, admiration, or disdain, nor do I care.

I love the tiny size.  It's so easy to park and maneuver, and yet has plenty of headroom and space for hauling groceries and shopping bags.  I occasionally struggle a little with driver-side legroom, but for the short trips I take for work and errands, it's not really a problem.

The motor is so quiet that some of my passengers have been startled when the car starts moving because they didn't even realize that it was running yet.

No more oil changes.  Oil is dirty and expensive, and scheduling oil changes is inconvenient at best.  That is now a thing of the past for me.

Saving the best for last, I am happy to be free from gasoline.  As of this writing, I've driven nearly 2,000 miles and haven't used a single drop.  This means:

  • No more gasoline smell on my hands and clothing.
  • No more handling of those filthy pumps.
  • No more breathing in those harmful fumes.
  • No more paying outrageous fuel prices.
  • No more air pollution.
  • No more consumption of non-renewable resources.
  • No more standing outside in bad weather waiting for my tank to fill.  I just plug it in at home or at the gym and go inside.

This is definitely the start of a beautiful friendship between me and electric vehicles.  If your lifestyle is such that an electric vehicle could suit your needs, then I recommend it without hesitation.


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.

Saturday, January 31, 2015

Software Design Principles

In software design, there is a direct, strong, and undeniable correlation between principles and quality.  These principles guide us to create good designs which become good code which becomes good software.  It is absolutely worth your time to understand these principles and remember them.
There are many more principles than these, but the ones listed here are solid, proven, fairly well known, and will guide you to create strong designs.

The Single Responsibility Principle says that each class and each function should have one single, specific, and well-defined purpose, and it should never do anything that is unrelated to its purpose.  This principle is essentially just a reminder of the importance of cohesion.

The Hollywood Principle says, “Don’t call us, we’ll call you.”  What it means is that some classes should serve a high-level purpose and be the ones that drive processes, while others should simply perform the low-level tasks and nothing more.  High level classes should invoke methods of lower-level classes, but never vice versa.

The Principle of Least knowledge says, “Only talk to your immediate friends.”  When diagramming your design in a UML class diagram, each class should only invoke methods of classes that are directly connected to it.  This provides many advantages; one of the most significant being that it greatly reduces coupling.

Occam’s Razor is a well-known scientific principle that we can modify slightly to fit the purpose of software design.  It says if two different designs are both satisfactory, then the simpler one is better.

The Open/Closed Principle says that classes should be open to extension but closed to modification.  The idea is that code should be designed so that new functionality can be added without changing the existing, working code.

The Liskov Substitution Principle says that if you can design your classes to depend on abstract classes and interfaces, then any subclass of those can be substituted in later regardless of how it implements the functionality behind the scenes.

Favor composition over inheritance.  In many (but not all) cases, using composition for code reuse works just as well as using inheritance.  Composition has the advantage of looser coupling, improves reusability, simplifies testing and maintenance, and provides numerous other benefits.

Separate the aspects that vary from the aspects that stay the same.  If your design must work within several different contexts, identify what is different between those contexts and what stays the same.  If you can separate the part that stays the same, then you only need to worry about adapting the part that differs.

Saturday, January 10, 2015

Fundamental Software Design Concepts

As with all areas of formalized knowledge, the field of software design is built upon a set of fundamental concepts.  These concepts give us a list of general design goals, and when we combine them in meaningful ways, they produce a set of tried-and-true principles for creating high-quality software designs.

Abstraction means that every class should only contain the data and functionality that it needs to serve its purpose – no more and no less.  Abstraction takes different forms, but it is generally something that we want to strive for.

Coupling means there is a dependency between two or more classes.  We want to minimize this for several reasons:  It makes it difficult to reuse code and complicates testing and maintenance efforts.  We cannot eliminate coupling completely because it is necessary for classes to collaborate.  However, we should aim to minimize it whenever possible.

Cohesion is a measure of how closely the members of a class are related.  A class should have one single well-defined purpose, and everything it contains should contribute to that one purpose.

Decomposition means that large, complex things should be divided into smaller, simpler things.

Modularization means that each component should have a specific, non-redundant purpose and well-defined interfaces.  This is related to decomposition.

Encapsulation means that the details of what an entity is made of (its variables and functions) are bundled into a single unit, such as a class.

Information hiding means that the encapsulated details of a class can be hidden from external entities for the sake of simplicity as well as reliability.  This is related to encapsulation.

Separation of interface and implementation means that the interface to a class should be separate from how it actually works behind the scenes.  This is a specific type of information hiding.

Sufficiency means that a component contains enough of its essential features to be usable.

Completeness means that a component contains everything that it needs and nothing more.

Primitiveness means that the design should be based on patterns that are easy to implement.

Separation of concerns means that stakeholders can focus on just a few issues at a time rather than trying to grasp the entire system at once.