Sei sulla pagina 1di 95

Creating High-Quality

Code
Hoa Nguyen
Outline

 Chapter 5: Design in Construction


 Chapter 6: Working Classes
 Chapter 7: High-Quality Routines
 Chapter 8: Defensive Programming
 Chapter 9: The Pseudo code Programming Process
Chapter 5: Design in Construction

 5.1 Design Challenges


 5.2 Key Design Concepts
 5.3 Design Building Blocks: Heuristic
 5.4 Design Practices
 5.5 Comments on Popular Methodologies
5.1 Design Challenges

 What is “Software Design” mean?


 The conception, invention, or contrivance of a scheme for
turning a specification for computer software into
operational software
 The activity that links requirements to coding and debugging
5.1 Design Challenges

 Design is a Wicked Problem


 Design is a Sloppy Process
 Design is about Tradeoffs and Priorities
 Design involves Restrictions
 Design is Nondeterministic
 Design is Heuristic Process
 Design is Emergent
5.2 Key Design Concepts

 Good design depends on understanding a handful of key


concepts. This section discusses the role of complexity,
desirable characteristics of designs, and levels of design
5.2 Key Design Concepts

 Managing Complexity
 Accidental and Essential Difficulties
 Importance of Managing Complexity
 Divide system into sub-systems
 Keep the routines short
 Write code easy for understand
 How to attach Complexity
 Minimum the amount of essential complexity that anyone’s
brain has to deal with at any one time
 Keep accidental complexity from needlessly proliferating
5.2 Key Design Concepts

 Desirable Characteristics of Design


 Minimal complexity (Primary goal)
 Avoid make “clever” design
 Ease of maintenance
 Loose coupling
 Extensibility
 Reusability
 High fan-in
5.2 Key Design Concepts

 Desirable Characteristics of Design


 Low-to-medium fan-out
 Portability
 Leanness
 Stratification
 Standard techniques
5.2 Key Design Concepts

 Levels of design
 Software system
 Division into subsystems
or package
5.2 Key Design Concepts

 Levels of design
 Software system
 Division into subsystems or package
 Common Subsystems: Business rules, User interface, Database
access, System dependencies,
 Division into classes
 Division into routines
 Internal routine design
5.3 Design Building Blocks: Heuristics

 Find real world objects


 Identify the objects and their attributes (methods and data)
 Determine what can be done to each object
 Determine what each object is allowed to do to other objects
 Determine the parts of each object that will be visible to other
objects-which parts will be public and which will be private
 Define each object’s public interface
5.3 Design Building Blocks: Heuristics

 Find real world objects


 Determine
Define thewhat
Identifyeachthe each
object’s
objects
parts object
can and
be
public
of done
each is allowed
interface
their to eachthat
object to do be
object
attributes to visible
(methods
will other
and objects
data)
to other
5.3 Design Building Blocks: Heuristics

 Form Consistent Abstractions


5.3 Design Building Blocks: Heuristics

 Encapsulate Implementation Detail


5.3 Design Building Blocks: Heuristics

 Inherit – When Inheritance Simplifies Design


 Hide Secrets (Information Hiding)
 Secrets and the Right to Privacy
5.3 Design Building Blocks: Heuristics

 Inherit – When Inheritance Simplifies Design


 Hide Secrets (Information Hiding)
 An Example of Information Hiding
 Two categories of Secret
5.3 Design Building Blocks: Heuristics

 Inherit – When Inheritance Simplifies Design


 Hide Secrets (Information Hiding)
 Barrier to information hiding
 Excessive distribution of information
 Circular dependencies
 Class data mistaken for global data
 Perceived preformation penalties
 Value of information hiding
5.3 Design Building Blocks: Heuristics

 Identify Areas Likely to Change


 Identify items that seem likely to change
 Separate items that are likely to change
 Isolate items that seem likely to change
5.3 Design Building Blocks: Heuristics

 Identify Areas Likely to Change


A few areas that are likely to change
 Business rules
 Hardware dependencies
 Input and Output
 Nonstandard language features
 Difficult design and construction areas
 Status variables
 Data-size constraints
5.3 Design Building Blocks: Heuristics

 Keep coupling loose


 Coupling Criteria
 Size

 Visibility

 Flexibility

 Kinds of Coupling
 Simple-data-parameter coupling
 Simple-object coupling
 Object-parameter coupling
 Semantic coupling
5.3 Design Building Blocks: Heuristics

 Look for Common Design Patterns


 Patterns reduce complexity by providing ready-made
abstractions
 Patterns reduce error by institutionalizing details of common
solutions
 Patterns provide heuristic value by suggesting design
alternatives
 Patterns streamline communication by moving the design
dialog to a higher level
5.3 Design Building Blocks: Heuristics

 Look for Common Design Patterns


5.3 Design Building Blocks: Heuristics

 Other Heuristics
 Aim for strong Cohesion
 Build Hierarchies
 Formalize Class Contracts
 Assign Responsibilities
 Design for Test
 Avoid Failure
5.3 Design Building Blocks: Heuristics

 Other Heuristics
 Choose Binding Time Consciously
 Make Central Points of Control
 Consider Using Brute Force
 Draw a Diagram
 Keep your Design Modular
5.4 Design Practices

 Iterate
 Divide and Conquer
 Top-Down and Bottom-Up Design Approaches
 Argument for Top Down
 Argument for Bottom Up
 Experimental Prototyping
 Collaborative Design
 How much Design is Enough?
5.4 Design Practices

 Capturing your Design Work


 Insert design document into the code itself
 Capture design discussions and decisions on a Wiki
 Write email summaries
 Use a digital cameras
 Save design flip charts
 Use CRC (Class, Responsibility, Collaborator) cards,
 Create UML diagrams at appropriate levels of detail
5.5 Comments on Popular Methodologies

 Capturing your Design Work


 Insert design document into the code itself
 Capture design discussions and decisions on a Wiki
 Write email summaries
 Use a digital cameras
 Save design flip charts
 Use CRC (Class, Responsibility, Collaborator) cards,
 Create UML diagrams at appropriate levels of detail
Chapter 5: Design in Construction

 Key Points
Chapter 6: Working Classes

 Class is a collection of data and routines that share a


cohesive, well-defined responsibility
 A key to being an effective programmer is maximizing the
portion of a program that you can safely ignore while
working on any one section of code
 Classes are the primary tool for accomplishing that
objective
Chapter 6: Working Classes

 6.1 Class Foundation: Abstract Data Type (ADTs)


 6.2 Good Class Interfaces
 6.3 Design and Implementation Issues
 6.4 Reasons to Create a Class
 6.5 Language-Specific Issues
 6.6 Beyond Classes: Packages
6.1 Abstract Data Type (ADTs)

 A collection of data and operations that work on that data


 An ADT might be a graphic window with all the operations
that affect it, a file and file operations, an insurance-rates
tables and the operations on it, …
6.1 Abstract Data Type (ADTs)

 ADTs and Classes


 ATDs form the foundation for the concept of classes
 Class is ADT + Inheritance + Polymorphism
6.1 Abstract Data Type (ADTs)

 Benefits
 Hide implementation details
 Changes do not affect the whole program
 Make the interface more informative
 Easier to improve performance
 Program is more obviously correct
 Program becomes more self-documenting
 Do not have to pass data all over program
 Able to work with real-world entities rather with low level
implementation structures
6.1 Abstract Data Type (ADTs)

 Some examples
6.1 Abstract Data Type (ADTs)

 Some examples
6.1 Abstract Data Type (ADTs)

 Guidelines
 Build or use typical low-level data types as ADTs, not at low-
level data types
 Treat common objects such as files as ADTs
 Treat even simple items as ADTs
 Refer to an ADT independently of the medium it’s store on
6.1 Abstract Data Type (ADTs)

 Handling Multiple Instances of Data with ADTs in Non-Object-


Oriented Environments
 Option 1: Explicitly identify instances each time you use ADT
service
 Option 2: Explicitly provide the data used by ADT services
 Option 3: Use implicit instances
6.2 Good Class Interfaces

 Good Abstraction - Define


 Abstraction is the ability to view a complex operation in a simplified
form
6.2 Good Class Interfaces

 Good Abstraction – How to get


 Present a consistent level of abstraction in the class interface
6.2 Good Class Interfaces

 Good Abstraction
 Present a consistent level of abstraction in the class interface
 Be sure you understand what abstraction the class in
implementing
 Provide services in pairs with their opposites
 Move unrelated information to another class
 Make interfaces programmatic rather than semantic when possible
6.2 Good Class Interfaces

 Good Abstraction
 Beware of erosion of the interface’s abstraction under
modification
 Do not add public members that are inconsistent with the
interface abstraction
 Consider abstraction and cohesion together
6.2 Good Class Interfaces

 Good Encapsulation
 Minimize accessibility of classes and members
 Do not expose member data in public
 Avoid putting private implementation details into a class’s
interface
 Do not make assumptions about class’s users
 Avoid friend classes
 Do not put a routine into the public interface just because it
uses only public routines
 Favor read-time convenience to write-time convenience
 Be very, very wary of semantic violations of encapsulation
6.3 Design and Implementation Issues

 Containment (“has a” Relationships)


 Implement “has a” through containment
 Implement “has a” through private inheritance as last resort
 Be critical of classes that contain more than about seven data
members
6.3 Design and Implementation Issues

 Inheritance (“is a” Relationships)


 Implement “is a” through public inheritance
 Design and document for inheritance or prohibit it
 Adhere to the Liskov Substitution Principle (LSP)
 Be sure to inherit only what you want to inherit
6.3 Design and Implementation Issues

 Inheritance (“is a” Relationships)


6.3 Design and Implementation Issues

 Inheritance (“is a” Relationships)


 Do not “override” a non-overridable member function
 Move common interfaces, data, and behavior as high as
possible in the inheritance tree
 Be suspicious of classes of which there is only one instance
 Be suspicious of base classes of which there is only one derived
class
 Be suspicious of classes that override a routine and do nothing
inside the derived routine
 Avoid deep inheritance trees
6.3 Design and Implementation Issues

 Inheritance (“is a” Relationships)


 Prefer polymorphism to extensive type checking

 Make all data private, not protected


6.3 Design and Implementation Issues

 When use “Inheritance” and when use “Containment”


6.3 Design and Implementation Issues

 Member Functions and Data


 Keep the number of routines in a class as small as possible
 Disallow implicitly generated member functions and operations
you do not want
 Minimize the number of different routines call by a class
 Minimize indirect routine calls to other classed
 In general, minimize the extent to which a class collaborates
with other classes
6.3 Design and Implementation Issues

 Constructors
 Initialize all member data in all constructors if possible
 Enforce the singleton property by using a private constructor
 Prefer deep copies to shallow copies until proven otherwise
6.4 Reasons to Create a Class

 Model real-world objects


 Model abstract objects
 Reduce complexity
 Isolate complexity
 Hide implementation details
 Limit effect of changes
 Hide global data
 Streamline parameter passing
 Make central points of control
6.4 Reasons to Create a Class

 Facilitate reusable code


 Plan for a family of programs
 Package related operations
 Accomplish a specific refactoring
 Classes to avoid
 Avoid creating god classes
 Eliminate irrelevant classes
 Avoid classes named after verbs
6.5 Language-Specific Issues
6.6 Beyond Classes: Package

 Standards for creating own package


Chapter 6: Working Classes

 Key Points
Chapter 7: High-Quality Routines

 7.1 Valid Reasons to Create a Routine


 7.2 Design at the Routine Level
 7.3 Good Routine Names
 7.4 How Long Can a Routine Be?
 7.5 How to Use Routine Parameters
 7.6 Special Considerations in the Use of Functions
 7.7 Macro Routines and Inline Routines
7.1 Valid Reasons to Create a Routine

 Reduce complexity
 Introduce an intermediate, understandable abstraction
7.1 Valid Reasons to Create a Routine

 Avoid duplicate code


 Support sub-classing
 Hide sequences
 Hide pointer operations
 Improve portability
 Simplify complicated Boolean tests
 Improve performance
7.1 Valid Reasons to Create a Routine

In addition, many of reason to create a class are also good


reasons to create a routine:
 Isolate complexity
 Hide implementation details
 Limit effects of changes
 Hide global data
 Make central point of control
 Facilitate reusable code
 Accomplish a specific refactoring
7.2 Design at the Routine Level

 Goal
 Each routine do one thing well and not do anything else
 How to make routines as cohesive as possible
 Functional cohesion
A routine performs one and only one operation
 Sequential cohesion
 Communicational cohesion
 Temporal cohesion
7.2 Design at the Routine Level

 Unacceptable kinds of cohesion


 Procedural cohesion
 Logical cohesion
 Coincidental cohesion
7.3 Good Routine Names

 Describe everything the routine does


 Avoid meaningless, vague, or wishy-washy verbs
 Do not differentiate routine names solely by number
 Make names of routines as long as necessary
 To name a function, use a description of the return value
 To name a procedure, use a strong verb followed by an
object
 Use opposites precisely
 Establish conventions for common operations
7.4 How long can a Routine Be?

 Allow to grow up to 100-200 lines (without comments,


blank lines)
7.5 How to Use Routine Parameters

 Put parameters in input-modify-output order


 Consider creating your own in and out keywords
 If several routines use similar parameters, put the similar
parameters in a consistent order
 Use all the parameters
 Put status or error variables last
 Do not use routine parameters as working variables
7.5 How to Use Routine Parameters

 Document interface assumptions about parameters


 Limit the number of routine’s parameters to about seven
 Consider an input, modify, output naming convention for
parameters
 Pass the variables or objects that the routine needs to
maintain its interface abstraction
 Use Named Parameters
 Make sure actual parameters match formal parameters
7.6 Special Considerations in the Use of
Functions
 Special Considerations in the Use of Functions
 When to Use a Function and When to Use a Procedure
 Setting the Function’s Return Value
 Check all possible return paths
 Do not return references or pointers to local data
7.7 Macro Routines and Inline Routines

 How to use Macro Routines and Inline Routines in C++


Chapter 7: High-Quality Routines

 Key Points
Chapter 8: Defensive Programing

 8.1 Protecting Your Program from Invalid Inputs


 8.2 Assertions
 8.3 Error-Handling Techniques
 8.4 Exceptions
 8.5 Barricade Your Program to Contain the Damage Caused
by Errors
 8.6 Debugging Aids
 8.7 Determining How Much Defensive Programming to Leave
in Production Code
 8.8 Being Defensive About Defensive Programing
8.1 Protecting Your Program from Invalid
Inputs
 Check the values of all data from external sources
 Check the values of all routine input parameters
 Decide how to handle bad inputs
8.2 Assertions

 Assertion is code that’s used during development – usually a


routine or macro – that allow a program to check itself as it
runs
 When an assertion is true, that means everything is
operating as expected. When it’s false, that means it has
detected an unexpected error in the code
 An Assertion usually takes 2 parameters: a Boolean
expression that describes the assumption that’s supposed to
be true, and a message to display if it is not.
8.2 Assertions

 Guideline for using Assertion


 Use error-handling code for conditions you expect to occur;
use assertions for conditions that should never occur
 Avoid putting executable code into assertions
 Use Assertions to document and verify pre-conditions and post-
conditions
 For highly robust code, assert and then handle the error
anyway
8.3 Error Handling Techniques

 Return a neutral value


 Substitute the next piece of valid data
 Return the same answer as the previous time
 Substitute the closest legal value
 Log a warning message to a file
 Return an error code
 Call an error-processing routine/object
 Display an error message whenever the error is encountered
 Handle the error in whatever way works best locally
 Shutdown
8.4 Exceptions

 Use exception to notify other parts of program about errors


that should not be ignored
 Throw an exception only for conditions that are truly
exceptional
 Do use an exception to pass the bulk
 Avoid throwing exceptions in constructors and destructors
unless you catch them in the same place
 Throw exceptions at the right level of abstraction
8.4 Exceptions

 Include in the exception message all information that led to


the exception
 Avoid empty catch blocks
 Know the exceptions your library code throws
 Consider building a centralized exception reporter
 Standardize your project’s use of exceptions
 Consider alternatives to exceptions
8.5 Barricade Your Program to Contain
the Damage Caused by Errors
8.5 Barricade Your Program to Contain
the Damage Caused by Errors
 Convert input data to the proper type at input time
8.6 Debugging Aids

 Do not automatically apply production constraints to the


development version
 Introduce debugging aids early
 Plan to remove Debugging Aids
8.7 Determine how much defensive
program to leave in production code
 Leave in code that checks for important errors
 Remove code that checks for trivial errors
 Remove code that results in hard crashes
 Leave in code that helps the program crash gracefully
 Log errors for your technical support personnel
 Make sure that the error messages you leave in are friendly
8.8 Being defensive about defensive
programing
Think about where you need to be defensive, and set your
defensive programing priorities accordingly
Chapter 8: Defensive Programing

 Key points
Chapter 9: The Pseudo code Programing
Process
 9.1 Summary of steps in Building Classes and Routines
 9.2 Pseudo code for Pros
 9.3 Constructing Routines for using PPP
 9.4 Alternatives to the PPP
9.1 Summary of Steps in Building Classes
and Routines
 Steps in Creating a Class
9.1 Summary of Steps in Building Classes
and Routines
 Steps in Building a Routine
9.2 Pseudo code for Pros

 Guideline for using Pseudo code effectively


9.2 Pseudo code for Pros

 Guideline for using Pseudo code effectively


9.2 Pseudo code for Pros

 Benefits
 Make review design easier
 Support idea of iterative refinement
 Make change easier
 Minimize commenting effort
 Easier to maintain than other forms of design document
9.3 Constructing Routines by using the
PPP
 Design the Routine
 Check the prerequisites
 Define the problem the routine will solve
 Name of routine
 Decide how to test the routine
 Research functionality available in the standard libraries
9.3 Constructing Routines by using the
PPP
 Design the Routine
 Think about error handling
 Think about efficiency
 Research the algorithms and data types
 Write the pseudo code
 Think about the data
 Check the pseudo code
 Try a few ideas in pseudo code, and keep the best (iterate)
9.3 Constructing Routines by using the
PPP
 Code the Routine
9.3 Constructing Routines by using the
PPP
 Check the code
 Mentally check the routine for errors
 Compile the routine
 Step through the code in the debugger
 Test the code
 Remove errors from the routine
9.3 Constructing Routines by using the
PPP
 Clean up Leftovers
 Check the routine’s interface
 Check for general design quality
 Check the routine’s variables
 Check the routine’s statements and logic
 Check the routine’s layout
 Check the routine’s documentation
 Remove redundant comments
9.4 Alternatives to PPP

 Alternatives to PPP
 Test-first development
 Refactoring
 Design by contract
 Hacking?
Chapter 9: The Pseudo code Programing
Process
 Key Points

Potrebbero piacerti anche