Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- The Guide to Clip-4-Win version 3.0 - http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
  
  You've seen two versions of a browse application, largely
  introduced as finished programs and explained "after the
  design".  It's time to do things "the right way around":
  starting with the design and ending with the code.
  
  In one sense, the opposite of browsing is data input, so let's
  develop a data entry application.  It's a simple example, to
  avoid getting bogged down in the details, but let's start with
  the MDI case - removing code to make an SDI version is trivial.
  
  Even though it's a simple example, the thought-processes
  involved in OOA/D are explored in a lot of detail.  You won't
  need so much detail once you're familiar with what's involved,
  but here it's going to be stressed in the hope that you can
  refer to it if/when you hit problems during future designs.  A
  number of the steps produce very much the same results (e.g.
  candidate classes), but sometimes you find some new detail
  that justifies the repetition.  By way of an example, some of
  the steps below omit things they should include, which are
  identified in other steps (see if you can spot them).  This
  reflects the actual results obtained.
  
  Here's a simple requirements specification: Produce an MDI
  application to maintain the "Departmental 'Phone File"
  (USERS.DBF) which is shipped with Clip-4-Win.
  
  There's more than one way you can proceed.  Here are two paths
  (A and B) which are often performed in parallel.
  
  Path A
  ======
  
  You may find it helpful to identify the inputs, outputs,
  physical/conceptual things, responses, and services used and
  provided.
  
  Inputs: the USERS.DBF file, user menu choices (by mouse,
  keyboard, or even pen), user data entry.
  
  Outputs: updates to the USERS file.
  
  Physical/conceptual things: application, main window, menus,
  USERS file, the form.
  
  Responses: the user interface: the main window, menu changes
  as the user chooses, the data entry form(s).  Note: you could
  list these under Outputs.
  
  Services used: none identified so far (unspecified parts of
  the Clip-4-Win Application Classes).
  
  Services provided: none identified so far.
  
  Path B
  ======
  
  A bit of thought, drawing diagrams, etc., should get you
  something like this:
  
  (a) The application is a kind of MDI application.
  (b) The application has a main window.
  (c) The main window has a (bar) menu.
  (d) The bar menu consists of popup menus and menu items.
  (e) The menu contains an item to allow a data entry form for
      the USERS file to be started, as well as standard items
      expected of Windows applications.
  (f) The main window has a status (message) bar.  (Optional.)
  (g) More than one form can be active at a time.
  (h) The form contains input fields for the fields in the USERS file.
  
  In practice, to allow for input errors you don't want to
  update the file immediately data is entered, so some buffering
  will be needed.  (In DOS Clipper applications you've no doubt
  done this many times, using LOCAL or STATIC variables.)
  
  To reduce the amount of repetitive code, this example only
  deals with editing existing records, but in a real application
  you'd want to add/delete records as well.  Also, to keep this
  example reasonably simple, you can only move through the file
  using Next/Previous buttons.
  
  Item (h) had better change to:
  
  (h) The form contains:
       -  input fields for the fields in the USERS file
       -  buttons for Ok / Cancel
       -  buttons for Next / Previous / Save
  
  Here are possible names for classes involved with the above
  items:
  
  (a) UsersApp
  (b) UsersWindow (or MainWindow)
  (c), (d), (e) The Clip-4-Win menu classes; (e) also refers to
                UsersForm
  (f) WStatusBar
  (g) UsersForm
  (h) UsersForm, maybe a class for each field, a class for the
      file (UsersTable), maybe classes for the buttons
  
  You can identify some responsibilities:
  
       -  something (S1) has to perform input validation
       -  something (S2) has to read the USERS file
       -  something (S3) has to update the USERS file
       -  one or more somethings (S4n) have to co-ordinate the
          form's/file's fields
       -  several somethings (S5n) have to respond to button pushes
  
  Let's re-visit services used and provided.
  
  Services used: the app uses the main window; the main window
  uses the menu, status bar, and form; the form uses the input
  fields and buttons; one or more things use the USERS file.
  
  Services provided: convenient, encapsulated access to:
  windows; menus; status bar; the form; input fields; data
  validation; buttons; the USERS file.
  
  To pin down the "somethings" (S1, ..., S5n) above, you need to
  know about handling forms in general.
  
  Forms are usually implemented using dialogs, for a number of
  reasons: they can be designed easily using a resource editor
  (such as the one contained in the Clip-4-Win Toolkit); they
  provide convenient behaviour with which users are familiar;
  they automatically size themselves based on screen resolution.
  Clip-4-Win provides many dialog-related features for these
  reasons.
  
  Dialogs are actually windows with extra behaviour, so you can
  use functions relating to windows on dialogs as well.  Because
  of the relationship between windows and dialogs, Clip-4-Win's
  WDialog class is derived from a window class (WWindowBase).
  
  At first sight, the following fact is a problem: a few of the
  functions that work on dialogs can also be used on non-dialog
  windows.  However, the real problem is that the functions have
  been misnamed!  They were clearly implemented for use with
  dialogs and were named because of that, even though they are
  more general purpose.
  
  Dialogs and other windows can contain controls, which are
  themselves kinds of windows.  Controls include text, (push)
  buttons, radio buttons, check boxes, list boxes, and so on.
  
  You have two fundamental choices, which can be summarised as:
       "dumb forms with smart controls"
  or
       "smart forms with dumb controls".
  
  Arguably, Windows uses "smart forms with dumb controls";
  certainly, Clip-4-Win does.  One result is that any
  complications become part of the form, allowing them to be
  centralised nicely in many cases.  Centralised code is usually
  easier to write, understand, and maintain, so this is a useful
  benefit, whereas having smart controls too often means
  scattered logic.  Naturally, the form can make use of any
  intelligence the controls possess - the form can just delegate
  its responsibility.
  
  Validation can be a problem in a GUI environment, because
  users are allowed to complete a form in almost any order.
  Your best defence is to do only simple validation on each
  field as it's entered, leaving full validation until the user
  indicates the form is supposed to be complete.
  
  Based on the above, you might reasonably decide to do the
  following:
  
  S1 (input validation): a picture per input field, full
  validation done by the form
  S2 (read the USERS file): requested by the form
  S3 (update the USERS file): requested by the form
  S4n (co-ordinate the form's/file's fields): done by the form
  S5n (respond to button pushes): done by the form
  
  The provisional list of classes so far is UsersApp,
  UsersWindow, menus, UsersForm, WStatusBar, data input
  class(es), UsersTable, and buttons.  Are they all good
  classes?  You may not be too sure as yet whether they have
  well-defined boundaries.  Each class is going to be used in
  the guise of one or more objects, so you have to check that
  each object would have both permanence and identity.  Nothing
  looks clearly wrong, so let's continue by going into more
  detail:
  
  UsersApp:
            uses (owns) the UsersWindow object
            creates the UsersWindow object
  
  UsersWindow:
            owns the WStatusBar object
            creates the WStatusBar object
            owns the bar menu object
            creates the bar menu object
            owns the UserForm object(s)
            creates the UsersForm object(s)
  
  bar menu:
            has zero or more menu item objects
            has zero or more popup menu objects
  
  popup menu:
            has zero or more menu item objects
            has zero or more popup menu objects
  
  menu item:
            has zero or one method name to invoke if chosen
            has zero or one code block to run if chosen
            has zero or one help object
  
  UsersForm:
            owns the UsersTable object
            creates the UsersTable object
            reads data using the UsersTable object
            writes data using the UsersTable object
            moves from record to record using the UsersTable object
            has data input field objects
            creates data input field objects
            gets data from data input field objects (to write using
               UsersTable)
            changes data in data input field objects (on moving records)
            has buttons for Ok, Cancel, Next, Previous, Save
            has methods for the buttons: Ok, Cancel, Next, Previous, Save
  
  WStatusBar:
            has status text
            displays the status text
  
  data input field:
            has data
            has a picture
            has methods to get, set and update the data
  
  UsersTable:
            has a file name
            has a work area number
            has an alias
            selects a unique (new) work area
            opens the file in the work area
  
  button:
            informs the UsersForm if pushed (clicked)
  
  
  This is just the sort of information designed to be put on CRC
  cards, which is why they're so useful.
  
  Now you've got a simple model of the application, but does it
  work?  Check its life-cycle, its inputs, outputs and
  responses:
  
  Initialisation:
            the UsersApp object needs to be created
            UsersApp creates the UsersWindow object
            UsersWindow creates its menu object
            UsersWindow creates its status bar object
            UsersApp starts processing user inputs
  
  User chooses the menu item to edit a record:
            the menu item invokes a method in the UsersWindow object
            UsersWindow creates a UsersForm object
            UsersForm creates a UsersTable object
            UsersTable finds an unused work area
            UsersTable creates a unique alias
            UsersTable opens the USERS file
            UsersForm creates and initialises the data input field objects
            UsersForm creates the buttons
            UsersForm displays itself
            UsersForm starts processing user inputs
  
  User pushes (clicks on) the Save button:
            the button informs UsersForm
            UsersForm performs validation
            if valid, UsersForm uses UsersTable to update the USERS file
  
  User pushes (clicks on) the Ok button:
            the button informs UsersForm
            UsersForm tells the UsersTable object to terminate
            UsersForm terminates itself
  
  User pushes (clicks on) the Cancel button:
            same as the Ok button
  
  User pushes (clicks on) the Next button:
            the button informs UsersForm
            UsersForm uses UsersTable to move to the next record
            UsersForm updates the data input field objects for the new record
  
  User pushes (clicks on) the Previous button:
            like the Next button, but in the opposite direction
  
  User wants to exit:
            UsersWindow tells any UsersForm objects to terminate
            UsersForm objects tell their UsersTable objects to terminate
            UsersWindow tells the UsersApp object to terminate
            UsersApp cleans up
            UsersApp exits to the operating system
  
  
  You would need to add anything in the above that wasn't already
  on your CRC cards.
  
  
  Turning to Clip-4-Win's Application Classes, what is there that
  can help?  You might tentatively suggest:
  
  UsersApp: is a kind of MDI application
            inherits WMDIApp
  
  UsersWindow: is a kind of MDI main window
            inherits WMDIFrame
  
  menus:    use the menuing commands
            could inherit WMenu, but can use it as it is
            could inherit WPopup, but can use it as it is
            could inherit WMenuItem, but can use it as it is
  
  UsersForm:     is a kind of form (dialog)
            inherits WDialog
  
  status bar:
            could inherit WStatusBar, but can use it as it is
  
  data input field:
            could inherit WGet, but can use it as it is
  
  UsersTable:
            could inherit WTable, but can use it as it is
  
  button:
            could inherit WPushButton, but can use it as it is
  
  
  Yet again, you could update your CRC cards.
  
  You can now readily check that these are good classes: they
  have well-defined boundaries and any objects have permanence
  and identity.
  
  With the detail above, writing the code is mostly very
  straightforward.  Rather than list it all here, two versions
  are shipped with Clip-4-Win.  There are two so that you have
  one that works if you don't have a resource compiler and one
  that takes advantage of resources.  The files are under the
  SOURCE\OO directory as USERS\USERSMDI.PRG and
  USERSRES\USERSMDI.PRG.  Explanations of the most important
  pieces follow, but first some general information.
  
  

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson