Fog Creek Software
Discussion Board

Command structure

I have a main command class that handles all my menu and toolbar button commands, among others.  I assign a command enum to the buttons tag property or to the Help index of a menu item (also handy for obvious reasons).  In this way I can control fan in\fan out.

In the form I use:

Private Sub tlbType_ButtonClick(ByVal Button As MSComctlLib.Button)
  Call Commands.Commands(Command:=Button.Tag)
End Sub

This leaves most forms with 300 - 400 lines of code and an interface (not GUI) that seldom changes.

Is this a good way to handle this or is there a better (standard) way of accomplishing the same thing


VB Monkey
Friday, August 1, 2003

You could reduce the amount of menu code by using a bunch of control arrays, but that would create a lot more problems than it would solve.  (=

If I remember correctly, .NET solves this by allowing multiple controls to call the same event handler (which can be defined right from the forms designer).  But from your code snippet, it looks like you're using VB<=6, so again, we're adding more complexity.

The main problem with having lots of code lying around is maintainability.  It's not going to significantly affect performance, and I'd be surprised if .exe size was an issue.  Honestly, if the code works and doesn't change much, why not just push it to the bottom of the module so you don't have to look at it?  If you use the right Hungarian warts, you can even force them to the bottom of the procedure combo box.  (=

Sam Livingston-Gray
Friday, August 1, 2003

I guess I wasn't clear or I am mis-understanding you. 

I use nothing but control arrays for menu's (I have to or I would run short of indexes by half <g>) and any non-trivial control.

What I am trying to accomplish is to have a class that essentially controls ALL commands irrespective of the location it was called (Menu, toolbar, code).

So if the New Command is called from:


    Call Commands.Commands(Command:=Menu.helpindex)


    Call Commands.Commands(Command:=Button.index)


    Call Commands.Commands(Command:=ebsCommands.enNew)

The command can be called from anywhere but is executed in ONE place.

What I am asking is, is there a simpler way of doing this?

Bare in mind that I have already enum EVERY menu item string, caption, etc.  for localization so control array/enum complexity is not an issue

VB Monkey
Friday, August 1, 2003

In my consulting experience (mostly VBA office, not classic VB), the most common solution is to put the functionality in the button handler itself.  This is a terrible practice and you have wisely avoided it. 

The second most common solution is for each button to call a distinct routine that handles the functionality for that button.  This works pretty well overall but can lead to some redunancies of code.

Centralizing the calls the way you do is not done as often, but personally I think it is the way to go.  Comment very well the purpose of the Commands routine and I think the overwhelming majority of maintenance programmers will be able to follow your thinking.

I would ask myself whether the Command subroutine is better off wrapped in a class module or a standard module.  I can imagine some very good reasons for doing it either way, so just be aware of why you made the choice.

I think your approach is sound.

Ran Whittle
Saturday, August 2, 2003


Thanks for the response.

I'm curious about the class\module isssue.

I do it so if the form doesn't exist, neither does the associated commands class.

I also have a controls class to handle control events for similar reasons.

i.e.:  cmdButton_MouseUp(...

as well as a Data class that handles any data specific (DB stuff) procedures.

The only thing that I have in modules are generic items.

45 forms
175 classes
3 modules

Is this mis-guided?

Thanks again

VB Monkey
Saturday, August 2, 2003

There's really no general answer.  Just try to keeps things as orderly and understandable as possible, and put like things with like things. 

Central command switchboards with a minimum of boilerplate delegation code can be very nice and neat... different tools allow for different techniques to implement them... unless there's a good reason not to, try to follow well known conventions / patterns.

One of your chief questions seems to be: "how tightly should I couple the structure of my program to my forms design?"

Again, this depends...

Consider whether you are doing similiar things in different places that might benefit from common functionality / code.

Consider what sort of changes might be wanted in future.

Try to build things up from coherent pieces.

In classic VB I'd usually make my forms very lightweight and put heavy logic elsewhere... but there are exceptions to every rule.

Where to draw the line between greater generality / potential for reuse, and just getting something done without trying to fit square pegs in round holes... ie. 'unnaturally forcing similiarity' is maybe the #1 perpetual problems of programming in every language.

Read up on Refactoring.  Fowler's book is highly regarded.

John Aitken
Sunday, August 3, 2003

Thanks John, I'll take a look.

VB Monkey
Sunday, August 3, 2003

*  Recent Topics

*  Fog Creek Home