Lemberg’s Advice On Mobile App Development
Originally published at blog.lemberg.co.uk.
This is not the ultimate developer’s guide. Our goal isn’t to teach you the principles of development. We would just like to share a few advices regarding mobile development that the other guides do not point out or put an emphasis on.
Priorities in development
There is one specific point in terms of mobile development — apps usually do not analyze data and rarely do they produce it — they usually just interpret and display it. So priorities are a bit different from the server side and desktop ones.
Readable and clear code
You should keep code as simple as possible. It should be noted that the development patterns are simply recommendations instead of requirements and guidelines that one ought to follow for coding. Different pattern guides is like a healthy collection of food recipes: each recipe is good in its own way and it can make you live a bit healthier but you can’t just use all of them or only the favorite ones. You have to take the right measures, in order to make your diet properly balanced. Same concept applies to patterns: you have to consider if the complexity that the code pattern brings is worth the profit.
Always try looking at your code from a neutral point of view, like a person that has never seen it before and is looking at it for the first time. This will help you to keep your code clear for others. There are two scenarios:
- Pattern overflow: too many patterns are used, this hiding the main logic under dozens of interface classes and some classes might be so tightly binded that even a minor change would require hours or even days of development just because the analysis of the effect of update will be сomplicated and the update itself might require significant code changes in case if the patterns didn’t carry out the expandability. Sometimes a simple code might be a lot more easier to expand than the patterned one in case the developer had no idea how the functionality would be expanded (which often happens with lightweight mobile applications).
- Unstructured code: provides hundreds or even thousands of lines of code describing similar or even duplicated logic without any patterns or reuse. It’s definitely hard to analyze because of the undeclared relations between classes. And duplicated code will definitely require duplicated updates.
So it’s important to maintain a balance between pattern usages and code legibility, code reuse and low coupling. In order to optimize or eliminate critical points (points in code with high risks of bug occurrence).
When code is written, it’s supposed to be as stable as possible, in order to decrease chances of accidental code/algorithm breaking by some updates.
First of all I would like to note that readability and simplicity of code will always increase its stability since anyone modifying it would be able to predict the result of his actions.
So in addition to the various pattern usages, you should try to keep the code as simple as possible and place comments wherever you use some uncommon on hard-to-understand methods (it’s also important not to overload code with comments since user might start skipping them in case he notices that the comments do not bring any useful info and miss something crucial).
You can also place additional checks (assertions) with descriptional error messages in critical points or just wherever the default crash won’t produce easy-to-analyze stack trace.
Also it’s recommended to place methods (which will be probably changed together) within same class to make modification as obvious as possible (in fact, such methods placement will usually get you a result of correct GRASP principles implementation).
In development process we usually are trying to a balance between code simplicity, stability and performance. Code simplicity and stability often correlate between each other but performance improvements usually do indeed complicate the code. During the past 5 years, smart phone’s capabilities have increased significantly. Some smart phones/tablets can be even compared with low-cost notebooks in terms of performance.
So in terms of modern non-gaming and non video/image/sound processing mobile applications performance has the lowest priority. In fact it does make sense to pay attention to performance, but only if performance issue becomes obvious or it doesn’t complicate the code significantly.
P.S. You should not confuse terms “performance” and “fluent UX”. Even the best performance possibly won’t guarantee a fluent UX of your app and vice versa: fluent UX of app can be reached even without any performance optimizations.
A few signs telling us that something went wrong
- Something has definitely went wrong if you are going to use copy-paste. Code you were going to copy should usually be encapsulated into a superclass or a model/utility class.
- High (Pathological) coupling signals about functionality that is badly splitted between the classes or modules. Each class (module) should deal with the problem it has the most information (input data) about, and it shouldn’t rely on any other internal structure.
- Low cohesion inside a class means that it could be broken down into smaller subclasses.
Building stable and predictable classes
First of all you should try to:
- make them immutable or limit their variety of states.
- minimize the amount of conditional flows (i.e. ‘if’/‘switch’ operators) — each conditional operator makes class/method behavior less predictable.
- build REST-like classes (similar to web services): method calls (except setters) shouldn’t change the state of the class. At the very least, changes to the class state shouldn’t be accumulative (apart from the cases when a collection structure is being formed). Each method that is adding a new data to the class state should take care of deleting the old data.
Minimize the amount of the single ‘get’ methods being used in scope of the same method. If possible, save the previous result, since you never know what logic could be running inside ‘get’ method every time it is being requested.
Additionally you could
- reinitialize classes instead of changing their state (use immutable classes).
- use immutable collections (or just local copies) wherever they aren’t supposed to be modified.
Such methods do have a performance drawback so you have to weigh up all the pros and cons before using them.
And finally classes should give public access to only specifically designated methods. Take special care of the “properties/configuration” inner static classes — those should be immutable when exposed or passed outside as a copy. Otherwise you won’t be able to handle all the property changes correctly. While non-static classes bring risks of memory leak occurrence.
If you have a project idea in mind, but don’t know where to start, we’re here to help you. Be sure to leave your comments below.
Originally published at blog.lemberg.co.uk.