Download presentation
Presentation is loading. Please wait.
Published byBuck Thornton Modified over 9 years ago
1
Object-oriented metrics Design decisions: Class Cohesion Open-Closed Single Responsibility Interface Segregation Dependency Inversion Liskov Substitution Law of Demeter Reused Abstractions
2
Class cohesion Class design should reduce the need to edit multiple classes when making changes to application logic. A fundamental goal of OO design is to place the –behaviour (methods) as close to the –data they operate on (attributes) as possible, so that changes are less likely to propagate across multiple classes
3
Class cohesion metrics Lack of Cohesion of Methods (LCoM) M #methods A attribute accessed by R(A) methods: LCoM = ((∑ R(A)-A) – M ) / (1- M)
4
Open-closed Once a class is tested and working, modifying its code can introduce new bugs. We avoid this by extending the class, leaving its code unchanged, to add new behaviour. Classes should be open to extension, but closed to modification
5
Open-closed metric Per successful check-in –classes extended and not modified / classes extended and/or modified
6
Single responsibility Changing code in a tested class can introduce new bugs. We seek to minimise the reasons why a class might need to change. The more different things a class does, the more reasons it might have to change.
7
Single responsibility metric Responsibility / class Responsibility := ?
8
Interface segregation If different clients depend on different methods of the same class, then a change to one method might require a recompile and redeployment of other clients who use different methods. Creating several client-specific interfaces, one for each type of client, with the methods that type of client requires, reduces this problem significantly.
9
Interface segregation If type T exposes N methods, and client C uses n of them, then T’s interface is n/N specific with respect to C. Average n/N for all clients of T
10
Dependency inversion Much of the duplication in code comes from client objects knowing about all sorts of specialised suppliers, that from the client’s perspective do similar things but in different ways. Polymorphism is a powerful mechanism that underpins OO design. It allows us to bind to an abstraction, and then we don’t need to know what concrete classes we are collaborating with. This makes it much easier to plug in new components with no need to change the client code.
11
Dependency inversion dependencies on abstractions / total dependencies
12
Liskov substitution principle Dynamic polymorphism is a pow erful mechanism that allows us to invert dependencies, reducing duplication and making change much easier. All OO design principles depend upon polymorphism, but we must ensure that any type can be substituted for any of its subtypes at run-time without having any adverse effect on the client. Subtypes must obey all of the rules that apply to their super-types, pre-conditions for calling methods, post- conditions of methods called, and invariants that always apply between method calls.
13
Frequently used OO metrics McCabe Efferent coupling Lack of Cohesion of Methods –Chidamber – Kemerer –Henderson-Sellers LOC # of attributes Inheritence level Nesting level
14
(weighted) McCabe Problem Without being given any additional information, how many execution paths could there be in the following code? String EvaluateSalaryAndReturnName( Employee e ) { if( e.Title() == "CEO" || e.Salary() > 100000 ) { cout << e.First() << " " << e.Last() << " is overpaid" << endl; } return e.First() + " " + e.Last(); } Answer: 23 (in just four lines of code!)
15
For the non-exceptional execution paths, the trick was to know C/C++'s short-circuit evaluation rule: 1. If e.Title() == "CEO" then the second part of the condition doesn't need to be be evaluated (e.g., e.Salary() will never get called), but the cout will be performed.[2] 2. If e.Title() != "CEO" but e.Salary() > 100000, both parts of the condition will be evaluated and the cout will be performed. 3. If e.Title() != "CEO" and e.Salary() <= 100000, the cout will not be performed. This leaves the exceptional execution paths: String EvaluateSalaryAndReturnName( Employee e ) ^*^ ^4^ 4. The argument is passed by value, which invokes the Employee copy constructor. This copy operation might throw. *. String's copy constructor might throw while copying the temporary return value into the caller's area. We'll ignore this one, however, since it happens outside this function (and it turns out that we have enough execution paths of our own to keep us busy anyway!). if( e.Title() == "CEO" || e.Salary() > 100000 ) ^5^ ^7^ ^6^ ^11^ ^8^ ^10^ ^9^
16
5. The Title() member function might itself throw, or it might return an object of class type by value, and that copy operation might throw. 6. To match a valid operator==, the string literal may need to be converted to a temporary object of class type (probably the same as e.Title()'s return type), and that construction of the temporary might throw. 7. If operator== is a programmer-supplied function, it might throw. 8. Similarly to #5, Salary() might itself throw, or it might return a temporary object and this construction operation might throw. 9. Similarly to #6, a temporary object may need to be constructed and this construction might throw. 10. Similarly to #7, this might be a programmer-provided function and therefore might throw. 11. Similarly to #7 and #10, this might be a programmer-provided function and therefore might throw (see note [2] again). cout << e.First() << " " << e.Last() << " is overpaid" << endl; 12-16. As documented in the draft standard, any of the five calls to operator<< might throw. 17-18. Similarly to #5, First() and/or Last() might throw, or each might return a temporary object and those construction operations might throw. return e.First() + " " + e.Last(); 19-20. Similarly to #5, First() and/or Last() might throw, or each might return a temporary object and those construction operations might throw. 21. Similarly to #6, a temporary object may need to be constructed and this construction might throw. 22-23. Similarly to #7, this might be a programmer-provided function and therefore might throw.
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.