Category: Building Software

  • Software Design – Measure Twice and Cut Once

    Software Design – Measure Twice and Cut Once

    It takes very little time in the software business to see that implementation is king.  Software design and similar pursuits that lack a deliverable outside of documentation are pushed aside far too often.  One may look at the poor success rate of software projects and draw a connection.  In this post, I plan on doing exactly that.

     

    Software is Complicated

    The first thing we must agree on is that software has gotten complicated.  There are all kinds of tools that help with coding and implementation.  However, these do not eliminate the challenge of building a useful and stable system.  The lines of code written by humans may be dropping, but the overall size of modern systems is growing all the time.  Thus, software design is needed to plug all of those pieces together and provide a path for the implementation team to build a cohesive system.  There are tens of thousands of “moving parts” in most modern systems and that means the same number of potential points of failure.

    The Vision Problem

    Code complexity is just the technical part of the problem.  The more significant reason for spending time on software design is due to vision.  A client, end-user, stakeholder, and developer all have their vision of a solution.  Some of the differences are due to gaps in knowledge.  For example, a subject matter expert has a deeper understanding of the problems to be solver than other team members.  This is not an issue unless we skip the step where that knowledge is transferred to others.
    A more substantial challenge is that we do not know what we do not.  Thus, there must be a conversation around software design.  The designers and implementation team needs to be on the same page as the end users and stakeholders.  When this does not happen, it is like giving someone directions to meet you, but they use a different (and incorrect) set of instructions.  When the destination or goal is not the same, then failure is almost guaranteed.

    An Old Problem

    The astounding aspect of this situation is that it is an old problem.  Even worse, it is one that has been solved.  The idea of measure twice and cut once goes back a long time.  However, that is precisely the purpose of software design.  In this case, the action is implementation instead of cutting, but it is nearly as final.  When you make the wrong cut on a piece of wood, you need to get new wood.  You can not “un-cut” the wood. Code is more forgiving; you can undo an action.  Unfortunately, we often realize that we need an “undo” far down the road from the mistake.  This leads to a lot of back-tracking, lost work, and potentially a duplication of effort or worse. A good design is likely to point out mistakes earlier when they are far less effort to correct.

    Not An Agile Problem

    I would be remiss if I ended this post without mentioning the Agile process.  The goal of Agile is to reduce overhead related to design and documentation, not eliminate it all together.  A proper Agile approach still includes planning; it just limits the scope to the upcoming implementation.  This can cause issues and turn up problems later than desired.  However, the trade-off is a more fluid approach to creating software and turning a presentation approach to something more like a conversation.  Agile assumes that we cannot correctly create a complete design from step one, but it does still embrace software design.
    Next time you are pressured to dive into implementation have confidence in pushing back.  When you fight for the value of good design, you improve the chances of project success.  After all, that is the ultimate goal of everyone on the team.
  • Upgrades vs Stability for Production Solutions

    Upgrades vs Stability for Production Solutions

    One of the pervasive properties of software is change.  Whether this change comes from regular enhancements or environmental updates, it is one that should be considered strategically for production software.  Thus, the balance of upgrades vs. stability needs to be considered as your solution ages.

    Easy Upgrades

    Modern software environments provide features that make upgrades easier than in the past.  A great example of this is WordPress and other “plugins supported” solutions.  The goal is to make administration of these sites easy and quick.  Thus, you often can upgrade a plugin or even the core software to the latest version with the click of a button.

    This ease extends to core environments as well.  There are a lot of automated update tools available to keep all of your software up to date.  The most well known of these is the windows update tool provided in many recent Windows OS versions.

    Impacts to Stability

    This ease of administration is excellent.  However, it is also hazardous.  An upgrade may break your entire site and lose sales.  As scary as that sounds, even worse side effects can happen.  Data may get corrupted, backups can become invalid, and fulfillment can be sent to the wrong address.  These worst-case scenarios are not exactly typical, but they can happen.  Upgrading your system can turn a steady running and reliable system into a nightmare.

    These concrete impacts are just one facet of the considerations.  Updates may change the user experience.  Something as trivial as moving a menu item can cause user headaches and negative backlash.  For some great examples of this, look at some of the Facebook changes over the years that caused a massive outcry from their user base.

    Managing Upgrades vs. Stability

    It may seem that these risks point to leaving your software in its original state as long as possible.  Fewer changes should lead to higher stability.  This is only partially true.  A stable system is more accessible to hack and may be steadily approaching a point of no return.  In the latter case, this can be a point where the system lacks the resources to support the user base or amounts of data within the system.

    There are also license considerations and support.  Older software may not be supported by vendors entirely or at all.  Thus, we need to find that balance.  Here are some high-level steps that can be taken to keep your solution up to date while minimizing risk.

    Scheduled or Periodic Updates

    Vendors do not release updates on the same schedule.  However, you can set a timetable for when you will apply updates so you can keep those updates on a plan suitable to your business.  I recommend updates on a frequency of two to four times a year.

    Test, Test, Test

    It is recommended that you have multiple environments during implementation.  This is even more important once you “go live.”  The value of these other environments is that they allow you to create an identical version of your production system for testing.  Thus, nearly all of the risk can be assumed by a “test” environment instead of production.  This is not a silver bullet, but it is pretty darn close.

    Backup, Backup, Backup

    Before any update is made, make sure the whole system is backed up.  This will allow for roll-back in case an update is not viable.

    Avoid Bleeding Edge

    When you follow the suggestions above, it should help you buy some time before implementing an update.  This should be embraced and used to allow you to pass the risk on to other customers.  They can perform the update, and their feedback will help you avoid problems and reduce risk.  In effect, waiting on an update allows others to be your guinea pig.

    The Bottom Line

    These are general suggestions, but embracing them can be very useful.  There is always going to be a challenge in finding the balance of upgrades vs. stability, but when you reduce risk, it makes success more likely.  Following the steps noted here can provide a win-win situation where you have current software and a stable experience for your customers.

  • Improving Quality through Testing as part of Implementation

    Improving Quality through Testing as part of Implementation

    I do not want to shock you, but software often has bugs.  We may call these “features” or “known issues,” but in the end they are bugs.  These defects are just part of being human and trying to craft large and complex solutions.  Sometimes we make mistakes.  The challenge with these errors is finding and eradicating them whenever possible.  Thus, improving quality.  That is where testing comes in.

    Not a Popular Focus

    It is hard to argue that QA and testing are treated with proper respect.  These tasks that are critical for good software are often dealt with as a “nice-to-have.”  Whether the focus is unit, system, or acceptance testing the needed time is rarely allotted.

    Software development has advanced and embraced the design and deployment steps along with implementation.  However, testing is still lagging in how we approach it.

    Embrace All Testing Types

    These are sweeping statements so your experience may be very different.  However, most projects are starting to embrace the value of testing, just in baby steps.  Development tools have been instrumental in this progress.  The ability to create and run unit tests along with implementation has made it almost an automatic step.  Unfortunately, this does not extend to the system and acceptance testing.  Even worse, that is where most bugs get through to a customer.

    Unit testing is great, but just the first step.  A good strategy will include system testing to make sure the pieces fit together and work properly.  Once that is accomplished, a solid acceptance plan is needed to ensure that requirements have been met. These testing types may have different names in your company, but they boil down to three areas.  Test the code modules and components by themselves.  Then verify that the modules work together properly.  Finally, check that the solution matches the original requirements.  Much like a game of telephone, it is not hard to confuse the original goals by the time we get to the end of the project.

    Improving Quality Requires Testing Throughout Implementation

    The problems with making testing a step at the end of coding are cost, effectiveness, and perception.  Cost is a function of fixing issues that arise.  There are several articles written about how the cost of fixing a bug increases as you move along the life cycle.  Thus, we will take that as a given.  The sooner a bug is found, the less the cost of fixing it.  Therefore, finding bugs early in development leave us more resources to create better quality software and deliver it on schedule.

    The impact of timing on the effectiveness of testing is not often discussed.  However, it becomes evident when we look at the situation.  A unit test or similar testing early on in the life cycle will have limited inputs and outputs to validate.  The permutations of data inputs and output are going to be small when compared to larger systems.  Once you start putting together those “units” the complexity increases exponentially.  Thus, testing the system increase in complexity as well.  Likewise, the likelihood of 100% test coverage starts to decrease dramatically.  When we include proper testing earlier in the life cycle, we can implement it before the software complexity gets out of hand.

    The Perception of Testing

    Finally, we need to look at how timing can impact the perception of testing.  When it is included throughout the implementation portion, it becomes just a part of development.  It works hand-in-hand with creating software, just like writing, compiling, and commenting code.  However, when testing comes at the end of the implementation phase, it can be seen as a blocker.  The software project was chugging along fine until the testing team stopped progress and forced the developers to go back and fix bugs.  This approach puts QA staff in the position of being the guardians of a release and the ones that bear the burden of saying whether it can proceed.  Thus, we put QA staff in the awkward position of doing their job right or letting us “ship” the product.

    Baby Steps

    I am a big fan of steady growth and improvement.  The issues listed above can be significant and even overwhelming to address in one shot. Instead, look for ways to make improvements with each release.  Start from simple tasks like good unit tests, get comfortable with them and then move forward.  Find the means to document, reproduce, and then automate as much as possible.  Once testing becomes automated and part of your daily development you will see dramatic improvements in software quality.  It is time for us to move software creation out of the realm of dark arts and into the light of reproducible high-quality processes.