Chapter Six - Building Blocks to Projects

Download Report

Transcript Chapter Six - Building Blocks to Projects

George Blank
University Lecturer
CS 602
Java and the Web
Object Oriented Software Development
Using Java
Chapter 6
Public and Helper Classes
• A class intended for general use should be a public
class. It must be declared public and reside in a file is
the same as the class name.
• A subordinate class used only by public classes is a
helper class. It should not be declared public and, if
it supports a single public class, should appear in the
same file as the public class.
Nested or not?
• If a helper class appears separately in a file with a
public class, it is accessible only to that public class.
See the example on the next slide.
• If a helper class is nested inside a public class, it is
accessible through that public class by subclasses of
that public class unless they are combined in the
same package. See the example on the slide
following the next slide.
Example LinkedList.Java
public class LinkedList implements List {
protected Node head, tail;
protected int count;
//..
//implementation of Linked List
}
class Node {
Object element;
Node next, prev;
}
Nested in LinkedList.Java
public class LinkedList implements List {
protected Node head, tail;
protected int count;
static protected class Node {
Object element;
Node next, prev;
}
//..
//implementation of Linked List
}
Separate interface from
implementation
• It is good programming practice to use interfaces
widely in Java. Whenever the functionality of a class
can be implemented in different ways, create an
interface that is polymorphic and broadly designed,
then create different classes that extend the
functionality to different cases. This requires a design
practice of thinking about the most general case of a
class before implementing the specific cases.
TFCL
• The use of general interfaces is an example
of the best practice of TFCL: Think first, code
later.
• In general, you want to spend time thinking
about the problem you are solving before you
start work on the solution. Clearly separate
the problem domain from the solution
domain.
Problems and Solutions
• Concentrating on understanding the problem before you
even consider a solution is an example of deferring
decision making. In general, the earlier you make a
decision the more likely you are to make a wrong
decision. Every time you start to write code, you select
one approach to a solution that precludes other
approaches. If you decide before fully understanding the
problem, you are less likely to choose the best, or even
a good approach.
Related Java functions
• The previous example, from the author of the
text, may be confusing, as the Java class
library provides an interface List and a Linked
List in the Collections framework, which we
will see in chapter 8.
• Here he is just showing an example of a
similar class. Do not confuse it with the class
library interfaces and classes.
Declaring an interface
• Also notice at this point how an interface is
implemented. Instead of declaring a class, we
declare an interface. Also, in an interface, there
can be no implementation details. The member
functions of the interface class are shown as
prototypes, showing their type, name and arguments.
Except in special cases, an interface and it’s
members are usually declared public to facilitate
creating classes to implement them.
Implementing the interface
• Once you have declared an interface, implementing it is simple.
All you have to do is declare a class that implements the
interface. The implementing class then must provide an
implementation for each of the methods declared in the
interface.
public class LinkedList implements list {
public int size {…implementation of size…}
…implementation of remaining class members…
Class Members
•
•
While the order of class members is semantically
insignificant to the Java compiler, it still matters to human
readers to make the class easy to understand.
A best practice is to order the members according to their
accessibility and roles:
1.
2.
3.
4.
Public constructors
Public accessor or selectors (do not modify state)
Public mutators or modifiers (change state of objects)
Nonpublic constructors and auxiliary methods
Good organization for a
Public Class
public class Aclass {
<public constants>
<public constructors>
<public accessors>
<public mutators>
<nonpublic fields>
<nonpublic auxiliary methods or nested classes>
}
Avoid public fields
• The object oriented principle of encapsulation
suggests that attributes of a class should not be
directly accessible. Instead, the fields should be
accessed indirectly through methods of the class.
• An accessor, get method, or getter is a method used
to obtain the value of a field.
• A mutator, set method, or setter is a method used to
change the value of a field.
Accessors and Mutators
• Requiring access to attributes only through accessors and
mutators allow those methods to enforce constraints and
security methods to avoid improper use of the fields and
inconsistent data.
• Preventing direct access to the data also protects against
problems such as inconsistency related to simultanous use by
different objects. Ths is a key virtue of encapsulation. The
discussion of PolarPoint on pages 211-213 of the text
explains the importance of this and is discussed on the next
slide.
Example of get and set
• Section 6.3 gives a clear example of information hiding and
the reason for using accessors and mutators.
• The class PolarPoint must be constrained to points that are
the length of the radius away from the origin. To prevent
invalid values for points, only a member method can set points
using a mutator. There is no direct access to the values. While
this is required for the example, it is good practice to use
accessors and mutators broadly, not just when there is a clear
need.
Complete Public Interface
• The set of public methods defined in a class
should provide full and convenient access to
all of the functionality of the class.
Separate Interface from
Implementation
• If the functionality of a class can be
implemented in different ways, it is advisable
to separate the interface from the
implementation.
• This implements the Object Oriented principle
of information hiding, so that changes in
implementation will not affect clients of the
class.
Java interfaces and C++ Headers
• Java interfaces are similar to C++ header files, but there are
key differences that make Java closer to the object model
ideal.
• In C++, the header and the implementation are two parts of a
class, the header can contain some of the implementation,
and all fields must be declared.
• In Java, the interface and implementation are completely
separate, the interface contains no implementation, and
private and protected fields are not declared.
Java Inheritance
• There are two key object oriented ideas that drive
inheritance in Java, hook methods and template
methods. In both cases, they give shape to a
process that is initially incomplete and is
completed by methods that inherit from or
implement them.
Hook Methods
• A hook method, usually an abstract method in an
abstract class, is a place holder that will be filled with
application specific logic in a later class that
implements the method.
• Java literature often refers to a hook method as a
“hot spot,” but that term doesn’t always refer to a
method. A hot spot can also be implemented as a
class or even an application.
Template Methods
• A template method contains a process flow detailing the
steps to be done, but some of the implementation is left
out, to be implemented from an abstract method or
overridden in a method that inherits from the template.
Templates are one of the “Gang of Four” patterns. They
are different from hook methods because they give a
structure to the task with partial implementation.
Contracts and Invariants
• While I will not test you on the material in section 6.2 of the
text, or require you to include contracts in your code, you
need to understand this material, particularly preconditions
and postconditions, in order to implement unit testing with
JUnit. Starting with this chapter, I will also require you to use
Javadocs to document your code, so understanding the
Javadocs variables can improve your documentation. You can
use Operation Contracts as your planning document, and/or
use Contracts in your code as an alternative to that.
Assertions (Section 6.2.3)
• While I will not require assertions in
homework or test you on them, I would
suggest that you try an assertion in a few of
your homework assignments so that you can
understand them as a useful tool. That
understanding is also something that will help
you use JUnit.
Canonical Form of Classes
• Classes designed for general use should follow canonical
form, including the following elements:
–
–
–
–
–
No-argument constructor
Object equality
String representation
Cloning
Serialization
• All of these items take additional work, but it is rewarded with
robust, maintainable and reusable code.
No Argument Constructor
• Having a constructor without arguments (in addition
to others that may require arguments) allows
instances of a class to be created by the JVM at run
time without the new operator.
• Many Java applications and frameworks depend on
the ability to load classes and create instances when
an uninstantiated class is referenced at run time.
• Dynamic loading is a key feature of Java.
Object Equality
• Textbook section 6.3.2 gives a good explanation of
the measures necessary so that subclasses that are
instances of a superclass can be compared at the
superclass level without the comparison failing
because the subclass is a different type.
• The comparison equality is more general than only at
the superclass level, but that concept helps
understand the purpose of comparability.
Hash Code
• Since identical classes should generate
identical hash codes, any general class that
generates hash codes should be
implemented in a way that objects that are
the same should generate identical hash
codes even if they are a subtype or
implementation of the same interface.
Cloning Objects
• Another operation that is problematic for
subtypes and implementation is cloning.
• How to make objects clonable is described in
the text, section 6.3.4.
• Notice the difference between a shallow copy
that copies the references but points to the
same list, and a deep copy that copies the list
as well. (Next slide)
Clones of a LinkedList
• Shallow Copy
list1
• Deep Copy
list1
Head
Head
Tail
Tail
Count: 3
list1.clone()
1
list1.clone()
2
Count: 3
2
3
1
Head
Head
Tail
Count: 3
1
3
Tail
2
Count: 3
3
Serialization
• Serialization transforms an object into a sequence
of bytes. This allows objects to be saved to files
or transferred across a network, and is another
key feature of Java.
• Classes that need to be stored in files or
transferred over a network should implement the
java.io.serializable interface. (Also see section
8.4.1 of the text)
Patterns
• Continuing the discussion on object-oriented
principles introduced in the last chapter, the
author focuses on useful abstractions,
particularly the use of software design
patterns, in chapter 6.
Applying patterns
• A house may involve many models, such as a
landscape model, a framing model, an
electrical wiring model, and a plumbing
model. Over time, architects have learned
that some designs are quite practical, such as
a center hall colonial, while others tend to
have severe limitations, such as an A-frame.
Design as philosophy
• One of the most influential philosophers of
structural design is Christopher Alexander, a
retired professor of architecture at the
University of California at Berkeley.
• His ideas have also been applied to software
design. See his web site at
http://www.patternlanguage.com/leveltwo/ca.
htm and select software from the left menu.
The Zen of Christopher Alexander
• The Quality Without a Name (QUAN)
– The essence of life and usefulness; freedom, harmony, wholeness,
comfort, durability, adaptability
• The Gate
– How we reach the Quality; a living common pattern language; the
universal “ether” of patterns and relationships in a domain
• The Timeless Way
– Apply patterns from the Gate by differentiating space in piecemeal
growth into a live design with the Quality
Books on Patterns
• Christopher Alexander
–
–
–
–
Notes on the Synthesis of Form, 1964
The Oregon Experiment, 1975
A Pattern Language: Towns, Building, Construction, 1977
The Timeless Way of Building, 1979
• Software Patterns
– Gamma, Helm, Johnson Vlissides, Design Patterns: Elements of Reusable
Object Oriented Software, 1995
– Bushmann, Meunier, Rohnert, Sommerlad, Stahl, Pattern-Oriented Software
Architecture: A System of Patterns, 1996
– Pattern Languages of Program Design (and PLOPD 2, 3, 4) 1995-1999
– Larman, Applying UML and Patterns, An Introduction to Object Oriented Analysis
and Design, 1997
Testing
• Chapter 6 introduces section 6.4 on unit
testing. Since the homework will require you
to use JUnit, see the supplemental lecture on
testing with JUnit. JUnit comes integrated
with the Net Beans and Eclipse development
environments, and I recommend that you do
the assignment in one of them.
Build and make tools
• There is also a supplemental lecture on Ant to
go with section 6.5. Most compilation
commands in Java are very verbose, and
typing the commands by hand can be very
time consuming and error prone. An
automated tool such as Ant is essential for
productivity.
Review Questions
• What does an accessor do?
• What does a mutator do?
• How are tests for equality different for strings than for
other objects? ... than for operators?
• What is serialization?
• When and e\why do we separate an interface from an
implementation?
Bibliography
• (Books listed on patterns)
• Jia, Xiaoping, Object Oriented Software
Development Using Java. Addison Wesley,
2003