DesignPatternsandRefactoring

上传人:gb****c 文档编号:243022491 上传时间:2024-09-14 格式:PPT 页数:43 大小:116KB
返回 下载 相关 举报
DesignPatternsandRefactoring_第1页
第1页 / 共43页
DesignPatternsandRefactoring_第2页
第2页 / 共43页
DesignPatternsandRefactoring_第3页
第3页 / 共43页
点击查看更多>>
资源描述
,Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,*,Design Patterns and Refactoring,History,A Pattern Language: Towns, Buildings, Construction,Christopher Alexander, 1977,The Timeless Way of Building,Christopher Alexander, 1979,Using Pattern Languages for Object-Oriented Programs,(a paper at the OOPSLA-87 conference), Ward Cunningham and Kent Beck, 1987,Design Patterns,Erich Gamma, Richard Helm, John Vlissides, and Ralph Johnson (known as the “Gang of Four”, or GoF), 1994,Refactoring: Improving the Design of Existing Code,Martin Fowler, 2000,2,Buzzwords,Design Patterns,describe the higher-level organization of solutions to common problems,UML,is a diagramming language designed for Object-Oriented programming,Design Patterns are always described in UML notation,Refactoring,is restructuring code in a series of small, semantics-preserving transformations (i.e. the code keeps working) in order to make the code easier to maintain and modify,Refactoring often modifies or introduces Design Patterns,Extreme Programming,is a form of,Agile Programming,that emphasizes refactoring,Unit testing,is testing classes in isolation,Unit testing is an essential component of Extreme Programming,Unit testing is supported by JUnit,3,Design Patterns,Design Patterns,describe the higher-level organization of solutions to common problems,Design Patterns are a current hot topic in O-O design,UML is always used for describing Design Patterns,Design Patterns are used to describe refactorings,4,UML,UML,stands for,U,nified,M,odeling,L,anguage,UML is a big, complicated diagramming language designed for Object-Oriented programming,UML comprises at least seven or eight different kinds of diagrams that can be used to describe:,the organization of a program,how a program executes,how a program is used,how a program is deployed over a network,and more,This talk will cover just a tiny bit of one kind of diagram, the,class diagram,5,UML class diagrams,Key:,+,means public visibility,#,means protected visibility,-,means private visibility,means default (package) visibility,static variables are underlined,Name of the class,Variables,optional,Methods,Card,cardId:int,-copy:boolean=false,constructor Card(int id),+isKind(desiredKind:int),+isSharable():boolean,+toString():String,Example:,6,UML relationships,A,B,Class Bextendsclass A,C,D,1.4,Class Ccontains 1 to 4 objectsof class D,Factory,Product,creates,Other kinds ofrelations,A,B,Class Bimplementsinterface A,7,Sample Design Patterns,There are a few dozen Design Patterns described in the GoF book,Ill only talk about a couple, to give some of the flavor of what they are all about,Ill try to use examples that are relevant to problems you have dealt with in this class (plus some Im particularly fond of),Im using UML diagrams in only a few examples, because they just take too much time to draw in PowerPoint,Specialized tools, such as Rational Rose, Together, and ArgoUML are much better for this,8,Problem: Uncertain delegation,Much of the point of polymorphism is that you can just send a message to an object, and the object does the right thing, depending on its type,However, if the object might be,null, you have to be careful not to send it any message,if (myObject != null) myObject.doSomething();,Examples:,You have an Ocean, represented by a sparse array containing a few Fish,You have a TrafficGrid, some of which contains Cars and Trucks,You want to send output to somewhere, possibly to /dev/null,If you do a lot with this object, you code can end up cluttered with tests for,null,9,Solution:,Null Object,Create another kind of object, a “null object,” representing the,absence,of any other kind of object,Example: An,Ocean,might contain,Inhabitant,s, where,Inhabitant,is subclassed by,BigFish,LittleFish,Algae, and,NothingButWater,This way, no location in the,Ocean,is,null,If,Inhabitant,contains a method,reproduce(), the subclass,NothingButWater,could implement this method with an empty method body,If appropriate, some methods of the null object could throw an Exception,Ideally, the superclass (,Inhabitant, in this example) should be abstract,10,Refactoring:,Introduce Null Object,The general idea is simple: Instead of having some variables (locations in the array) be,null, have them be “null objects”,However, this requires numerous changes in the code,Its,hazardous,to change working codeyou introduce bugs that it can take days to find,Refactoring is all about:,doing an operation like this in,small steps,having an,automated,set of unit tests, and,running unit tests,frequently, so that if an error occurs you can pinpoint it immediately,This approach makes refactoring much safer and protects against hard-to-find bugs,As a result, programmers are far more willing to refactor,11,Introduce Null Object,: In detail, I,Create a subclass of the source class to act as a null version of the class. Create an,isNull,operation on the source class and the null class. For the source class it should return false, for the null class it should return true.,You may find it useful to create an explicitly,nullable,interface for the,isNull,method.,As an alternative you can use a testing interface to test for,nullness,Compile.,Find all places that can give out a,null,when asked for a source object. Replace them to give out a null object instead.,12,Introduce Null Object,: In detail, II,Find all places that compare a variable of the source type with null and replace them with a call to,isNull,.,You may be able to do this by replacing one source and its clients at a time and compiling and testing between working on sources.,A few assertions that check for,null,in places where you should no longer see it can be useful.,Compile and test.,Look for cases in which clients invoke an operation if not null and do some alternative behavior if null.,For each of these cases override the operation in the null class with the alternative behavior.,Remove the condition check for those that use the overridden behavior, compile, and test.,13,Refactoring details,The details of,Introduce Null Object,were copied directly from Fowler, pages 261-262,I am,not,going into this much detail in any of the remaining examples,Notice, however, that with this list of “baby steps” in front of you, you can do the refactoring a little at a time, with well-marked places to do testing, so that its very easy to catch and correct errors,Note also that to do this, you need a good set of,totally automated tests,otherwise the testing you have to do is just too much work, and you wont do it,Unless, that is, you have a superhuman amount of discipline,JUnit,(now built in to BlueJ) is a great start,14,Scenario: Big fish and little fish,The scenario: “big fish” and “little fish” move around in an “ocean”,Fish move about randomly,A big fish can move to where a little fish is (and eat it),A little fish will,not,move to where a big fish is,BigFish,move(),Fish,move(),LittleFish,move(),15,Problem: Similar methods in subclasses,Here we have a,Fish,class with two subclasses,BigFish,and,LittleFish,The two kinds move the same way,To avoid code duplication, the,move,method ought to be in the superclass,Fish,However, a,LittleFish,wont move to some locations where a,BigFish,will move,The test for whether it is OK to move really ought to be in the,move,method,More generally, you want to have,almost,the same method in two or more sibling classes,16,Solution:,Template method,Note: The Design Pattern is called “Template Method”; the refactoring is called “Form Template Method”,We wont bother making this distinction in the remainder of the lecture,In the superclass, write the common method, but call an auxiliary method (such as,okToMove,) to perform the part of the logic that needs to differ,Write the auxiliary method as an,abstract,method,This in turn requires that the superclass be,abstract,In each subclass, implement the auxiliary method according to the needs of that subclass,When a subclass instance executes the common method, it will use its own auxiliary method as needed,17,The,move(),method,General outline of the method:,public void move() ,choose a random direction;,/ same for both,find the location in that direction;,/ same for both,check if its ok to move there;,/ different,if its ok, make the move;,/ same for both,To refactor:,Extract the check on whether its ok to move,In the,Fish,class, put the actual (template),move(),method,Create an abstract,okToMove(),method in the Fish class,Implement,okToMove(),in each subclass,18,The,Fish,refactoring,BigFish,move(),Fish,move(),LittleFish,move(),BigFish,okToMove(locn):boolean,Fish,move(),okToMove(locn):boolean,BigFish,okToMove(locn):boolean,Note how this works: When a,BigFish,tries to move, it uses the,move(),method in,Fish,But the,move(),method in,Fish,uses the,okToMove(locn),method in,BigFish,And similarly for,LittleFish,19,Problem: Constructors create objects,Constructors make objects.,Only,constructors can make objects. When you call a constructor of a class, you,will,get an instance of that class.,Sometimes you want more flexibility than that,You may want to guarantee that you can never have more than one object of a given class,You may want to create an object only if you dont already have an equivalent object,You may want to create an object without being sure exactly what,kind,of object you want,The key insight is that, although only constructors make objects, you dont have to call constructors,directly,you can call a,method,that calls the constructor for you,Several “creational” Design Patterns are based on this observation,20,Singleton,A Singleton is a class that can have only one instance,You may want just one instance of a null object, which you use in many places,You may want to create just one,AudioStream, so you can only play one tune at a time,class Singleton private static Singleton instance = new Singleton();,/ dont let Java give you a default public constructor,private Singleton() ,Singleton getInstance() return instance; .,21,The,Factory Method,Design Pattern,Suppose you write a class that works with several different kinds of objects,You can do this if the classes all have a common interface,You may want to be able to create objects, without being dependent on the kind of object,A factory methods can create instances of different classes, depending (say) on its parameters,Example:,Image createImage (String ext) if (ext.equals(gif) return new GIFImage(); if (ext.equals(jpg) return new JPEGImage(); .,22,Problem: Reducing interdependencies,Suppose you have an application that provides multiple services,Suppose further that the application consists of a large number of classes,You want to provide access to those services, without requiring the user to know all the internal details,For example, you have a simulation of an ocean, containing assorted kinds of fish, and you want to provide access to that simulation,Just to make the problem interesting, suppose that you have two or more such applications (say, Oracle, MySql, and Access 2000) and you want to write a program that works with any of them,Solution: Use the,Fa,ade,Design Pattern,23,The,Fa,ade,Design Pattern,Create a class that accepts many different kinds of requests, and “forwards” them to the appropriate internal class,If the back ends vary, you man need to write a separate Interface class for each (all implementing the same,interface,), but the users of your Facade class dont need to change,Example:,class Ocean public void setBigFishGestationPeriod(int period) BigFish.setGestationPeriod(period); public int getNumberOfAlgae() return Algae.getCount(); .,Of course, the Facade class can do other things as well,24,The,Immutable,Design Pattern,There are many benefits to objects that cannot be changed after they have been created,Such objects are called,immutable,Objects that refer to an immutable object never have to worry about whether that object has been changed,Immutable objects are thread-safethis is a significant efficiency concern, because synchronization is expensive,Example:,String,s in Java,Its,easy,to make immutable objects in Java:,Make all instance variables,private, and,Provide,no,methods that change those variables,25,Delegation,(or, when,not,to use inheritance),When you create a subclass, you agree to inherit all its (non-private) fields and methods,What if you dont want them all?,Example: A,Vector,can do everything that a,Stack,should be able to do, and much, much more,You may want to inherit just,some,of the functionality, and probably add some of your own,Inheritance doesnt let you do thatat least, not easily,If your class wants to hide variables or methods inherited from a superclass, it shouldnt inherit from that superclass,If an object needs to be a different subclass at different times (say, a,LittleFish,turning into a,BigFish,), then it shouldnt be a subclass of that class in the first place,Instead of inheriting, just,use,an instance of that class, and,delegate,to it,26,Example: Stacks,class Stack Vector contents = new Vector(); public void push(Object o) contents.add(o);,/ delegate to the Vector, public Object pop() return contents.remove(contents.size() 1); .,27,An example,Some time ago I was working on code to evalute expressions,Expressions can be parsed into a tree structure,Now what?,You could walk the tree and, at each node, use a switch statement to do the right thing,I “discovered” a better solution (basically, a simple form of the,Command,Design Pattern),+,2,*,5,x,Tree for,2 + 5 * x,Command,lhs:Command,rhs:Commandvalue:int,evaluate():int,0.2,28,Using my “,Command,” pattern,class Add extends Command int evaluate( ) int v1 = lhs.evaluate().value; int v2 = rhs.evaluate().value; value = v1 + v2; return value; ,To evaluate the entire tree, evaluate the root node,This is just a rough description; there are a lot of other details to consider,Some operands are unary,You have to look up the values of variables,Etc.,Command,lhs:Command,rhs:Commandvalue:int,evaluate():int,0.2,29,The,Command,Design Pattern,Reasons for using the Command Design Pattern:,You want to control,if,when,and,in what order,the commands are executed,You want to keep a log of commands executed,Popular reason: You want to manage,undo,and,redo,operations,Possible class organization (from GoF):,AbstractCommand,with,doIt(),and,undoIt(),methods,ConcreteCommand,subclasses of,AbstractCommand,Invoker,is a class that creates,ConcreteCommand,objects if it needs to invoke a command,CommandManager,to decide what, when, and how to execute and undo commands,30,Refactoring,Refactoring is:,restructuring (rearranging) code.,.in a series of small, semantics-preserving transformations (i.e. the code keeps working).,.in order to make the code easier to maintain and modify,Refactoring is,not,just any old restructuring,You need to keep the code working,You need small steps that preserve semantics,You need to have unit tests to prove the code works,There are numerous well-known refactoring techniques,You should be at least somewhat familiar with these before inventing your own,31,When to refactor,You should refactor:,Any time that you see a better way to do things,“Better” means making the code easier to understand and to modify in the future,You can do so without breaking the code,Unit tests are essential for this,You should,not,refactor:,Stable code (code that wont ever need to change),Someone elses code,Unless youve inherited it (and now its yours),32,Design vs. coding,“Design” is the process of determining, in detail, what the finished product will be and how it will be put together,“Coding” is following the plan,In traditional engineering (building bridges), design is perhaps 15% of the total effort,In software engineering, design is 85-90% of the total effort,By comparison, coding is cheap,33,The refactoring environment,Traditional software engineering is modeled after traditional engineering practices (= design first, then code),Assumptions:,The desired end product can be determined in advance,Workers of a given type (plumbers, electricians, etc.) are interchangeable,“Agile” software engineering is based on different assumptions:,Requirements (and therefore design) change as users become acquainted with the software,Programmers are professionals with varying skills and knowledge,Programmers are in the best position for making design decisions,Refactoring is fundamental to agile programming,Refactoring is sometimes necessary in a traditional process, when the design is found to be flawed,34,A personal view,In my opinion,Design, because it is a lot more creative than simple coding, is also a lot more fun,Admittedly, “more fun” is not necessarily “better”,.but it does help you retain good programmers,Most small to medium-sized projects could benefit from an agile programming approach,We dont yet know about large projects,Most programming methodologies attempt to turn everyone into a mediocre programmer,Sadly, this is probably an improvement in general,These methodologies work less well when you have some very good programmers,35,Back to refactoring,When should you refactor?,Any time you find that you can improve the design of existing code,You detect a “bad smell” (an indication that something is wrong) in the code,When,can,you refactor?,You should be in a supportive environment (agile programming team, or doing your own work),You should have an adequate set of automatic unit tests,36,Example 1:,switch,statements,switch,statements are very rare in properly designed object-oriented code,Therefore, a,switch,statement is a simple and easily detected “bad smell”,Of course, not all uses of,switch,are bad,A switch statement should,not,be used to distinguish between various kinds of object,There are several well-defined refactorings for this case,The simplest is the creation of subclasses,37,Example 1, continued,class Animal final int MAMMAL = 0, BIRD = 1, REPTILE = 2; int myKind;,/ set in constructor,. String getSkin() switch (myKind) case MAMMAL: return hair; case BIRD: return feathers; case REPTILE: return scales; default: return integument; ,38,Example 1, improved,class Animal String getSkin() return integument; class Mammal extends Animal String getSkin() return hair; class Bird extends Animal String getSkin() return feathers; class Reptile extends Animal String getSkin() return scales; ,39,How is this an improvement?,Adding a new animal type, such as,Amphibian, does not require revising and recompiling existing code,Mammals, birds, and reptiles are likely to differ in other ways, and weve already separated them out (so we wont need more,switch,statements),Weve gotten rid of the flags we needed to tell one kind of animal from another,Basically, were now using Objects the way they were meant to be used,40,JUnit tests,As we refactor, we need to run JUnit tests to ensure that we havent introduced errors,public void testGetSkin() assertEquals(hair, myMammal.getSkin();assertEquals(feathers, myBird.getSkin();assertEquals(scales, myReptile.getSkin();assertEquals(integument, myAnimal.getSkin();,This should work equally well with either im
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 大学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!