An Agile Overview

This chapter provides a brief introduction to some of the core concepts in the book, including Java, object-oriented programming, and test-driven development. You will get answers to the following questions:

• What is “agile”?

• What is Java?

• What is object-oriented programming?

• Why OO?

• What is an object?

• What are classes?

• Why UML?

• What is inheritance?

• Why test-driven development?

What Is “Agile?”

This book is called Agile Java. “Agile” is a new catchphrase for describing a bunch of related software development methodologies. Loosely defined, a methodology is a process for building software. There are many ways to approach constructing software as part of a team; many of these approaches have been formalized into published methodologies. There are dozens of major processes in use; you may have heard the names of some of them: waterfall, RUP (Rational Unified Process), XP (extreme programming), and Scrum.

Methodologies have evolved as we learn more about how to effectively work. Waterfall is an older approach to building software that promotes copious documentation, rigid up-front (i.e., at the start of the project) definitions of requirements and system design, and division of a project into serialized phases. Its name derives from a diagram that shows progress flowing down from one phase to the next.

While waterfall may be appropriate for some efforts, it has some limitations that can cause severe problems on other software development projects. Using a waterfall process means that you are less able to adapt to change as a project progresses. For these reasons, waterfall is sometimes referred to as a heavyweight process. It is heavy because it requires considerable baggage and restricts development teams from being able to rapidly respond to change.

In contrast, agile processes, a fairly recent phenomena, are lightweight processes. When following an agile process, there is less emphasis on written documentation and on having everything finalized up front. Agile processes are designed around accommodating change. XP is probably the most well-known example of an agile process.

RUP is another very well-known process. Technically RUP is a process framework: It supplies a catalog of things you can mix and match in order to create your own customized process. Such a RUP process instance can straddle the fence between being a heavyweight and an agile process.

When following any kind of process, heavyweight or agile, you must always do the following things when building software:

analysis: determine what you need to build by gathering and refining requirements for what the software should do

planning: figure out how long it will take to build the software

design: determine how to put together what you are building

coding: construct the software using one or more programming languages

testing: ensure that what you built works

deployment: deliver the software to the environment in which it will be executed and used

documentation: describe the software for various audiences, including end users who need to know how to use the software and developers who need to know how to maintain the software

review: ensure, through peer consensus, that the software remains maintainable and retains high quality

If you are not doing all of these things, you are hacking—producing code with abandon and no consideration for business needs. Some processes such as XP appear not to promote everything in the above list. In reality, they do, but in a different, kind-of-sideways fashion.

I cover little with respect to methodology in this book. You can find shelves of books devoted to learning about methodologies. Most development teams use a hybrid methodology—they take successful techniques from various published methodologies and adapt them to their own needs. Many development shops do not even acknowledge a methodology at all. But even these shops usually follow some sort of unstated process.

This book is about constructing the software. Agile Java is centered on a technique known as test-driven development, or TDD. TDD is not a methodology itself but a practice that you can use as part of virtually any software development process. TDD derives from XP, where it is one of about a dozen required practices. You do not need to do XP in order to do TDD or in order to use this book!

I do not discuss XP or other methodologies often in this book. I've centered Agile Java on a technique that will allow you to build and mold your code in an agile fashion. You will learn how to accommodate change in your system via TDD. Even if you are using the most rigid process imaginable, you can still use the techniques in Agile Java to construct high-quality Java code.

What Is Java?

When you hear people refer to Java, they often mean the Java language. The Java language allows you to write instructions, or code, that your computer will interpret in order to execute a software application, or program. Examples of applications are Microsoft Word, Netscape, and the little clock that runs in the corner of your monitor. Coding, or programming, is the act of writing programs.

Another thing people mean when they refer to Java is the Java platform. The term platform usually indicates an underlying operating system, such as Windows or Unix™, on which you can run applications.1 Java acts as a platform: It not only defines a language but also gives you a complete environment in which to build and execute your programs. The Java platform acts as a layer between your application and the underlying operating system; it is a mini–operating system in itself. This allows you to write code in a single language and execute it on virtually all major operating systems today.

1 [WhatIs2004].

You will download the Java software development kit (SDK), which provides you with three main components:

• a compiler (javac)

• a virtual machine, or VM (java)

• a class library, or API (application programming interface)

The compiler is a program that reads Java source files, ensures they contain valid Java code, and produces class files. A source file is a text file that contains the code you type. The class files you generate using the compiler contain byte codes that represent the code you typed in. Byte codes appear in a format that the VM can rapidly read and interpret.

The VM (or JVM—Java virtual machine) is a program that executes the code within your class files. The term “virtual machine” derives from the fact that it acts as if it were a complete platform, or operating system, from the standpoint of your Java programs. Your code does not make direct calls to the operating system application programming interface (API), as it might if you were programming directly for Windows in a language such as C or C++.

Instead, you write code only in the Java language and use only a set of libraries, known as class libraries, or APIs, provided as part of the Java SDK. You might see references to the VM as an interpreter, since that is its chief responsibility: The VM interprets the needs of your code and dispatches these needs to the underlying operating system as necessary. The VM is also responsible for allocating and controlling any memory that your code needs.

Java is known as an object-oriented programming language. The basic premise of an object-oriented programming language is that you can create abstractions of real-world things, or objects, in code. For example, you can create a Java code representation of a calculator that emulates some of the characteristics and behavior of a real-world calculator.

If you have never programmed before, you are in luck: Object-oriented (OO) programming is much easier to learn from scratch than if you have already learned a non-OO programming language like Cobol or C. If you have been tainted by a procedural or declarative language, you may want to read this chapter a few times. Expect that learning OO is not easy; expect to spend a few months before the light bulb in your head stays on all the time without blinking.

This chapter explains the basics of object orientation. Conceptually, OO is reasonably straightforward, but it can take some time for the ideas to sink in, particularly without concrete code examples. Hence, this chapter is brief; instead, you will learn the bulk of OO as you learn to code in Java.

Why OO?

Object-oriented programming has been around for quite some time—since the 1960s—but only during the 1990s did it begin to truly take off in terms of acceptance. Much of what we know about how to program well with objects has been discovered in the past decade. The most important thing we have learned is that OO, done properly, can improve your ability to manage and maintain software applications as they mature and grow.

What Is an Object?

An object is a code-based abstraction of some relevant concept. If you are building a payroll system, an object could be a programming representation of a check, an employee's rate classification, or a check printer. It could also be an abstraction of an activity, such as a routing process to ensure that employees are directed to the appropriate processing queue. Abstraction is best defined as “amplification of the essential, elimination of the irrelevant.”2

2 [Martin2003].

A check object might contain many details such as check number, payee, and amount. But the payroll system is not interested in things such as the size and color of the check, so you would not represent these things in payroll code. You might consider them for the check printing system.

There is some value to using objects that have real-world relevancy, but you must be careful not to take the real world too far into your code. As an example, a payroll system might have an employee object, containing details such as an employee ID and his salary. You also want to ensure that you can give raises to an employee. A real-world design might suggest that the code for giving raises belongs elsewhere, but in fact the most appropriate solution in an OO system is for the employee object to execute the code to apply a raise. (“What? An employee giving himself a raise??”) In Agile Java, you will discover how to make these sorts of design decisions.

An object-oriented system should be primarily about behavior. The core concept of OO is that objects send messages to each other in order to effect behavior. One object sends a message to another object to tell it to do something. As a real-world example, I send you a message to you by telling you to lock the front door. In an OO system, a security object sends a message to a door controller object, telling it to secure the door it controls (see Figure 1).

Figure 1. Sending a Message

image

The object being sent the message—the door controller in this example—is known as the receiver. The receiver decides what to do with the message. You decide to lock the front door by turning the deadbolt. A different person might have chosen to use the latch. In the OO system, the door controller object might have interacted with a hardware device to activate an electromagnetic lock or to cause an electronic deadbolt to eject.

In either case, the sender of the message is interested only in an abstract concept: that the receiver secure the door. The message sender doesn't care how the door is secured; the details of how that happens is something that only the receiver knows. This is a key concept in OO known as encapsulation: Objects should hide unnecessary details from other objects in the system.

The fact that different implementations can be dropped into place without the client knowing or caring which one is going to be used represents another very important OO concept known as polymorphism. The security system shouldn't know or care whether the door controller is an electromagnetic lock controller or an electronic deadbolt controller. You will learn about polymorphism in greater detail in one of the lessons.

What Are Classes?

There might be five electromagnetic doors in the building where the security system is deployed, all located in different areas. Each door is thus a separate object with a different physical address. However, all doors share the common behavior of needing to be secured, so they all can be classified similarly. A class provides a way of defining commonality for a related grouping of objects. It is a template, or blueprint, for constructing new objects.

The OO security system might define a Door class. The Door class specifies that all Door objects must provide secure and release (unlock) behavior. Furthermore, each Door object should retain its own location. A picture of this Door class is shown in Figure 2.

Figure 2. The Door Class

image

The class box shows the name of the class in the first (topmost) compartment. The second compartment lists the attributes—the information that each Door object will store. The third compartment lists the behaviors that each Door object supports—the messages that each door will respond to.

Figure 3. Door Objects in Memory

image

In an object-oriented programming language, you use the Door class as a basis for creating, or instantiating, new objects. Each object that you instantiate is allocated a unique area in memory. Any changes you make to an object are exclusive of all other objects in memory.

A class diagram is used to represent the structure of an object-oriented system. It shows how classes relate to, or associate with, each other. A class diagram can provide a quick visual understanding of a system. You can also use it as one of the primary indicators of the quality of a system's design.

The basis of all relationships in a class diagram is the association. An association between two classes is formed when one class is dependent on the other class or when both classes are dependent on each other. Class A is dependent on class B if class A works only when class B is present.

A main reason class A becomes dependent upon class B is that class A sends one or more messages to class B. Since the Security object sends a message to the DoorController object, the Security class is dependent upon the DoorController class.

You show a one-way dependency between two classes with a navigable association (see Figure 4).

Figure 4. Class Dependency

image

Why UML?

This book uses the UML (Unified Modeling Language) standard to illustrate some of the code. The class boxes shown in earlier sections use UML. The UML is the de facto standard for modeling object-oriented systems. The chief benefit of using UML is that it is universally understood and can be used to quickly express design concepts to other developers.

UML itself is not a methodology; it is a diagramming language. It is a tool that can be used to support documenting any kind of object-oriented system. UML can be used on projects using virtually any methodology.

This book will explain the rudiments of the UML it uses. A good place to obtain a better understanding of UML is the book UML Distilled, by MartinFowler.3 Also, you can find the latest version of the UML specification online at http://www.omg.org/technology/documents/formal/uml.htm.

3 See [Fowler2000].

Most of the UML diagrams in this book show minimal detail. I usually omit attributes, and I only show behaviors when they are particularly relevant. By and large, I intend for the UML to give you a quick pictorial representation of the design of the system. The UML representation is not the design—it is a model of the design.4The design is the code itself.

4 [Martin2003/Reeves1992].

To the extent that UML helps you understand the design of the system, it is valuable and worthwhile. Once it begins duplicating information that is more readily understood by reading code, UML becomes a burdensome, expensive artifact to maintain. Use UML judiciously and it will be an invaluable tool for communication.

What Is Inheritance?

A brief discussion of an object-oriented concept known as inheritance may help you to understand one of the concepts in the first lesson. Inheritance is a relationship between classes in the system that allows for one class to use another class as a basis for specialization of behavior.

In our real-world example, doors are a class of things that you can shut and open and use as entry/exit points. Beyond that commonality, you can specialize doors: There are automatic doors, elevator doors, bank vault doors, and so on. These are all still doors that open and close, but they each provide a bit of additional specialized behavior.

In your security system, you have the common Door class that specifies secure and release behavior and allows each Door object to store a location. However, you must also support specialty doors that provide additional behaviors and attributes. An AlarmDoor provides the ability to trigger an audible alarm when activated and is also able to operate as a secure door. Since the secure and release behaviors of the AlarmDoor are the same as those in the Door class, the AlarmDoor can designate that it is inheriting from the Door class and need only provide specification for alarm activation.

Inheritance provides the AlarmDoor class with the ability to reuse the secure and release behaviors without having to specify them. For an AlarmDoor object, these behaviors appear as if they were defined in the AlarmDoor class.

Figure 5. Inheritance

image

Note that the relationship between AlarmDoor and Door is also a navigable association. AlarmDoor is dependent upon Door—it cannot exist without Door, since AlarmDoor inheXrits its code behavior and attributes from Door. UML shows the inheritance relationship as a directional arrow with the arrowhead closed instead of opened.

In the first lesson, you'll use inheritance to take advantage of a test framework. In a later lesson, you'll learn about inheritance in greater depth.

Why Test-Driven Development?

You will write virtually all code in this book using TDD. TDD is a technique where you specify the system in terms of tests. You write tests prior to (or as) you write the production code; you do not write production code then supply tests after the fact.5

5 [Langr2001].

TDD is a simple, short-cycled mechanism that you repeat throughout your coding day. Each cycle lasts from seconds to minutes, and consists of the following steps:

  1. Write a specification, in code and in the form of a unit6 test.

    6 The test verifies a functional unit of your code. Another term for unit test is programmer test.

  2. Demonstrate test failure (you haven't implemented the specification yet).
  3. Write code to meet the specification.
  4. Demonstrate test success.
  5. “Refactor,” or rework the code, to ensure that the system still has an optimally clean code base.

That's it. You run all tests against the entire system at all times, ensuring that no new code breaks anything else in the system.

Tests drive several positive aspects of the system:

quality. TDD minimizes the number of defects, since by definition, you test everything in the system. You improve your system's design, since TDD drives you toward more decoupled designs—designs where classes are not as heavily dependent upon other classes in the system.

documentation of capability. Each unit test specifies the appropriate use of a production class.

malleability. Having tests in place means that you can continually improve the quality of the code base without fear of breaking something that already works. This can result in lower maintenance costs.

consistent pacing. Since each cycle in TDD is very short, feedback levels are high. You quickly discover if you are going down a rat hole. You learn to maintain a very consistent, sustainable rate of development.

An additional benefit of TDD is that it helps demonstrate the examples in this book. You quickly learn how to translate specifications into test code and how to translate test code into production J2SE 5.0 code.

From a developer's standpoint, TDD is infectious.7 Most developers who give it an honest try retain it as a valuable tool in their development toolbox. Many of the developers I've talked to about TDD, including some seasoned Java pioneers, say that they never want to go back to the “old way” of doing things. I was first exposed to the idea of always writing tests for code in 1996, when I saw Kent Beck speak at a Smalltalk Solutions conference. My personal reaction was “I'm a programmer, not a tester!” Today, I'm amazed at the value it brings me and the amount by which it improves my development capabilities. I wouldn't do it otherwise.

7 [Beck1998].

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.19.217