How broad should an interface be? Advice needed.

  • Thread starter Thread starter eric.burgin
  • Start date Start date
E

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 :)
 
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.
 
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.
 
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.
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.
 
Back
Top