|
| Re: Interface inheritance |
 |
Tue, 4 Mar 2008 08:21:32 -0500 |
On Tue, 04 Mar 2008 13:46:49 +0100, Christian Kaufmann wrote:
> Now I think it's better to avoid inheritance of interfaces and if I
> need the Id() method then I just add that to the IEvent interface.
>
> Other programmers in our company prefere to use interface inheritance
> because with this you can save some typing.
>
> So I'm looking for arguments pro or contra interface inheritance. When
> does it make sence, when is it better to avoid and why?
I have found, more than once, that I have gone the easy route
(inheriting) and have regretted it later because I could not reuse the
interfaces somewhere else or change to a cleaner model.
You really shouldn't use inheritance because it saves typing but
because it makes sense. My rule is something along the strength of the
dependency between the two and how likely it is that I am going to
access them together. To use your examples, if I am editing an item I
am always going to combine saving the values with loading them so it
makes sense to inherit, but the saving and loading has nothing to with
the application's use of your code, or observing changes.
--
Marc Rohloff [TeamB]
|
| Post Reply
|
| Re: Interface inheritance |
 |
Tue, 04 Mar 2008 13:18:40 +000 |
Christian Kaufmann a écrit :
> Now I think it's better to avoid inheritance of interfaces and if I
> need the Id() method then I just add that to the IEvent interface.
>
> Other programmers in our company prefere to use interface inheritance
> because with this you can save some typing.
>
> So I'm looking for arguments pro or contra interface inheritance. When
> does it make sence, when is it better to avoid and why?
Interfaces describe behaviour; if behaviour A includes the elements of
behaviour B, then A can derive from B.
e.g.
IStreamable
IBusinessRule
If all business rules are allowed to be streamable then IBusinessRule
should derive from IStreamable; that way, by implementing the "larger"
interface, classes are required to also implement any interfaces that
make up the overall behaviour.
However, if you state that not all business rules may be streamable then
derivation is not appropriate.
Simpler example :
IHuman
IClever
IPerson
IPerson should inherit from IHuman because you can't have a person that
is not human, however not all persons are clever, so derivation is not
suitable :-)
Joanna
--
Joanna Carter [TeamB]
|
| Post Reply
|
| Re: Interface inheritance |
 |
Tue, 4 Mar 2008 13:24:00 -0500 |
"Christian Kaufmann" <christian.kaufmann@gmx.net> wrote in
message
news:6ngqs3ls78jc905b7vkoq8035fh8061ujp@4ax.com...
>
> //@@ general interface for all BO's
> IBSItem = interface
> end;
>
> //@@ interface to an editable BO
> IBSItemEditable = interface(IBSItem)
> end;
>
> //@@ interface to a application specific BO
> IEvent = interface
> end;
>
> Now I think it's better to avoid inheritance of interfaces and if I
> need the Id() method then I just add that to the IEvent interface.
Then you will have Id defined in multiple interfaces.
As other have pointed out, the best criteria for deciding is whether one
interface really needs the other interface to function - which means in
practice that if every object that implements interface IFoo will, by
definition, also need to implement interface IBar, then it probably makes
sense for IFoo to inherit from IBar.
In your example, any object that is editable will, by definition, also need
to be readable from data storage. Thus it makes sense that the writable
interface inherit from a readable interface.
However, your readable interface currently is tied directly to your base
business object interface. This is where I see inheritance that should be
eliminated. I often design business objects that are not, themselves, read
from or saved to a database but rather perform processes against other
business objects that are.
Thus, I would suggest something more like the following (if you really want
separate read and write interfaces):
// basic business class interface
IBSItem = interface
// whatever all BOs will have *apart* from reading or writing
end;
// interface to read from storage
IBSReadInterface = interface
procedure Load;
property ID: integer;
// etc.
end;
// interface to write to storage - **inherit read interface**
IBSWriteInterface = interface(IBSReadInterface)
function Validate: boolean;
procedure Save;
// etc.
end;
// an actual BO interface - ** inherit from IBSItem **
IEvent = interface(IBSItem)
end;
Now when you implement an object, you can decide whether it is *persistable
at all*, and if so, whether it is read-only or writable too:
TBaseItem = class(TInterfacedObject, IBSItem)
// implement IBSItem
end;
// if TEvent does not need to be read or stored
TEvent = class(TBaseItem, IBSItem);
end;
// if TEvent can only be read
TEvent = class(TBaseItem, IBSItem, IBSReadInterface);
end;
// if TEvent is writable
TEvent = class(TBaseItem, IBSItem, IBSWriteInterface );
end;
Personally, I don't see value in separate read and write interfaces, but
rather simply whether an object is subject to storage at all. After all, if
an object is readable from storage, it had to have been written by something
at some time. Further, the *same* object might be writable in one
application and read-only in another - you should not need to implement two
separate business objects to achieve this, but rather flag an individual
object as being read-only when appropriate (possibly an attribute set by a
persistence layer that can be opened as read-only).
--
Wayne Niddery - TeamB (www.teamb.com)
Winwright, Inc. (www.winwright.ca)
|
| Post Reply
|
| Interface inheritance |
 |
Tue, 04 Mar 2008 13:46:49 +010 |
Hi,
we use a lot of interfaces for our business objects (garbage
collection, circular references). Here are some examples:
//@@ general interface for all BO's
IBSItem = interface
procedure ApplyFull(const AData: IBSColumns);
procedure ApplyMinimal(const AData: IBSColumns);
function Id: Integer;
function IsNull: Boolean;
function IsSame(const AOther: IInterface): Boolean;
procedure Reload;
end;
//@@ interface to an editable BO
IBSItemEditable = interface(IBSItem)
function GetEditValues: IBSWritableColumns;
procedure SetEditValues(const AValue: IBSWritableColumns);
function Changed: Boolean;
procedure Delete;
property EditValues: IBSWritableColumns read GetEditValues write
SetEditValues;
procedure Save;
end;
//@@ interface to a application specific BO
IEvent = interface
function AgeGroups: IAgeGroups;
function BaseEvent: IEvent;
procedure ClearResults;
function Duration: TDateTime;
function Id: Integer;
function IsNull: Boolean;
function IsSame(const AOther: IInterface): Boolean;
function Number: String;
function Rounds: TBSSwRounds;
procedure Save;
procedure UpdateAgegroups(ADefaults: IBSXmlElement);
procedure UpdateAllHeatStatus(AStatus: TRaceStatus);
end;
Now I think it's better to avoid inheritance of interfaces and if I
need the Id() method then I just add that to the IEvent interface.
Other programmers in our company prefere to use interface inheritance
because with this you can save some typing.
So I'm looking for arguments pro or contra interface inheritance. When
does it make sence, when is it better to avoid and why?
|
| Post Reply
|
| Re: Interface inheritance |
 |
Tue, 4 Mar 2008 15:51:50 -0000 |
> Simpler example :
>
> IHuman
>
> IClever
>
> IPerson
I don't understand.
|
| Post Reply
|
|
|