开发者

Need advice on how to design this. Composition or inheritance?

I'm trying to design a client / server solution. Currently it contains three projects. The client, the server, and a library that each use (because they both require a lot of the same stuff).

For example, both the client and the server (in this case) read incoming data in the exact same way. Because of this, both the client and the server have their own MessageReader object. The MessageReader will first read the first 4 bytes of incoming stream data to determine the length of the data and then read the rest. This is all performed asynchronously. When all the data is read the class raises its own MessageRead event or if there was an IOException while reading it raises its own ConnectionLost event.

So this all works fine. What's the problem? Well, the client and the server are a bit different. For example, while they may read data in the same way, they do not write data in the same way. The server has a Dictionary of clients and has a Broadcast method to write to all clients. The client only has a single TcpClient and can only Write to the server. Currently all this behavior is within each respective WinForm and I want to move it to a Client and Server class but I'm having some problems.

For example, remember earlier when I was talking about the MessageReader and how it can raise both a MessageRead event and a ConnectionLost event? Well, now there's a bit of a problem because in designing the Client class I have to capture these two events and re-raise them because the client form should not have access to the MessageReader class. It's a bit ugly and looks like this:

class Client
{
    private MessageReader messageReader = new MessageReader();

    public delegate void MessageReceivedHandler(string message);
    public delegate v开发者_开发技巧oid ConnectionLostHandler(string message);

    public event ConnectionLostHandler ConnectionLost;
    public event MessageReceivedHandler MessageReceived;

    public Client()
    {
        messageReader.ConnectionLost += messageReader_ConnectionLost;
        messageReader.MessageReceived += messageReader_MessageReceived;
    }

    private void messageReader_MessageReceived(string message)
    {
        if (ConnectionLost != null)
        {
            ConnectionLost(message);
        }
    }

    private void messageReader_ConnectionLost(string message)
    {
        if (MessageReceived != null)
        {
            MessageReceived(message);
        }
    }
}

This code is ugly because its basically duplicate code. When the MessageReader raises the MessageReceieved handler the Client has to capture it and basically re-raise its own version (duplicate code) because the client form should not have access to the message reader.

Not really of a good way to solve it. I suppose both Client and Server could derive from an abstract DataReader but I don't think a client is a data reader, nor is the server. I feel like composition makes more logical sense but I can't figure out a way to do this without a lot of code duplication and confusing event handlers.

Ouch, this question is getting a bit long.. I hope I don't scare anyone away with the length. It's probably a simple question but I'm not really sure what to do.

Thanks for reading.


Composition.

I didn't even read your code or text. I find that the average developer (almost) never needs inheritance but they like to use it quite a bit.

Inheritance is fragile. Inheritance is hard to get correct. It's harder to keep it in check with SOLID.

Composition is easy to understand, easy to change, and easy to DI, Mock, and test.

SOLID


I ended up using inheritance for this even though the relationship wasn't strong. The code duplication it got rid of was worth it. Was able to place all the events both classes shared in to the base class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜