Showing posts with label Software Development. Show all posts
Showing posts with label Software Development. Show all posts
-
Getting Used to Life Without a Big Design
As Scrum teams begin to become adept at the technical practices, they will naturally begin to shift further away from anticipating users' needs and more toward adapting to them. This will result in a number of changes for the agile architect or designer to become accustomed to. The new realities caused by this shift include the following:
• Planning is harder. Estimating, planning, and committing to deliverables is already hard; it becomes more difficult in the absence of an up-front design. A lot of thinking goes into creating an up-front design. Some of that thinking is helpful in estimating how long things will take and in combining estimates into plans. The upside to forgoing the big up-front design, however, is that the work that needs to be estimated is often simpler so that individual features can be estimated more quickly and easily.
• It is harder to partition the work among teams or individuals. Having a big, up-front design in hand makes it easy to see which features should be developed simultaneously and which should be developed in sequence. This makes it easier to allocate work to teams or individuals.
• It is uncomfortable not to have design done. Even though we've always known that no up-front design can be 100% perfect, we took comfort in its existence. "Surely," we reasoned, "we've thought of all the big things so any changes will be minor."
• Rework will be inevitable. Without a big up-front design, the team will certainly hit a point where it needs to undo some part of the design. This two-steps-forward-one-step-back aspect of iterative development can be unsettling to professionals trained to identify all needs and make all design decisions up front. Fortunately, refactoring and the automated tests created during test-driven development can keep most rework efforts from becoming very large.
Doing a large, up-front design became popular because of the belief that doing so would save time and money. The cost of the up-front design plus the cost of adjustments was viewed as less expensive than the many small changes necessary with emergent design.
In the past, it was entirely possible that doing a large, up-front design would save time and money. After all, Barry Boehm demonstrated in Software Engineering Economics (1981) that defects are more expensive to fix the later in the development process they are discovered. But the technical practices employed by good Scrum teams can dramatically alter the equation. When a team uses good technical practices—test-driven development, a heavy reliance on automated unit tests, refactoring, and pair programming among them—it may find itself in the situation where it is cheaper to adapt to user needs by reworking the application more often than it is to anticipate those needs and rework only occasionally.
In traditional development there is a large cost on upfront analysis and design. This investment keeps down the number of later changes. But when a change is needed, it is relatively expensive to make because the change violates the primary assumption that change will be largely unnecessary. By contrast, the Scrum view shows many more changes, but the size of each bit of rework is smaller. This is the result of anticipating that change will be needed, but not knowing exactly where. Because of that, a Scrum team pursues technical excellence, always keeping the code well factored, with as simple a design as possible, and with a suite of automated tests for early detection of regression problems. So, while there are more occasions for rework, each is less of a setback.
Source of Information : Pearson - Succeeding with Agile Software Development Using Scrum 2010
more
-
Pair Programming
Pair programming is the practice of having two developers work together to write code. It originated from the idea that if occasional code inspections are good, constant code inspections are better. Many of the practices just described are made easier through the use of pair programming. Learning how to do test-driven development is made easier when working together. Feelings of collective ownership are created when code is produced in pairs. And having the discipline to leave the code cleaner than you found it comes easier when another developer is sitting beside you.
Clearly, there are some benefits to pair programming. That's why I invented it. OK, I didn't really invent it, but I like to think I did. I did happen across it out of true necessity, which is, after all, the mother of invention. In 1986 I was hired by Andersen Consulting in its Fos Angeles office. On my first day on the job I completed a skills survey. I marked myself as "proficient" with the C programming language, even though I was very much a beginner at the language. But, I reasoned, I'm studying it every night after work, and I will be proficient by the time they read this skills survey. Unfortunately for me, they read the survey the next day. And on the day after that I was on a plane from Fos Angeles to the New York office to a project that desperately needed C programmers.
After arriving in New York, I met another programmer who had also been transferred because he knew C. I knew I couldn't deceive him, so I came clean and confessed my exaggeration on the skills survey. "Ugh," he said, "I lied, too." Our solution was that we would work together—pair programming, although we didn't call it that. We figured that between us we were as good as one "proficient" C programmer. And, we reasoned, if we worked together on everything, they wouldn't know which of us to fire.
It worked like a dream. He and I worked together for much of the next eight years at three different companies, pairing as much as possible, especially on anything difficult. We wrote some amazing and incredibly complex products, always with low defect rates W e also felt that even though there were two heads for every pair of hands on the keyboard, we were highly productive when working this way.
Since those early, positive experiences with pair programming, I've been hooked. I knew it was a good way to write code. On the other hand, many of us in this industry (myself included) were first attracted to this work because we could sit in a cubicle with our Sony Walkman playing (yes, it was that long ago) and not have to talk with anyone all day. Even now, there are days when I enjoy nothing more than listening to some loud music on my headphones while code is flowing from my fingers as fast as I can type. Because I still relish those days, I have a hard time ever mandating to a team that they must do pair programming 100% of the time.
Fortunately, most teams have realized that the vast majority of the benefits of pairing can be achieved even when it is not done all day, every day. So, when coaching teams, I always push them to adopt pair programming on a part-time basis; use it for the riskiest parts of the application. I encourage teams to find the guidelines that help them pair enough, while stressing that enough is somewhere greater than 0%, but also acknowledging that I can understand the reasons they may have for wanting it to be less than 100%.
There are many advantages to pair programming, even for teams who do it less than 100% of the time. Although most studies show a slight increase in the total number of person-hours used when pairing, this is offset by a decrease in the total duration of the effort. That is, while pairing takes more person-hours, fewer hours pass on the clock (Dyba et. al 2007). Although projects are always under financial pressure, the overriding concern is not so much person-hours as time to market. Pair programming has also been shown to improve quality. In a survey of studies, Dyba and colleagues found that each study showed an improvement in quality with pair programming. Additionally, pair programming facilitates knowledge transfer and is an ideal way to bring new developers up to speed on the application. It is also an effective practice for working in uncharted territory or solving difficult problems in known parts of the system.
"It costs more; I don't want to pay two programmers to do the job of one . "
Pair programming will cost more in the short term. However, that additional initial cost may very likely be paid back with shorter schedules and with higher quality, leading to lower maintenance costs down the road. Rather than take industry studies as your proof either way, prove this to yourself. Pair on the most difficult modules and see if they have fewer defects and are easier to maintain later, perhaps in comparison to similar modules from other programs done without pair programming.
" We're in a hurry. We can't have two programmers on one task."
Actually, if you're in a hurry this is the time you need pair programming the most. I've already mentioned that pairing leads to shorter project durations (while increasing overall effort, or person-hours). Additionally, there is even some evidence (Williams, Shukla, and Anton 2004) that pairing is an effective way to counter Brooks' Law ("adding manpower to a late software project makes it later"). In other words, if you have an aggressive deadline or are tempted to add people to a late project, these are ideal times to incorporate pair programming.
" When working on a tough problem , I need some quiet time to think through the problem."
Talk with your pairing partner and agree to separate for an hour or whatever you need to think through the problem. When you resume pairing, start by sharing any insights either of you had.
Thing To Try Now
In your next sprint planning meeting, commit to doing some pairing. Make the commitment explicit by adding tasks to the sprint backlog: " Mike and Bob pair for t w o hours," " Mike and Mehta pair for an afternoon," and so on. This is a good way to at least get comfortable with pairing. It is too easy to put off pairing with a vague commitment to try it sometime in the near future. Having tasks in the sprint backlog, though, acts as a constant nagging reminder, and, as a result, is much more likely to result in action.
Source of Information : Pearson - Succeeding with Agile Software Development Using Scrum 2010
more
-
Continuous Integration
Creating an official nightly build of a product has been known as an industry best practice since at least the early 1990s. Well, if a nightly build is a good idea, building a product continuously is an even better one. Continuous integration refers to integrating new or changed code into an application as soon as possible and then testing the application to make sure that nothing has been broken. Rather than checking in code perhaps every few days or even every few weeks, each programmer on a Scrum team running continuous integration is expected to check in code a few times each day—and to run a suite of regression tests over the entire application.
Continuous integration is usually achieved with the help of a tool or script that notices when code has been checked into the version control system. Cruise Control was the first product to gain popularity for automating continuous integration. It could build a product, run as many tests as desired against it, and could then automatically send a notification to the developer who broke the build (or to the entire team). Cruise Control could also send build results to additional feedback devices such as lava lamps, ambient orbs, spare monitors, LED displays, and more.
Some teams opt for a manual approach, in which developers initiate the build and test for each check-in. I strongly recommend against this. Although it is possible to be successful with a manual approach to continuous integration, my experience is that developers will occasionally skip the build and test. It is just too tempting to occasionally think, "I changed only two lines and it worked on my machine." It's also tempting to forgo the build and test when checking in code after your planned quitting time for the day: "Yikes, it's almost six o'clock," a developer may think. "I'm sure this works and I don't want to wait 15 minutes for the tests to finish...." Given the ease with which a continuous integration tool can be configured, it is almost always one of the first things I coach teams to do.
For most developers, the first exposure to automated continuous integration is eye-opening. I know it was for me. I'd become very accustomed to the benefits of a nightly build but had somehow never made the mental leap that if once a day is good, many times a day would be better. After working in a continuously integrated environment for a day, I was hooked. Not only could we eliminate all risk of big integration issues at the end of a project, but also the entire development team would be receiving near-real-time feedback on the status of the product.
" Maintaining a build server and all those tests takes time away from other work ."
A Scrum team will require a suitable automated testing environment regardless of whether it also does continuous integration. So, the only additional overhead is that of setting up and maintaining the build server environment. For most applications this investment will be paid back within the first month by the t i m e saved on integration issues.
" Our system is too complex; it takes hours t o run a full integration test—we can't build continuously ."
These days it is not uncommon to encounter a Scrum team with a test suite that takes hours to run. The solution is normally to partition the test suite rather than abandon the idea of continuous integration. Stephen Marsh and Stelios Pantazopoulos worked on the TransCanada pipeline project and did exactly this.
Several months into the project it became evident that running the full regression test in under fifteen minutes was not possible. As a result the regression test was split into two: a smoke test and a full test. The first ran after every check-in and included all test scripts from the current delivery milestone [sprint] and a subset of scripts from past milestones. The second ran once an hour and included all test scripts from all milestones. The first proved to be complete enough the majority of the time. Only on rare occasions did the second one fail. (2008, 241)
THINGSTO TRY NOW
• An official nightly build is a must for any Scrum team. Getting at least this much in place should be one of the first things you do if you don't have it already. The effort to get a nightly build in place will be paid back within a month at the most, so there's no excuse to be without one. Plan this into your next sprint.
• If you already have a nightly build, take the next step and start building continuously.
• If you have a continuous build, but no tests run as part of it, add some. Getting the first test of each type from this pyramid is a hurdle. But after the first test has been integrated, the rest come much more easily.
Source of Information : Pearson - Succeeding with Agile Software Development Using Scrum 2010
more
-
Collective Ownership
Collective ownership refers to all developers feeling ownership over all artifacts of the development process, but especially of the code and automated tests. Because of the fast pace of a Scrum project, the team needs to avoid the trap of saying, "That's Ted's code. We can't touch it." Collective ownership encourages each team member to feel responsible for all parts of the program so that any programmer can work on any module of the program. When modifying a module, the programmer then shares responsibility for its quality with the module's initial writer.
Collective ownership is not intended to cause a free-for-all in the coding. Programmers will still tend to have certain areas they specialize in and prefer to work in, but everyone on the team shares the following responsibilities:
• Ensure that no developer becomes so specialized he can contribute only in one area.
• Make certain that no area becomes so intricate that it is understood and worked upon by only one developer.
A natural benefit of fostering a feeling of collective ownership is that it encourages developers to learn new parts of the system. In doing so they generally also learn new ways of doing things. Good ideas used in one part of the application are more quickly propagated to other areas as programmers moving in and out of parts of the application carry the ideas like pollen.
"It's m y code; I don't want to have to fix any on e else's bugs."
I don't blame you, but keep in mind they are also fixing your bugs. In fact, from my experience a t e am practicing collective ownership will write cleaner code (and presumably therefore have fewer bugs). No one wants to look bad in front of coworkers. If some code is " mine " and no one will see it, I might be tempted to get a little sloppy; not so if anyone can see my code at any time. For proof of this look no further than your guest bathroom. Which do you keep cleaner: the bathroom only you use or the one that visitors are likely to see?
"I don't want anyone else looking at my code and making judgments about my skills, character, upbringing, and soon."
This is a natural fear. The best way over this fear is to write better code. If you always did your best to write high-quality code, any judgments others made would be positive. If you're not confident in your ability to write high-quality code, pair as often as you can with other programmers as a way of improving.
"Development is faster if each person own s one part of the system."
This depends entirely on the time frame over which w e are measuring. If you and I are building a throwaway system over the next t w o weeks, it will indeed most likely be faster for each of us to own one part of the application. If, however, w e are part of a much larger effort and are going to have to maintain the system for the long term, the learning, cross-training, and other benefits of collective ownership weigh heavily in its favor.
THINGSTO TRY NOW
• Pretend that the owner of any critical area is away on vacation and nearly impossible to reach. For a couple of sprints, make the deliberate decision that the "obvious person" is never allowed to take on tasks related to that area of expertise. If the area expert is needed, that expert is available by phone only—literally call the person who is sitting t w o cubicles away.
• The next time you work in code that is difficult to work with, fix it—even if it was written by someone else. If you feel that this is overstepping your authority, ask the original programmer to work with you in making the code easier to use.
Source of Information : Pearson - Succeeding with Agile Software Development Using Scrum 2010
more
-
Refactoring
Consider the classic definition offered by Fred Brooks in The Mythical Man Month of what happens as a software system is modified over time.
All repairs tend to destroy the structure, to increase the entropy and disorder of the system. Less and less effort is spent on fixing original design flaws; more and more is spent on fixing flaws introduced by earlier fixes. As time passes, the system becomes less and less well-ordered. Sooner or later the fixing ceases to gain any ground. Each forward step is matched by a backward one. Although in principle usable forever, the system has worn out as a base for progress.
Fortunately, since 1975 when Brooks first wrote this, our industry has learned ways to modify systems such that the system does not decay further with each modification. The ability to modify without introducing decay is essential to Scrum because Scrum teams build products incrementally. As Ron Jeffries says, "In agile, the design simply must start simple and grow up. The way to do this is refactoring."
Refactoring refers to changing the structure but not the behavior of code. Let me give you an example. Suppose a programmer has two methods that each contain three identical statements. These three common statements can be extracted from both methods and put into one new method that is called from both of the old locations. This refactoring (formally known as extract metlwtf) has slightly improved the readability and maintainability of the program because it is now more obvious that some code is reused and the duplicated code has been moved to a single place. The structure of the code has been changed while its behavior has not.
Refactoring is not only crucial to the success of TDD, but it also helps prevent code rot. Code rot is the typical syndrome in which a product is released, its code is allowed to decay for a few years, and then an entire rewrite is needed. By constantly refactoring and fixing small problems before they become big problems, we can keep our applications rot free. Robert C. Martin calls this the Boy Scout Rule.
The Boy Scouts of America have a simple rule that we can apply to our profession: Leave the campground cleaner than you found it. If we all checked-in our code a little cleaner than when we checked it out, the code simply could not rot.
"If they wrote it right the first time , they wouldn't need to refactor now."
This is kind of like saying, "If Toyota built better cars, they wouldn't need oil changes, new tires, or any maintenance ever." Applications will need maintenance; refactoring is choosing to do it a little at a time when doing so is cheap. Most of the managers or product owners I've met who take a "you aren't allowed to refactor" stance do so because teams have abused the ability to refactor in the past. A typical example is the team that reserves the last three days of every tenday sprint for refactoring. Another is the team that tells its product owner, "No, w e can't do that important feature this sprint because w e need to refactor what w e wrote the last sprint." If the whole team needs three days to refactor every sprint, that's a sign of different troubles. If the team has planned refactorings that are so large they have to turn down features the product owner would like included, the refactoring probably belongs on the product backlog itself.
THINGS TO TRY NOW
• Start a refactoring backlog of all the things you want to clean up. If the team is collocated, simply write it on a big sheet of paper hanging somewhere. If not, use the electronic equivalent. You want the list to be as informal as possible. The goal is to fix all the issues and then destroy the list. Institutionalizing the refactoring list in a custom-built database w i t h a custom web client, RSS feeds, and iPhone support will encourage the list to remain forever.
• Learn the refactorings that can be performed automatically by your integrated development environment.
• When a refactoring opportunity is identified, have team members write it on an index card. Post the cards in a small, delineated area on a wall in the team room. As the area fills, feel mounting pressure to complete one or more refactoring.
• At the end of your next two-hour-long programming session, spend 20 or 30 minutes cleaning up something you noticed as you were touching or looking at existing code.
• During your next retrospective, facilitate a discussion about refactoring with your teammates, including the product owner. At what threshold should refactoring switch from a personal decision to a whole-team decision? Clearly, I can rename a poorly named variable I come across without a t e am discussion. What if the developers come across a two-day change; can they just make it, or does the product owner need to approve the effort first?
Source of Information : Pearson - Succeeding with Agile Software Development Using Scrum 2010
more
-
Test-Driven Development
If you were to look at how programmers write code on a traditional development team, you would find that they typically select a portion of the program to tackle, write the code, attempt to compile it, fix all the compile errors, walk through the code in a debugger, and then repeat. This process is very different from a test-driven approach, which is also shown in that figure. A programmer doing test-driven development works in very short cycles of identifying and automating a failing test, writing just enough code to pass that test, and then cleaning the code up in any necessary ways before starting again. This cycle is repeated every few minutes, rather than every few hours.
I find test-driven development (TDD) invaluable. One of the biggest reasons is that it ensures that no untested code makes it into the system. If all code must be written in response to a failing test, then if we do nothing else, we at least achieve full code coverage with TDD. You might think a test-right-after approach would achieve the same result. However, I've found that when programmers make a commitment to write their unit tests "right after" they finish implementing a feature, they often do not do so. The pressure to get started programming the next feature can be tremendous. So programmers tend to write tests for only a subset of the new functionality or put testing on a list of things to get to later, and then find that later never comes.
It is appropriate to think of TDD as being as much a design practice as a programming practice. After all, the tests a programmer writes and the order in which they are written guide the design and development of a feature. A programmer doesn't create a list of 50 small unit tests and then randomly choose which to implement first. Instead each test is selected and sequenced so that the uncertainties of the feature are addressed early. In this way, the selection and implementation of tests does indeed drive the development process, resulting in a design that, at least in part, emerges from the needs of the system.
There is some debate about whether TDD leads to more robust or otherwise better designs.1 But there is no doubt that TDD is helpful as a practice that helps programmers think through their designs. A design that is hard to test, for example, may indicate poorly structured code. My recommendation is to do TDD for its testing benefits; any potential design improvements it brings are a bonus.
"I am working on a complex system. I need t o do some architectural work first ."
Yes, on a complex or large system, you probably do. There is nothing to say that TDD as a micro-level practice cannot be effectively combined with a small amount of up-front architectural thinking. The question of how much, if any, architectural thinking to do up front is best considered with achieving that balance in mind.
" Always writing a test first is bound to take longer; I don't have time to waste ."
There is evidence that doing TDD takes about 15% longer than not doing TDD (George and Williams 2003). But there is also evidence that TDD leads to fewer defects. Two studies at Microsoft found that the number of bugs found went down by 2 4% and 3 8% with the use of TDD (Sanchez, Williams, and Maximilien 2007, 6). So, yes, TDD may take longer initially, but the time will come back to the team in the form of reduced bug fixing and maintenance time.
THINGSTO TRY NOW
• Commit to spending at least one full day in the coming week doing test-driven development. If you've never done TDD before, you will likely need to work w i t h another programmer to get the hang of it. Even if your partner doesn't have TDD experience either, it will be easier to learn together.
• Getting comfortable with how to write a failing test before writing the implementation can be difficult. It's a very different way of working. One way to gain a better understanding of it is to try gang programming. Gather four to eight programmers in a conference room equipped with a laptop and projector. Pick a programmer to start coding while everyone else looks at the projected source code. Find one failing test you can write, and then have the programmer write the code that makes the test pass. After 15 minutes or so, pass the laptop to another programmer. Continue writing code and passing the laptop until the task is complete.
• If trying TDD on your full application is too difficult right now, find an ancillary project you can try it on. How about that data conversion program everyone has been putting off? Or the stand-alone program one of the system administrators asked for last month?
Source of Information : Pearson - Succeeding with Agile Software Development Using Scrum 2010
more
Subscribe to:
Posts (Atom)