1 / 39

Patterns

Patterns. Intention revealing selector Naming based on side effects Double-dispatching method Accessing methods Query methods Boolean property setting Converter methods Constructors. Composed Method. How big should a method be? Write methods that perform one identifiable task.

Télécharger la présentation

Patterns

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Patterns

  2. Intention revealing selector • Naming based on side effects • Double-dispatching method • Accessing methods • Query methods • Boolean property setting • Converter methods • Constructors

  3. Composed Method • How big should a method be? • Write methods that perform one identifiable task. • Few lines per method. • Consistent level of abstraction. • Minimizes number of methods you have to change in subclass. • Minimizes code copying in subclass.

  4. Composed Method Usage • Top down • - self input; process; output • Bottom up • - common expressions • - long loop bodies • - comments • From client - two or more messages to another object is suspicious

  5. Methods from Comments • Comments indicate "identifiable task" • If you need to comment a block of code, it probably should be a separate method. • Turn method comment into method name.

  6. Reversing Method • Good code has a rhythm that makes it easy to understand. Code that breaks the rhythm is harder to read and understand. • Point • printOn: aStream • x printOn: aStream. • aStream nextPutAll: ‘ @’. • y printOn: aStream

  7. Reversing method • Point • printOn: aStream • aStream • print: x; • nextPutAll: ‘ @’; • print: y

  8. Reversing method • Make a method on the parameter. • Derive its name from the original message. • Take the original receiver as a parameter. • Implement the method by sending the original message to the original receiver.

  9. Method object • What do you do about a method that is too big but that can’t be decomposed because of all the temporary variables that are used? • Turn method into a class. Temporary variables and arguments become instance variables. Then you can decompose the method.

  10. Example of Method Object • In class Class • readNewSubclassOn: aCodeReader in: aNameSpace • | fullName numInstVars numMetaInstVars • metaclassFormat allMetaclassInstVars metaclassInstVars classFormat allClassInstVars classInstVars newMeta class bookkeepingInfoStart bookkeepingInfoSize | • fullName := aCodeReader readByteSymbol.

  11. aCodeReader fileFormat >= 10 • ifTrue: • [metaclassFormat := aCodeReader readLong. • numMetaInstVars := aCodeReader readLong. • allMetaclassInstVars := aCodeReader readByteStringCollection. • metaclassInstVars := allMetaclassInstVars • copyFrom: allMetaclassInstVars size - numMetaInstVars + 1 • to: allMetaclassInstVars size. • classFormat := aCodeReader readLong. • numInstVars := aCodeReader readLong. • allClassInstVars := aCodeReader readByteStringCollection. • classInstVars := allClassInstVars copyFrom: allClassInstVars size - numInstVars + 1 to: allClassInstVars size] • ifFalse: • [metaclassFormat := aCodeReader readLong. • metaclassInstVars := aCodeReader readByteStringCollection. • numMetaInstVars := metaclassInstVars size. • classFormat := aCodeReader readLong. • classInstVars := aCodeReader readByteStringCollection. • numInstVars := classInstVars size].

  12. Make class NewSubclassReader, a subclass of Object. • Make instance variables for arguments, receiver, and temporaries: aCodeReader aNameSpace superclass fullName numInstVars numMetaInstVars metaclassFormat allMetaclassInstVars metaclassInstVars classFormat allClassInstVars classInstVars newMeta class

  13. readNewSubclassOn: aCodeReader in: aNameSpace • (NewSubclassReader on: aCodeReader in: aNameSpace) readNewSubclass

  14. readNewSubclass • self initializeClassInformation. • self makeNewMetaclass. • self makeNewClass. • self isNewClassIncompatibleWithSuperclass ifTrue: • [CodeReader invalidClassFormatSignal • raiseWith: fullName • errorString: ' : ', fullName]. • self checkShapeChange. • self readSubclassInfoFromCodeReader. • ^class

  15. Extract method • Turn an expression into a method of its own • References to arguments or temporaries turn into arguments of new method. • References to instance variables don’t change • ^ in the expression can be a problem

  16. Execute Around Method • Pairs of actions that must be taken together • Open file / close file • Start tag / end tag • aCursor showWhile: [ … ] • aFile openDuring: [ aThing printOn: aFile]

  17. Simple Superclass Name • What should we call the root of a hierarchy? • Complex name conveys full meaning. • Simple name is easy to say, type, extend. • But need to show that subclasses are related.

  18. Simple Superclass Name • Give superclasses simple names: two or (preferably) one word • - Number • - Collection • - VisualComponent

  19. Qualified Subclass Name • What should you call a subclass that plays a role similar to its superclass? • Unique name conveys most information • Derived name communicates relationship to superclass

  20. Qualified Subclass Name • Use names with obvious meaning. Otherwise, prepend an adjective to most important superclass. • - OrderedCollection • - UndefinedObject • - CloneFigureCommand, CompositeCommand, ConnectionCommand

  21. Variables: Roles vs. Types • Types are specified by classes • aRectangle • aCollection • aView • Roles - how an object is used • location • employees • topView

  22. Role Suggesting Instance Variable • What should you name an instance variable? • Type is important for understanding implementation. But class comment can describe type. • Role communicates intent, and this is harder to understand than type.

  23. Role Suggesting Instance Variable • Name instance variables for the role they play. Make the name plural if the variable is a collection. • Point: x, y • Interval: start, stop, step • Polyline: vertices

  24. Type Suggesting Parameter Name • Name of variable can either communicate type or role. • Keywords communicate their parameter's role, so name of variable should give new information.

  25. Type Suggesting Parameter Name • Name parameters according to their most general expected class, preceded by "a" or "an". If there is more than one parameter with the same expected class, precede the class with a descriptive word.

  26. Temporaries • Name temporaries after role they play. • Use temporaries to: • collect intermediate results • reuse result of an expression • name result of an expression • Methods are simpler when they don't use temporaries!

  27. Class Comments • Every class should have a comment that describes the purpose of the class and the types of its instance variables

  28. Method comments • Name of method should describe what it does. • Name of arguments should describe what they are. • Name of method should describe return type. • Method comment should describe anything else that isn’t obvious.

  29. Common State • Different instances of a class have different values for some state. How do you represent it? • Declare an instance variable in the class. • Name the variable using Role Suggesting Instance Variable Name. Initialize it with either Lazy Initialization, Explicit Initialization, or a Constructor Parameter Method.

  30. Explicit Initialization • How do you initialize instance variables to their default value? • Make the code readable instead of changeable. • Implement a method “initialize” that sets all the values. Override the class method “new” to invoke it on new instances.

  31. Lazy Initialization • How do you initialize instance variables to their default value? • Emphasize ease of change. • Force all accesses to variable to go through accessing method. Make Getting method check whether the variable has been initialized and initialize it if necessary.

  32. Lazy Initialization • Timer>>count • count isNil • ifTrue: [count := self defaultCount] • ^count

  33. Default Value Method • How do you represent the default value of a variable? • Create a method that returns the value. Prepend “default” to the name of the variable as the name of the method.

  34. Constant Method • How do you code a constant? • Create a method that returns the constant.

  35. How do you get and set an instance variable’s value? • Direct Variable Access: Access and set the variable directly. • Indirect Variable Access: Use a Getting Method and a Setting Method

  36. Collection Accessor Method • How do you provide access to an instance variable that holds a collection? • Provide methods that delegate to the collection. To name the methods, add the name of the collection to the collection name. • addEmployee: • includesEmployee:

  37. Enumeration Method • How do you provide access to collection elements? • Implement a method that executes a Block for each element of the collection. Name the method by concatenating the name of the collection and “Do:” • employeesDo:

  38. How to make a good program • Make it run the test cases • Make it easy to understand, simple, follow coding standards, and eliminate duplication. • It is OK to get the tests to run first, and then worry about making your program readable. • It is OK to make sure your program is always readable.

  39. How to make a good program • It is not OK to hand in programs that are hard to understand, that don’t follow standard patterns, and that have a lot of duplication.

More Related