::Z::Thinking::

::Simple::
文章 - 124,收藏 - , 评论 - 49, trackbacks - 0

16:Analysis and Design

The object-oriented paradigm is a new and different way of thinking about programming.

Manypeople have trouble at first knowing how to approach an OOP project.Now that you understand the concept of an object, and as you learn tothink more in an object-oriented style, you can begin to create “good”designs that take advantage of all the benefits that OOP has to offer.This chapter introduces the ideas of analysis, design, and some ways toapproach the problems of developing good object-oriented programs in areasonable amount of time. Feedback

Methodology

A methodology (sometimes simply called a method) isa set of processes and heuristics used to break down the complexity ofa programming problem. Many OOP methodologies have been formulatedsince the dawn of object-oriented programming. This section will giveyou a feel for what you’re trying to accomplish when using amethodology. Feedback

Especially in OOP, methodology is a field ofmany experiments, so it is important to understand what problem themethodology is trying to solve before you consider adopting one. Thisis particularly true with Java, in which the programming language isintended to reduce the complexity (compared to C) involved inexpressing a program. This may in fact alleviate the need forever-more-complex methodologies. Instead, simple methodologies maysuffice in Java for a much larger class of problems than you couldhandle using simple methodologies with procedural languages. Feedback

It’s also important to realize that the term“methodology” is often too grand and promises too much. Whatever you donow when you design and write a program is a methodology. It may beyour own methodology, and you may not be conscious of doing it, but itis a process you go through as you create. If it is an effectiveprocess, it may need only a small tune-up to work with Java. If you arenot satisfied with your productivity and the way your programs turnout, you may want to consider adopting a formal methodology, orchoosing pieces from among the many formal methodologies. Feedback

While you’re going through the developmentprocess, the most important issue is this: Don’t get lost. It’s easy todo. Most of the analysis and design methodologies are intended to solvethe largest of problems. Remember that most projects don’t fit intothat category, so you can usually have successful analysis and designwith a relatively small subset of what a methodology recommends.[102]But some sort of process, no matter how small or limited, willgenerally get you on your way in a much better fashion than simplybeginning to code. Feedback

It’s also easy to get stuck, to fall into“analysis paralysis,” where you feel like you can’t move forwardbecause you haven’t nailed down every little detail at the currentstage. Remember, no matter how much analysis you do, there are somethings about a system that won’t reveal themselves until design time,and more things that won’t reveal themselves until you’re coding, ornot even until a program is up and running. Because of this, it’scrucial to move fairly quickly through analysis and design, and toimplement a test of the proposed system. Feedback

Thispoint is worth emphasizing. Because of the history we’ve had withprocedural languages, it is commendable that a team will want toproceed carefully and understand every minute detail before moving todesign and implementation. Certainly, when creating a DatabaseManagement System (DBMS), it pays to understand a customer’sneeds thoroughly. But a DBMS is in a class of problems that is verywell-posed and well-understood; in many such programs, the databasestructure is the problem to be tackled. The class ofprogramming problem discussed in this chapter is of the “wild-card” (myterm) variety, in which the solution isn’t simply re-forming awell-known solution, but instead involves one or more “wild-card factors”—elements for which there is no well-understood previous solution, and for which research is necessary.[103]Attempting to thoroughly analyze a wild-card problem before moving intodesign and implementation results in analysis paralysis because youdon’t have enough information to solve this kind of problem during theanalysis phase. Solving such a problem requires iteration through thewhole cycle, and that requires risk-taking behavior (which makes sense,because you’re trying to do something new and the potential rewards arehigher). It may seem like the risk is compounded by “rushing” into apreliminary implementation, but it can instead reduce the risk in awild-card project because you’re finding out early whether a particularapproach to the problem is viable. Product development is riskmanagement. Feedback

It’s often proposed that you “build one to throw away.” With OOP, you may still throw partof it away, but because code is encapsulated into classes, during thefirst pass you will inevitably produce some useful class designs anddevelop some worthwhile ideas about the system design that do not needto be thrown away. Thus, the first rapid pass at a problem not onlyproduces critical information for the next analysis, design, andimplementation pass, it also creates a code foundation. Feedback

That said, if you’re looking at a methodologythat contains tremendous detail and suggests many steps and documents,it’s still difficult to know when to stop. Keep in mind what you’retrying to discover: Feedback

  1. What are the objects? (How do you partition your project into its componentparts?)
  2. What are their interfaces? (What messages do you need to send to eachobject?)

Ifyou come up with nothing more than the objects and their interfaces,then you can write a program. For various reasons you might need moredescriptions and documents than this, but you can’t get away with anyless. Feedback

The process can be undertaken in five phases,and a Phase 0 that is just the initial commitment to using some kind ofstructure. Feedback

Phase0: Make a plan

You must first decide what steps you’re going to have in your process. It sounds simple (in fact, allof this sounds simple), and yet people often don’t make this decisionbefore they start coding. If your plan is “let’s jump in and startcoding,” fine. (Sometimes that’s appropriate when you have awell-understood problem.) At least agree that this is the plan. Feedback

You might also decideat this phase that some additional process structure is necessary, butnot the whole nine yards. Understandably, some programmers like to workin “vacation mode,” in which no structure is imposed on the process ofdeveloping their work; “It will be done when it’s done.” This can beappealing for a while, but I’ve found that having a few milestonesalong the way helps to focus and galvanize your efforts around thosemilestones instead of being stuck with the single goal of “finish theproject.” In addition, it divides the project into more bite-sizedpieces and makes it seem less threatening (plus the milestones offermore opportunities for celebration). Feedback

When I began to study story structure (so thatI will someday write a novel) I was initially resistant to the idea ofstructure, feeling that I wrote best when I simply let it flow onto thepage. But I later realized that when I write about computers thestructure is clear enough to me that I don’t have to think about itvery much. I still structure my work, albeit only semi-consciously inmy head. Even if you think that your plan is to just start coding, youstill somehow go through the subsequent phases while asking andanswering certain questions. Feedback

Themission statement

Anysystem you build, no matter how complicated, has a fundamentalpurpose—the business that it’s in, the basic need that it satisfies. Ifyou can look past the user interface, the hardware- or system-specificdetails, the coding algorithms and the efficiency problems, you willeventually find the core of its being—simple and straightforward. Likethe so-called high concept from a Hollywood movie, you can describe it in one or two sentences. This pure description is the starting point. Feedback

The high concept is quite important because itsets the tone for your project; it’s a mission statement. You won’tnecessarily get it right the first time (you may be in a later phase ofthe project before it becomes completely clear), but keep trying untilit feels right. For example, in an air-traffic control system you maystart out with a high concept focused on the system that you’rebuilding: “The tower program keeps track of the aircraft.” But considerwhat happens when you shrink the system to a very small airfield;perhaps there’s only a human controller, or none at all. A more usefulmodel won’t concern the solution you’re creating as much as itdescribes the problem: “Aircraft arrive, unload, service and reload,then depart.” Feedback

Phase1: What are we making?

In the previous generation of program design (called procedural design), this is called “creating the requirements analysis and system specification.”These, of course, were places to get lost; documents with intimidatingnames that could become big projects in their own right. Theirintention was good, however. The requirements analysis says “Make alist of the guidelines we will use to know when the job is done and thecustomer is satisfied.”[104] The system specification says “Here’s a description of what the program will do (not how)to satisfy the requirements.” The requirements analysis is really acontract between you and the customer (even if the customer workswithin your company, or is some other object or system). The systemspecification is a top-level exploration into the problem and in somesense a discovery of whether it can be done and how long it will take.Since both of these will require consensus among people (and becausethey will usually change over time), I think it’s best to keep them asbare as possible—ideally, to lists and basic diagrams—to save time(this is in line with Extreme Programming, which advocates very minimaldocumentation, albeit for small- to medium-sized projects). You mighthave other constraints that require you to expand them into biggerdocuments, but by keeping the initial document small and concise, itcan be created in a few sessions of group brainstorming with a leaderwho dynamically creates the description. This not only solicits inputfrom everyone, it also fosters initial buy-in and agreement by everyoneon the team. Perhaps most importantly, it can kick off a project with alot of enthusiasm. Feedback

It’s necessary to stay focused on the heart ofwhat you’re trying to accomplish in this phase: Determine what thesystem is supposed to do. The most valuable tool for this is acollection of what are called “use cases,” or in Extreme Programming,“user stories.” Use cases identify key features in the system that willreveal some of the fundamental classes you’ll be using. These areessentially descriptive answers to questions like:[105] Feedback

  • “Who will use this system?”
  • “What can those actors do with the system?”
  • “How does this actor do that with thissystem?”
  • “How else might this work if someone else were doing this, or if thesame actor had a different objective?” (to reveal variations)
  • “What problems might happen while doing this with the system?”(to revealexceptions)

Ifyou are designing a bank auto-teller, for example, the use case for aparticular aspect of the functionality of the system is able todescribe what the auto-teller does in every possible situation. Each ofthese “situations” is referred to as a scenario,and a use case can be considered a collection of scenarios. You canthink of a scenario as a question that starts with: “What does thesystem do if...?” For example, “What does the auto-teller do if acustomer has just deposited a check within the last 24 hours, andthere’s not enough in the account without the check having cleared toprovide a desired withdrawal?” Feedback

Use case diagrams are intentionally simple to prevent you from getting bogged down in system implementation details prematurely:

TIJ337.png

Each stick person represents an “actor,” whichis typically a human or some other kind of free agent. (These can evenbe other computer systems, as is the case with “ATM.”) The boxrepresents the boundary of your system. The ellipses represent the usecases, which are descriptions of valuable work that can be performedwith the system. The lines between the actors and the use casesrepresent the interactions. Feedback

It doesn’t matter how the system is actually implemented, as long as it looks like this to the user. Feedback

A use case does not need to be terriblycomplex, even if the underlying system is complex. It is only intendedto show the system as it appears to the user. For example: Feedback

TIJ338.png

The use cases produce the requirementsspecifications by determining all the interactions that the user mayhave with the system. You try to discover a full set of use cases foryour system, and once you’ve done that you have the core of what thesystem is supposed to do. The nice thing about focusing on use cases isthat they always bring you back to the essentials and keep you fromdrifting off into issues that aren’t critical for getting the job done.That is, if you have a full set of use cases, you can describe yoursystem and move on to the next phase. You probably won’t get it allfigured out perfectly on the first try, but that’s OK. Everything willreveal itself in time, and if you demand a perfect system specificationat this point you’ll get stuck. Feedback

If you do get stuck, you can kick-start thisphase by using a rough approximation tool: Describe the system in a fewparagraphs and then look for nouns and verbs. The nouns can suggestactors, context of the use case (e.g., “lobby”), or artifactsmanipulated in the use case. Verbs can suggest interactions betweenactors and use cases, and specify steps within the use case. You’llalso discover that nouns and verbs produce objects and messages duringthe design phase (and note that use cases describe interactions betweensubsystems, so the “noun and verb” technique can be used only as abrainstorming tool because it does not generate use cases).[106] Feedback

The boundary between a use case and an actorcan point out the existence of a user interface, but it does not definesuch a user interface. For a process of defining and creating userinterfaces, see Software for Use by Larry Constantine and Lucy Lockwood, (Addison-Wesley Longman, 1999) or go to www.ForUse.com. Feedback

Although it’s a black art, at this point somekind of basic scheduling is important. You now have an overview of whatyou’re building, so you’ll probably be able to get some idea of howlong it will take. A lot of factors come into play here. If youestimate a long schedule then the company might decide not to build it(and thus use their resources on something more reasonable—that’s a goodthing). Or a manager might have already decided how long the projectshould take and will try to influence your estimate. But it’s best tohave an honest schedule from the beginning and deal with the toughdecisions early. There have been a lot of attempts to come up withaccurate scheduling techniques (much like techniques to predict thestock market), but probably the best approach is to rely on yourexperience and intuition. Get a gut feeling for how long it will reallytake, then double that and add 10 percent. Your gut feeling is probablycorrect; you can get something working in that time. The“doubling” will turn that into something decent, and the 10 percentwill deal with the final polishing and details.[107]However you want to explain it, and regardless of the moans andmanipulations that happen when you reveal such a schedule, it justseems to work out that way.[108] Feedback

Phase2: How will we build it?

In this phase you must come up with a designthat describes what the classes look like and how they will interact.An excellent technique in determining classes and interactions is the Class-Responsibility-Collaboration(CRC) card. Part of the value of this tool is that it’s so low-tech:You start out with a set of blank 3 x 5 cards, and you write on them.Each card represents a single class, and on the card you write: Feedback

  1. The name of the class. It’s important that this name capture theessence of what the class does, so that it makes sense at a glance. Feedback
  2. The “responsibilities” of the class: what it should do. This cantypically be summarized by just stating the names of the methods (since thosenames should be descriptive in a good design), but it does not preclude othernotes. If you need to seed the process, look at the problem from a lazyprogrammer’s standpoint: What objects would you like to magically appearto solve your problem? Feedback
  3. The “collaborations” of the class: What other classes does itinteract with? “Interact” is an intentionally broad term; it couldmean aggregation or simply that some other object exists that will performservices for an object of the class. Collaborations should also consider theaudience for this class. For example, if you create a class Firecracker,who is going to observe it, a Chemist or a Spectator? The formerwill want to know what chemicals go into the construction, and the latter willrespond to the colors and shapes released when it explodes. Feedback

Youmay feel that the cards should be bigger because of all the informationyou’d like to get on them. However, they are intentionally small, notonly to keep your classes small but also to keep you from getting intotoo much detail too early. If you can’t fit all you need to know abouta class on a small card, then the class is too complex (either you’regetting too detailed, or you should create more than one class). Theideal class should be understood at a glance. The idea of CRC cards isto assist you in coming up with a first cut of the design so that youcan get the big picture and then refine your design. Feedback

One of the great benefits of CRC cards is incommunication. It’s best done in real time, in a group, withoutcomputers. Each person takes responsibility for several classes (whichat first have no names or other information). You run a live simulationby solving one scenario at a time, deciding which messages are sent tothe various objects to satisfy each scenario. As you go through thisprocess, you discover the classes that you need along with theirresponsibilities and collaborations, and you fill out the cards as youdo this. When you’ve moved through all the use cases, you should have afairly complete first cut of your design. Feedback

Before I began using CRC cards, the mostsuccessful consulting experiences I had when coming up with an initialdesign involved standing in front of a team—who hadn’t built an OOPproject before—and drawing objects on a whiteboard. We talked about howthe objects should communicate with each other, and erased some of themand replaced them with other objects. Effectively, I was managing allthe “CRC cards” on the whiteboard. The team (who knew what the projectwas supposed to do) actually created the design; they “owned” thedesign rather than having it given to them. All I was doing was guidingthe process by asking the right questions, trying out the assumptions,and taking the feedback from the team to modify those assumptions. Thetrue beauty of the process was that the team learned how to doobject-oriented design not by reviewing abstract examples, but byworking on the one design that was most interesting to them at thatmoment: theirs. Feedback

Once you’ve come up with a set of CRC cards, you may want to create a more formal description of your design using UML.[109]You don’t need to use UML, but it can be helpful, especially if youwant to put up a diagram on the wall for everyone to ponder, which is agood idea (there is a plethora of UML diagramming tools available). Analternative to UML is a textual description of the objects and theirinterfaces, or, depending on your programming language, the code itself.[110] Feedback

UML also provides an additional diagrammingnotation for describing the dynamic model of your system. This ishelpful in situations in which the state transitions of a system orsubsystem are dominant enough that they need their own diagrams (suchas in a control system). You may also need to describe the datastructures, for systems or subsystems in which data is a dominantfactor (such as a database). Feedback

You’ll know you’re done with Phase 2 when youhave described the objects and their interfaces. Well, most ofthem—there are usually a few that slip through the cracks and don’tmake themselves known until Phase 3. But that’s OK. What’s important isthat you eventually discover all of your objects. It’s nice to discoverthem early in the process, but OOP provides enough structure so thatit’s not so bad if you discover them later. In fact, the design of anobject tends to happen in five stages, throughout the process ofprogram development. Feedback

Fivestages of object design

Thedesign life of an object is not limited to the time when you’re writingthe program. Instead, the design of an object appears over a sequenceof stages. It’s helpful to have this perspective because you stopexpecting perfection right away; instead, you realize that theunderstanding of what an object does and what it should look likehappens over time. This view also applies to the design of varioustypes of programs; the pattern for a particular type of program emergesthrough struggling again and again with that problem (which ischronicled in the book Thinking in Patterns (with Java) at www.BruceEckel.com). Objects, too, have their patterns that emerge through understanding, use, and reuse. Feedback

1. Object discovery. This stage occursduring the initial analysis of a program. Objects may be discovered bylooking for external factors and boundaries, duplication of elements inthe system, and the smallest conceptual units. Some objects are obviousif you already have a set of class libraries. Commonality betweenclasses suggesting base classes and inheritance may appear right away,or later in the design process. Feedback

2. Object assembly. As you’re buildingan object you’ll discover the need for new members that didn’t appearduring discovery. The internal needs of the object may require otherclasses to support it. Feedback

3. System construction. Once again, morerequirements for an object may appear at this later stage. As youlearn, you evolve your objects. The need for communication andinterconnection with other objects in the system may change the needsof your classes or require new classes. For example, you may discoverthe need for facilitator or helper classes, such as a linked list, thatcontain little or no state information and simply help other classesfunction. Feedback

4. System extension. As you add newfeatures to a system you may discover that your previous design doesn’tsupport easy system extension. With this new information, you canrestructure parts of the system, possibly adding new classes or classhierarchies. This is also a good time to consider taking features out of a project. Feedback

5. Object reuse. Thisis the real stress test for a class. If someone tries to reuse theclass in an entirely new situation, they’ll probably discover someshortcomings. As you change it to adapt to more new programs, thegeneral principles of the class will become clearer, until you have atruly reusable type. However, don’t expect most objects from a systemdesign to be reusable—it is perfectly acceptable for the bulk of yourobjects to be system-specific. Reusable types tend to be less common,and they must solve more general problems in order to be reusable. Feedback

Guidelines for objectdevelopment

These stages suggest some guidelines when thinking about developing your classes: Feedback

  1. Let a specific problem generate a class, then let the class grow and matureduring the solution of other problems. Feedback
  2. Remember, discovering the classes you need (and their interfaces) is themajority of the system design. If you already had those classes, this would bean easy project. Feedback
  3. Don’t force yourself to know everything at the beginning. Learn as yougo. This will happen anyway. Feedback
  4. Start programming. Get something working so you can prove or disprove yourdesign. Don’t fear that you’ll end up with procedural-stylespaghetti code—classes partition the problem and help control anarchy andentropy. Bad classes do not break good classes. Feedback
  5. Always keep it simple. Little clean objects with obvious utility are betterthan big complicated interfaces. When decision points come up, use anOckham’s Razor[111]approach: Consider the choices and select the one that is simplest, becausesimple classes are almost always best. Start small and simple, and you canexpand the class interface when you understand it better. It’s easy to addmethods, but as time goes on, it’s difficult to remove methods from aclass. Feedback

Phase3: Build the core

This is the initial conversion from the roughdesign into a compiling and executing body of code that can be tested,and especially that will prove or disprove your architecture. This isnot a one-pass process, but rather the beginning of a series of stepsthat will iteratively build the system, as you’ll see in Phase 4. Feedback

Your goal is to find the core of your systemarchitecture that needs to be implemented in order to generate arunning system, no matter how incomplete that system is in this initialpass. You’re creating a framework that you can build on with furtheriterations. You’re also performing the first of many systemintegrations and tests, and giving the stakeholders feedback about whattheir system will look like and how it is progressing. Ideally, you areexposing some of the critical risks. You’ll probably discover changesand improvements that can be made to your original architecture—thingsyou would not have learned without implementing the system. Feedback

Part of building the system is the realitycheck that you get from testing against your requirements analysis andsystem specification (in whatever form they exist). Make sure that yourtests verify the requirements and use cases. When the core of thesystem is stable, you’re ready to move on and add more functionality. Feedback

Phase4: Iterate the use cases

Once the core framework is running, each feature set you add is a small project in itself. You add a feature set during an iteration, a reasonably short period of development. Feedback

How big is an iteration? Ideally, eachiteration lasts one to three weeks (this can vary based on theimplementation language). At the end of that period, you have anintegrated, tested system with more functionality than it had before.But what’s particularly interesting is the basis for the iteration: asingle use case. Each use case is a package of related functionalitythat you build into the system all at once, during one iteration. Notonly does this give you a better idea of what the scope of a use caseshould be, but it also gives more validation to the idea of a use case,since the concept isn’t discarded after analysis and design, butinstead it is a fundamental unit of development throughout thesoftware-building process. Feedback

Youstop iterating when you achieve target functionality or an externaldeadline arrives and the customer can be satisfied with the currentversion. (Remember, software is a subscription business.) Because theprocess is iterative, you have many opportunities to ship a productrather than having a single endpoint; open-source projects workexclusively in an iterative, high-feedback environment, which isprecisely what makes them successful. Feedback

An iterative development process is valuablefor many reasons. You can reveal and resolve critical risks early, thecustomers have ample opportunity to change their minds, programmersatisfaction is higher, and the project can be steered with moreprecision. But an additional important benefit is the feedback to thestakeholders, who can see by the current state of the product exactlywhere everything lies. This may reduce or eliminate the need formind-numbing status meetings and increase the confidence and supportfrom the stakeholders. Feedback

Phase5: Evolution

This is the point inthe development cycle that has traditionally been called “maintenance,”a catch-all term that can mean everything from “getting it to work theway it was really supposed to in the first place” to “adding featuresthat the customer forgot to mention” to the more traditional “fixingthe bugs that show up” and “adding new features as the need arises.” Somany misconceptions have been applied to the term “maintenance” that ithas taken on a slightly deceiving quality, partly because it suggeststhat you’ve actually built a pristine program and all you need to do ischange parts, oil it, and keep it from rusting. Perhaps there’s abetter term to describe what’s going on. Feedback

I’ll use the term evolution.[112]That is, “You won’t get it right the first time, so give yourself thelatitude to learn and to go back and make changes.” You might need tomake a lot of changes as you learn and understand the problem moredeeply. The elegance you’ll produce if you evolve until you get itright will pay off, both in the short and the long term. Evolution iswhere your program goes from good to great, and where those issues thatyou didn’t really understand in the first pass become clear. It’s alsowhere your classes can evolve from single-project usage to reusableresources. Feedback

What it means to “get it right” isn’t just thatthe program works according to the requirements and the use cases. Italso means that the internal structure of the code makes sense to you,and feels like it fits together well, with no awkward syntax, oversizedobjects, or ungainly exposed bits of code. In addition, you must havesome sense that the program structure will survive the changes that itwill inevitably go through during its lifetime, and that those changescan be made easily and cleanly. This is no small feat. You must notonly understand what you’re building, but also how the program willevolve (what I call the vector of change).Fortunately, object-oriented programming languages are particularlyadept at supporting this kind of continuing modification—the boundariescreated by the objects are what tend to keep the structure frombreaking down. They also allow you to make changes—ones that would seemdrastic in a procedural program—without causing earthquakes throughoutyour code. In fact, support for evolution might be the most importantbenefit of OOP. Feedback

With evolution, you create something that atleast approximates what you think you’re building, and then you kickthe tires, compare it to your requirements, and see where it fallsshort. Then you can go back and fix it by redesigning andreimplementing the portions of the program that didn’t work right.[113]You might actually need to solve the problem, or an aspect of theproblem, several times before you hit on the right solution. (A studyof Design Patterns is usually helpful here. You can find information in Thinking in Patterns (with Java) at www.BruceEckel.com.) Feedback

Evolution also occurs when you build a system,see that it matches your requirements, and then discover it wasn’tactually what you wanted. When you see the system in operation, you mayfind that you really wanted to solve a different problem. If you thinkthis kind of evolution is going to happen, then you owe it to yourselfto build your first version as quickly as possible so you can find outif it is indeed what you want. Feedback

Perhaps the most important thing to remember isthat by default—by definition, really—if you modify a class, its super-and subclasses will still function. You need not fear modification(especially if you have a built-in set of unit tests to verify thecorrectness of your modifications). Modification won’t necessarilybreak the program, and any change in the outcome will be limited tosubclasses and/or specific collaborators of the class you change. Feedback

Planspay off

Of course you wouldn’t build a house without alot of carefully drawn plans. If you build a deck or a dog house yourplans won’t be so elaborate, but you’ll probably still start with somekind of sketches to guide you on your way. Software development hasgone to extremes. For a long time, people didn’t have much structure intheir development, but then big projects began failing. In reaction, weended up with methodologies that had an intimidating amount ofstructure and detail, primarily intended for those big projects. Thesemethodologies were too scary to use—it looked like you’d spend all yourtime writing documents and no time programming. (This was often thecase.) I hope that what I’ve shown you here suggests a middle path—asliding scale. Use an approach that fits your needs (and yourpersonality). No matter how minimal you choose to make it, somekind of plan will make a big improvement in your project, as opposed tono plan at all. Remember that, by most estimates, over 50 percent ofprojects fail (some estimates go up to 70 percent!). Feedback

By following aplan—preferably one that is simple and brief—and coming up with designstructure before coding, you’ll discover that things fall together farmore easily than if you dive in and start hacking. You’ll also realizea great deal of satisfaction. It’s my experience that coming up with anelegant solution is deeply satisfying at an entirely different level;it feels closer to art than technology. And elegance always pays off;it’s not a frivolous pursuit. Not only does it give you a programthat’s easier to build and debug, but it’s also easier to understandand maintain, and that’s where the financial value lies. Feedback

ExtremeProgramming

I have studied analysis and design techniques, on and off, since I was in graduate school. The concept of Extreme Programming (XP) is the most radical, and delightful, that I’ve seen. You can find it chronicled in Extreme Programming Explained by Kent Beck (Addison-Wesley, 2000) and on the Web at www.xprogramming.com.Addison-Wesley also seems to come out with a new book in the XP seriesevery month or two; the goal seems to be to convince everyone toconvert using sheer weight of books (generally, however, these booksare small and pleasant to read). Feedback

XP is both a philosophy about programming workand a set of guidelines to do it. Some of these guidelines arereflected in other recent methodologies, but the two most important anddistinct contributions, in my opinion, are “write tests first” and“pair programming.” Although he argues strongly for the whole process,Beck points out that if you adopt only these two practices you’llgreatly improve your productivity and reliability. Feedback

Writetests first

Testing hastraditionally been relegated to the last part of a project, afteryou’ve “gotten everything working, but just to be sure.” It hasimplicitly had a low priority, and people who specialize in it have notbeen given a lot of status and have often even been cordoned off in abasement, away from the “real programmers.” Test teams have respondedin kind, going so far as to wear black clothing and cackling with gleewhenever they break something (to be honest, I’ve had this feelingmyself when breaking compilers). Feedback

XP completely revolutionizes the concept oftesting by giving it equal (or even greater) priority than the code. Infact, you write the tests before you write the code that willbe tested, and the tests stay with the code forever. The tests must beexecuted successfully every time you do a build of the project (whichis often, sometimes more than once a day). Feedback

Writing tests first has two extremely important effects. Feedback

First, it forces a clear definition of theinterface of a class. I’ve often suggested that people “imagine theperfect class to solve a particular problem” as a tool when trying todesign the system. The XP testing strategy goes further than that—itspecifies exactly what the class must look like, to the consumer ofthat class, and exactly how the class must behave. In no uncertainterms. You can write all the prose, or create all the diagrams youwant, describing how a class should behave and what it looks like, butnothing is as real as a set of tests. The former is a wish list, butthe tests are a contract that is enforced by the compiler and the testframework. It’s hard to imagine a more concrete description of a classthan the tests. Feedback

Whilecreating the tests, you are forced to completely think out the classand will often discover needed functionality that might be missedduring the thought experiments of UML diagrams, CRC cards, use cases,etc. Feedback

The second importanteffect of writing the tests first comes from running the tests everytime you do a build of your software. This activity gives you the otherhalf of the testing that’s performed by the compiler. If you look atthe evolution of programming languages from this perspective, you’llsee that the real improvements in the technology have actually revolvedaround testing. Assembly language checked only for syntax, but Cimposed some semantic restrictions, and these prevented you from makingcertain types of mistakes. OOP languages impose even more semanticrestrictions, which if you think about it are actually forms oftesting. “Is this data type being used properly?” and “Is this methodbeing called properly?” are the kinds of tests that are being performedby the compiler or run-time system. We’ve seen the results of havingthese tests built into the language: People have been able to writemore complex systems, and get them to work, with much less time andeffort. I’ve puzzled over why this is, but now I realize it’s thetests: You do something wrong, and the safety net of the built-in teststells you there’s a problem and points you to where it is. Feedback

But the built-in testing afforded by the design of the language can only go so far. At some point, youmust step in and add the rest of the tests that produce a full suite(in cooperation with the compiler and run-time system) that verifiesall of your program. And, just like having a compiler watching overyour shoulder, wouldn’t you want these tests helping you right from thebeginning? That’s why you write them first, and run them automaticallywith every build of your system. Your tests become an extension of thesafety net provided by the language. Feedback

One of the things that I’ve discovered aboutthe use of more and more powerful programming languages is that I amemboldened to try more brazen experiments, because I know that thelanguage will keep me from wasting my time chasing bugs. The XP testscheme does the same thing for your entire project. Because you knowyour tests will always catch any problems that you introduce (and youregularly add any new tests as you think of them), you can make bigchanges when you need to without worrying that you’ll throw the wholeproject into complete disarray. This is incredibly powerful. Feedback

In this third edition of this book, I realizedthat testing was so important that it must also be applied to theexamples in the book itself. With the help of the Crested Butte Summer2002 Interns, we developed the testing system that you will see usedthroughout this book. The code and description is in Chapter 15. Thissystem has increased the robustness of the code examples in this bookimmeasurably. Feedback


Pairprogramming

Pair programming goes against the ruggedindividualism that we’ve been indoctrinated into from the beginning,through school (where we succeed or fail on our own, and working withour neighbors is considered “cheating”), and media, especiallyHollywood movies in which the hero is usually fighting against mindlessconformity.[114]Programmers, too, are considered paragons of individuality—“cowboycoders,” as Larry Constantine likes to say. And yet XP, which is itselfbattling against conventional thinking, says that code should bewritten with two people per workstation. And that this should be donein an area with a group of workstations, without the barriers that thefacilities-design people are so fond of. In fact, Beck says that thefirst task of converting to XP is to arrive with screwdrivers and Allenwrenches and take apart everything that gets in the way.[115] (This will require a manager who can deflect the ire of the facilities department.) Feedback

The value of pair programming is that oneperson is actually doing the coding while the other is thinking aboutit. The thinker keeps the big picture in mind—not only the picture ofthe problem at hand, but the guidelines of XP. If two people areworking, it’s less likely that one of them will get away with saying,“I don’t want to write the tests first,” for example. And if the codergets stuck, they can swap places. If both of them get stuck, theirmusings may be overheard by someone else in the work area who cancontribute. Working in pairs keeps things flowing and on track.Probably more important, it makes programming a lot more social andfun. Feedback

I’ve begun using pair programming during theexercise periods in some of my seminars, and it seems to significantlyimprove everyone’s experience. Feedback

Strategiesfor transition

If you buy into OOP,your next question is probably, “How can I get mymanager/colleagues/department/peers to start using objects?” Thinkabout how you—one independent programmer—would go about learning to usea new language and a new programming paradigm. You’ve done it before.First comes education and examples; then comes a trial project to giveyou a feel for the basics without doing anything too confusing. Thencomes a “real world” project that actually does something useful.Throughout your first projects you continue your education by reading,asking questions of experts, and trading hints with friends. This isthe approach many experienced programmers suggest for the switch toJava. Switching an entire company will of course introduce certaingroup dynamics, but it will help at each step to remember how oneperson would do it. Feedback

Guidelines

Here are some guidelines to consider when making the transition to OOP and Java: Feedback

1. Training

The first step is someform of education. Remember the company’s investment in code, and trynot to throw everything into disarray for six to nine months whileeveryone puzzles over unfamiliar features. Pick a small group forindoctrination, preferably one composed of people who are curious, workwell together, and can function as their own support network whilethey’re learning Java. Feedback

An alternative approach is the education of allcompany levels at once, including overview courses for strategicmanagers as well as design and programming courses for projectbuilders. This is especially good for smaller companies makingfundamental shifts in the way they do things, or at the division levelof larger companies. Because the cost is higher, however, some maychoose to start with project-level training, do a pilot project(possibly with an outside mentor), and let the project team become theteachers for the rest of the company. Feedback

2. Low-risk project

Try a low-risk project first and allow formistakes. Once you’ve gained some experience, you can either seed otherprojects from members of this first team or use the team members as anOOP technical support staff. This first project may not work right thefirst time, so it should not be mission-critical for the company. Itshould be simple, self-contained, and instructive; this means that itshould involve creating classes that will be meaningful to the otherprogrammers in the company when they get their turn to learn Java. Feedback

3. Model from success

Seek out examples of good object-orienteddesign before starting from scratch. There’s a good probability thatsomeone has solved your problem already, and if they haven’t solved itexactly you can probably apply what you’ve learned about abstraction tomodify an existing design to fit your needs. This is the generalconcept of design patterns, covered in Thinking in Patterns (with Java) at www.BruceEckel.com. Feedback

4.Use existing class libraries

An important economicmotivation for switching to OOP is the easy use of existing code in theform of class libraries (in particular, the Standard Java libraries,which are covered throughout this book). The shortest applicationdevelopment cycle will result when you can create and use objects fromoff-the-shelf libraries. However, some new programmers don’t understandthis, are unaware of existing class libraries, or, through fascinationwith the language, desire to write classes that may already exist. Yoursuccess with OOP and Java will be optimized if you make an effort toseek out and reuse other people’s code early in the transition process.Feedback

5. Don’t rewrite existing code in Java

It is not usually the best use of your time totake existing, functional code and rewrite it in Java. If you must turnit into objects, you can interface to the C or C++ code using the JavaNative Interface or Extensible Markup Language (XML). There areincremental benefits, especially if the code is slated for reuse. Butchances are you aren’t going to see the dramatic increases inproductivity that you hope for in your first few projects unless thatproject is a new one. Java and OOP shine best when taking a projectfrom concept to reality. Feedback


Managementobstacles

If you’re a manager, your job is to acquireresources for your team, to overcome barriers to your team’s success,and in general to try to provide the most productive and enjoyableenvironment so your team is most likely to perform those miracles thatare always being asked of you. Moving to Java falls in all three ofthese categories, and it would be wonderful if it didn’t cost youanything as well. Although moving to Java may be cheaper—depending onyour constraints—than the OOP alternatives for a team of C programmers(and probably for programmers in other procedural languages), it isn’tfree, and there are obstacles you should be aware of before trying tosell the move to Java within your company and embarking on the moveitself. Feedback


Startupcosts

The cost of moving to Java is more than justthe acquisition of Java compilers (the Sun Java compiler is free, sothis is hardly an obstacle). Your medium- and long-term costs will beminimized if you invest in training (and possibly mentoring for yourfirst project) and also if you identify and purchase class librariesthat solve your problem rather than trying to build those librariesyourself. These are hard-money costs that must be factored into arealistic proposal. In addition, there are the hidden costs in loss ofproductivity while learning a new language and possibly a newprogramming environment. Training and mentoring can certainly minimizethese, but team members must overcome their own struggles to understandthe new technology. During this process they will make more mistakes(this is a feature, because acknowledged mistakes are the fastest pathto learning) and be less productive. Even then, with some types ofprogramming problems, the right classes, and the right developmentenvironment, it’s possible to be more productive while you’re learningJava (even considering that you’re making more mistakes and writingfewer lines of code per day) than if you’d stayed with C. Feedback

Performanceissues

A common question is,“Doesn’t OOP automatically make my programs a lot bigger and slower?”The answer is, “It depends.” The extra safety features in Java havetraditionally extracted a performance penalty over a language like C++.Technologies such as “hotspot” and compilation technologies haveimproved the speed significantly in most cases, and efforts continuetoward higher performance. Feedback

When your focus is on rapid prototyping, youcan throw together components as fast as possible while ignoringefficiency issues. If you’re using any third-party libraries, these areusually already optimized by their vendors; in any case it’s not anissue while you’re in rapid-development mode. When you have a systemthat you like, if it’s small and fast enough, then you’re done. If not,you begin tuning with a profiler, looking first for speedups that canbe done by rewriting small portions of code. If that doesn’t help, youlook for modifications that can be made in the underlyingimplementation so no code that uses a particular class needs to bechanged. Only if nothing else solves the problem do you need to changethe design. If performance is so critical in that portion of thedesign, it must be part of the primary design criteria. You have thebenefit of finding this out early using rapid development.

Chapter 15 introduces profilers, whichcan help you discover bottlenecks in your system so you can optimizethat portion of your code (with the hotspot technologies, Sun no longerrecommends using native methods for performance optimization).Optimization tools are also available. Feedback

Common design errors

When starting your team into OOP and Java,programmers will typically go through a series of common design errors.This often happens due to insufficient feedback from experts during thedesign and implementation of early projects, because no experts havebeen developed within the company, and because there may be resistanceto retaining consultants. It’s easy to feel that you understand OOP tooearly in the cycle and go off on a bad tangent. Something that’sobvious to someone experienced with the language may be a subject ofgreat internal debate for a novice. Much of this trauma can be skippedby using an experienced outside expert for training and mentoring. Feedback

Summary

This chapter was only intended to give youconcepts of OOP methodologies, and the kinds of issues you willencounter when moving your own company to OOP and Java. More aboutObject design can be learned at the MindView seminar “Designing Objectsand Systems” (see “Seminars” at www.MindView.net).


[102] An excellent example of this is UML Distilled, 2nd edition, by Martin Fowler (Addison-Wesley 2000), which reduces the sometimes-overwhelming UML process to a manageable subset.

[103]My rule of thumb for estimating such projects: If there’s more than onewild card, don’t even try to plan how long it’s going to take or howmuch it will cost until you’ve created a working prototype. There aretoo many degrees of freedom.

[104] An excellent resource for requirements analysis is Exploring Requirements: Quality Before Design, by Gause & Weinberg (Dorset House 1989).

[105] Thanks for help from James H Jarrett.

[106] More information on use cases can be found in Use Case Driven Object Modeling with UML by Rosenberg (Addison-Wesley 1999) . A good overview of user stories is found in Planning Extreme Programming, by Beck & Fowler (Addison-Wesley 2001).

[107]My personal take on this has changed lately. Doubling and adding 10percent will give you a reasonably accurate estimate (assuming thereare not too many wild-card factors), but you still have to work quitediligently to finish in that time. If you want time to really make itelegant and to enjoy yourself in the process, the correct multiplier ismore like three or four times, I believe. See PeopleWare, byDeMarco & Lister (Dorset House 1999) for studies of the effect ofschedule estimates on productivity and a debunking of “Parkinson’s Law.”

[108] Planning Extreme Programming (ibid.) has some valuable insights on planning and time estimation.

[109] For starters, I recommend the aforementioned UML Distilled, 2nd edition.

[110] Python (www.Python.org) is often used as “executable pseudocode.”

[111]“What can be done with fewer ... is done in vain with more ... the mindshould not multiply things without necessity.” William of Ockham,1290-1349.

[112] At least one aspect of evolution is covered in Martin Fowler’s book Refactoring: Improving the Design of Existing Code (Addison-Wesley 1999), which uses Java examples exclusively.

[113] This is something like “rapidprototyping,” in which you were supposed to build a quick-and-dirtyversion so that you could learn about the system, and then throw awayyour prototype and build it right. The trouble with rapid prototypingis that people didn’t throw away the prototype, but instead built uponit. Combined with the lack of structure in procedural programming, thisoften leads to messy systems that are expensive to maintain.

[114] Although this may be a more American perspective, the stories of Hollywood reach everywhere.

[115]Including (especially) the PA system. I once worked in a company thatinsisted on broadcasting every phone call that arrived for everyexecutive, and it constantly interrupted our productivity (but themanagers couldn’t begin to conceive of stifling such an importantservice as the PA). Finally, when no one was looking I started snippingspeaker wires.



Trackback: http://tb.donews.net/TrackBack.aspx?PostId=237381


[点击此处收藏本文]  发表于2005年01月12日 5:54 PM




正在读取评论……