VB.NET Interfaces – Understanding and Implementation

interfacesvb.net

Im working on a small program and I thought i would use it as a chance to get a better understanding of things I haven't really used before, mainly Interfaces and Inheritance from base classes.

Basically it is a facility use request program and after a request is made it needs to email the requester all the information they filled out. The form breaks down into main request information(contact, group name, etc..), facility rooms, facility & room equipment, requested dates, optional external document. I've separated each section of the form into their own custom class so I can easily pass information between layers but when putting information into email template I ran into an issue. Request information and external document information will only appear once per request so I can easily just find and replace the placeholders I setup. The other classes however can have multiple instances per request. The way I set up to get around this was this

I created 2 interfaces

Public Interface SingleInstance
   Public function PlaceHolderReplace() as Hashtable
End Interface
Public Interface MultipleInstances
   Public function PlaceHolderReplace(mi as string 'multiple instance place holder to replace) as string
end Interface

With these setup I realized the replace function for each class would be the same based on how many instances of the class there were per request so I decided to create 2 base classes that implement the interface from above.

Public Class SInstance
Implements SingleInstance
   Public function PlaceHolderReplace() as Hashtable Implements SingleInstance.PlaceHolderReplace
      (code adding placeholder names and class property values to hashtable)
   End Function
End Class
Public Class MInstance
Implements MultipleInstances
   Public function PlaceHolderReplace(strPlcHolder as String) as string Implements MultipleInstances.PlaceHolderReplace
      (code to loop through all properties of current class and make changes to supplied string and return string with replacements)
   End Function
End Class

So far this is working out I can combine each set of single or mutliple instance type classes into 2 lists of interfaces and pass them through to the necessary replacement procedures I have. The single instances just loops through each returned hash table and make the replacements. The procedure to replace all multiple instance isolates all repeating data placeholders and loops through all classes in the interface returning a combined string for all instances of the specific class. As I was building the this I came across several questions that I couldn't really answer.

  • Is this really the best use of Interfaces? It makes sense for inheritance because each class can run one of two functions so creating two base classes and just using inheritance to determine which one to run makes sense. The issue is the interfaces are only implemented in one class each so really they only exist so that I can put classes that aren't related into one list.

  • Is this affecting performance? With the multiple instance classes because they are unrelated putting them in a single list causes me to have to check the current class and match the property placeholders against what is in the repeating data place holders to make sure they exist before replacing them. Alternatively if I just call each classes function explicitly I would still have to check the repeating data place holder anyway to find out which one to run. They way I have it set seems like it would take longer because each repeating data place holder has to loop through every class in the list even if they are unrelated.

  • Is this the best way for me to test how interfaces work? It would really be nice to have something to refer back to if I have a brain fart. Since all I get is the ability to put unrelated classes into a single list and that might be affecting performance.

I could see how this setup would help when this program needs to expand which I have been told is almost guaranteed to happen but if it is going to expand I don't want performance to suffer due to the way I set it up. Any help with these questions would be great thanks.

Best Answer

In my opinion you picked a fairly interesting, but less typical example to understand "how interfaces work". Nevertheless it is a valid use case.

An interface serves multiple purposes. First, they act as an contract between two parties on how they can interact together, or how some kind of exposed functionality is to be used. Ok, for a fully complete and valid contract we would need some more things, but let's just focus on the code part. The interface describes what methods are available, and what their args and return values are. It's not only for documentation, also tools like the compiler get the information how to set up things properly when an interface method gets called.

Interfaces are also commonly used to decouple things, this is an important and inherent part of their nature. The interface designed above can be implemented by, say, three different classes. These classes do not have to have an common ancestor, as it would be necessary with normal inheritance. They can be completely different in nature, they may even be implemented using different programming languages (the latter has become less important with .NET but was an important point with COM).

A third aspect is, that a given class may implement multiple interfaces, but does not necessarily have to implement all of them. This is quite useful, for example:

  • A newer version of an (published) interface becomes available. Older clients can still use the old servers, newer clients ask whether or not a particular interface is supported or not an react appropriately.

  • A particular implementation only supports certain aspects of a feature set (for whatever reason). Same here, the client asks for the interfaces he may need and reacts appropriately, depending on the support provided by the server.

  • Often different interfaces serve completely different purposes, thus are separated into smaller logical pieces. Smaller interfaces help to stay more focused on a certain task, they are also typically much easier to handle and implement.

  • The support of a particular interface signals a specific trait. For example, with C# the IDisposable interface is used to indicate the needs for a special cleanup treatment to release a certain critical resource properly.

What you did above is more or less a variant of the latter. You basically have lists of elements who either implement the one or the other interface, providing you with the information about the appropriate treatment of that instance. In your case there is no need for the common feature set to be exposed via interface, you already express this via inheritance.

That's fine, however you could improve the approach by putting all instances into only one single List (Of Object) or List (Of IMyBaseInterface). To query all elements, you would have to iterate through that list, check which of the two interfaces is supported by each entry, and react appropriately.

Regarding the performance aspect: Im not an VB specialist, but I would doubt that even in VB querying interfaces and calling interface methods will be a performance bottleneck, unless you do a really large number of such operations quickly, e.g. in a loop.

Related Topic