jdmonin / JSettlers2

Java Settlers project home, downloads, and GPLv3 source code. To download the latest version as a JAR, see https://github.com/jdmonin/JSettlers2/releases/latest .
http://nand.net/jsettlers/
GNU General Public License v3.0
157 stars 63 forks source link

refactoring server side class to highlights responsabilities #23

Closed alesky78 closed 7 years ago

alesky78 commented 7 years ago

hello Jeremy

I would like to propose to you same little reorganizations in the code... My proposal came out after I have studied the code of the server side implementation. In particular I have analysed the packages: soc.server soc.server.genericServer soc.messages

strong point that I recognized in JSettlers2 code, is that it is full of javadoc documentation. This help me in this days to drive my study on the server architecture. Obviously the javadoc cannot cover completely the understanding, and you have to navigate the code and the classes. In fact another aspect that I find extremely important when you develop code is that classes with roles/names well defined and relationship well identified are extremely important point to interpretate/understand architecture of software already implemented.

And here there is the biggest complexity that I found. I agree with the centralization of the code, but in JSettlers2 I found that same time the centralization applied overwrite the concept of responsibility in few classes and the result is an hidden architecture that force too much the reading of the code to understand it... I mean there are same classes that are overloaded of responsibilities, and this hide the server architecture. I think that if in the soc.server there was 3/4 classes more to take the responsibilities of same aspects of the server processing, the system could benefit of a more simple understanding for people like me that want to read the code and understand it and in case support the project. I saw, for example, that you already start to do it in the version 2.0 with the class soc.server.SOCGameHandler for example...

so in conclusion this is my simple proposal

class SOCImboundMessageQueue the responsibility of this class is to 1- store the messages received from the client by the Connection and the LocalStringConnection objects that today is done in the inQueue Server class property 2- remove the relationship between Connection and the LocalStringConnection whit the Server Object that today is done by the method public void treat(String s, StringConnection c) in Server object.. the two connection will call treat over the SOCImboundMessageQueue 3- manage the message received and dispatch to the correct handler for the execution, that today is done by the inner class Treater in the Server class, move the class in SOCImboundMessageQueue this will remove the logic for the Server and SocServer classes

class SOCServerMessageHandler like the SOCGameMessageHandler this class has the responsibility to maintain and implement the messages management that still is in the SocServer dispatched by the method public void processCommand(String s, StringConnection c) that mean that all the method handleSERVERPING... handleVERSION... handleAUTHREQUEST.... handleJOIN... should be moved here

class SOCGameMessageHandler is just the renaming of the SOCGameHandler to maintain the same name convention of the SOCServerMessageHandler

class SOCMessageHandlerDispatcher the responsibility of this class is to 1- receive the event from the SOCImboundMessageQueue (see the point 2 class Treater) and dispatch to the correct message Handler SOCServerMessageHandler or SOCGameMessageHandler

class NetStringServerSocket remove has inner class in Server and make as public class in the package soc.server.genericServer of for the rest of the hierarchy LocalStringServerSocket and StringServerSocket

class NetStringConnection rename the class Connection in NetStringConnection to maintain the same name convention whit its server socket counterpart NetStringServerSocket has it already exists also for LocalStringServerSocket and LocalStringConnection

in this way I think that is more simple to identified 3 main blocks in the server architecture 1 - connection management and initialization of the server infrastructure --> SOCServer class 2 - message received and handling --> SOCImboundMessageQueue 3 - server business logic --> SOCMessageHandlerDispatcher,SOCGameMessageHandler,SOCServerMessageHandler

have a more clear definition of the chain of the message management Connection --> SOCImboundMessageQueue --> SOCMessageHandlerDispatcher

and finally have two extra classes that in the javadoc that can explain clearly the server messaging model of the software: SOCImboundMessageQueue and SOCMessageHandlerDispatcher

please Jeremy let me know your point of view

jdmonin commented 7 years ago

Hello Alessandro,

Thank you for spending time on studying the server and giving thought to refactoring to make things clearer. I completely agree that consistent naming and clearly defined responsibilities help keep the structure more elegant and understandable. I'm glad the javadocs helped out; detailed and up-to-date documentation is an important goal for me.

I like the refactoring you've proposed. I would do some parts slightly differently. Here is the action plan I'd like to do:

Do you want me to do all these steps, or would you like to do some of them? If you're taking on some of it, about when would you like to make your changes and submit them? That way you and I aren't working on the same classes at the same time. :)

You've put a lot of thought into this and brought good suggestions, and I'm grateful! Please let me know what you think about the revised plan and timing.

Many thanks, -Jeremy

alesky78 commented 7 years ago

Jeremy if you agree i think that it is better to do this work in two steps

1 step refactoring the connection objects... create the SOCInboundMessageQueue and integrate in the project.

in this step the SOCInboundMessageQueue will integrate with the SocServer dispatched by the method public void processCommand(String s, StringConnection c)

but at list this part is closed and consistent and we can do same little test

2 step refactoring the handler, also becoue this one dipend for the completation of the SOCInboundMessageQueue

I'm glade to partecipate to the project... :)

For now I will start wih the step 1 and push a commit... i will complete in a coule of day

regarding the way we collaborate and integrate the software... how do you prefer? fork and push is ok for you: I will fork your actual master.. will do the changes in my master and propose a push to your master...

jdmonin commented 7 years ago

Alessandro,

That sounds good to me. Please go ahead with Step 1 and when ready send a pull request. If you have any questions don't hesitate to comment here or email me. Thanks for your help, this is exciting!

jdmonin commented 7 years ago

Step 1 is now merged. Thank you for that!

jdmonin commented 7 years ago

Hello Alessandro,

Let's coordinate the next steps: I want to do SOCServerMessageHandler. I can also do SOCMessageDispatcher and/or SOCGameMessageHandler unless you want one or both of those.

Please let me know, -Jeremy

alesky78 commented 7 years ago

Hi Jeremy i think I can start step 2.

the issue for me look like that in this phase... there are several point to analyze how to implement before to start wiht a full implementation... in particular the dispatcher.... in my vision there was only one dispatcher able to reconize if the message must be processed by the game handeler or the server handler... you forecast two instead...

another point that must be clarified is how to decise what is the dispatcher to use... for example today for the game messages you have a marker interface SOCMessageForGame

and in the when the server is processing the messages by void processCommand(String s, StringConnection c) it verify to use gameHandeler mesagess by if (mes instanceof SOCMessageForGame)

may be you want to have another marker interface like SOCMessageForServer? i mean the solution strategies are different...

may be at this point is better if for now I just create only the class SOCServerMessageHandler and I do only this changes for now

let my know

jdmonin commented 7 years ago

Hi Alessandro,

Here's what I think would make sense next:

If that sounds good to you, please go ahead. I'm grateful for your help and energy with this, although I will need to do SOCServerMessageHandler myself.

Thanks again and have a good weekend, -Jeremy

jdmonin commented 7 years ago

Thanks! Your PR for SOCGameMessageHandler is merged. To dispatch at SOCServer independent of game types, I created interface GameMessageHandler and lookups for a game's message handler from SOCGameListAtServer.

jdmonin commented 7 years ago

SOCMessageDispatcher is written. I'm preparing to write SOCServerMessageHandler next. At this point it should be possible to start moving handler methods from SOCGameHandler to SOCGameMessageHandler if you want, my upcoming server work doesn't involve those classes.

alesky78 commented 7 years ago

Hi Jeremy I prefer that you complete this work by yourself... I will remain in stand by until it is not completed.... later I will be happy to continue to help you in other task..... I think that you have a clear view over the way that you want to achieve this part of the server designee.

if I understand well what you are doing.. in the end we will have the SOCMessageDispatcher class that should have only the references to the SOCServerMessageHandler and the SOCGameListAtServer to get the correct SOCGameMessageHandler to use for the specific game. In this way all the business logic of the message processing will be completely decoupled from the SOCServer class and moved to the SOCServerHandler

there are only few point that I would like give you my opinion...

1 - with the integration between the inboundMessageQueue and InboundMessageDispatcher you don't need more the variable private Server server in the inboundMessageQueue object.. it is correctly never used.

2- the InboundMessageDispatcher is an inner interface in the Server, but look like that has sense to have this interface defined in the genericServer package also because its method is called only from the InboundMessageQueue and not from the SOC concrete implementation classes... I mean is part of the generic server infrastructure...

Alessandro

jdmonin commented 7 years ago

Hi Alessandro,

Thank you, those are good points. I'll keep working on this refactoring.

-Jeremy

jdmonin commented 7 years ago

Hi Alessandro,

I think we can call this one done. I've completed the method moves, and followed up with javadoc and README.developer updates. To prevent clutter in future diffs I also removed trailing whitespace from the java sources.

This refactoring was a nice idea, thank you again. The responsibilities within server classes are clearer, and in reviewing this part of JSettlers I clarified other javadocs and cleaned up small things along the way.

I've added this to VERSIONS.txt as:

Although I might work on the javadocs a bit more, this feels complete to me. If you have suggestions please comment or open a new issue.

Thanks once more! -Jeremy

alesky78 commented 7 years ago

Thank to you Jeremy :) great job 👍

jdmonin commented 7 years ago

Thank you, it was fun!