Samples from “A Dropout’s Guide to Designing and Building Android Apps”
A few people have requested a preview of the content in my recent ebook, so I’ve decided to include a few excerpts in a blog post.
If you would like to pick up a copy, you can find the download link here.
From Chapter 2: Preliminaries
“Most introductory material won’t even discuss threading, as it is a more advanced topic. However, there are very few apps you can hope to build properly without some kind of threading involved. I won’t go in to the more technical details, but I will explain the practical details so that you can get started quickly.
Pretend for a moment that you (MainThread/UiThread) are working at a hipster coffee shop (which won’t be so hard to imagine for some of you). When business is slow and the orders aren’t particularly large or complicated, you can probably get away with one person working both the cash register and making the orders. However, when business several large and complicated orders come in at the same time, a problem arises.
With only a single person (“Thread”) to deal with a large queue of orders, while there’s still a line up of customers ready to order, you can expect pretty bad reviews and the loss of many customers. Naturally, the solution to this problem is to call your coworker (“Background Thread”) over and have them make the orders while you continue to work the register (or vice versa).
That’s basically how Threads will work in your apps. Think of Threads as the workers that execute the code, and understand that certain operations (like network and database operations) should really be delegated to Threads in the background of the app. Failure to do so will lead to your app becoming unresponsive to user input (which is very annoying for the user), and may eventually cause the OS to kill your app due to unresponsiveness. I’ll revisit Threading and solutions to the problem of Threading later.”
From Chapter 4: How To Design And Build Apps (Theory)
Why Do We Call It Software Architecture?
“As I mentioned in the introduction, I had much difficulty learning programming in the initial stages. This was mostly because my brain (and likely yours as well) was not designed to memorize disparate lines of code and files. I thought this meant that I was bad at programming, but as it turns out, the main issue was simply not having an appropriate way to ‘think’ about software.
It turns out that there are more perspectives to think about and discuss software designs than just the code itself; which can be thought of as the “Implementation Perspective”. At the highest and broadest perspective, we simply talk about ideas such as “Note apps,” which are things that even a layman can discuss. In other words, it is at times both acceptable and good practice to discuss software based on simple ideas and language. In fact, this must be the case at the start of any new project.
The next perspective can be understood as discussing software in terms of Objects, with names, that have ‘responsibilities’ and ‘relationships’ to other Objects.
My favorite metaphor to explain this perspective, comes from building architecture. While I’m no architect, I have little doubt that the process to designing a house starts by creating a blueprint of the structure. One need not be very talented or experienced to assert that a house will most likely require the following Rooms: • A Bedroom to sleep in • A Kitchen to store and prepare food in • A Bathroom to wash up and handle your business in
Now, it isn’t enough to just list out the names and requirements of each room; we must also consider the relationships these rooms ought to have with one another. Should the Bathroom be situated at the other end of the Structure relative to the Bedroom? Does the shape of the building necessitate a Hallway to connect the various rooms, or might it be better to create a more open concept? Of course there are many ways to design a structure, depending on the requirements at hand and the individual style of the Architect. I’d simply like to emphasize that once we have given each room a Responsibility, we can now make assertions about the structure as a whole. It turns out that software apps are not so different. Although the layout, scale, and requirements of each app may change, they can almost always be dissected into Objects with the same few Responsibilities.
As a beginner, one may be tempted to put everything in one ‘room’, which is often referred to as having a ‘God Activity’. This means that code which is responsible for drawing things on the screen, making decisions about user input and the storage and manipulation of data, is all contained within the same Class. While it may appear easier to do this at first (and many tutorials often appear to encourage this practice without realizing that a beginner might actually think this is proper), you’ll soon start to realize that these objects become unmaintainable, untestable, and positively illegible. “
From Chapter 5: How To Design And Build Apps (Practice)
What Exactly Does Model Mean?
I’m sure I don’t need to remind you at this point that programmers have a terrible habit of not only using overly technical words to describe otherwise straightforward concepts, but they also appear to love re-using and redefining them at will. Model is exactly such a term, which has grown to mean everything from a single Class responsible for storing Data (such as a ‘Note’), to an entire layer in a Software Architecture Design. Names like Model-View-ViewModel, which I’m personally very irritated by, tend to confuse things ever further.
The big joke at this point is that everyone has used and minced up these words so much that I don’t even know what the original definitions or intentions were. All I can do is become guilty of the same crime as everyone else, and give are my own definitions. For our purposes, I will simply make the following distinction between two types of ‘Models’. The one definitive thing I would like to say, is that regardless of whether it is a single class, or a whole Layer, Model implies the responsibility of storage of and access to data.
A DataModel, commonly known as a POJO (Plain Old Java Object) in Java, is a single Class that describes an Object derived from the Problem Domain. Rather than passing disparate variables around the app, it makes more sense to create an Object which can then be passed around. Not to mention it is easier to read Apps which use such DataModels. For our Note app, the only DataModel we’ll need is called ‘Note’. It is simply a version of what we figured out in the Problem Domain, represented in Java code.
Designing DataModels is usually a straightforward process. Determine what kind of information such a Class will require (understanding that it may need to change as your project’s requirements change), add some getters, setters, and a constructor as necessary, and you’re basically done. Also note that it is perfectly acceptable to nest these Classes within each other, as so: basic_java_samples/NestedClass.java basic_java_samples/Set.java
As I mentioned before, if a DataModel is to be written to a database, you’ll often want to create some kind of Unique ID as one of its Variables. For example, as opposed to sending an entire Note from one Activity to another (such as when the User clicks on a Note in NoteListActivity), it is far more economical to pass the clicked Note’s ID to the other Activity, and look it up from there.
One last point is that if you must save a DataModel to a “Bundle” Object (which is used to pass data between Activities and to store Data within the onSaveInstanceState(Bundle) method), you can have your DataModel implement the “Parcelable” interface. This simply allows it to be serialized, or decomposed, for easy transport and storage. Think of it like shipping a bed; it’s easier to transport it in pieces and assemble it on the other end.
When I say Data layer, you can also think of the term “Model” to denote a layer of a given software architecture. Any class which contains implementation that falls under the responsibility of data storage and access, can be considered part of the Model.
In an architecture which properly divides the responsibilities of its Layers (and Classes, by extension), the Model should really only provide the following functions: • Provide CRUD (Create, Read, Update, Delete) operations to a repository of some kind. This will generally be a database, either on the device (local), in cloud storage (remote), or both. • Provide reasonable error messages when things go wrong
That’s really all there is to the Model at a bird’s eye view. The complexities arise when we need to wire the Model up to the rest of the app.