Skip to content

ThanksForAllTheFish/minigame-backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commits
 
 
 
 
 
 

Repository files navigation

* Disclaimer
This code comes from a test I was submitted for an interview. The interview did not end up well, but the comments I received were important to me and they allowed me to notice some mistakes I was doing without even recognize them. Moreover, some of those mistakes are also stated in "Seven Languages in Seven Weeks", so now I assume they are good practices. From that interviewed I did few minor changes (used final where possible - thank you IDE - added a thread pool executor to make my server multithreaded and added a time provider to wrap calls to System.currentTimeMillis()), but I did not change anything in the design or in the logic. Since I do not know if it is good practice to show code used in interviews, please do not proceed reading if so.

* Unit tests
I tried to stick at TDD as much as possible. Honestly, sometimes it is difficult, especially when dealing with data structure with minor behaviours. However, besides `org.mdavi.minigame.receiver.score.ReverseComparator` which is indirectly tested, all other classes should have their correspondent unit test which has a coverage ratio of more than 90% (obtained with EclEmma plugin for eclipse). There are cases which I have general no idea how to unit test, such as IOException related to problem with `OutputStream`s.
You will find two peculiarities in `org.mdavi.minigame.session.SingletonSessionHolder`:
	1). the protected method `eventuallyCleanUpExpiredSessions`: as the comment states, the method should be private but I extended its visibility to protected to allow unit testing. Though I do not like the approach so much, I found no other suitable way to test it. Moreover, I am watching Uncle Bob's videos and he does approve the approach as well since 'the need to change the visibility of a method may be the sign that sooner or later that method will be needed somewhere else'.
	2) a TODO comment in the same method: I had no idea how to test that branch, I struggled for a while then simply had to give up. I will be glad to have an opinion from your side.

* Naming
I always try to be the clearest I can with classes, methods, variables and tests name, so I hope you will have no difficulties to read my code. If anything is unclear, again, please give me a feedback: there is always room for improvement!
Naming is also the reason why there are almost no comment in my code.

* The code
My code compiles only using Java 7, since I used a construction introduced in Java 7 (like List<Integer> list = new ArrayList<>() - sorry for the cheap example, I do not remember its name).
To generate the session key, I used `java.util.UUID#randomUUID` available since Java 5 and which, I believe, can guarantee enough uniqueness.
Since I could not use anything not included in the native Java libraries, I googled more than usual and I found a very nice solution for converting an `InputStream` into a `String` using a `Scanner`: nice to know. In that point, I am assuming the `InputStream` to not be null, which will generate a `NullPointerException` and therefore an internal server error.
I like to partitioning my code into Main/Domain partion, that is why you will find many interfaces and few `new` statement (actually there are `new` statements only for members, not for collaborators) around the domain code and `new`s and mess (branches and so on) in the main partition. I identified the main partion mainly with `org.mdavi.minigame.HttpServerMain` an `org.mdavi.minigame.receiver.MiniGameRequestReceiverFactory` which are responsible for the creation of the collaborators and with `org.mdavi.minigame.RequestHandler` which is resposible for the error handling.
About inputs and outputs integers, as you asked for 31 bit unsigned integer number, I decided to allow only positive numbers starting from 0, so I could use `int` as primitive type (from 0 to 2^31-1 there are exactly 31 bit).
As a side, I used maven for dependency management and compilation, so you can use it as well if you like to import the project into eclipse or make your own executable jar.

* Concurrency
I am absolutely no expert with concurrency and I do not feel confortable using it. I almost never used it at work, so I had to recover the knowledge from University Time. However, I think I identified only two classes which needed to be synchronized: the session and the score holder.
About the session holder, namely `org.mdavi.minigame.session.SingletonSessionHolder`, it was the first one of the two I wrote and I found and used Bill Pugh's JVM based interisting approach. I left all the synchronization issues to the `ConcurrentHashMap`, since all the operation I need to perfom on that map are already atomic by nature. For instance, when I get a session, the get method is already synchronized and I do not need any other mean of protection on the session. I had some thought over the `eventuallyCleanUpExpiredSessions` method again, since it may be quite expensive in terms of time, but in the end I decided not to synchronized it because it is again limited to only get the session, then it is the session itself to know whether it is valid and in the the removal is guaranteed by the `ConcurrentHashMap` and I do not care whether something else happens on the map in between the get and the remove.
About the score holder, namely `org.mdavi.minigame.receiver.score.SingletonScoreHolder`, I found two points which need to be synchronized:
	1). while posting a new score, I decided to synchronized on a user-base: the idea is that a user can perform only one action at a time, why more users can post in the same time without compromising the integrity of the map.
	2). on the other hand, while getting the high scores, I want the operation to lock the entire map so that as long as the computation of the high scores is performed no other operation can be done on the map.

About

Simple backend server implentation for game scores management

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages