(Adapted from an internal memo written while reviewing some code and shared with a team new to writing code which works with data from a remote server)
You’re on the 6th floor here, imagine you have to confirm some numbers and take a document to be signed to the 6th floor of next building. You also have to bring back two documents from there. The elevators are not working in either building. Calling on the phone or digitizing and emailing these documents aren’t allowed (law/confidentiality/whatever). How many trips will you take?
- Run down the stairs of this building, run up the next confirm the numbers and return.
- Take the document to be signed (again going down and up the stairs) and return.
- Go again to bring each document back.
- Take the numbers to be confirmed and the document to be signed over. Get that done. Bring back the other documents from there all in one trip
If you chose Scenario A and are not on some special diet or exercise program and neither are you preparing for a marathon, we have a problem.
If you chose Scenario B, there’s hope. I hope you will apply the same analogy/logic when writing code. Having to run down and back up the stairs is what you could think of as happening every time you cross a "code boundary" (Not-A-Real-Term TM). It’s what you’re making the CPU do when choosing/writing an algorithm which could be better. Depending on what level you want to understand the analogy/metaphor at, a "code boundary" can be many things – going from local machine to over the network, from RAM to disk, from one CPU cache level to another, from Java to Native code/C++ (JNI) etc. Have you seen the Code And Web Texture Packer Sprite Sheet performance video that recommends that you use a texture atlas to minimize state changes? The same logic applies - execution going from application code, out to driver, to GPU.
Project/ SendSentenceActivity.java and PlayGameActivity.java are two sources which were reviewed.
PlayGameActivity shows the sentences by the two players so far and a play button.
SendSentenceActivity is shown when the player presses the play button. It shows the bonus words and keywords which will give the player points when used in the sentence s/he plays/sends.
When the player presses the send button in
SendSentenceActivity, it checks for duplicate sentences, other game mode specific validation (Double-Dog) etc, calculates a score and then…
(If you guessed "sends the sentence to the server", wrong answer!)
…sends it to the server to "replace Bonus Words". The handler on the server for this receives (only) the bonus words and updates their status (used or not used) for the particular game (story).
SendSentenceActivity then closes and sends the sentence (and score) to
PlayGameActivity (passed along with the Intent object), which then initiates a subsequent network request (
story.addSentence). But right before that, it makes up to two more network requests to update any achievements unlocked on that sentence.
From both - client and server - points of views, this can clearly be improved. From the client side, the app should collect together all the data it needs to send to the server and send it in one shot (batch it). From the server side, it should provide the API/request end points in a way to minimize the number of calls required to the server. Teams should discuss their plans and lead to reviewing each other’s code (by discussing in a scrum or separately - "Here’s what I’m doing or planning to do for X, does anyone see any issues or have an improvement to suggest?") to make sure issues such as this are identified early and everyone learns more.
In this particular case, just one API
sendSentence could do all the validation, calculate points, achievements, update used words etc and return the required data. An added benefit of having validation happen on the server is anti-cheating. You cannot trust the data from the client in a client-server model. If you think something can be open to cheating, move that logic to the server. The only reason you may want to think of working on the client side is to balance the distribution of processing on clients vs central processing on the server if it's not "work" that needs to be validated - but that's another discussion.
I hope the class names and description above gave enough context for the case and illustrated the concept.
A related talk/see also: Networking Best Practices from Apple WWDC 2012. Requires Registered Apple Developer account to view. Free account will do too.