So I made a socket communication library. And a part of it is IConnection
public enum ConnectionState
{
NotConnected, Connecting, Connected, Authenticated, Disconnecting, Disconnected
}
public interface IConnection
{
ConnectionState State { get; }
event Action Connected;
event Action Disconnected;
event Action Authenticated;
event Action AuthenticationFailed;
// this two methods are the core of my question
void OnAuthenticated();
void OnAuthenticationFailed();
bool Send(byte[] data);
void Connect();
void Close();
}
Of course IConnection
provides information about connection state and is able to fire Connected/Disconnected
events as it holds Socket
. There is no doubt.
Now, users of IConnection
would also like to know when it becomes authenticated. For example, server might listen to that events, and once connection is authenticated - send client's initial configuration data. Or client might listen to that events and decide to start communication or retry authentication process.
But. The problem is, authentication process exists in the protocol layer. IConnection
has no idea such layer even exists. Protocol layer actually uses IConnection
to send serialized to byte[]
message to the other party. And for this one particular message kind, protocol layer is able to send data upon connection in ConnectionState.Connected
state.
So, for IConnection
to be able to change it's state and inform subscribers on auth process i had to implement this two methods
void OnAuthenticated();
void OnAuthenticationFailed();
Which are, obviously called from protocol layer authentication process code.
I feel like I'm doing something wrong here. And since i work alone, any thoughts will be much appreciated.
3 Answers 3
You're not quite correct saying that IConnection has no ideas about protocol layer - in your defininition IConnection provides events about authentication process. So your code should have some connections between IConnection and protocol layer. I have no clue about entire relationships between layers in your application, but I can suggest some method:
provide function for calling events (like you suggested)
implement IConnection in protocol layer
realization of IConnection listens what happens in protocol layer (i.e. AssignAuthentificationService function)
implement IAuthentifiedConnection that knows about protocol layer
-
\$\begingroup\$ So you find normal situation when one class calls
IConnection.OnAuthenticated()
and thenIConnection
itself fires theAuthenticated
event? \$\endgroup\$Anri– Anri2013年02月14日 10:00:23 +00:00Commented Feb 14, 2013 at 10:00 -
\$\begingroup\$ Actually i like the last idea,
IConnection
implementation, or to be precise extension of default implementation might exist in Protocol layer / business logic \$\endgroup\$Anri– Anri2013年02月14日 12:47:18 +00:00Commented Feb 14, 2013 at 12:47
Remember that interfaces are usage contracts. They do not define how a class should be implemented.
Hence it's up to the implementation to handle the authentication process. So if we look at the contract only, the OnXxx
methods do not belong in it.
If we are looking at implementations there is nothing that says that all future implementations of the class would required a third party to handle the authentication.
However, your current implementation do. So what you could do to allow third party to interact with the connection is to create a second interface which only targets that: IRequireThirdPartyAuthentication
which has those to methods.
Your implementation should have the following layout:
public class MyConnection : IConnection, IRequireThirdPartyAuthentication
{
}
Are you sure that all connections will require authentication? If not: Create interface inheritance as ivn suggested.
I ended up moving the core part of the protocol like authentication, keep-alive service and basic message types that will be most likely used everywhere to the Communication assembly.
So now IConnection does auth process itself as it is aware of core protocol.
Authenticated
event? \$\endgroup\$