Search This Blog

Loading...

Thursday, June 2, 2011

Development: Habits of Effective Software Development


Motivational sayings and commonsense questions do not create a strategy for making you into an effective developer. You need to consider  the how in delivering quality software. Along those lines, a set of habits is shared among effective software developers. They are outlined in the following sections.

Communicate

The picture of the egg-headed recluse software engineer sitting in the dark part of some basement while banging away on a keyboard like an eccentric secretary is an outmoded stereotype (well mostly, the dark is good). As you learned before, software is built to satisfy a need in some particular business process. To be successful, you need to tap in and really appreciate that need. This is very difficult to do by reading a specification.
You want to talk to the users, and, if you cannot talk to the users, you want to talk to someone who was a user or speaks with users. You want to learn what it is they do, how they are successful, and how your software will help them be more successful. If the use of your software is simply by management fiat, then your software purpose is already on critical life support.
You also want to communicate with your fellow developers explaining to them what you learned, learning from their mistakes, and coordinating how your software will work together. Make it a point to try to establish some social interaction among your teammates, even if it is an occasional lunch or brief chat.
Software can be a hard and stressful job; it helps if you have a basic familiarity with your teammates.

Model

Before you go running out to buy the latest in fashion apparel, check the this article. It is pretty clear that this article will not have you doing any posing! Modeling builds upon communication by allowing a more tangible way to visualize a given concept or idea.
Don’t assume that everyone on your team needs to attend Unified Modeling Language (UML) training or buy thousands of dollars of UML modeling software. UML is a great package for expressing a lot of things in a common format that should be understandable by a wide variety of people from users to developers. Indeed, you know this is not the case. The key to any notation is that it must be well understood by those who read it. If your team is UML-savvy or will commit to being that way, then it is a fantastic notation planned out by a large committee of very smart people.
Of course, the old joke is, “A camel is a horse designed by a committee.” This means that you should recognize that UML contains a tool-set that extends well beyond what you may need for your project’s modeling needs. The key is to find a notation that everyone (including users) understands and stick with it.
Also, if your tools provide more of a hindrance than an aid in your modeling, don’t use them. Scott Ambler suggests in his book Agile Modeling:Effective Practices for Extreme Programming and the Unified Process that you can draw your models on a white-board, take a digital camera snapshot of the white-board, and have exactly what you need without the burden or cost of a tool.

Be Agile

Change is an inevitable part of software development. Not only is technology consistently changing, but so is your customer’s business process, if for no other reason than the fact that you have actually provided some automation support.
Teaching a course in Object Oriented Software Development, I often point out to my students that, despite being a sophisticated software engineering professional who has developed many software solutions to improve the way people do business, I could not easily come up with a set of requirements for a system that would improve my business process. The fact is like most people in the working world.
I don’t spend a lot of time thinking about how I do what I do. If asked to do so, I would probably relate my ideal system as an approximation of what I already experience. This would immediately change when you, the software team, introduced a new system to me because my entire frame of reference is now relative to what you have placed before me. Things that I once thought were important would no longer be so-improvements that I assumed would be better turn out not to be, and so on. Ultimately, it is a very natural and appropriate thing for my requirements to change!
You frequently hear software engineers bemoan the fact that the requirements keep changing. This is quite puzzling because software engineers presumably chose their profession based on the desire to develop software, and changing requirements facilitate that goal. Changing requirements is not really the problem. The problem is that the software team is not in the habit of accommodating change; that is, they are not very agile. Lou Holtz once said, “
Life is 10 percent what happens to you and 90 percent how you respond to it.
This saying goes a long way toward distilling the attitude that a software engineer should possess to be effective in modern Java development.

Be Disciplined

Before you go running out and hacking and slashing your way to programming heaven, ensure that you maintain your discipline. Discipline is about maintaining your focus in the presence of a tremendous amount of distraction. This is not about holding your hand over a hot candle or walking across burning coals. You do what you should do, not what you can do.
Recall the principles of quality software development and ensure that you are not violating any of them. Often, rushing to do something will actually cause you to take longer. Be mindful of things slipping, like little bugs that should have been caught before or lapses in judgment for the sake of expediency. However, in the same regard, do not slow things down simply for the sake of caution. Simply slowing
down to avoid making a mistake will not definitely allow you to avoid the mistake, but it will certainly reduce the amount of time you have to spend correcting it. This is a very typical concern when trying to fix a bug or develop an innovative way to handle something
that was unanticipated. By desiring to do something new and cool, you can lose sight of how important it really is in accomplishing the goal of the system.

Trace Your Actions to Need

Discipline goes hand in hand with tracing your actions to the need that your software is meant to address. It is very important that you are able to understand why each of you built each of the components of your system.
Traceability refers to the ability for you to follow your need all the way through the system. For example, you may have a need to provide a printed report. You would then see that traced into a set of use cases, or software requirements, which would then be realized in certain design elements, which would then be implemented in certain pieces of code, which would then be compiled into certain executables or
libraries, which would then be deployed to a certain machine and so forth. So, you are thinking, “Well, that is really neat, but what does all of that really buy me?” The answer is simple. Say you received a request to change the code to support another type of printer. The ability to trace your code through lets you understand where your potential adaptations could be made.
Traceability is not meant to be some huge undertaking requiring mountains of paperwork and a large database, spreadsheet, or document, nor does it require some dumbed-down version of the code to explain it to those who are not able to read or write code. Traceability only requires that someone who can do something about it should be able to find his or her way through the code.

Don’t Be Afraid to Write Code

It seems self-evident, but you would be surprised how often coding is relegated to such a minor part of software development-particularly on complex systems, where it is most needed. Often, there is a desire to figure it out on paper first, find the right design pattern, or model it just right.
However, certain logical constructs are simply unable to be elegantly expressed anywhere but in the code. Also, a compiler verifies a number of assumptions in your design, and your runtime environment will do the same.
It is also easier to estimate how long it will take to do something if you actually do something very similar. A scaled-back prototype that covers the bounds of your system can go a long way to understanding exactly how complex or time-consuming a particular task may actually be.
Furthermore, in Java development, you simply do not have the luxury of assuming that you understand everything about your system. With the high degree of reuse that exists in Java development, your system is invariably dependent on code developed outside of your design space. So, it is foolish to assume that a given API works like you assume it does. There are too many variables involved in the equation.
Part of the fearlessness toward writing code involves changing code. Refactoring changing the design of existing code is an important part of software development. [FOWLER]

Think of Code as a Design, not a Product

Refactoring demonstrates a key habit in effective software development. Code should not be considered the product that you deliver. After all, you rarely actually deliver the source code to the user. Instead, you deliver them compiled byte code that operates in accordance with your source code.
This is because your source code is part of the design. As mentioned previously, there are some logical constructs that cannot be expressed anywhere but inside code. Furthermore, source code provides a human-understandable expression of logic that is then compiled into byte codes (and further gets converted into machine instructions).
You may be saying, “
Well, of course, source code is not the product, who said it was?
” You may never run into a problem with an organization that fails to realize this premise, but it is unlikely. Simply pay careful attention to the disproportionate focus paid to the design phase and the relative number of designers who cannot write code. This will demonstrate that the focus of the project is misplaced.

Read a Lot

This may seem like a shameless plug by a self-serving author, but the simple fact is that software is always changing and improving. There are new technologies, implementations, APIs, standards, and so forth. Software development is a knowledge occupation, and part of the job (as well as developing any system) is learning. Learning new technologies, learning better approaches, and even learning more
about the tools and APIs currently used in your solutions are critical to success. A large part of this has to do with the rise of the Internet and open source software. Java has extended beyond just being a programming language and more toward a software development community.
If you have a software problem, you should first check online to see if someone has already solved that problem. Furthermore, you could check to see how others in your situation have overcome problems you have yet to encounter.

Build Your Process from the Ground Up

Your process is the way you, as a team, do business. No matter what your management tries to do in terms of instituting a process, your team will have to buy into how you will do business. The key to building an effective process is to start from the ground up. Management will set expectations for the outcomes they want and how they will measure your performance. If they place a high value on documentation and paperwork, you need to ensure those expectations are met.
The key part is that your team will need to work together and that will decide how you meet the expectations of management. If you do not agree as a team to a process, then process can become a political football. You do not want to get into a situation where process is used to try to differentiate between coworkers.
Once that starts happening, you will find that the techniques become more important than good software principles, and you start to lose the ability to trace your actions to your software’s need.
An important consideration in building your process from the ground up is recognizing where your process really begins and ends. Development team wars have been waged simply on the basis of the question of integrated development environment (IDE) standardization, like Eclipse. You should ask yourselves whether you really want to standardize on an IDE. Even though you certainly need something to be able to interoperate among team members with effective configuration management (discussed subsequently), you still don’t want to make someone have to fight their development tools.
Software is hard enough without having to fight against your tools. This is the key consideration in building your process. Decide what your team can agree on to make everyone the most effective. If you cannot agree, then management may have to get involved, but this should be avoided.

Manage Your Configuration

Configuration management is important because stuff happens. A hard drive goes bad, your latest improvement goes very badly, and so forth. These are all examples of things that happen in the normal course of software development.
You should recognize that there is a distinct difference between configuration management and source code control. Configuration management is a process in which you control how your system is put together. The key goal in configuration management is that you can replicate your configuration in another place. You do not just maintain configuration control of your source code but also your runtime
environment (including dependent libraries, application server configuration, Java Runtime Environment, or database schema), that is, anything you would need in order to re-create your system. 
Source code control using a tool like the Concurrent Versioning System (SVN) is used to allow multiple developers to work on files and integrate their changes while saving the history of previous revisions. SVN is the dominant tool in the open source environment and is cleanly integrated into most of the major IDEs. Of course, source control is useless if you do not commit your changes!

Unit Test Your Code

When you design and write code, you are writing test cases. You are writing test cases to handle the intended case, that is, how the system should behave as you go through the system. As you do that, you are making certain assumptions about how your system will react given a certain set of circumstances.
For example, if I check to see that an object is not null here, I am assuming that it will not be null up to a certain point.
As you write code, you tend to develop your complex logic to support the intended case, checking for needed preconditions required for your code to work. However, there is often a set of scenarios for which your code was designed to work. Unit testing allows you to test those scenarios.
I will discuss how to use an open source tool called TestNG, which is a similar regression testing framework as JUnit, to perform unit testing, but unit testing becomes an important part of the habit known as continuous integration.

Continuously Integrate

Having a strong set of unit tests that ensure the functionality of the individual components of your system, you could now combine these together into one cohesive product and run all of the unit tests on all the components to see how well the system as a whole functions, as illustrated in Figure 1.
Figure 1
You should note that, even if you are not very good about unit testing, continuous integration can still apply and provide great value to your development team. As you combine the efforts of your entire development team, you will see how things actually play together and ensure valid assumptions toward each other’s code.
The more you integrate your system together, the more confident you will become in the success of the product as a whole. This helps mitigate risk by discovering problems early when they can be fixed.
Continuous integration ties directly into maintaining short development iterations.

Maintaining Short Iterations

As previously noted, the sooner you discover problems, the less likely they are to affect your overall development success. The trick to doing this is to maintain short development iterations. This means that you should be able to go through the development life cycle (requirements, code, design, and test) in a short period of time.
You should try to involve your customer in each iteration if possible because, as mentioned previously, your software will change their context. This means they will start describing what they want within the context of what you built, not in some abstract concept.
How short depends on your team, but for the purposes of this discussion, you should measure it in weeks, not months. You want to put enough in an iteration to be meaningful in the shortest period of time. Two weeks to a month is a good rough estimate for your first iteration. After that, you can use your own success or failure to determine your next iteration.

Measure What You Accomplished---Indirectly

There is an old joke in software estimation, “What is the difference between a fairy tale and a software estimate? One doesn’t start with once upon a time.” This joke takes to task the idea that software estimation is really hard, and most techniques are frequently described as black magic.
However, successful software estimates are based on experience. Experience is based on trying to quantify what you have done before (and how long it took) as a predictor of how long the next thing will take. Because the typical workplace doesn’t punish overestimation as much as underestimation early is good, late is bad you start to have these highly defensive estimates of software effort. These estimates start to build on one another and, because you cannot come in too low or your next estimate will not be as believable, you start to have down time. You start to gold plate (that is, add unnecessary and untraceable features) your system and gain a sense of inactivity.
The opposite phenomenon also occurs. Because software developers cannot be trusted to make estimates (because they are gold plating and sitting around), management steps in and promises software based on their guesses on how long something should take. Usually, they are setting aggressive schedules simply for some marketing purpose and frame it as a technical challenge to the developers. Developers are optimists and fighters, so they accept the ridiculous schedules until they get burned out and leave for a new job.
So, how do you avoid these dysfunctional circumstances? You measure what you have done by using an indirect measure to keep you honest. Extreme Programming (XP) has a concept known as velocity.
XP is discussed subsequently, but the concept of velocity can be paraphrased as follows:
1. You have a set of tasks, each of which you assign a certain number of points related to how much effort it will take to accomplish it.
2. You then estimate how many points each of the developers on your team will be able to accomplish for a given iteration---taking into account leave and so forth. Your iteration is time-boxed to a specific amount of time (for example, two weeks is common).
3. You perform the work and keep track of how many points you were actually able to accomplish.
4. You start the process over for new tasks, adjusting them based on the actual results. As you get better or your system becomes better understood, your velocity will increase.
Of course, nothing scares developers more than metrics. As Mark Twain once said, “There are three types of lies: lies, damned lies, and statistics.” Developers understand that metrics can be oversimplified or distorted beyond their actual meaning. This is why teamwork and communication is so important.
You should only allow these metrics to be visible to those who actually are involved in using them. You can make it a secret handshake; that is, if you don’t have a velocity, you don’t get to know the velocity.
Of course, on the subject of sensitive but necessary measures of your development performance, you should also look into tracking your issues.

Track Your Issues

Another volatile subject on a development team is bug reporting and tracking. As previously mentioned, it is hard for you to understand what your customers want, and it is hard for them to understand what they want. Furthermore, your users will use your software in ways that you did not anticipate and they will discover undocumented features of your system.
However, if you get past the concept of blame and simply focus on the inevitability of bugs and changes, you can make your issue tracking system a good way of keeping track of things that need to be done.
Whether you use a sophisticated online system or a simple spreadsheet, it is important that you keep track of the loose ends. You will find that it is a great practice to allow your users to directly input feedback on your product.
How you choose to triage your responses is up to you, but it is very helpful to always have an open ear to listen to the user. Of course, if you let them constantly enter things in the system, you will need to make it appear that you are actually listening on the other end.