Software Design and Structure

img1.gif

A computer system consists of more than just a program.  As programmers we focus mostly on the software.  Since they make the software by typing, programmers are inclined to START with typing.  However, this can lead to messy, poorly planned software that either works poorly or never gets finished.  It's like buying a bunch of bricks and starting to build a house without making a plan first.

A better diagram puts the program at the end of the design process - good developers follow a process like:

This puts the program at the end of the process, rather than in the middle or the beginning.

img2.gif

As beginning programmers you still don't know what is possible because you don't know the entire language yet.  That makes planning and design pretty difficult.  So we will still start with demo programs, but you should at least try to think about users and design - especially the place of Objects and Classes in OOP.

OOP Design

Good Object-Oriented Programs use lots of classes to keep features clearly separate.  This makes it easier to track down errors and make changes in the program.  A common design pattern for a Java program is based on the model shown above, with 5 components:

In PC's, the Input and Output are usually lumped together into the User-Interface.  The rest should be clearly separated.  That means a good program should have separate classes or methods that deal with data files.  These should not be mixed together with the I/O methods and classes.  

Keeping things separated requires a lot of data-flow (arrows above) -  data moving from one module to the another and back again.  At the I/O end, data-flow is generally pretty simple and involves only primitive data types.  But on the back-end data items get lumped together into larger structures.  We need to use these data-structures to pass data from one method to another.  Examples of data-structures include:

We might try to prevent lots of data-flow by using global variables - keeping all the data in one part of memory that is accessible to all parts of the program.  But this often causes conflicts when one method unexpectedly changes some data, interfering with the function of another method.

In OOP, objects allow us to package any set of data together and then copy it from one part of the program to another.  Classes allow us to separate functionality (features) into clearly separate parts of the program.  If classes are well designed, they can be re-used many times to make many similar objects.  Even better, well designed classes can be re-used in many different programs.  You do this all the time in Java, when you use the String or Math or BufferedReader classes in your programs.

We will use our Attendance Applicationn to illustrate and learn some of the programming and structure techniques associated with good OOP.

Basic Application Structure 

The diagrams below outline a basic concept for constructing an OOP application.  You can write multiple classes in a single .java file.  Only the first class can be public, and it must be named the same as the file.  The rest of the classes cannot be public.  Any class that extends EasyApp will display a window.  Others, like data, will not be displayed - they are used to store either data or algorithms.  

 Standard Structure

 img4.gif

 Standard App Code File

  import ...

 public class App extends EasyApp
{
public static void main(String[] args)
{ new App(); }
    Button ...
Menu ...
    public void actions...

}
 class Inputs extends EasyApp
{ public Inputs()

{ ... }
}
 class Outputs extends EasyApp
{ public Outputs(.. parameters ..)
{ .... }

}
 class Data
{ String name;
int value;
String moreInfo;
...
}
 class Search
{ public Search(String find, Data result)
{ for ...
..
}
}  

We will continue our construction of an Attendance App based on the basic structural concepts above.

 

import java.io.*;                  // imports only once at top of file
import java.awt.*;

public class AttendanceApp extends EasyApp
{
   public static void main(String[] args)
   {  new AttendanceApp(); }

   Button bTake = addButton("Take Attendance",50,50,150,50,this);
   Button bCount = addButton("Count Attendance",50,150,150,50,this);
   Button bDate = addButton("Print Date",50,250,150,50,this);

   public void actions(Object source, String command)
   {
      if (source == bTake)
      {  new AttendanceTaker(); }
      else if (source == bCount)
      {  new AttendanceCounter(); }
      else if (source == bDate)
      {  new DatePrinter(); }
   }   
}

class AttendanceTaker extends EasyApp   // EasyApp makes a Window and controls
{
   public AttendanceTaker()
   {
      try
      {
         PrintWriter file = new PrintWriter(
                               new FileWriter("c:\\attendance\\mulkey.txt",true));
                             // APPENDS to the file because of ,true
                             // If file doesn"t exist, it will be created (empty)
                             // If Folder or Drive doesn"t exist, an error occurs
         String name;
         do
         {
            name = input("Name");
            if (name.equals("quit"))    // don"t write "quit" into the file
            {   file.println("---");  }   // print line --- at end of date 
            else
            {   file.println(name); }    
         } while (! name.equals("quit")); // stop when user types "quit"
         file.close();
      }
      catch (IOException ex)
      {  output(ex.toString()); }         // Display error-message
      dispose();                       // close window when finished
   }
} 

 
class AttendanceCounter extends EasyApp
{
   public AttendanceCounter()
   {
      try
      {
         String find = input("Type a name to count");
         BufferedReader file = new BufferedReader(
                                 new FileReader("c:\\attendance\\mulkey.txt"));
         String name;
         int count = 0;
         while (file.ready())
         {
            name = file.readLine();
            if (name.equals(find))
            {  count = count + 1;  }
         } 
         file.close();
         output(find + " found " + count + " times."); // print once at the end
      }
      catch (IOException ex)
      {  output(ex.toString()); }
      dispose();
   }
}

class DatePrinter extends EasyApp
/****
BEFORE - the text-file contains attendance information in this format:
   Date
   Name
   Name
    ...
   Name
   ---

PROCESS -
   open the file
   input a DATE
   loop through the file, reading each line, looking for the DATE
      when it finds the DATE
      continue through the file, reading NAMES
         output each NAME
      stop when you get to "---"
      then quite altogether
   if it gets to the end of the file, stop

RESULT - 
   A list of names on the screen showing who was absent that day
   
*****/
{
   public DatePrinter() 
   {
      try
      {
         BufferedReader file = new BufferedReader(
                                new FileReader("c:\\attendance\\mulkey.txt"));
         output("Does nothing yet");        
         file.close();
      }
      catch (IOException ex)
      {  output(ex.toString()); }
      dispose();
   }         
}