Hi Al & welcome!
        Like yourself I too am a self-taught Delphinian, and for a long time
depended highly on the Delphi Lists as my ONLY contact with other
programmers.  Had it not been for the great people here I'd probably still
be trying to figure the basics out!
        The subject you have asked about, "the separation of business logic
and the user interface" is as apt to get you as many responses and debates
as the separation of church and state did over two hundred years ago! <g>
It's one of those topics I've found for which there not only is no
definitive answer but also no way to approach it except on an application by
application basis!  
        For me, and perhaps because when I first started coding this
particular subject was being discussed  quite a bit, it seems that almost
any type of application warrants some thought and planning in this area.
>From something very simple, like refactoring your code so that all
calculations and logic not directly initiated or caused by a user event are
moved into separate procedures and/or functions and even into separate units
when feasible, so that not only can the programmer quickly change the
interface without having to worry that in doing so he has "broken" any
logic, but also so that now these same procedures and functions can be
called if and when needed for other reasons, by other events, and at best by
other applications!
        But most programmers I've talked to about this seem to relate the
subject mostly to their writing of database applications.  I'm not sure why
they only think of it in these situations...perhaps it's because the very
nature of a database application leans toward this kind of separation more
readily, or perhaps and simply because they tend to think of the
relationships inherent to database applications as being a more literal
example of the definition implied by "business logic".  
        In any case, try not to think of the separation of logic and
interface/gui as something meant to describe a method, rule, or a solution
to be applied to a particular need, but as a design concept that you can use
to help make clear in your own head, and then in your code, as a way of
making your applications more efficient, easier to alter or update, less
prone to errors and/or obsolescence, and easier to document and share with
other programmers.  And as a side benefit, don't forget that in doing so you
may also provide yourself with code that is much easier to reuse in other
applications and libraries!
        On a more concrete level, the way I go about designing an
application is much the same as the way I was taught to design "living
systems" when I was an Architecture major in college.  It's more than likely
quite different than the methods used by most programmers, but I find it
works just as well for me no matter what it is I must conceptualize.  I
won't get into it here and now, but I will tell you how I go about ensuring
that the application as it is being coded, benefits from the separation we
are talking about.
        Let's say that I've reached a point where I have pretty much laid
out what data my application must provide it's user and how that data is to
be displayed.  This means that we have our interface...generally
speaking...and we know what data goes in and what data must come out!  I lay
these down on paper as if they were mathematical equations and then design
the methods that can take our input and work with it until it has output
which can be used to satisfy our interface's requirements.  As everything
the application does is initiated by the user's interaction with the
interface, I next decide what interface events will be used, and the order
they will be used in.  In many cases the events themselves will provide a
needed result without first having to run any real logic of consequence,
such as when a mouse-click will open a dialog that allows the user to select
a color and then makes the color change as well.  And other times, an event,
such as clicking the "enter" button, will do something a little more
complex, like doing a calculation, comparing the result against a previous
calculation, and then displaying the result in the interface.  In such
cases, I usually start by writing a function to do the actual calculations
and comparing, and then allow the event to use it.  But I NEVER write such
logic inside the event method!  
        Later on, after I've reached a point where my application is working
to some degree, I'll go back and revisit such functions to see if either the
application or I would benefit from separating it into two or more
parts...again with each part being either a procedure or function designed
for one particular purpose.  For example, in this case I might decide that
the function called will handle the calculations and send the result back to
the original event code, but then the result will be used as a parameter for
a new function to be called which handles the actual comparisons!  Why I
might decide to do these things could be as simple as my application
requiring such a calculation and/or comparison to be handled from some other
event or point within it, or as complicated as wanting to keep all logic in
a server application where it can be employed by any or all client-side
applications that must connect to it!  In any event, I've never regretted
doing this kind of refactoring even if it isn't particularly necessary for
the application at this time.  If nothing else it allows me to place such
logic into a library unit where I can always reference it later and even by
another application if necessary!  In fact, because of late I've been doing
a lot of database work, I've built up a number of units working this way
which I now can call from any DataModule I create.  And where I used to only
provide this kind of separation by using my datamodule to hold all my data
read/write code as well as all my business logic code, I now try to keep
three distinct levels of separation available in my database applications.
The interface, the DataModule, and the business logic.  And because I also
try to place any logic that might be reusable in my library files instead of
in my project files, you might say that I really keep four levels available!
        You asked about methods and/or events that can allow you to
auto-update and/or report state to and from the distinct parts of your
application...in particular, methods and/or events which are not provided by
components themselves, but must be created yourself.  
        The easiest example I can think of off the top of my head would be
the way you update a status pane at the bottom of an editor so that you
always know what column and line your cursor is currently at.  It's not
difficult at all.  But you do have to decide the most appropriate place in
your application to report these ever changing values and call the methods
you write to do the updating from that point or points!  Here's the
procedure I use to handle this.  I add it to the private section of my
Form's unit...the form on which the TMemo and TStatusPane are found:

Procedure TMemoF.UpdateCursorPosData;
Var
    CharPos: TPoint;
Begin
    CharPos.Y := MMemo.CaretPos.Y;
    CharPos.X := MMemo.CaretPos.X;
    Inc(CharPos.Y);
    Inc(CharPos.X);
    LineStatPane.Caption := 'Line: ' + IntToStr(CharPos.Y) + ' Col: ' +
IntToStr(CharPos.X);
End;

        In this situation I need only call this procedure from one place in
my code, and that is within the TMemo's Onchange event.  But many times
you'll find that it isn't always such a clear cut and defined thing to
decide!
        I could easily refactor this procedure further by separating the
actual data logic from the last line of it's code which handles the
interface display/update, however since this is purely for the sake of the
interface and is so simple, I wouldn't do so.  But each procedure or
function you write should be evaluated for such things on their own merits!
        In other situations you may have event code that you wish to call
from within code in some other part of your application.  For example, where
you must dynamically create menu items.  In this case, since the items you
will create at runtime do not even exist at designtime, you have no way of
creating their event code.  Take a menu item's OnClick event for example.
All you want each created menu item's OnClick event to do is call a
particular TAction that you have already coded, but you can't generate the
event method so that you can call the TAction in the first place!  This is
easy to deal with as well.  I'll probably get corrected for saying this the
way I am, but events can be assigned just like properties can.  So in this
example you might do the following:

MyNewMenuItem.OnClick := MyMenuItemClick;

Where MyNewMenuItem has first been created and assigned to a particular
TPopUpMenu, and where MyMenuItemClick is a procedure you wrote yourself.
        Of course there are other ways that can be employed to report
changes in state so that they can in turn be used to update, such as using
Messages.  But that is a deep subject all by itself and I wouldn't feel
comfortable addressing it here and now.
        I hope I've provided you with at least some information that you
will find useful. However, should you want to know more or to clarify
certain aspects of this or any subject, please feel free to ask away.  One
thing you NEVER have need to worry about on this list, and that is sounding
stupid or like an absolute newbie!  We all start out the same!             

from: Robert Meek at: [EMAIL PROTECTED] 
dba "Tangentals Design" home of "PoBoy"
freeware Windows apps and utilities
located at: www.TangentalsDesign.com
Proud to be a moderotor for the
"Delphi Programming Lists" at: elists.org 



-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf
Of Alan Colburn
Sent: Thursday, September 01, 2005 4:53 PM
To: [email protected]
Subject: Separating GUI from Business Class

Hi all --

My name is Al Colburn. I'm new to this list so I wanted to introduce myself.

I'd probably describe myself as advanced beginner-intermediate in my Delphi 
understanding, all self taught. (Do Delphi courses even exist? :-)

I've reached a stage where I'd really like to develop good coding habits, 
including keeping GUI code separate from the rest of an application. I'm 
writing today for any tips on how to do this. So far, I've tended to just 
create properties in a business class corresponding to user/GUI input data, 
and functions returning information corresponding to GUI output displays.

Are there other common ways to "bridge the gap" between the two (or more) 
classes? I'm told, for example, that you can create custom events in a 
business class that would automatically update the GUI anytime output values

changed. If this is something y'all recommend, I'm very much in the dark 
about how this is done--I really don't understand custom events and how they

are generated. If you could point me toward a good place to learn more on 
the topic I'd be much obliged.

Thanks, in advance. I'm looking forward to getting to know you all. -- Al C.

_________________________________________________________________
Don't just search. Find. Check out the new MSN Search! 
http://search.msn.click-url.com/go/onm00200636ave/direct/01/


_______________________________________________
Delphi mailing list -> [email protected]
http://www.elists.org/mailman/listinfo/delphi

Reply via email to