If you drop a rock in a pond, the still water will ripple as a reaction to the rock.   This one action propogates ripples throughout the pond, maybe even reaching the farthest shores.   This example illustrates something that is not orthogonal.   One change in the pond, the presence of the rock, created changes throughout the whole pond.
In math orthogonal lines are defined as the following: |
This math example relates to orthogonality because a change in one part of your program (moving along the X-axis) should not affect a separate part (the Y value).
Event Planning
When you are planning an event such as a wedding reception or a business function, you want to make things run as smoothly as possible.   Even though events are inherently time-coupled, you can try to decouple as much as possible.   Here are some things that might be done:
Since responsibilities are clear-cut, if someone gets sick, it is easy to see where a replacement is needed.
- Separate the tasks to be done between helpers.
i.e. Decorations, catering, invitations, etc.
- Keep the tasks separate so that each job is distinct.
i.e. Don't have the person handling the catering also pick up the decorative flowers.
- Run through a checklist to make sure every task was met sufficiently.
i.e. Make sure that the caterer got 200 servings of chicken.
This idea will be used throughout this lesson to parallel planning an event with a software process.
Concepts
- Design components that are self-contained.
- Components are independent with a well-defined purpose.
Benefits
- Orthogonal systems are easier to change and control.
- When components are independent, you can make truly local fixes. In interdependent systems, a "local" fix can ripple throughout other components.
Put plainly, orthogonality eliminates effects between unrelated things.Productivity Gains and Risk Reduction
Two major attributes of orthogonality are increased productivity and reduced risk.
Gains in Productivity
- Changes are localized.   This reduces development and testing time.
- It is easier to write small, self-contained components rather than a single large block of code.
- Promotes reuse.   When responsibilities are specific and well-defined, components can combine more easily with new ones (in other programs).
- Subtle gain in productivity when combining orthogonal components.
Component 1 => does M things
Component 2 => does N things
Combining these two components results in the ability to do MxN things.
Risk Reductions
- Diseased sections of code are isolated so it is easier to take out bad sections without affecting other components.
- Resulting system is more robust.
i.e. A ripple of errors caused by a change in code is restricted to its component.
- Easier to test and thus better tested.
i.e. Tests are easier to design and run on smaller components.
- System won't be as closely linked to a certain vendor, product, or platform.
The tasks need to be well-defined responsibilities with minimal overlap.
The task separation depends on:
Here are the necessary steps:
- The project.
- Any areas subject to change.
- The number of people available.
With orthogonal groups, if a change needs to be made, the whole team does not need to discuss it.   Only the subteam making the change will need to meet since their responsibilities are separated from the other subteams.   Even though tasks are distinct, it is still a good idea for subteams to communicate.
- Separate infrastructure from application.
Each major component will have its own subteam.   i.e. database, communications, interface, and middleware.
- Divide the application functionality between members of subgroups.
Task Separation in Event Planning
For the event a different group will be in charge of these areas:
- Decorations
- Catering
- Invitations
- Entertainment
- Location arrangements
Each has distinct responsibilities, so if the menu changes, only the catering group will have to meet to coordinate the change.   Some groups might have to talk a bit.   For example, the decoration group will need to know if their decorations will fit in the location provided.
Synonyms: orthogonal systems, modular, component-based, layered.
Systems are made of cooperating modules, each independently implementing its functionality.
Modules are sometimes layered:
- Each layer is an abstraction that uses the abstraction below it.
- The bottom layers are flexible to change without affecting code.
- Layering reduces large dependencies between modules.
Question: If I change the requirements of a function, how many modules are affected?
The answer should be 1.
Good Advice: Don't rely on properties of things you can't control.   Your design should be decoupled from changes in the real world.
i.e. You shouldn't use a telephone number as a customer ID in case area codes change.Design in Event Planning
The teams should work together.   The invitation people can give the other groups an idea of how many people RSVP'd.   The location group picks a location that will accomodate all the people.   Then upon these things, the decorators and entertainment groups can know their space provided and the caterers can estimate how much food is needed.   The decorators also can work upon what the location provides them with.
As for the good advice...Suppose the event is outside.   The decorators should provide for a chance of rain.   A canopy may be put up or there just in case.
Ways to keep code orthogonal:
- Keep code decoupled => "shy code".
Modules shouldn't share anything unnecessary or rely on each other.
- Avoid global data.
Global data ties modules together that share data.
Code is easier to understand and maintain if data is explicitly passed in.- Avoid similar functions.
Duplicate code reflects structural problems.Making an Event Happen
The catering group does need to know how many RSVPs the invitation group received, but it doesn't need to know who RSVP'd.
The catering people shouldn't prepare tablecloths and centerpieces because this would duplicate the decorating committee's job and show a problem in the structure of group responsibility.
With an orthogonal system, system testing can be performed at the individual module level.   Unit testing is easier to specify and perform than integration testing.
Suggestion: Use built-in unit tests that run at each build process.
There should be only one module to build and link a unit test.
Only one module should be needed to fix a bug.
When one fix is made, the problem should be fixed not create more problems.Testing the Event
The different groups can perform unit testing on their part of the project to make sure they are on track.   The decorations committee can check to see if their decorations will go up properly and if they fit the location.   The catering committee can have their menu taste-tested.   The invitations committee can retally their RSVP list.   The location committee can make sure all the permits they need for the location are approved.   The band can make sure that all their equipment works properly and fits in the space the location provides.
You are writing a class called Parser that parses input lines into fields.   Here are two examples.   Which Java signature has a more orthogonal design?
Example 1
class Parser 1 {
      public Parser1(InputStreamReader rdr) { ...
      public void readNextLine ( ) throws IOException { ...
      public int numFields ( ) { ...
      public String getField(int fieldNo) { ...
}
Example 2
class Parser2 {
      Parser2(String line) { ...
      int numFields ( ) { ...
      String getField(int fieldNo) { ...
}
Answer
Class Parser2 is more orthogonal.   It parses lines without focusing on details such as where the lines came from.   Since it focuses on its own job, it makes the code easier to develop and increases flexibility.   Parser2 can parse lines coming from a file, created by another routine, or passed in through the environment.