Suggestions for decoupling units?

From: Raptor (bogus_at_none.com)
Date: 02/23/05


Date: Tue, 22 Feb 2005 17:38:53 -0800

It made sense to put all the string stuff in a strings unit, the file stuff
in a files unit, etc. Until, that is, I wished to use a single unit in
another project and discovered that everything was connected to everything
else. Not good. I was sucked into that kind of code organization, one Uses
at a time.

So last evening I started refactoring my app to eliminate unit
interdependence.

Ran across this today, in an article on "Xtreme Programming."

"All code should be refactored as often as possible. Refactoring is a
process of improving a code's structure without changing its functionality.
Refactoring produces highly decoupled objects which makes them easy to test,
easy to use, more flexible, and therefore, more changeable."

Seems to fit my experience. "Decoupling" sounds good.

I'm presently defining decoupling, and a decoupled code unit as:

a) having only standard Delphi libraries in the Uses clauses,
b) communicating with the rest of the program entirely through an object
structure if possible, and
c) not requiring custom internal tailoring to fit each project.

I've started with my menus unit. At present I place the arrays of strings
with which I create the menus in the uMenus unit. That's easy enough to pass
as a parameter, I imagine.

My event handlers, though, are presently written like this:

procedure TEventHandlers.MenuOnClickEvent(Sender: TObject);
var
  s: string;
begin
  {case MenuItem.Name of} s := TMenuItem(Sender).Name; if
  'mnuFile0' =s then begin end else if
  'mnuFileNew1' =s then begin end else if
  'mnuFileOpen1' =s then begin end else if

where the "begin end" is replaced with something like

'mnuFileOpen1' =s then DoMenuFileOpen else if

I place this in the uMenus unit as well, which would mean rewriting the unit
for each new project. To decouple per the rules above, I'd need to place
this code outside the uMenus unit and pass it as a something like a
Menus.EventHandlers parameter. I'm unsure how to do this.

I'm presently defining

type
  TEventHandlers = class
    procedure PopupOnClickEvent(Sender: TObject);
    procedure MenuOnClickEvent (Sender: TObject);
end;

var
  EventHandlers : TEventHandlers;

and using it in my code like this when I create a menu item

MenuItems[i].onClick := EventHandlers.MenuOnClickEvent;

How would I do that inside my TMenus class? I'm guessing it would take some
form like

type
  TEventHandler = class
    procedure OnClickEvent (Sender: TObject);
end;

type
  TMenus = class(TComponent)
  private
    fEvents: TEventHandler;
  protected
  public
  published
    destructor Destroy; ...
    constructor Create ...
    procedure CreateMenu ...
    procedure EventHandler: TEventHandler read fEvents write fEvents;

Raptor



Relevant Pages

  • Re: [QUIZ] Dice Roller (#61) ([SOLUTION])
    ... string. ... not been merciless enough when refactoring. ... a comment about one of the parse regexps and a comment in the tests about Fixnum and class methods. ...
    (comp.lang.ruby)
  • Re: Design Patterns
    ... Buy, borrow, or steal a copy of Refactoring by Martin Fowler. ... switch statement to do this, but wanted to try to use UML as a learning ... object CompareValue, string CompareToValue, ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: Refactoring into ravioli code
    ... public String[] matchNamesThatStartWith (String matchMe) { ... Readability over overly merciless refactoring every time ...
    (comp.object)
  • Refactoring into ravioli code
    ... WikiPedia would seem to disagree but I would see ravioli as an example ... public String[] matchNamesThatStartWith { ... iterates the list calling a test method implemented in specific ... Readability over overly merciless refactoring every time ...
    (comp.object)