+ All Categories
Home > Documents > Chapters 1 and 26 General Introduction

Chapters 1 and 26 General Introduction

Date post: 23-Feb-2016
Category:
Upload: archer
View: 75 times
Download: 0 times
Share this document with a friend
Description:
Chapters 1 and 26 General Introduction. Summary prepared by Kirk Scott. This general introduction covers two chapters in the book: Chapter 1: Introduction Chapter 26: Introducing Extensions. Chapter 1 covers general information about the contents and organization of the book - PowerPoint PPT Presentation
Popular Tags:
111
Chapters 1 and 26 General Introduction Summary prepared by Kirk Scott 1
Transcript
Page 1: Chapters 1 and 26 General Introduction

1

Chapters 1 and 26General Introduction

Summary prepared by Kirk Scott

Page 2: Chapters 1 and 26 General Introduction

2

• This general introduction covers two chapters in the book:

• Chapter 1: Introduction• Chapter 26: Introducing Extensions

Page 3: Chapters 1 and 26 General Introduction

3

• Chapter 1 covers general information about the contents and organization of the book

• In addition to mentioning this, I outline the organization of the course, which differs from the book

• Chapter 26 talks about over-arching object-oriented design principles which will be exemplified by the patterns that will be covered

Page 4: Chapters 1 and 26 General Introduction

4

Design Patterns in JavaChapter 1

Introduction

Summary prepared by Kirk Scott

Page 5: Chapters 1 and 26 General Introduction

5

Intended Audience, Coverage, etc.

• The classic book, Design Patterns, was written by Gamma, Helm, Johnson, and Vlissides

• This book covers the same set of 23 patterns• The book is intended for software

programmers/developers who know Java and want to improve their skills as designers

Page 6: Chapters 1 and 26 General Introduction

6

What is a Pattern?

• A pattern is a way of doing something• It can be thought of as a technique for

accomplishing some goal• This book dwells on the intent of patterns as

an organizing characteristic• The chapters have been reorganized for the

purposes of this course to emphasize common structure rather than common intent

Page 7: Chapters 1 and 26 General Introduction

7

Where do Patterns Come From?

• Software development is repetitive: Quite often, different programmers have to solve the same problem

• Experienced programmers have compared notes and discovered that they arrived at common solutions to the same problem

• Over time, these common solutions have been documented as the best known approach to solving a given problem

Page 8: Chapters 1 and 26 General Introduction

8

Why Design Patterns?

• Observe that in school, you learn to program first and learn about design later

• When you compare your solution to a problem with someone else’s solution, you may realize that the other solution is simpler, more efficient, or more desirable in some other way

• In practice, it is helpful to have knowledge of design before trying to code a solution to a problem

Page 9: Chapters 1 and 26 General Introduction

9

Why Design Patterns? Cont’d.

• Design patterns are one step up from straight code writing

• They represent recognized software solutions in terms of (small) collections of classes related in a certain way and containing certain sets of methods

• It is important to keep in mind that the implementation is not the pattern—a pattern is the abstract design which embodies the intent

Page 10: Chapters 1 and 26 General Introduction

10

Why Design Patterns? Cont’d.

• Design patterns have been developed most extensively in the object-oriented realm

• The authors point out that there are currently over 100 documented design patterns

• The 23 covered in the book have been chosen for historic reasons

• They are certainly worth knowing, whether they are absolutely the most important

Page 11: Chapters 1 and 26 General Introduction

11

Why Design Patterns? Cont’d.

• In particular, whether the most important or not, the 23 chosen patterns provide a broad introduction to and illustration of what patterns are and what they’re good for

• The authors assert that if a person wants to become a good Java programmer, it is necessary to study design patterns

• Design patterns are the first step out of the swamp of syntax that an introduction to programming is

Page 12: Chapters 1 and 26 General Introduction

12

Why Java?

• Java is a consolidation language• This means that it is a kitchen sink language in the

footsteps of C and C++, and for this reason, if no other, it is popular

• Object-oriented programming is based on classes and instances, and this paradigm is currently the most popular approach to implementing graphical user interfaces, for example

• Java’s characteristics make it likely that future popular languages will follow in Java’s footsteps

Page 13: Chapters 1 and 26 General Introduction

13

UML

• Implementations of patterns are done in code• However, the pattern itself consists of the

relationships among classes and so on• UML is one of several notations for diagramming

object-oriented designs• It is probably the most popular one currently• The point is that some abstract representation of

patterns is desirable, rather than appealing always to the code of a particular implementation

Page 14: Chapters 1 and 26 General Introduction

14

Challenges

• The book contains questions• These may be short answer questions• They may also be programming questions based

on the book’s example code• This course will not give these challenges as

assignments• Instead, the challenges and the authors’ solutions

will be examined to see what can be gained from them

Page 15: Chapters 1 and 26 General Introduction

15

The Organization of the Book

• This book organizes the patterns according to the intent which the authors ascribe to them

• This raises the question of how to classify intent• The authors suggest that categories of patterns

can be recognized according to how the patterns make it possible to go beyond the basic characteristics built into the structure of Java

Page 16: Chapters 1 and 26 General Introduction

16

The Organization of This Book, cont’d.

• The authors use as an initial example the idea of interfaces

• Suppose you have a class/method which requires an object of a class which implements a given interface

• Suppose you have an object of a class which does not implement the required interface

• Is there a way of applying the method defined in the interface to an object of a class that doesn’t implement the interface?

Page 17: Chapters 1 and 26 General Introduction

17

The Organization of This Book, cont’d.

• The obvious answer is to rewrite the class to implement the interface

• If that is not possible, there is an alternative• There is a design pattern known as the Adapter pattern

(not to be confused with adapter classes in Java) which accomplishes this goal

• The Adapter pattern, and others with similar intents, are classified in an intent category known as Interfaces

• In the authors’ scheme, all of these patterns belong together

Page 18: Chapters 1 and 26 General Introduction

18

The Organization of This Book, cont’d.

• The book classifies patterns into these five categories based on intent:– Interfaces– Responsibility– Construction– Operations– Extensions

Page 19: Chapters 1 and 26 General Introduction

19

The Organization of This Book, cont’d.

• The book, as a consequence is organized in the same way

• The authors admit that various patterns may fit more than one category

• In such cases, the pattern is given in detail in the first category where it fits, and is mentioned briefly in subsequent sections

• The classification of patterns is not an absolute, but some classification is useful and necessary, and is a starting point for suggesting alternative classifications

Page 20: Chapters 1 and 26 General Introduction

20

The Organization of This Book, cont’d.

• What follows is a complete preview of the contents of the book

• Intent Category: Interfaces. • Patterns: Adapter, Façade, Composite, Bridge• Intent Category: Responsibility. • Patterns: Singleton, Observer, Mediator,

Proxy, Chain of Responsibility, Flyweight

Page 21: Chapters 1 and 26 General Introduction

21

The Organization of This Book, cont’d.

• Intent Category: Construction. • Patterns: Builder, Factory Method, Abstract

Factory, Prototype, Memento• Intent Category: Operations. • Patterns: Template Method, State, Strategy,

Command, Interpreter• Intent Category: Extensions. • Patterns: Decorator, Iterator, Visitor

Page 22: Chapters 1 and 26 General Introduction

22

The Organization of the Course

• In this course the patterns will be organized and presented by structural similarity, not by intent

• Also, this course covers some Java/object-orientation topics which aren’t necessarily design patterns and are not necessarily covered in the book

Page 23: Chapters 1 and 26 General Introduction

23

• The grouping of patterns in the course is given on the following overheads

• The groups are given—but the order of the groups is not necessarily the order in which the groups will be covered in class

Page 24: Chapters 1 and 26 General Introduction

24

• Structural Category: Threads.• Patterns: Strictly speaking, this is not a

pattern• Note: This is included immediately in order to

support the first homework assignment• Structural Category: Construction and

Cloning.• Patterns: Singleton, Prototype, Builder, Proxy

Page 25: Chapters 1 and 26 General Introduction

25

• Structural Category: Model-View-Controller Related Patterns.

• Patterns: Observer, Memento• Note: This does not involve many patterns,

but it’s of great importance• It is included early in order to have the second

homework assignment be based on this

Page 26: Chapters 1 and 26 General Introduction

26

• Structural Category: Generic Interfaces and Encapsulation.

• Patterns: Mediator, Façade, Adapter, Flyweight, Decorator, State

• Structural Category: Java Interfaces.• Patterns: Iterator, Template, Strategy

Page 27: Chapters 1 and 26 General Introduction

27

• Structural Category: Interfaces, Dynamic Binding, and Polymorphism.

• Patterns: Factory Method, Abstract Factory, Command, Bridge

• Structural Category: Composite and Related Patterns.

• Patterns: Composite, Chain of Responsibility, Interpreter, Visitor

Page 28: Chapters 1 and 26 General Introduction

28

Welcome to Oozinoz!

• The book’s examples are based on an integrated code base which is collectively known as Oozinoz (oohs and ahs), which deals with software needed for the production of fireworks

• The authors’ examples will be presented and explained

Page 29: Chapters 1 and 26 General Introduction

29

Principles of Object-Oriented Design

• For people interested in the topic of patterns, the book cites this Web site: www.c2.com

• There is no need to go there for the purposes of this course

• From that page there is a link to a Wiki with a collection of patterns that goes beyond the ones covered in the book

Page 30: Chapters 1 and 26 General Introduction

30

Summary

• This is the book’s summary of the chapter, verbatim:– “Patterns are distillations of accumulated wisdom

that provides a standard jargon, naming the concepts that experienced practitioners apply.

– The patterns in the classic book Design Patterns are among the most useful class-level patterns and are certainly worth learning.

Page 31: Chapters 1 and 26 General Introduction

31

Summary, cont’d.

– This book explains the same patterns as those documented in Design Patterns but uses Java and its libraries for its examples and challenges.

– By working through the challenges in this book, you will learn to recognize and apply an important part of the wisdom of the software community.”

Page 32: Chapters 1 and 26 General Introduction

32

Design Patterns in JavaPart V

Extension PatternsChapter 26

Introducing Extensions

Summary prepared by Kirk Scott

Page 33: Chapters 1 and 26 General Introduction

33

The Introduction Before the Introduction

• In the book’s overall scheme, the purpose of this chapter is to introduce extension patterns

• The chapter also reviews some patterns that have been introduced already, assuming you’ve gone through the earlier chapters

• Because this course is organized differently, these two purposes are not important

Page 34: Chapters 1 and 26 General Introduction

34

• The chapter also discusses some high-level object-oriented design principles

• These are important• This is why I put this chapter at the beginning• These high-level concepts build on object-

oriented ideas that were introduced in CSCE 202

Page 35: Chapters 1 and 26 General Introduction

35

Object-Oriented Constructs and Principles

• Here are four concepts/terms encountered in CSCE 202 that are relevant to this discussion:

• 1. Encapsulation• = Declare instance variables private—nothing

can be touched except by a method call• 2. Interfaces• = An object of a given class may be referred to

by an interface which it implements

Page 36: Chapters 1 and 26 General Introduction

36

• 3. Polymorphism• = A given superclass reference may refer to

various kinds of objects which are instances of subclasses

• 4. Dynamic binding• = At runtime the system determines the right

version to use when a method is called on a polymorphic reference

Page 37: Chapters 1 and 26 General Introduction

37

• The book will introduce these 4 additional ideas, which are related to the problem of arriving at a good object-oriented design:

• Responsibility• Coupling• The Liskov Substitution Principle• The Law of Demeter

Page 38: Chapters 1 and 26 General Introduction

38

Responsibility

• In simple terms, responsibility means that classes/objects should be self-contained

• Their definitions should contain all of the instance variables and methods needed in order to manipulate them fully and accomplish desired goals with them

• This is the norm, known as distributed responsibility

Page 39: Chapters 1 and 26 General Introduction

39

• Responsibility can also be usefully concentrated in some cases

• Various design patterns will illustrate both distributed and concentrated responsibility

• In other words, the generally desirable goal of distributed responsibility will be relaxed in some patterns in order to achieve some particular goal

Page 40: Chapters 1 and 26 General Introduction

40

Coupling

• There is a related concept, known as coupling• Ideally, objects are independent of each other• This generally desirable condition is known as

loose coupling• Loose coupling might be thought of as meaning

fewer connections• This would mean fewer places where you had to

worry about a change in one object propagating to another

Page 41: Chapters 1 and 26 General Introduction

41

• Inevitably, sometimes a change in one object will trigger a change in another

• As usual, there are also cases where tighter coupling is desirable

• Various design patterns will illustrate both loose and tight coupling

Page 42: Chapters 1 and 26 General Introduction

42

The Liskov Substitution Principle and the Law of Demeter

• This chapter adds two major items to the list of object-oriented design principles:

• The Liskov Substitution Principle• The Law of Demeter

Page 43: Chapters 1 and 26 General Introduction

43

• These principles are interesting in their own right• They draw together some important insights that

apply to object-oriented design in general• As the design patterns are introduced, at various

points it may become apparent that the patterns, in general, are bounded by these principles

• There may also be places where a given pattern can be seen to push the boundaries of one of the principles in order to achieve a particular goal.

Page 44: Chapters 1 and 26 General Introduction

44

Extending Code and the Design Principles

• You rarely write code in a vacuum• You have an existing code base and your task

is to add new features, classes, applications to it

• Remember the idea presented in CSCE 202 of “inspired copying”

• Extension means programming within the context of given code

Page 45: Chapters 1 and 26 General Introduction

45

• Not only is it important to have rules of thumb to help you write good code from scratch

• As a programmer, extending a code base, it would be helpful to have some rules of thumb to decide whether or not the code you are adding is any good

Page 46: Chapters 1 and 26 General Introduction

46

The Liskov Subsitution Principle (LSP)

• One of the aspects of object-orientation that should be familiar to you is the following:

• A subclass is in an “is-a-kind-of” relationship with its superclass

• In general, a subclass is a more specific kind of the superclass

• At the very least, it has the same set of instance variables, since instance variables can’t (or shouldn’t) be overridden

Page 47: Chapters 1 and 26 General Introduction

47

• The subclass is made more specific by having more instance variables

• It is also made more specific by adding or overriding methods, if necessary

• In Java, it’s always syntactically possible to have a superclass reference to a subclass object

Page 48: Chapters 1 and 26 General Introduction

48

• The superclass reference won’t have access to the instance variables and unique methods of the subclass

• However, the superclass reference will have access to any methods inherited by the subclass

• It will also have access to any methods overridden in the subclass

Page 49: Chapters 1 and 26 General Introduction

49

• The ability to have superclass references is important when defining method parameters in an inheritance hierarchy

• A method defined in a superclass with a superclass explicit parameter doesn’t have to be overridden in the subclass, with the explicit parameter re-typed to the subclass

• It can simply be used with a subclass explicit parameter

Page 50: Chapters 1 and 26 General Introduction

50

• The book states that subclasses should be logical, consistent extensions of their superclasses

• Trying to define the meaning of logical and consistent leads to the Liskov Substitution Principle

• The book paraphrases the principle as follows:• “An instance of a class should function as an

instance of its superclass.”

Page 51: Chapters 1 and 26 General Introduction

51

• Another way of putting this is, “Anything you can do to a superclass object, you can do to a subclass object.”

• Java expects this and supports it syntactically• The real question is whether or not the

internal logic of classes for a given problem domain agree with this

Page 52: Chapters 1 and 26 General Introduction

52

The Machine and Ellipse Examples

• The book gives two problematic examples which are shown on the next overhead

Page 53: Chapters 1 and 26 General Introduction

53

Page 54: Chapters 1 and 26 General Introduction

54

The Machine/UnloadBuffer Example

• The Machine/UnloadBuffer example illustrates questions that arise in the problem domain

• Superficially, you might want to class UnLoadBuffers with Machines

• Without knowing how machines and buffers are designed, it’s not clear whether this is a correct software design decision

Page 55: Chapters 1 and 26 General Introduction

55

• However, the book gives the following additional information:

• According to the way their fireworks factory is set up, you can’t add tubs to an UnloadBuffer

• This implies that you also could not get tubs associated with an UnloadBuffer

Page 56: Chapters 1 and 26 General Introduction

56

• However, the Machine class has an addTub() and a getTubs() method

• And the diagram shows the UnloadBuffer class as also having these methods

• What does it mean for these methods to appear in that class?

• How would you do the implementation?

Page 57: Chapters 1 and 26 General Introduction

57

• If all machines except for UnloadBuffer have this characteristic, you have a design problem

• Do you force the implementation of addTub() and getTubs() into each subclass of machine except for UnloadBuffer, when all of that code will be duplicate?

• Do you implement the UnloadBuffer class outside of the Machine hierarchy?

Page 58: Chapters 1 and 26 General Introduction

58

• Do you leave the UnloadBuffer in the hierarchy and leave the methods in Machine, but somehow ignore the methods for UnloadBuffer?

• The UML diagram shows this last choice, with addTub() and getTubs() overridden in UnloadBuffer

Page 59: Chapters 1 and 26 General Introduction

59

• Maybe what should happen if it is not really possible to call these methods on an UnloadBuffer, is to throw an exception

• But you still have to ask, why was a programmer given the option/lured into calling a method which can only throw an exception?

Page 60: Chapters 1 and 26 General Introduction

60

• The design as shown puts the burden on client code to catch exceptions for a faulty design

• An alternative would be to have the overridden versions of the method do nothing at all

• One approach to this would be to provide bogus, empty implemtations

Page 61: Chapters 1 and 26 General Introduction

61

• But anytime you provide bogus implementations, you know something is not quite right

• In this case it is even worse than throwing an exception

• What happens to a tub after a call has been made to add it to an UnloadBuffer?

• Does it go into outer space?

Page 62: Chapters 1 and 26 General Introduction

62

• The point is that this is a bad design, and the problem with the design can be identified as a violation of the Liskov Substitution Principle

• The problem is that it is not possible to use an instance of an UnloadBuffer anywhere that you use an instance of a machine

Page 63: Chapters 1 and 26 General Introduction

63

• The UnloadBuffer class doesn’t seem to be a proper subclass of the Machine class

• This is essentially just an elaborate example of concepts discussed in CSCE 202

• When designing object-oriented software, problems will result if you haven’t got the inheritance hierarchy arranged correctly

• This example also introduces things like bogus implementations, which may be the lesser of two evils in some of uses of patterns to come

Page 64: Chapters 1 and 26 General Introduction

64

The Ellipse/Circle Example

• The book deals with the Ellipse/Circle example in a challenge.

• Challenge 26.1• A circle is certainly a special case of an ellipse,

or is it? Say whether the relationship of the Ellipse and Circle classes in Figure 26.1 is a violation of LSP.

Page 65: Chapters 1 and 26 General Introduction

65

Page 66: Chapters 1 and 26 General Introduction

66

• Solution 26.1• “In mathematics, a circle is certainly a special case of

an ellipse. • However in OO programming, an ellipse has certain

behaviors that a circle does not. • For example, an ellipse may be twice as wide as it is

tall; a circle can’t do that. • If that behavior is important to your program, a Circle

object won’t function as an Ellipse object and will represent a violation of LSP.

Page 67: Chapters 1 and 26 General Introduction

67

• Note that if you’re considering immutable objects, this may not apply.

• This is simply an area in which naïve mathematics is not a smooth fit for the semantics of standard type hierarchies.”

Page 68: Chapters 1 and 26 General Introduction

68

Violations…

• It may sometimes be useful to violate the Liskov Substitution Principle

• This seems to be eternally true in software development

• The additional requirement when you do this is to clearly identify the violation

• Justify it• And identify and deal with all possible

consequences

Page 69: Chapters 1 and 26 General Introduction

69

• We will see an example of this in the chapter on bridges/drivers

• The choice will have to do with how many methods you put into an interface

• Do you put a subset of methods in, so that all implementing classes could implement them?

• Or do you put a superset of methods in, forcing some of the implementing classes to have bogus implementations?

Page 70: Chapters 1 and 26 General Introduction

70

• The second option is more flexible, in the sense that all possible methods are supported in all cases where they are valid

• The shortcoming is that they also exist in cases where they aren’t valid

• As long as the invalid cases don’t cause any harm—or it is possible to detect and deal with invalid cases in client code, then the advantages might outweigh the disadvantages

Page 71: Chapters 1 and 26 General Introduction

71

The Law of Demeter (LoD)

• Demeter• From Wikipedia, the free encyclopedia

Page 72: Chapters 1 and 26 General Introduction

72

• In Greek mythology Demeter (pronounced /dəˈmiːtər/; də-MEE-tər; Greek: Δημήτηρ, Dēmētēr, probably "earth-mother")[1][2] was the goddess of the harvest, who presided over grains, the fertility of the earth, the seasons (personified by the Hours), and the harvest. Though Demeter is often described simply as the goddess of the harvest, she presided also over the sanctity of marriage, the sacred law, and the cycle of life and death. She and her daughter Persephone were the central figures of the Eleusinian Mysteries that also predated the Olympian pantheon.

• Her Roman cognate is Ceres.

Page 73: Chapters 1 and 26 General Introduction

73

Page 74: Chapters 1 and 26 General Introduction

74

• In Greek mythology, Persephone /pərˈsɛfəniː/, also called Kore /ˈkɔəriː/,[1] is the daughter of Zeus and the harvest-goddess Demeter, and queen of the underworld; she was abducted by Hades, the god-king of the underworld.[2][3]

• The myth of her abduction represents her function as the personification of vegetation which shoots forth in spring and withdraws into the earth after harvest; hence she is also associated with spring and with the seeds of the fruits of the fields. Persephone as a vegetation goddess (Kore) and her mother Demeter were the central figures of the Eleusinian mysteries that predated the Olympian pantheon. In the Linear B (Mycenean Greek) tablets dated 1400-1200 BC found at Pylos, the "two mistresses and the king" are mentioned; John Chadwick identifies these as Demeter, Persephone and Poseidon.[4]

• In Classical Greek art, Persephone is invariably portrayed robed; often carrying a sheaf of grain. In Roman mythology, she is called Proserpina.

Page 75: Chapters 1 and 26 General Introduction

75

Page 76: Chapters 1 and 26 General Introduction

76

• The book quotes a paper by Lieberherr and Holland on the Law of Demeter:

• “Informally, the law [of Demeter] says that each method can send messages to only a limited set of objects: to argument objects, to the [this] pseudovariable, and to the immediate subparts of [this].”

Page 77: Chapters 1 and 26 General Introduction

77

• Stated more explicitly, the law goes like this:• When writing method code, you may be

working with the implicit parameter• You can call methods directly on the implicit

parameter

Page 78: Chapters 1 and 26 General Introduction

78

• Because the code you’re writing is in the class of the implicit parameter, you have direct access to the instance variables of the implicit parameter

• You can also call methods on the instance variables of the implicit parameter

Page 79: Chapters 1 and 26 General Introduction

79

• When writing method code, you may also be working with an explicit parameter

• You can also call methods directly on the explicit parameter

Page 80: Chapters 1 and 26 General Introduction

80

• If the explicit parameter is not of the same type as the class that the method occurs in, then you don’t have direct access to its instance variables

• In that case, you can’t call methods on the instance variables of the explicit parameter

Page 81: Chapters 1 and 26 General Introduction

81

• In summary, you’re allowed to call methods on objects that you have a direct reference to

• You shouldn’t be calling methods second-hand• In other words, if you have to call a get

method to get a reference to an instance variable of something, you shouldn’t then be calling a method on that object

Page 82: Chapters 1 and 26 General Introduction

82

• This also goes back to a discussion that occurs early in CSCE 202

• If you are enforcing encapsulation rigidly, a get method for an instance variable that is a reference to an object will return a clone of the object, not the object itself

• But in practice, a get method may return a reference to the object itself

Page 83: Chapters 1 and 26 General Introduction

83

• The Law of Demeter has to do with this case• Even if you can get a reference to an instance

variable, you should not be calling methods on it• If some operation is truly desirable, then there

should be a method in the current class that calls a method in the second class that performs the desired operation

• This should be built into the classes, not cobbled together by string together calls to get methods

Page 84: Chapters 1 and 26 General Introduction

84

Illustrating a Violation of the Law of Demeter

• The book points out that the Law of Demeter can be easier to understand if you consider cases that would violate it

• They set up this scenario• There is a MaterialManager object with a

method X that takes a Tub object (named tub in the book) as an explicit parameter

Page 85: Chapters 1 and 26 General Introduction

85

• Tub objects have a location instance variable• A location is a machine, for example• A machine, in turn, has an instance variable

that tells whether the machine is up or down

Page 86: Chapters 1 and 26 General Introduction

86

• In the code for method X, you might write code to find whether the machine where a tub is located is up or down:

• if(tub.getLocation().isUp()){

• …• }

Page 87: Chapters 1 and 26 General Introduction

87

• According to the Law of Demeter, it’s OK to call tub.getLocation()

• That’s just one level deep into the explicit parameter

• That call returns a reference to the location instance variable (machine) where the tub is located

Page 88: Chapters 1 and 26 General Introduction

88

• The Law of Demeter says that calling a method on the machine reference returned by that call is not OK

• In other words, the code as written violates the law

• Syntactically, it’s OK, but it’s not a good idea

Page 89: Chapters 1 and 26 General Introduction

89

• Challenge 26.2• Explain why the expression

tub.getLocation().isUp() might be viewed as unhealthy.

Page 90: Chapters 1 and 26 General Introduction

90

• Solution 26.2• “The expression tub.getLocation().isUp() might

lead to programming errors if there are any subtleties around the value of a tub object’s Location property.

• For example, the location might be null or might be a Robot object if the tub is in transit.

• If location is null, evaluating tub.getLocation().isUp() will throw an exception.

Page 91: Chapters 1 and 26 General Introduction

91

• If the location is a Robot object, the problem may be even worse, as we try to use a robot to collect a tub from itself.

• These potential problems are manageable, but do we want the ensuing code to be in the method that uses the tub.getLocation().isUp() expression?

Page 92: Chapters 1 and 26 General Introduction

92

• No. • The necessary code may already be in the Tub

class! • If not, it belongs there, to prevent us from having

to recode around the same subtleties in other methods that interact with tubs.”

• Explanatory note: Remember that method X as given here is in the MaterialManager class, which makes use of tubs

Page 93: Chapters 1 and 26 General Introduction

93

• Comment mode on:• A simple-minded but possibly effective way of

thinking about the Law of Demeter is that it is concerned with encapsulation when dealing with the internals of classes.

• Recall that a truly correct get() method for an object reference would return a clone(), not the original

Page 94: Chapters 1 and 26 General Introduction

94

• If you then called a method on the clone, what effect would that have on the original?

• The answer is, no effect• But of course, the point is that you really want to

operate on the original because an effect is desired

• But to operate on the original of a reference which you obtained with a get() call would violate encapsulation

Page 95: Chapters 1 and 26 General Introduction

95

• The book’s challenge solution is complete and correct

• It can be briefly summarized as follows:• Method X in MaterialManager deals with tubs,

but it should be protected from having to deal with the internals of tubs

Page 96: Chapters 1 and 26 General Introduction

96

• The challenge solution states that “the logic may already be in the Tub class”

• If it isn’t, but it’s needed, that is the place to put it

• The solution to the Demeter/encapsulation problem is to put needed methods where they belong

Page 97: Chapters 1 and 26 General Introduction

97

• Method X in MaterialManager deals with tubs• It is apparently ultimately concerned with

whether or not a tub’s location (machine) is up or down

• The code for method X should only make calls on tubs, not on their location instance variables

Page 98: Chapters 1 and 26 General Introduction

98

• The thing to do is add a method to the Tub class that has to do with a tub’s location

• The method could be descriptively named something like, isMyLocationUpOrDown()

• Then method X could be written without violating the Law of Demeter

• Instead of this:• tub.getLocation().isUp()• You could write this:• tub.isMyLocationUpOrDown()

Page 99: Chapters 1 and 26 General Introduction

99

• The code for method X is protected from having to know what the interface or internals of the Location class are

• It only has to know the interface for the Tub class, which is the class that it works with directly

• The interface for the Tub class now includes a method that encapsulates an operation involving one of its instance variables

Page 100: Chapters 1 and 26 General Introduction

100

• In general, a sequence of calls of the form a.b.c() may be a danger sign

• The book states that the Law of Demeter is more subtle than this:

• “Expressions of the form a.b.c are bad.”• This is clear• It would certainly be possible to write

expressions of the form a.b.c() which didn’t violate the Law of Demeter.

Page 101: Chapters 1 and 26 General Introduction

101

• The law is based on an understanding of things like responsibility and coupling

• Responsibility: Does the Tub class have all of the methods needed to “take care of itself”?

• Coupling: If you fail to use the Law, will changes in tub locations have a negative impact in the method X code for MaterialManager?

Page 102: Chapters 1 and 26 General Introduction

102

• As always, there may be cases where you know you are violating the law, but some other consideration causes you to do so

• In other words, there may be cases where a.b.c() does violate the law, but you choose to use such an expression anyway

Page 103: Chapters 1 and 26 General Introduction

103

Removing Code Smells

• The title of this subsection is unfortunate• It refers to the idea that there are certain signs that may

appear in code indicating that the code is problematic• Could you get any more childish than saying that

someone’s code smells?• The only outcome of that approach that I can foresee is

a dialog along these lines:• “Your code smells.”• “No, your code smells.”

Page 104: Chapters 1 and 26 General Introduction

104

• It’s a completely unproductive way of looking at things

• If you have to resort to the term “smells” in order to describe what’s wrong, it’s a sign that your analytical or expressive abilities are lacking

Page 105: Chapters 1 and 26 General Introduction

105

• The book mentions this source, “Refactoring: Improving the Design of Existing Code” by Fowler et al.

• This reference contains 22 signs that code can be improved by refactoring

• The textbook does not cover these 22 signs• The book has a challenge in this subsection, but

it’s impossible to do if you don’t know the signs, so it’s not included in these overheads

Page 106: Chapters 1 and 26 General Introduction

106

Summary

• The authors describe code writing as a process of extension followed by refactoring

• I always describe it as copying existing code, adapting it, and then debugging—repeat as necessary…

• The authors also state that there is no complete, objective technique for assessing code quality

Page 107: Chapters 1 and 26 General Introduction

107

• The Liskov Substitution Principle provides one guideline for writing good code

• It should always be possible to substitute a subclass object for a superclass object

• You need to be able to identify and justify any violations of this that might exist in code you write

Page 108: Chapters 1 and 26 General Introduction

108

• The Law of Demeter is another guideline for writing good code

• You shouldn’t be calling methods on references to instance variables you obtained by calling get() methods

• The authors summarize this by saying that applying the Law of Demeter reduces dependencies between classes

Page 109: Chapters 1 and 26 General Introduction

109

• This goes back to distributed responsibility and loose coupling as the default ideals for object-oriented code design

• You need to be able to identify and justify any violations of this that might exist in code you write

Page 110: Chapters 1 and 26 General Introduction

110

• Other authors have identified problems that occur in code design

• They have also identified preferable refactorings• Some of the refactorings are similar to

recognizable design patterns• Lots of design patterns can be understood as

tools for extending existing pieces of code or coordinating the tasks of different programmers in developing a complete system

Page 111: Chapters 1 and 26 General Introduction

111

The End


Recommended