tags:

views:

195

answers:

4

Lets say we have this interface:

public interface ILog
{
    void Add(Message message);
}

It should of course also have some way of accessing those added messages. But what do you think is more natural and correct? That ILog implements IEnumerable property? Or maybe both? Or will having both be a bit weird and unecessary? Or should it maybe be an IEnumerator instead of IEnumerable? (Or that is maybe completely wrong? Haven't quite grasped the difference between those...)

public interface ILog : IEnumerable<Message>
{
    void Add(Message message);
}

public interface ILog
{
    IEnumerable<Message> Messages { get; }
    void Add(Message message);
}

public interface ILog : IEnumerable<Message>
{
    IEnumerable<Message> Messages { get; }
    void Add(Message message);
}

This is of course probably a bit subjective, but I would like to hear others opinion. I don't really know, nor have I anyone else to ask :p

A: 

IMO, you need only to inherit your interface from IEnumerable<Message>, so you do not need special property to get messages, because IEnumerable has corresponding method GetEnumerator. This is most elegant and natural for .net framework.

arbiter
Sounds reasonable.
Svish
+1  A: 

Going the .NET Framework way, you should define a collection-class ("MessageCollection") that inherits from Collection{T}. This provides the funtionality to add or remove messages and implements the interface IEnumerable{T} .

Your interface should define a read-only property "Message" that returns an instance of your defined collection-class.

public interface ILog {
  MessageCollection Messages {get;}
  void AddMessage(Message message); // Additional method.
}

public class MessageCollection : Collection<Message>{
  // Addional methods.
}
Jehof
Hm, this sounds a bit overkill in this case, but a good thought that I probably might use some other time. The ICollection<T> interface contains a bit too much stuff that I don't really need or want to implement.
Svish
Then implement only the IEnumerable<Message> interface and add the the void Add(Message) on type MessageCollection. If you want further functionality you can add them to the class. Due to "Framework Design Guidlines" a collection is a type that implements IEnumerable and represents a list of items. In your case a list of "Messages"
Jehof
+1  A: 

Gut feeling: make it a member.

If the interface only contains AddMessage and messgae enumeration, you could inherit. However, in this case the role of ILog itself is questionable.

First, message generation is virtually always separate from message consumption. So I'd split up ILog into ILogTarget (containing the AddMessage), and ILogMessages, providing message enumeration.

(This separation might be artificial and over the top for your application, so take this just as a general remark).

Even in this case, I'd make IEnumerable Messages a member of ILogMessages, simply because that interface might grow: You might add an IEnumerable Errors or separate filtering options.

As a minor convenience issue, a member is also easier discovered through intellisense.

peterchen
Very good points. Splitting it might be a bit overkill at the moment, but yeah. All good points.
Svish
+1  A: 

I'd suggest that ILog shouldn't have an enumerator at all - the code that is doing the logging has no need to enumerate through all of the messages.

The key is that one class can implement multiple interfaces - so you can (and should) keep each interface focussed on a particular use.

So, I'd create a second interface (say, ILogStore) that implements an enumerator of the messages:

public interface ILogStore
{
    IEnumerable<LogMessage> GetMessages();
}

I'd make this a member function to allow for possible future overloads. Say, you want to get all of the log messages from a particular subsystem:

public interface ILogStore
{
    IEnumerable<LogMessage> GetMessages();
    IEnumerable<LogMessage> GetMessagesBySubsystem(string subsystem);
}

and so on.

Bevan