Quick Index
Video


Video accompanying this page...

Problem Statement


Problem Statement (New Objects)
(new objects -- the problem "todo")

For a turtle graphics system, design a circular, rectangular and elliptical turtle.

The objects must be able to perform the behaviors shown.
   Circular       Rectangular      Elliptical
    Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
drawOn(canvas)   drawOn(canvas)	  drawOn(canvas)
moveBy(vector)   moveBy(vector)	  moveBy(vector)
scale(factor)    scale(factor)	  scale(factor)
setColor(color)  setColor(color)  setColor(color)
setStyle(style)  setStyle(style)  setStyle(style)
turn(angle)      turn(angle)	  turn(angle)
forward(dist)    forward(dist)	  forward(dist)


Given Context (Environment)


We want to know the given (pre-existing) problem context (environment). This will tell us what other objects are available so that we an reuse and not re-invent.

Object Types in Goody Bag
(existing objects)

Here are some available object types.

We have a general super-type "Shape" and specific sub-types "Circle", "Rectangle" and "Ellipse".
                Shape
                  |
  ----------------+----------------
  |               |               |
Circle        Rectangle        Ellipse
Behaviors in Goody Bag
All of these behaviors are available for our use. Remember that the three sub-types inherit these methods (so the methods are available for them as well).
   Shape
------------------------
(behaviors/methods)
drawOn
moveBy
scale
setColor
setStyle
setPosition
getPosition


Initial Design


We start our design by using the problem statement along with research to come up with an initial design.

Initial Design
In this case, we get lucky, and the problem statement gives us an initial design. We'll use it.
   Circular       Rectangular      Elliptical
    Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
drawOn(canvas)   drawOn(canvas)	  drawOn(canvas)
moveBy(vector)   moveBy(vector)	  moveBy(vector)
scale(factor)    scale(factor)	  scale(factor)
setColor(color)  setColor(color)  setColor(color)
setStyle(style)  setStyle(style)  setStyle(style)
turn(angle)      turn(angle)	  turn(angle)
forward(dist)    forward(dist)	  forward(dist)


Getting Organized


Overview


Before starting the object design normalization process, we'll get a bit organized.

Organizing Steps


Initial Design
Our starting point is the initial design.

Let's get organized.
Circular       Rectangular      Elliptical
 Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
drawOn           drawOn          drawOn
moveBy           moveBy          moveBy
scale            scale           scale
setColor         setColor        setColor
setStyle         setStyle        setStyle
turn             turn            turn
forward          forward         forward
Identify Common Methods
We first identify common methods between the object types.

In this case, all methods are common (highlighted).

We'll identify this common group as "COMMON-1" (there is no magic in the name -- any name that makes sense to you).

NOTE WELL -- The only reason we're using a group here is to abbreviate our documentation. It is an optional step.
Circular       Rectangular      Elliptical
 Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
drawOn           drawOn          drawOn
moveBy           moveBy          moveBy
scale            scale           scale
setColor         setColor        setColor
setStyle         setStyle        setStyle
turn             turn            turn
forward          forward         forward
Method Group "COMMON-1"
The method listing for group "COMMON-1".
COMMON-1 Methods:

Updated Initial Design
Now we update the design.

It's a bit more concise isn't it?
Circular       Rectangular      Elliptical
 Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
COMMON-1        COMMON-1         COMMON-1

1NF - Use Components


Overview


First normal form (1NF) is when the design includes any sub-components (e.g., "ivars") that we can delegate work to (reuse logic).

We ask this question:

Could components (ivars) be added to provide required functionality?

Performing First Normal Form (1NF)


The following are the steps to attain 1NF.

Initial Design
Given an initial design.
Circular       Rectangular      Elliptical
 Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
COMMON-1        COMMON-1         COMMON-1
Method Group "COMMON-1"
Given method group "COMMON-1" (within initial design).
COMMON-1 Methods:

Context
This is our problem context.

The problem context is like a goody bag of available reusable components.
                Shape
                  |
  ----------------+----------------
  |               |               |
Circle        Rectangle        Ellipse

   Shape
------------------------
(behaviors/methods)
drawOn
moveBy
scale
setColor
setStyle
setPosition
getPosition
Identify Redundant Methods
The highlighted methods show us that most of the new (design) methods are redundant (already handled by existing objects such as Shape, Rectangle, Circle and Ellipse).

Note that the existing methods have "extra" methods we will not use (setPosition, getPosition) -- that is no problem, it is like going to a restaurant and ordering just a few items (a subset) from the menu.
COMMON-1      Shape
Methods      Methods
(New)       (Existing)
---------   ----------
drawOn      drawOn
moveBy	    moveBy
scale	    scale
setColor    setColor
setStyle    setStyle
turn        setPosition
forward     getPosition
Method Group "COMPONENT-1"
Here is the new method group "COMPONENT-1" from the previous step. We form this group only to abbreviate our documentation (it is an optional step).

And because there are only two methods remaining in the COMMON-1 group, we'll just show those methods directly (don't need to abbreviate).
COMPONENT-1 Methods:

Updated Method Group "COMMON-1"
Just a little housekeeping.

We remove the methods we identified as redundant (component) from the "COMMON-1" method group.
COMMON-1 Methods:

Updated Initial Design
The updated initial design.
Circular       Rectangular      Elliptical
 Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
COMPONENT-1    COMPONENT-1     COMPONENT-1
turn           turn            turn
forward        forward	       forward
Normalization Question
Now we ask the key question to allow us to achieve "first normal form":

  • Could components (ivars) be added to provide required functionality?


Circular       Rectangular      Elliptical
 Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
COMPONENT-1    COMPONENT-1     COMPONENT-1
turn           turn            turn
forward        forward	       forward


In the previous step we determined that we have a large group of methods "COMPONENT-1" that can be delegated to components.

Therefore, the answer is yes.

This is called code reuse, and is what we strive for.
Available Components
We know that all of these component types understand the methods we have grouped into "COMPONENT-1".
                Shape
                  |
  ----------------+----------------
  |               |               |
Circle        Rectangle        Ellipse
Components Design Try 1
Here is our first cut at adding components.

Each of our three turtle object types now has a component.
CircularTurtle    RectangularTurtle    EllipticalTurtle
  |                 |                    |
 circle            rectangle            ellipse
  |                 |                    |
  +---- aCircle     +---- aRectangle     +---- anEllipse
Components 'HAS-A' Check
We should cross-check as we go.

So we do a quick a 'HAS-A' check to help verify the components. Yes, the "has-a" statements sound reasonable. ✔
CircularTurtle has-a Circle
RectangularTurtle has-a Rectangle
EllipticalTurtle has-a Ellipse
First Normal Form (1NF) Achieved
We have achieved first normal form -- a.k.a. "composition (components)".

The important thing here is that all the methods in the "COMPONENT-1" group are delegated methods which are effectively "freebies" (no new logic needed).
   Circular       Rectangular      Elliptical
    Turtle          Turtle           Turtle
--------------------------------------------------
(components/ivars)
circle           rectangle        ellipse
(behaviors/methods)
COMPONENT-1    COMPONENT-1     COMPONENT-1
turn           turn            turn
forward        forward	       forward

2NF - Generalize Components


Overview


Second normal form (2NF) is when all components in the design are generalized where practical.

We ask this question:

Could any of the component types be a more general type?

Performing Second Normal Form (2NF)


Rule 2NF - Generalizing Components
We review the designed components (highlighted).

We then ask:
  • Could any of the component types be more general?
CircularTurtle    RectangularTurtle    EllipticalTurtle
  |                 |                    |
 circle            rectangle            ellipse
  |                 |                    |
  +---- aCircle     +---- aRectangle     +---- anEllipse
Review Component Diagrams
We review the type diagrams (or class diagrams).

We have four potential component types.

Three are more specific sub-types (circle, rectangle, ellipse) and one is a more general super-type (Shape).
                Shape
                  |
  ----------------+----------------
  |               |               |
Circle        Rectangle        Ellipse
Recall Method Group "COMPONENT-1"
From our 1NF work, we came up with the group of methods "COMPONENT-1" shown here.
COMPONENT-1 Methods:

Method Check
We note that the more general type (Shape) is the provider of the required ("COMPONENT-1") methods. The check passes.. ✔

Note: if the required methods were not in the more general type, we should then stay with the more specific types (e.g. "Circle", "Rectangle", ...).
   Shape
------------------------
(behaviors/methods)
drawOn(canvas)
moveBy(vector)
scale(factor)
setColor(color)
setStyle(style)
Components 'HAS-A' Check
We do the 'HAS-A' check. Yes, the "has-a" statements sound reasonable. The check passes. ✔
CircularTurtle has-a Shape
RectangularTurtle has-a Shape
EllipticalTurtle has-a Shape
Generalized Components
To achieve 2NF we have generalized the component types to "Shape" objects.
CircularTurtle    RectangularTurtle    EllipticalTurtle
  |                 |                    |
 circle            rectangle            ellipse
  |                 |                    |
  +---- aShape     +---- aShape     +---- aShape
Improve Component Names
How might we improve (tweak) the component (ivar) names?


With more general component types, it makes sense to also use more general component names as shown ("shape") -- having clear names is immensely helpful.

CircularTurtle    RectangularTurtle    EllipticalTurtle
  |                 |                    |
 shape             shape                shape
  |                 |                    |
  +---- aShape      +---- aShape         +---- aShape
Second Normal Form (2NF) Achieved
We have achieved second normal form (2NF) -- a.k.a. "generalizing components".
   Circular       Rectangular      Elliptical
    Turtle          Turtle           Turtle
--------------------------------------------------
(components/ivars)
shape            shape         shape
(behaviors/methods)
COMPONENT-1    COMPONENT-1     COMPONENT-1
turn           turn            turn
forward        forward	       forward

Component "shape" is object type "Shape"


3NF - Use Inheritance


Overview


Third normal form (3NF) is where common supertypes have been added (where practical) to eliminate redundancy

We ask this question:

Do two or more of the designed object types have redundant components or functionality?

Rule 3NF - Inheritance
First let's review the 2NF design.

And then ask: Do two or more of the designed object types have redundant components or functionality?

The answer is a resounding "YES". The components and all the methods are repeated (redundant) on the different turtles.

Note: When 3NF applies, it will often be obvious like it is here.
CircularTurtle    RectangularTurtle    EllipticalTurtle
  |                 |                    |
shape            shape            shape
  |                 |                    |
  +---- aShape     +---- aShape     +---- aShape

 Circular       Rectangular      Elliptical
  Turtle          Turtle           Turtle
--------------------------------------------------
COMPONENT-1     COMPONENT-1       COMPONENT-1
turn            turn              turn
forward         forward	          forward

Component "shape" is object type "Shape"
Component Type Check
We check to make sure the component types are equivalent.

The components all are of type "Shape", so the check passes. ✔.

If the compared components were of type "Apple" and "Orange" then these components would not be redundant.
CircularTurtle    RectangularTurtle    EllipticalTurtle
  |                 |                    |
 shape            shape            shape
  |                 |                    |
  +---- aShape     +---- aShape     +---- aShape
Trying a Supertype
Take a shot at designing a supertype.


                Turtle
                  |
  ----------------+----------------
  |               |               |
Circular     Rectangular      Elliptical
Turtle          Turtle          Turtle


We try a supertype "Turtle" (we simply choose a name that sounds reasonable).
Sub-Type 'IS-A' Check
We do a 'IS-A' check to make sure the inheritance is reasonable.

Yes, the "is-a" statements sound reasonable. The check passes. ✔.

CircularTurtle is-a Turtle
RectangularTurtle is-a Turtle
EllipticalTurtle is-a Turtle
Turtle Sub-Components (Ivars)
Our designed turtle has one sub-component
Turtle
  |
shape
  |
  +---- aShape
Turtle Behaviors (Methods)
Our designed turtle has behaviors (methods)
COMPONENT-1 (group)
turn
forward
Designer's Gold! 👍🏽
We can delete the three subclasses. At this time, they are not doing anything (they have no sub-components and no behaviors).

This simplification is designer's gold.
                Turtle
                  |
  ----------------+----------------
  |               |               |
Circular     Rectangular      Elliptical
Turtle          Turtle          Turtle
Third Normal Form (3NF) Achieved
We have achieved third normal form (3NF) -- a.k.a. "inheritance".

Remember that all of the methods are trivial delegated methods except the two highlighted.

Thus, we only have new logic in two methods!

Note that, for the final design, we have expanded out the method group "COMPONENT-1" to list the actual method names.
    Turtle
------------------------
(components/ivars)
shape
(behaviors/methods)
drawOn(canvas)*
moveBy(vector)*
scale(factor)*
setColor(color)*
setStyle(style)*
turn(angle)
forward(dist)

*delegated method
Component "shape" is object type "Shape"

Example #1 Conclusion


Recall Our Initial Design
In our initial design we needed to complete more than twenty methods.
   Circular       Rectangular      Elliptical
    Turtle          Turtle           Turtle
--------------------------------------------------
(behaviors/methods)
drawOn(canvas)   drawOn(canvas)	  drawOn(canvas)
moveBy(vector)   moveBy(vector)	  moveBy(vector)
scale(factor)    scale(factor)	  scale(factor)
setColor(color)  setColor(color)  setColor(color)
setStyle(style)  setStyle(style)  setStyle(style)
turn(angle)      turn(angle)	  turn(angle)
forward(dist)    forward(dist)	  forward(dist)
Final Design (3NF)
In our final design we have new logic in only two methods.

The delegated methods are basically "freebies".

Twenty-plus methods simplified to two methods -- it's been a very good day in the land of normalized objects!
    Turtle
------------------------
(components/ivars)
shape
(behaviors/methods)
drawOn(canvas)*
moveBy(vector)*
scale(factor)*
setColor(color)*
setStyle(style)*
turn(angle)
forward(dist)

*delegated method
Component "shape" is object type "Shape"