If the logic operates on interface members, as opposed to implementation members, then writing a helper method [or extension method] is advised.
public IRandom
{
byte NextByte ();
}
public static class IRandomExtensions
{
// logic that acts against public interface IRandom
// may be applied to all implementations
public static int GetNextUnbiasedInteger (this IRandom random) { }
public static IEnumerable<T> Shuffle<T> (
this IRandom random,
IEnumerable<T> items) { }
}
If business logic operates against implementation members,
public class SomeCommand : ICommand
{
// an implementation-specific member, NOT a member
// of ICommand
public int SomeControlCount { get; set; }
}
// a method that references implementation-speciic
// details. where should this go?
public void DoSomething ()
{
SomeCommand command;
int count = command.SomeControlCount;
}
then likely we should more tightly bind this to the implementing class. If this is a common enough occurrence, then a base class may make sense.
Personally, complex hierarchies are more trouble than they are worth, use your own judgement with respect to maintainability, legibility, and reuse, and you should be ok!
Hope this helps! :)