Fog Creek Software
Discussion Board




Programming to Interfaces

A while ago, I was reading (can't remember where for the life of me - maybe here?) about programming to interfaces with regard to good programming practise.

Well, right now, I'm practising and I'm a little excited. I could always see that it made sense to do it, but now that I'm doing it, I can't believe I've never done it!

The project is in VB6, but that doesn't seem to affect my ability to do it. I'm making generalisations out of VBs strongly typed forms (as in MainForm is TypeOf MainForm) to handle things like the toolbar buttons on the mainform, status bar messages etc. It's brilliant.

Has anybody else had a similar experience?

Geoff Bennett
Sunday, May 25, 2003

Sounds like you're starting to see the benefits of object-oriented programming.  Kind of a nice experience, huh?

I have experienced similar bouts of, "You know, this whole inheritance thing is pretty neat. Someone should tell other programmers about this!"  *grin*

What I enjoy most is learning about a new technique or technology and it "clicking in" with a bunch of problems I had encountered over the years for which it would have been a perfect solution...had I only learned about it earlier.

I experienced this quite a bit when I first learned object-oriented programming, and continue to experience it as I learn more about the (very large and very useful) set of classes comprising the .NET Framework.

Dave
Sunday, May 25, 2003

I've been using OOP for a little while now, but programming directly to classes, instead of interfaces. This resulted in more code sometimes to deal with explicit instances of objects (as in the form example above).

Now I can test to see if the ActiveForm supports a particular interface (as in IList) and then react to that, instead of testing to see if the form was a particular class (as in frmStudents)

This cut one routine down from hundreds of lines to about 30. I have three interfaces, IList, IDetail and IPrint and the main form has a single method that any children can call when they need to reflect their state change in toolbars/status bars etc. The code now looks like this:

dim frmList as IList
dim frmDetail as IDetail
dim frmPrint as IPrint

if not (ActiveForm is nothing) then
  if typeof ActiveForm is IList then
    set frmList = ActiveForm
    SetToolbarState(tbNew, frmList.CanAddNew)
    SetToolbarState(tbOpen, frmList.CanOpen)
    SetToolbarState(tbDelete, frmList.CanDelete)
  end if
  if typeof ActiveForm is IDetail then
    ...
  end if
  if typeof ActiveForm is IPrint then
    ...
  end if
end if

Then in the event for the relevant toolbar button in the main form, it does the same basic thing (error handling omitted):

private sub AddNew()

  dim frmList as IList

  if not (ActiveForm is nothing) then
    if typeof ActiveForm is IList then
      set frmList = ActiveForm
      frmList.AddNew
    end if
  end if

end sub

Now each form in the application inherits one or two of those interfaces, and I don't have to code for that fact. When I add a new form, I just implement them and it automatically gets integrated with the main form.

It's beautiful.

Geoff Bennett
Sunday, May 25, 2003

It is a beautiful thing, but let me inject a note of caution here.  Often when programmers get a taste of the representative power of OOP, they go Object Happy and make EVERYTHING into an interface. 

I've seen plenty of code where IBar objects talk to IFoo objects, but the only implementors of IBar and IFoo are Bar and Foo classes, and they're in the same executable!  Worse, frequently people cast back out of the interface to the concrete class because they know that an IFoo is always a Foo object -- in which case, what's the point? Having a nice, crisp, abstract, well-defined interface to a class is great, but you need to use it judiciously.

The thing to keep in mind is the difference between IS A and CAN DO.  Interfaces represent CAN DO relationships.  If the object implements IFrobnicator then the object CAN DO frobnication.  If the object inherits from Frobnicator then the object IS A frobnicator. 

Or, another way to look at it is that classes say "I care deeply about the implementation details" but interfaces say "I care nothing about the implementation details."  When you say "Dim X as MyFrobnicator" then you want X to be a specific kind of Frobnicator.  When you say "Dim X as IFrobnicator" then you don't care how X works as long as it can Frobnicate.  This is a subtle difference! 

Good luck!
Eric

Eric Lippert
Monday, May 26, 2003

Yeah, you can go object mental if you are not careful. You can also get a lot of people who invest a lot of time in code structure elegance and lose sight of the project goal. Ultimately your implementation has to go somewhere.

Did a lot of it in my recent project and pulled it off. Needed to rip the GUI out of a static application and have it work remotely (essentially converting calls to local methods to something that can be called remotely). A lot of interfaces to abstract out fundamental classes (a bit too much actually, but I wasn't familiar enough with the code to make exceptions) so the same code can execute as normally or remotely. This means that I could write a third implementation, a test mode which is somethign that I really desperately need (500+ datapoints to cover).

Richard
Tuesday, May 27, 2003

However if you're writing in VB it's near mandatory to create a true seperate interface, otherwise upgrading will bite you. We have stuff like:

Dim Account as IAccount
Set Account=CreateObject("MyObject.ClassAccount")

And a seperate IDL which shows the Interface to the account class. This means you can stop having to use the binary compatibility switch in VB and get most of the early binding advantages without the pain later.

Peter Ibbotson
Tuesday, May 27, 2003

I organized my CAD/CAM user interface around interfaces in the most recent version. It goes

Core Objects - > UI Interfaces/Application -> Command Objects -> UI Object/ UI Forms Interfaces - > VB Forms.

The only thing in my EXE now is a bunch of forms implementing the UI Forms Interfaces and registering themselves on start up.

Core Objects are manipulated through Command Objects which implement the Command pattern from the GoF Design Pattern. Which allows me to have full undo/redo capability in my software.

One advantages is that I can have the UI look however I want by creating a new executable with the forms implementing the interfaces.

To change the UI and what commands are avaliable (like for a Lite version of the software) I replace both the EXE and the UI Objects/Forms Interface.



Robert Conley
Tuesday, May 27, 2003

*  Recent Topics

*  Fog Creek Home