The public interface of a class is cohesive if all of its features are related to the concept that the class
represents.
If you find that the public interface of a class refers to multiple concepts, then that is a good sign that it may be time
to use separate classes instead.
A class depends on another class if it uses objects of that class.
If many classes of a program depend on each other, then we say that the coupling between classes is high.
Conversely, if there are few dependencies between classes, then we say that the coupling is low
It is a good practice to minimize the coupling (i.e., dependency) between classes.
UML (“Unified Modeling Language”)
UML is a notation for object-oriented
analysis and design invented by Grady Booch, Ivar Jacobson, and James Rumbaugh, three leading researchers in
object-oriented software development.
methods that operate on a particular instance of an object.
The UML notation distinguishes between object diagrams and class diagrams.
in a class diagram the class names are not underlined
In a
class diagram, you denote dependency by a dashed line with a -shaped open arrow tip that points to the dependent
class.
It is a good practice to minimize the coupling (i.e., dependency) between classes.
2.Consistency
When you have a set of methods, follow a consistent scheme for
their names and parameters.
This is simply a sign of good craftsmanship.
4. Packages
Organizing Related Classes into Packages
A Java program consists of a collection of classes.
As programs get larger, however, simply distributing the classes over multiple files isn't enough. An additional
structuring mechanism is needed.
A Java package is a set of related classes.
To put classes in a package, you must place a line
package packageName;
as the first instruction in the source file containing the classes.
A package name consists of one or more identifiers separated by periods.
there is a special package, called the default package, which has no name.
If you did not include any package statement at the top of your
source file, its classes are placed in the default package.
Importing Packages
If you want to use a class from a package, you can refer to it by its full name (package name plus class name).
For example, java.util.Scanner refers to the Scanner class in the java.util package:
java.util.Scanner in = new java.util.Scanner(System.in);
You can instead import a name with an import statement:
import java.util.Scanner;
Then you can refer to the class as Scanner without the package prefix.
The import directive lets you refer to a class of a package by its class name, without the package
prefix.
You can import all classes of a package with an import statement that ends in .*. For example, you can use the
statement
import java.util.*;
you don't need to import other classes in the same package. For example, when you implement the class
homework1.Tester, you don't need to import the class homework1.Bank. The compiler will find the Bank class without
an import statement because it is located in the same package, homework1.
Package Names
there is a more important reason for packages: to avoid name clashes.
Use a domain name in reverse to construct unambiguous package names.
How Classes are Located
A package is located in a subdirectory that matches the package name.
The parts of the name between periods represent successively nested directories.
the package com.horstmann.bigjava would be placed in a subdirectory com/horstmann/bigjava.
The path of a class file must match its package name.
class path
You need to add the directories that might contain packages to the class path
In UNIX, the command might be export CLASSPATH=/home/walters/lib:.
A typical example for Windows would be set CLASSPATH=c:\home\walters\lib;
Class path contains the base directories that may contain package directories
Self Test
quistion
answer
Why is the CashRegister class from Chapter 4 not cohesive?
Some of its features deal with payments, others with coin values
Why does the Coin class not depend on the CashRegister class?
None of the coin operations require the CashRegister class
Why should coupling be minimized between classes?
If a class doesn't depend on another, it is not affected by interface changes in the other class
Why might you want to add a precondition to a
method that you provide for other programmers?
Then you don't have to worry about checking for
invalid values–it becomes the caller's responsibility
When you implement a method with a precondition and you notice that
the caller did not fulfil the precondition, do you have to notify the caller?
No–you can take any action that is convenient for you
Which of the following are packages?
java No
java.lang Yes
java.util Yes
java.lang.Math No
Can you write a Java program without ever using import statements?
Yes–if you use fully qualified names for all classes, such as java.util.Random and java.awt.Rectangle
Suppose your homework assignments are located in the directory /home/me/cs101 (c:\me\cs101 on Windows).
Your instructor tells you to place your homework into packages. In which directory do you place the class hw1.problem1.TicTacToeTester?
/home/me/cs101/hw1/problem1 or, on Windows, c:\me\cs101\hw1\problem1
3.Preconditions and Postconditions
precondition
A precondition is a requirement that the caller of a method must meet. If a method is called in
violation of a precondition, the method is not responsible for computing the correct result.
a precondition is an important part of the method, and you must document it.
/**
* Deposits money into this account.
* @param amount the amount of money to deposit
* (Precondition: amount >= 0)
*/
Preconditions are typically provided for one of two reasons:
1. To restrict the parameters of a method
2. To require that a method is only called when it is in the appropriate state
A method is responsible for operating correctly only when its caller has fulfilled all preconditions
What should a method actually do when it is
called with inappropriate inputs?
1. A method can check for the violation and throw an exception. Then the method does not return to its caller;
instead, control is transferred to an exception handler. If no handler is present, then the program terminates.
this approach can be inefficient, particularly if the same check is carried out many times by several methods.
2. A method can skip the check and work under the assumption that the preconditions are fulfilled. If they aren't,
then any data corruption (such as a negative balance) or other failures are the caller's fault.
The second approach can be dangerous.
An assertion
An assertion is a condition that you believe to be true at all times in a particular program location
throwing an exception is another reasonable option. But
assertions have one advantage: You can turn them off after you have tested your program,
Many beginning programmers think that it isn't “nice” to abort the program when a precondition is violated. Why not
simply return to the caller instead?
That is legal—after all, a method can do anything if its preconditions are violated. But it is not as good as an assertion
check. If the program calling the deposit method has a few bugs that cause it to pass a negative amount as an input
value, then the version that generates an assertion failure will make the bugs very obvious during testing—it is hard
to ignore when the program aborts. The quiet version, on the other hand, will not alert you, and you may not notice
that it performs some wrong calculations as a consequence. Think of assertions as the “tough love” approach to
precondition checking.
postcondition
If a method has been called in accordance with its preconditions, then it must ensure that its
postconditions are valid.
Condition that is true after a method has completed
There are two kinds of postconditions
1. The return value is computed correctly.
2. The object is in a certain state after the method call is completed.
/**
* Deposits money into this account.
* (Postcondition: getBalance() >= 0)
* @param amount the amount of money to deposit
* (Precondition: amount >= 0)
*/
Don't document trivial postconditions that repeat the @return clause
Note that we formulate pre- and postconditions only in terms of the interface of the class.
Thus, we state the precondition of the withdraw method as amount <= getBalance(), not amount <= balance. After all, the caller,
which needs to check the precondition, has access only to the public interface, not the private implementation.