440 likes | 563 Views
Class and Method Design. MSO 08/09, Chapter 10, WP. Positioning. Why are we talking about “class” and “method” design? Is this course is not supposed to be about “system” ?. (Dennis et al, Wiley).
E N D
Class and Method Design MSO 08/09, Chapter 10, WP
Positioning Why are we talking about “class” and “method” design? Is this course is not supposed to be about “system” ? (Dennis et al, Wiley) Because in the end we have to build our classes and methods, and they represent lots of work, of which we again has “design” issue.
Objectives of chapter 10, learning to: • write designs • write specifications. • aware of some design* criteria Implementation Design Certain issues in Ch. 10 are actually closer to implementation than design! So our scope will also extend a bit to implementation.
Keep an objective perspective.... (Wikipedia) • Overall Dennis et al tend to lean towards “waterfall” SDLC heavy emphasis on well documented designs. • Keep in mind that we also have the “agile” model. (Dennis et al, Wiley)
Some relevant statements from Agile However, too much documentation is worse than too little. Huge software documents take a great deal of time to produce, and even more time to keep in sync with the code. If they are not kept in sync, then ... become a significant source of misdirection. (Robert C. Martin, Agile Processes, 2001) Software cannot be ordered like a commodity. You cannot write a description of the software you want and then have someone develop it on a fixed schedule for a fixed price. Time and time again, attempts to treat software projects in this manner have failed. (Robert C. Martin, Agile Processes, 2001) But knowing nothing about well documented designs would be too naive either! So we proceed with Dennis et al; on the field you will have to use your own judgment as to whether to use Waterfall or Agile, or a mix of both.
How will we proceed ? • We’ll use the book’s example: Internet CD shop • Using this example we’ll go through the design steps. • We'll discuss some design/development criteria • And some other issues like dynamic binding.
Internet CD Shop, excerpt from ‘system request’ • System Request: Internet Shop • Project sponsor: Margaret Mooney, VP of Marketing • Business Requirement: • ... The provided functionalities : • Search through our CDs inventory • Identify the retail stores that have a given CD product • Schedule product pickup from a store • Place an order if product is not in stock • ... • Business Value: • ... 750.000 $ yearly increase in sales.
Designing a class and method • Dennis et al: • Add more specifications • When needed iteratively optimize and restructure your design • Map design to an implementation language • For a class: • attributes and operations • types and visibility • constraints
Class CD CD -------------- +CD Number +CD Name +Pub Date +Artist Name +Artist Number +Vendor /Vendor ID -------------- Package CD
Dennis’ CRC card of the class CD Class name : CD Description : represents a CD Responsibilities : Collaborators : Order Item, CD List, Vendor, Mkt Info Constraint Duplicated information , hopefully you have a CASE tool to maintain consistency.
Constraints CD Vendor < distributes 0..* 1..1 CD -------------- +CD Number +CD Name ... +Vendor +VendorID -------------- { CD Vendor.distributes } { VendorID = Vendor.ID }
Constraints SubTotal =Sum(ProductOrder.Qty * ProductOrder.Product.Price) • pre-conditions and post-conditions (for methods) • (class) invariants Tax = State.GetTaxRate() * SubTotal
Object Constraint Language (OCL) • Formal. You may want to take a look at it. • Now part of UML standard. • Examples: CD -------- Vendor VendorID Vendor < distributes 0..* 1..1 context CDinvself.Vendor.distributesincludes(self) context CDinvself.VendorID = self.Vendor.ID
Basic OCL • Class invariant:context<class name> inv : <boolean expression> • Specifying pre/post-condition of an operation:context<class name>::<operation name>(<parameters>) : <return type>pre: <boolean expression>post: <boolean expression> • Logical operators like “and”, “or”, “implies” etc to form your boolean expression.
Basic OCL • “self” refers to an object of the described class; can be omitted if unambiguous. • Referring to an attribute of an object: <object expression> . <attribute> • Calling an operation of an object: <object expression> . <operation> ( <parameters> ) • Navigating through relations: <object expression> . <your own side of relation> <object expression> . <partner’s role>
Basic OCL • OCL provides several concepts of collections: Set, Bag, Seq • Navigation through a relation • by default results in a Set of objects • but a single object if the relation maps to 1..1 multiplicity • a whole bunch of standard “properties” on collections: size, includes, forall, ...Usage: <collection expression> –> <collection property>
Method Contract Primarily is used to specify the pre- and post-conditions of a method. Method name : GetReview(int k) Class Name : Mkt Info Clients : CDAssociated Use Cases : AskCDInformation Responsibilities: returning the latest k reviews about this CD Arguments received: obvious Type of value returned: list of Reviews Pre-condition: 0k<10 Post-condition: returned list contains at most k elements.
Method specification • In Dennis et all it contains lots of information (Fig. 10-14) e.g. • types of the arguments and return val. • events that trigger the method • list of other methods called from within the specified method • explanation on the used algorithm • Many would call Dennis’ “contract” as “specification”. We can just as well do this in the “contract” I’m not sure if we should really document this kind of details in a design. I would document this in the implementation.
Method contract in OCL MktInfo ------------ ------------ getReview Review reviewedBy > 1..1 0..* contextMktInfo :: GetReview(int k) : Seq(Review) pre : 0k<10 post : result size() k and result forall( r | self.reviewedBy include(r) )
Quiz : express these “business rules” VIP : boolean Top100 0..1 promotedBy > < listedBy 0..* • Top100 only has 1 instance! • Every CD listed in top-100 should have a sample clip. • A VIP vendor must distribute all CDs in top 100. has >
So, is our design good !? • Coad & Yourdon: “a good design is one that balances trade-offs to minimize the total cost of the system over its entire lifetime”. • Dennis et al suggest these as design criteria : cohesion, coupling, connascence • These are concepts from software quality metrics • You can't measure them without having an implementation • We should be aware of them as we develop
Cohesion • is the extent to which the elements of a 'module' are related to one another. • Originally by Stevens, Myers, Constantine, 1974! • High cohesion (good): if all methods of the class CD are related to a single purpose. • Cohesion is lower when CD provides • a set of methods to inspect a CD • a set of utility methods to format reviews • Very low if ... • Difficult to measure with an automated tool...
Coupling • Also originally by Stevens, Myers, Constantine, 1974. • The coupling between two modules is the manner and degree of interdependence between them [IEEE]. • E.g. the coupling is high (bad) if changing the internal implementation of A may impact B will increase your maintenance cost ! • Otherwise the coupling is low (good)
Coupling types between module A and B • Some of the traditional notions of coupling, from low to high: • no coupling • data coupling • stamp coupling • control coupling • global coupling • content coupling
Coupling (explained at the "procedures" level) • Data coupling : A,B interact by passing 'elementary' data.E.g. between min and max here: min(int x, int y) { if x<max(x,y) return x else y } • Stamp coupling: A,B interact by passing composite data, each using only part of them.E.g. between discount and notify discount(CD x) { x.price = x.price – 10 ; notify(x.vendor, x) }
Coupling • control coupling: in the interactions between A and B, one passes parameters that alter the algorithm of the other.E.g. : getBestReview() { ... z = getReview(1) ... } getReview(int k) { if (k == -1) then ... // return all reviews else if (k > 0) then ... // return k-th review else ... // return empty list }
Coupling • Common/global coupling: interactions between A and B use global variables (rather than purely using parameters). • Content coupling: if A requires access to B's internal information.In most modern languages, content coupling is not even possible.
Declaration coupling [Binkley & Schach, 98] • If module A uses something declared in module B. • A refers to an attribute in B • A calls a method of B • A inherits a member from B • A has an attribute of type B • A has a method with a parameter of type B • ... • Very broad definition, but still useful
So, what can we do with these ? • We can scan our software and calculates e.g. • The overall decl. coupling • Decl. coupling per package • But this is so trivial! Well, keep in mind that real software have hundreds of classes. Strategic information like this can be a valuable instrument as you try to steer your development and maintenance processes.
Law of Demeter • Coming from a design guideline for developing OO software in 1987 reduce coupling. Make it so that each object only talk with its friends. CD MktInf Review 1..* x : CD r : Review m : MktInf getAReview() we get a Review “r” here getOtherReviews() Returning all reviews by written by r.author
Law of Demeter • More concretely, inside a method m(x,y) in a class C we should only calls: • methods of self/this • methods of objects in the attributes/relations of self/this • methods of x and y • methods of objects created in m • E.g. this would be considered bad : class CD { ...getRelatedReviews() { return promotedBy.getAReview().getOtherReviews } ...
Law of Demeter • Advantage: the resulting software tends to be more maintainable and adaptable. • Experimental results in 1996 by Basili et al suggests that Law of Demeter reduces the probability of software fault. • Critics: classes may become excessively cluttered with wrapper methods • negatively impact maintenance. • decrease cohesiveness
Mapping Design to Implementation Lang. • The choice of impl. lang. can be imposed by your business setup • Several possible scenarios: • OO lang. with multiple inheritance watch out for inheritance conflict. • OO lang. with single inheritance have to factor out M-Inh in your design. • Non OO lang mapping would be too complicate.
Multiple inheritance language • C++, Eiffel, Python ... • To watch out inheritance conflict • Two inherited members have different names but same semantic. • Two inherited members have same name but different semantics Plant ------------- show() pour() Drink -------------- pour() Coffee
Factoring out Mult. Inheritance • Java is single inheritance • Java "Interface" is not really a superclass :as in: class Coffee extends Drink implements Plant { ... } • In "Plant" we can't have fields nor method bodies, thus we can't let Coffee inherit them either. Plant ------------- LatinName------------- show() Drink -------------- pour() Coffee
Simulate MI with delegation Plant ------------- LatinName------------- show() • But: the compiler won't see that a Coffee can also be seen as a Plant. • You have to manually initialize with the right plant. • You have to explicitly add Plant's members to Coffee. Drink -------------- pour() public class Coffee extends Drink { ... private Plant p = ... ; public show() { return p.show() ; } public getLatinName() { return p.LatinName ; }} Coffee
Other solution: Abstract Coupling • Drink and Plant are now Interfaces • Additionally we have classes DrinkImp and PlantImp as the actual implementation of Drink and Plant. • Let Coffee implements both interfaces • Add (in Coffee) delegations to DrinkImp and PlantImp
MI via Abstract Coupling interface Plant { show() } class PlantImp implements Plant { String LatinName ; String show() { ... } ; ...} class Coffee implements Drink, Plant { ... private ImpDrink d = ... ; private ImpPlant p = ... ; show() { return p.show() ; } pour() { return d.pour() ; }getLatinName() { return p.LatinName ; } ...}
Few other issues to mention • Overriding method • Polymorphism
Overiding class Drink { ... pour() // pour the drink into a cup } class Coffee extends Drink { ...} pour is not overriden. pour() // pour the coffee into a coffee cup pour() // pour water into Senseo machine
Polymorphism • Literally: ability to take multiple shapes. • In programming it is a feature allowing values of different types to be handled uniformly. • In FP:a program that can handle a list of any type. • In Java:a program that can handle any Plant, or any instance from its subclasses. head :: [a]Int class Plant { ... show() { ... } }
Dynamic Binding • Because you can override, polymorphism in Java leads to this issue: So, which method is called here? class Application { helper(Plant p) { ... ; return p.show() } main(args) { if (args.length > 0) helper(new Plant()) : else helper(new Coffee()) ; ... } } This is only known at the runtime dynamic binding. Threat : semantic inconsistency.