Eliza 0 - Getting started - a skeleton app

by Ravi Bhavnani


This initial version of Eliza is a stub (i.e. a skeleton) of the full-blown version of Eliza that will eventually be written.  In its initial form, Eliza will behave like a parrot; it'll simply echo what the user says until the conversation ends. Eliza assumes the user wants to end the conversation if they type "BYE".

Although this version of Eliza is simplistic, it demonstrates several important software enginering concepts:

  1. Modularization and separation of concerns
  2. Generalization of behavior (by expressing the behavior of a class in an interface)
  3. Information hiding

Modularization and separation of concerns

The two modules in our initial version of Eliza are:

  • a "driver" program
  • the logic of Eliza
The driver program has no idea how Eliza works.  It simply calls Eliza in a loop until the conversation ends.  It's highly unlikely that the driver program will change over time.  But it's almost certain that the code within Eliza will grow and improve over time.

This allows one piece of software (Eliza) to evolve over time without impacting other pieces (the driver program), because the 2 modules (the driver and Eliza) are concerned with different things.

Real-world example

A car needs a fuel tank (to hold fuel) and a radiator (to help cool the engine). Although both items are required in the final assembly of a car, they function independently and can each be repaired/replaced without impacting the other.

Generalization of behavior (by expressing the behavior of a class in an interface)

An interface (in C# and Java) is a "contract" - i.e. a promise to offer specific behavior. This allows for different versions of Eliza (i.e. "different implementations of the interface") to be used by the driver program, so long as each implementation fully honors the contract described by the interface.

Real-world example

Lamps use light bulbs. A light bulb's interface is defined by the following contract (i.e. agreement):

  • I will have a base that can be screwed into a standard lightbulb socket.
  • I will give out light when you send an electric current through me.

There can be many implementations of this interface - i.e. many brands of lightbulbs. For example:

  • GE 100W clear bulb
  • Philips 60W Soft White bulb
  • 10W Soft Glow Nightlight
  • Sylvania LED bulb
  • etc.

all of which honor the contract defined by the light bulb interface.

In C# and Java, interfaces (by convention) are defined in a file whose name begins with "I" - e.g. ILightBulb.cs, while implementations of an interface leave off the "I" e.g. GE100WattClearBulb.cs, Philips60WSoftWhiteBulb.cs.

Information hiding

It's a good idea to publicize as little of a class to code that consumes the class. This allows you to modify the internals (the private parts) of the class at will, as long as you don't break the public view of the class.

Real-world example

A bulb's filament (a private part of a bulb) can be improved upon (and changed) by the manufacturer over time, without affecting consumers who buy bulbs.

In C#, we hide information (variables and methods) by preceding them with an access modifier keyword such as "public", "private", "protected" and "internal". If you omit an access modifier, the compiler assumes you mean "internal".

Suggestion:
ALWAYS explicitly specify the access modifier of a variable or method, as this will force you to stop and think about the item's visibility level.
 

Most of the content at this site is copyright © Ravi Bhavnani.
Questions or comments?  Send mail to ravib@ravib.com