Abstract
definition of, 54
Abstractions
insisting on, in writing inheritable code, 159
separating from concretions, 123–125
supporting, in intentional testing, 194
template method pattern, 125–129
Across-class types, 86
Ad infinitum, 3
Antipattern
Argument-order dependencies, removing, 46–51
defaults, explicitly defining, 48–49
hashes for initialization arguments, using, 46–48
multiparameter initialization, isolating, 49–51
Automatic message delegation, 105–106
Behaves-like-a relationships, 189
Behavior
acquired through inheritance, 105–139
data structures, hiding, 26–29
depending on, instead of data, 24–29
instance variables, hiding, 24–26
set of, 19
Behavior Driven Development (BDD), 199, 213
Big Up Front Design (BUFD), 8–9
Booch, Grady, 188
Break-even point, 11
Bugs, finding, 193
Case statements that switch on class, 96–98
kind_of? and is_a?, 97
responds_to?, 97
Category used in class, 111
Class. See also Single responsibility, classes with
avoiding dependent-laden, 55
case statements that switch on, 96–98
code, organizing to allow for changes, 16–17
deciding what belongs in, 16–17
decoupling, in writing inheritable code, 161
dependent-laden, avoiding, 55
grouping methods into, 16
references to (See Loosely coupled code, writing)
responsibilities isolated in, 31–33
Ruby based vs. framework, 53–54
type and category used in, 111
virtual, 61
Class-based OO languages, 12–13
Class class, 14
Classical inheritance, 105–106
Class of an object
Class under test, removing private methods from, 214
Code. See also Inheritable code, writing; Inherited code, testing
dependency injection to shape, 41–42
depending on behavior instead of data, 24–29
embracing change, writing, 24–33
initialization, 121
loosely coupled, writing, 39–51
open–closed, 185
organizing to allow for changes, 16–17
putting its best (inter)face forward, writing, 76–79
relying on duck typing, writing, 95–100
single responsibility, enforcing, 29–33
truths about, 53
Code arrangement technique, 184
Cohesion, 22
Command messages, 197, 216–218
Compile/make cycle, 102, 103, 104
Compiler, 54, 101, 103–104, 118
Composition
benefits of, 187
consequences of, accepting, 187–188
for has-a relationships, 183, 190
inheritance and, deciding between, 184–190
objects combined with, 163–190
summary, 190
Concretions
abstractions separated from, 123–125
Context
minimizing, 79
Costs
Coupling
decoupling classes in writing inheritable code, 161
decoupling subclasses using hook messages, 134–138
between superclasses and subclasses, managing, 129–138
Coupling between objects (CBO), 37–38
C++, 102
Data
depending on behavior instead of, 24–29
instance variables, hiding, 24–26
Decoupling
classes in writing inheritable code, 161
subclasses using hook messages, 134–138
Defaults, explicitly defining, 48–49
Demeter. See Law of Demeter (LoD)
Demotion failure, 123
Dependencies
argument-order, removing, 46–51
coupling between objects, 37–38
direction of (See Dependency direction)
injecting (See Dependency injection)
loosely coupled code, writing, 39–51
objects speaking for themselves, 147
recognizing, 37
scheduling duck type, discovering, 146–147
summary, 57
abstractions, recognizing, 54–55
change in, likelihood of (See Likelihood of change)
concretions, recognizing, 54–55
dependent-laden classes, avoiding, 55
failure of, 60
in loosely coupled code, 39–42
Dependency Inversion Principle, 5
Dependent-laden classes, avoiding, 55
definition of, 4
Design decisions
deferring, 193
Design flaws, exposing, 194
Design Patterns: Elements of Reusable Object-Oriented Software (Gamma, Helm, Johnson, and Vlissides), 6, 188
Documentation
of duck types, 98
of roles, testing used in, 212–213
supplying, in testing, 193
Domain objects, 64, 83, 96, 199
Doubles, role tests to validate, 224–229
DRY (Don’t Repeat Yourself ), 5, 24, 27, 28, 45, 50, 196
defining, 85
documenting, 98
overlooking, 87
sharing between, 99
trust in, placing, 98
using role tests to validate doubles, 224–229
for behaves-like-a relationships, 189
case statements that switch on class, 96–98
code that relies on, writing, 95–100
scheduling, discovering, 146–147
summary, 104
Dynamic typing
Embedded types of inheritance
Explicit interfaces, creating, 76–78
External messages, isolating, 44–45
Extra responsibilities
Factories, 51
File data type, 12
Fowler, Martin, 191
Framework class, vs. Ruby based class, 53–54
vs. is-a relationships, 188–189
Hashes used for initialization arguments, 46–48
Hidden ducks
Highly cohesive class, 22
Hunt, Andy, 5
Incoming messages, testing, 200–213
injecting dependencies as roles, 208–213
injecting dependencies using classes, 207–208
interfaces, deleting unused, 202–203
isolating object under test, 205–207
proving public interface, 203–204
Inheritable code, writing, 158–162
abstraction, insisting on, 159
antipatterns, recognizing, 158–159
classes, preemptively decouple, 161
shallow hierarchies, creating, 161–162
template method pattern, using, 160
Inheritance
abstract class, finding, 116–129
behavior acquired through, 105–139
composition and, deciding between, 184–190
consequences of, accepting, 184–186
family tree image of, 112
implying, 117
for is-a relationships, 188–189
multiple, 112
problem solved by, 112
recognizing where to use, 106–114
relationships, drawing, 114
rules of, 117
single, 112
summary, 139
superclasses and subclasses, coupling between, 129–138
Inherited code, testing, 229–239
behavior, testing unique, 236–239
inherited interface, specifying, 229–232
subclass responsibilities, specifying, 233–236
Inherited interface, specifying, 229–232
Inheriting role behavior, 158
Initialization arguments, 41–43
in isolation of instance creation, 42–43
Initialization code, 121
Injection of dependencies. See Dependency injection
Instance variables, hiding, 24–26
Intention, constructing, 64–65
Interface
inherited, specifying, 229–232
Interfaces. See also Private interfaces; Public interfaces
code putting its best (inter)face forward, writing, 76–79
summary, 83
Interface Segregation Principle, 5
is_a?, 97
vs. has-a relationships, 188–189
Isolation
of instance creation, 42–43, 42–44
of multiparameter initialization, 49–51
of responsibilities in classes, 31–33
JavaScript, 106
kind_of?, 97
Law of Demeter (LoD), 5, 80–83
defining Demeter, 80
in embedded references to messages, 45
vs. number of dependents, 55–57
Liskov, Barbara, 160
Liskov Substitution Principle (LSP), 5, 160, 230–231, 237, 239
Loosely coupled code, writing, 39–51
remove argument-order dependencies, 46–51
Managing dependencies, 3
Message, 15
Message chaining, 38–39, 80–83
Messages. See also Incoming messages, testing
applications, creating, 76
automatic message delegation, 105–106
delegating, 82
likely to change, embedded references to, 45
message forwarding via classical inheritance, 112
Methods
extra responsibilities extracted from, 29–31
grouping into classes, 16
gross oversimplification, 154–155
more accurate explanation, 155–156
very nearly complete explanation, 156–158
Meyer, Bertrand, 188
MiniTest, 200
Modules
definition of, 143
role behavior shared with, 141–162
Monkey patching, 100
Multiparameter initialization, isolating, 49–51
Multiple inheritance, 112
NASA Goddard Space Flight Center applications, 6
NilClass, 113
Object class
Object-Oriented Analysis and Design (Booch), 188
Object-oriented design (OOD), 1–14. See also Design
dependencies managed by, 3
masters of, 188
overview of, 1
Object-oriented languages, 12–14
Object-oriented programming, 11–14
object-oriented languages in, 12–14
overview of, 11
procedural languages in, 12
Objects. See also Parts object
combined with composition, 163–190
messages used to discover, 74–76
speaking for themselves, 147
Object under test, 200, 202, 205–207
Open–closed code, 185
Overridden methods, 115
creating PartsFactory, 177–178
leveraging PartsFactory, 178–180
making more like array, 172–176
Polymorphism, 95
depending on, caution in, 79
Private methods, testing, 213–215
removing from class under test, 214
Programing languages
statically or dynamically typed, 100–104
syntax in, 118
context independence, seeking, 71–73
example application: bicycle touring company, 63–64
intention, constructing, 64–65
message-based application, creating, 76
messages used to discover objects, 74–76
sequence diagrams, using, 65–69
“what” vs. “how,” importance of, 69–71
Query messages, 196, 197, 215–216
Refactoring
barriers to, reducing, 215
definition of, 191
in extracting extra responsibilities from methods, 29–31
rule for, 123
strategies, deciding between, 122–123
testing roles and, 220–221, 226
in writing changeable code, 191–192
Refactoring: Improving the Design of Existing Code (Fowler), 191
use composition for has-a relationships, 190
use duck types for behaves-like-a relationships, 189
use inheritance for is-a relationships, 188–189
responds_to?, 97
Responsibilities, organizing, 143–145
Responsibility-Driven Design (RDD), 22
Reversing dependency direction, 51–53
Roles
concrete code, writing, 147–150
inheritable code, writing, 158–162
injecting dependencies as, 208–213
role behavior shared with modules, 141–162
summary, 162
testing, in duck typing, 219–224
tests to validate doubles, 224–229
Ruby based class vs. framework class, 53–54
Runtime type errors, 101, 103–104
Sequence diagrams, using, 65–69
Shallow hierarchies in writing inheritable code, 161–162
Single inheritance, 112
Single responsibility, classes with
benefits of, 31
code embracing change, writing, 24–33
design decisions, when to make, 22–23
determining, 22
example application: bicycles and gears, 17–21
extra responsibilities and, 29–33
importance of, 21
summary, 34
Single Responsibility Principle, 5
SOLID design principles, 5, 160
Source code repository, 59
Source lines of code (SLOC), 10–11
Specializations, 117
Spike a problem, 198
Static typing
duck types and, subverting with, 100–101
Subclass behavior
Subclasses
decoupling using hook messages, 134–138
superclasses and, coupling between, 129–138
Superclass behavior
Superclasses
subclasses and, coupling between, 129–138
Syntax, 118
Template method pattern
in writing inheritable code, 160
Test Driven Development (TDD), 199, 213
Testing
abstractions, supporting, 194
bugs, finding, 193
cost-effective, designing, 191–240
creating test doubles, 210–211
design decisions, deferring, 193
design flaws, exposing, 194
documentation, supplying, 193
knowing your intentions, 193–194
summary, 240
Testing outgoing messages, 215–218
command messages, proving, 216–218
query messages, ignoring, 215–216
Thomas, Dave, 5
Touch of Class: Learning to Program Well with Objects and Contracts (Meyer), 188
TRUE code, 17
Types, 85. See also Duck typing
across-class, 86
within-class, 63
Type used in class, 111
Unified Modeling Language (UML), 65–66, 114
Use case, 64, 65, 66, 67, 69, 74
Variables, defining, 12
Virtual class, 61
“What” vs. “how,” importance of, 69–71
Wilkerson, Brian, 22
Wirfs-Brock, Rebecca, 22
Within-class types, 63
18.117.93.0