27
Designing Classes 2 How to write classes in a way that they are easily understandable, maintainable and reusable

Designing Classes 2 How to write classes in a way that they are easily understandable, maintainable and reusable

Embed Size (px)

Citation preview

Designing Classes 2

How to write classes in a way that they are easily understandable,

maintainable and reusable

Code Quality

Two important concepts for quality of code:Two important concepts for quality of code:

• Coupling Coupling – as little as possible please– as little as possible please• Cohesion Cohesion – as much as possible please– as much as possible please

Coupling

• Coupling refers to links between Coupling refers to links between separate units of a program.separate units of a program.

• If two classes depend closely on If two classes depend closely on many details of each other, we say many details of each other, we say they arethey are tightly coupledtightly coupled..

• We aim forWe aim for loose couplingloose coupling..

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Loose Coupling

• Loose couplingLoose coupling makes it possible to: makes it possible to:

• understand how a class works understand how a class works without having without having to understand how the classes it uses workto understand how the classes it uses work;;

• change the implementation of a class change the implementation of a class without affecting those classes that use itwithout affecting those classes that use it..

This improves maintainability … makes change easier.This improves maintainability … makes change easier.This improves maintainability … makes change easier.This improves maintainability … makes change easier.

Cohesion

CohesionCohesion relates to: the relates to: the the number and the number and diversity of tasksdiversity of tasks for which a single unit for which a single unit is responsible.is responsible.

If a programming unit is responsible for If a programming unit is responsible for one logical task, we say it hasone logical task, we say it has high high cohesioncohesion..

Cohesion applies both at the level of Cohesion applies both at the level of classesclasses and of and of methodsmethods..

We aim forWe aim for high cohesionhigh cohesion..

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

High Cohesion

• High cohesionHigh cohesion makes it easier to: makes it easier to:

• understand what a class or method understand what a class or method does does (because it only does one thing)(because it only does one thing);;

• Choose and use Choose and use descriptive namesdescriptive names;;

• reusereuse classes or methods. classes or methods.

This improves usability … and makes change easier.This improves usability … and makes change easier.This improves usability … and makes change easier.This improves usability … and makes change easier.

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Cohesion of Classes

Classes should represent just one,Classes should represent just one,and only one, well defined entity.and only one, well defined entity.

Classes should represent just one,Classes should represent just one,and only one, well defined entity.and only one, well defined entity.

Cohesion of Methods

A method should be responsible for A method should be responsible for one,one,

and only one, well defined task.and only one, well defined task.

A method should be responsible for A method should be responsible for one,one,

and only one, well defined task.and only one, well defined task.

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Code Duplication

This is an indicator of bad design.This is an indicator of bad design.This is an indicator of bad design.This is an indicator of bad design.

It makes maintenance harder.It makes maintenance harder.It makes maintenance harder.It makes maintenance harder.

It can lead to introduction of errors,It can lead to introduction of errors,especially during maintenance.especially during maintenance.

It can lead to introduction of errors,It can lead to introduction of errors,especially during maintenance.especially during maintenance.

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

World of Zuul

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad Problems• Fields in Fields in RoomRoom are all are all publicpublic..• The fact that a The fact that a RoomRoom has has fourfour exits is exits is

burnt into the interface of its burnt into the interface of its setExitssetExits method. method.

• The The GameGame class references class references RoomRoom fields.fields.

• So, the implementation of the So, the implementation of the GameGame and and RoomRoom classes are classes are coupledcoupled. A . A change in one (e.g. adding more exits change in one (e.g. adding more exits to a to a RoomRoom) means changing the other ) means changing the other (e.g. the (e.g. the createRoomscreateRooms, , printWelcomeprintWelcome and and goRoomgoRoom methods of methods of GameGame).).

• This is This is BAD!BAD!

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad Problems• There are duplicated code fragments There are duplicated code fragments

in the in the GameGame class (in class (in createRoomscreateRooms and and printWelcomeprintWelcome methods). methods).

• Changing the details of Changing the details of oneone of these of these fragments means changing fragments means changing allall..

• This is This is BAD!BAD!• Factorise the duplicated code into a Factorise the duplicated code into a

single method (see Code 7.2, p209, single method (see Code 7.2, p209, of the book: of the book: printLocationInfoprintLocationInfo) and ) and duplicate its invocation instead.duplicate its invocation instead.

• Now, there is only Now, there is only oneone fragment of fragment of code to maintain. This is code to maintain. This is Good!Good!

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad

• There are duplicated code fragments There are duplicated code fragments in the in the GameGame class (in class (in createRoomscreateRooms and and printWelcomeprintWelcome methods). methods).

• Changing the details of Changing the details of oneone of these of these fragments means changing fragments means changing allall..

• This is This is BAD!BAD!• Factorise the duplicated code into a Factorise the duplicated code into a

single method (see Code 7.2, p209, single method (see Code 7.2, p209, of the book: of the book: printLocationInfoprintLocationInfo) and ) and duplicate its invocation instead.duplicate its invocation instead.

• Now, there is only Now, there is only oneone fragment of fragment of code to maintain. This is code to maintain. This is Good!Good!

Chapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-better

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad • Make fields in Make fields in RoomRoom privateprivate and provide an and provide an

accessor method to get them (Code 7.4, p213).accessor method to get them (Code 7.4, p213).• In In GameGame, can no longer reference directly the , can no longer reference directly the

exit fields (all exit fields (all RoomRooms) of s) of RoomRoom..• In In GameGame..printLocationInfoprintLocationInfo (which does so (which does so

reference), we could just change it to use the reference), we could just change it to use the accessor method, rather than the field.accessor method, rather than the field.

• However, it’s neater to invoke a (new) method of However, it’s neater to invoke a (new) method of RoomRoom to get the exit information it needs to print to get the exit information it needs to print (Code 7.6, p218). Each (Code 7.6, p218). Each RoomRoom object has that object has that information, so it is really its information, so it is really its responsibilityresponsibility..

• For For GameGame..goRoomgoRoom (which also does so reference), (which also does so reference), thirteenthirteen lines of code collapse to lines of code collapse to oneone (see p214). (see p214).

Chapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-better

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad • Make fields in Make fields in RoomRoom privateprivate and provide an and provide an

accessor method to get them (Code 7.4, p213).accessor method to get them (Code 7.4, p213).• In In GameGame, can no longer reference directly the , can no longer reference directly the

exit fields (all exit fields (all RoomRooms) of s) of RoomRoom..• In In GameGame..printLocationInfoprintLocationInfo (which does so (which does so

reference), we could just change it to use the reference), we could just change it to use the accessor method, rather than the field.accessor method, rather than the field.

• However, it’s neater to invoke a (new) method of However, it’s neater to invoke a (new) method of RoomRoom to get the exit information it needs to print to get the exit information it needs to print (Code 7.6, p218). Each (Code 7.6, p218). Each RoomRoom object has that object has that information, so it is really its information, so it is really its responsibilityresponsibility..

• For For GameGame..goRoomgoRoom (which also does so reference), (which also does so reference), thirteenthirteen lines of code collapse to lines of code collapse to oneone (see p214). (see p214).

Chapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-better

• Look carefully at this accessor method …Look carefully at this accessor method …

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

public Room getExit (String direction)public Room getExit (String direction){{ if (direction.equals (" if (direction.equals ("northnorth")) {")) { return return northExitnorthExit;; } } if (direction.equals (" if (direction.equals ("easteast")) {")) { return return eastExit;eastExit; } } if (direction.equals ("if (direction.equals ("southsouth")) {")) { return return southExitsouthExit;; } } if (direction.equals (" if (direction.equals ("westwest")) {")) { return return westExitwestExit;; } } return return nullnull;;}}

public Room getExit (String direction)public Room getExit (String direction){{ if (direction.equals (" if (direction.equals ("northnorth")) {")) { return return northExitnorthExit;; } } if (direction.equals (" if (direction.equals ("easteast")) {")) { return return eastExit;eastExit; } } if (direction.equals ("if (direction.equals ("southsouth")) {")) { return return southExitsouthExit;; } } if (direction.equals (" if (direction.equals ("westwest")) {")) { return return westExitwestExit;; } } return return nullnull;;}}

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad Chapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-better

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad • Make fields in Make fields in RoomRoom privateprivate and provide an and provide an

accessor method to get them (Code 7.4, p213).accessor method to get them (Code 7.4, p213).• In In GameGame, can no longer reference directly the , can no longer reference directly the

exit fields (all exit fields (all RoomRooms) of s) of RoomRoom..• In In GameGame..printLocationInfoprintLocationInfo (which does so (which does so

reference), we could just change it to use the reference), we could just change it to use the accessor method, rather than the field.accessor method, rather than the field.

• However, it’s neater to invoke a (new) method of However, it’s neater to invoke a (new) method of RoomRoom to get the exit information it needs to print to get the exit information it needs to print (Code 7.6, p218). Each (Code 7.6, p218). Each RoomRoom object has that object has that information, so it is really its information, so it is really its responsibilityresponsibility..

• For For GameGame..goRoomgoRoom (which also does so reference), (which also does so reference), thirteenthirteen lines of code collapse to lines of code collapse to oneone (see p214). (see p214).

Chapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-better

• It It mapsmaps a a StringString ( (directiondirection) into an ) into an exitexit RoomRoom..• But that’s just the function of a:But that’s just the function of a:

• So, replace the four exit fields with one of the So, replace the four exit fields with one of the above (above (privateprivate of course) – Code 7.5. Now, we of course) – Code 7.5. Now, we can have as many exits as we like.can have as many exits as we like.

• Finally, replace the Finally, replace the setExitssetExits method (which method (which burns the message burns the message “four exits”“four exits” into its definition) into its definition) with a single with a single setExitsetExit method (which we can method (which we can invoke for as many exits as we like) – p216/217.invoke for as many exits as we like) – p216/217.

• Now, Now, RoomRoom is independent of its number of exits. is independent of its number of exits.

HashMap<String, Room>HashMap<String, Room>HashMap<String, Room>HashMap<String, Room>

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

World of Zuul

Chapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-badChapter 7: zuul-bad

Chapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-betterChapter 7: zuul-better

MORAL: class MORAL: class diagrams are diagrams are not enough to not enough to

tell whether the tell whether the design is good.design is good.

MORAL: class MORAL: class diagrams are diagrams are not enough to not enough to

tell whether the tell whether the design is good.design is good.

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Responsibility-Driven Design

• Where should we add new fields and Where should we add new fields and new methods new methods (and to which class)(and to which class)??

• The class that holds the data The class that holds the data (fields)(fields) processes processes (methods)(methods) the data. the data.

• Responsibility-driven designResponsibility-driven design leads to leads to low coupling.low coupling.

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Localising Change

• One aim of reducing coupling One aim of reducing coupling and responsibility-driven design and responsibility-driven design is to localise change.is to localise change.

• When a change is needed, as When a change is needed, as few classes as possible should few classes as possible should be affected.be affected.

Improve maintainability … make change easier.Improve maintainability … make change easier.Improve maintainability … make change easier.Improve maintainability … make change easier.

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Think Ahead

• When designing a class, think When designing a class, think what changes are likely to be what changes are likely to be made in the future.made in the future.

• Aim to make those changes easy.Aim to make those changes easy.

Improve maintainability … make change easier.Improve maintainability … make change easier.Improve maintainability … make change easier.Improve maintainability … make change easier.

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Refactoring

• When classes are maintained, When classes are maintained, code usually needs to be added.code usually needs to be added.

• Lists of fields, lists of methods Lists of fields, lists of methods and the code inside methods and the code inside methods tend to become longer.tend to become longer.

• Every now and then, classes and Every now and then, classes and methods should be methods should be refactoredrefactored to to maintain maintain cohesioncohesion and and low low couplingcoupling..

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Refactoring and Testing

• When When maintainingmaintaining code, separate code, separate the the refactoringrefactoring from making other from making other changes.changes.

• Do the refactoring firstDo the refactoring first, without , without adding to the functionality.adding to the functionality.

• Test before and after refactoringTest before and after refactoring to ensure that nothing gets to ensure that nothing gets broken.broken.

e.g.e.g. zuul-badzuul-bad toto zuul-betterzuul-better..

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Design Questions

• Common questions:Common questions:• How long should a class be?How long should a class be?• How long should a method be?How long should a method be?

Answered with regard to Answered with regard to cohesioncohesion and and couplingcoupling..Answered with regard to Answered with regard to cohesioncohesion and and couplingcoupling..

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Design Guidelines

• A method is too long if it does more then one logical task.

• A class is too complex if it represents more than one logical entity.

Note: these are Note: these are guidelinesguidelines … …everything is still open to the designer.everything is still open to the designer.

Note: these are Note: these are guidelinesguidelines … …everything is still open to the designer.everything is still open to the designer.

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

Review• Programs are continuously changed.Programs are continuously changed.

• It is important to anticipate change It is important to anticipate change and make it as easy as possible.and make it as easy as possible.

• Quality of code requires much more Quality of code requires much more than just performing correctly!than just performing correctly!

• Code must be Code must be understandableunderstandable and and maintainablemaintainable..

Objects First with Java - A Practical Introduction using BlueJ, © David J. Barnes, Michael Kölling

• Good quality code Good quality code avoids duplicationavoids duplication, , displays displays high cohesionhigh cohesion, , low couplinglow coupling..

• Coding style (Coding style (commentingcommenting, , namingnaming, , layoutlayout, etc.) is also very important., etc.) is also very important.

• There is a big difference in the amount There is a big difference in the amount of work required to of work required to maintainmaintain poorly poorly structured and well structured code.structured and well structured code.

• In fact, unless it is well structured, In fact, unless it is well structured, the the code is doomedcode is doomed … it will not be used for … it will not be used for long.long.

Review