Home All Groups Group Topic Archive Search About

How broad should an interface be? Advice needed.

Author
28 Nov 2006 1:13 AM
eric.burgin
I have not heavily used interfaces in the past so I am looking for
advice.  An interface may not be the best solution but it was the first
idea I had and was working at first.

Here is the situation, I have been asked to create an application that
will provide a "script" of things to say, yes/no questions to ask,
information to look up etc.

This could be used by multiple clients to I am creating a class library
to implement the functionality.  I have created a class Script that
contains a collection of steps in the script and a property CurrentItem
that returns the current step in the script.

I originally thought I would create an interface iScriptItem, have each
type of item implement it, and make the CurrentItem property of Script
an iScriptItem.

iScriptItem contained three properties: ID, Text, and Type

So from the client, we could move through the items in the script like
this:

Dim myScript as New Script

Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnNext.Click
    myScript.MoveNext()
    ConsoleWriteLine(myScript.CurrentItem.Text)

End Sub


This works great.  The problem is when I get to the point where my
script steps have different properties, for example,
I have a "Statement" step that displays text to the user.  It has the
property "NextItem"
I also have a "Question" step that has two properties called "YesItem"
and "NoItem" and does not need a NextItem property

The problem is, in the code above, these properties are not available
because CurrentItem is defined an an iScriptItem.

So here is my question.  Is it better to have the interface contain all
the properties that may be used in the different item types (even
though they won't all be used by all the types), leave the interface
simple and use CType to convert CurrentItem to the correct type of
object (based on the type property), or some better way to do it?  Is
my design idea just way off?

Again, I don't have a lot of experience with interfaces so this may
have been the wrong way to go about this.  I don't have a lot of code
written as I am really in the early design phase and it's mostly on my
white board :)

Author
28 Nov 2006 3:31 AM
Robert
Show quote Hide quote
> This works great.  The problem is when I get to the point where my
> script steps have different properties, for example,
> I have a "Statement" step that displays text to the user.  It has the
> property "NextItem"
> I also have a "Question" step that has two properties called "YesItem"
> and "NoItem" and does not need a NextItem property
>
> The problem is, in the code above, these properties are not available
> because CurrentItem is defined an an iScriptItem.
>
> So here is my question.  Is it better to have the interface contain all
> the properties that may be used in the different item types (even
> though they won't all be used by all the types), leave the interface
> simple and use CType to convert CurrentItem to the correct type of
> object (based on the type property), or some better way to do it?  Is
> my design idea just way off?

You seem to have 3 types of items: Scripts, Statements, and Questions.
So, define 3 interfaces: Scripts, Statements, and Questions.

Some of your objects might have one implemented, others might have two.

Try: Implements IScript, IStatement. The new TryCast statement might
be of use..

Interfaces are more useful between projects.  This way you can have a
consumer of your logic pass in a custom object to be processed.

I do not see any gains from having unused properties on some objects.
Author
28 Nov 2006 4:28 AM
eric.burgin
Script has a property called CurrentItem.  This property can contain
one of any type of item that can be in the script: Statement, Question,
etc. (I think there are 5 total)

What I was trying to do was make CurrentItem a "generic" type
iScriptItem that would return  any of these types of items.

The ways I'm thinking of doing it are:
  Have Statement, Question, etc implement iScriptItem OR
  Have Statement, Question,, etc inherit from an abstract base class
ScriptItem


In either of these scenarios, the client code will need to convert the
CurrentItem property to a object of the correct type before accessing
the derived class' specific properties.

Are either of these approaches the "right" way or am I missing
something?

The other option I can think of is  have only one type of object
ScriptItem that contains ALL the properties including a "Type" property
that indicates what this ScriptItem object represents

I guess what it boils down to is I have an element(a property in this
case but it could as easily be a function) that could return one of
multiple types of objects.


Robert wrote:
Show quoteHide quote
> You seem to have 3 types of items: Scripts, Statements, and Questions.
> So, define 3 interfaces: Scripts, Statements, and Questions.
>
> Some of your objects might have one implemented, others might have two.
>
> Try: Implements IScript, IStatement. The new TryCast statement might
> be of use..
>
> Interfaces are more useful between projects.  This way you can have a
> consumer of your logic pass in a custom object to be processed.
>
> I do not see any gains from having unused properties on some objects.
Author
28 Nov 2006 3:16 PM
Branco Medeiros
eric.bur***@usbank.com wrote:
<snip>
> Here is the situation, I have been asked to create an application that
> will provide a "script" of things to say, yes/no questions to ask,
> information to look up etc.
<snip>
Show quoteHide quote
> I originally thought I would create an interface iScriptItem, have each
> type of item implement it, and make the CurrentItem property of Script
> an iScriptItem.
>
> iScriptItem contained three properties: ID, Text, and Type
>
> So from the client, we could move through the items in the script like
> this:
>
> Dim myScript as New Script
>
> Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles btnNext.Click
>     myScript.MoveNext()
>     ConsoleWriteLine(myScript.CurrentItem.Text)
>
> End Sub
>
>
> This works great.  The problem is when I get to the point where my
> script steps have different properties, for example,
> I have a "Statement" step that displays text to the user.  It has the
> property "NextItem"
> I also have a "Question" step that has two properties called "YesItem"
> and "NoItem" and does not need a NextItem property
<snip>

Instead of interface, I'd base the different items on a base class.
That's because the base class plays the role of stablishing a base type
*and also* providing a common ground functionality for things such as
the MoveNext method you refer in the snippet above. I'd take the
interface route only if planning to have completely disparate object
types to become script items. Even then, maybe I'd prefer a
"ScriptItemAdapter" type (based on the base class) that would accept
implementors of a given interface.

Also, I guess you'll find it helpfull to have an enumeration for the
different types of ScriptItems. It will make it easier to select a
specific cast (instead of using TryCast for each different type):

  <aircode>
    Dim SKind As ScriptItemKind = ThisItem.Kind

    Select Case SKind
    Case ScriptItemKind.Statement
      Dim S As Statement = CType(ThisItem, Statement)
      ...
    Case ScriptItemKind.Question
      Dim S As Question = CType(ThisItem, Question)
      ...
    Case Else
    'Oops, an unknown kind!?
    'raise error or else
    End Select
  </aircode>

HTH,

Regards,

Branco.