Quantcast
Channel: Antipodal Apps
Viewing all articles
Browse latest Browse all 12

Model Design

$
0
0

iOS is my first real foray into serious application design.  In the past I’ve worked on lower level project like device drivers.  As such, I’m still learning the best ways to apply application patterns like MCV.

As I study I’ve coming to understand the best practices around abstracting business logic into Model classes. Originally, I had understood Models as a thin layer over the datastore.  Despite this I’ve always liked to encapsulate abstract business logic into understandable, well organized, modules.  Not necessarily classes, as in many of my past projects have been in non-object-oriented languages.

There are a few practices that I’ve found very useful.

Modeling Behavior

In Prison Pushups, without understanding the process I naturally abstracted out the rules of the Prison Pushups game into a single class.  This class managed all of the rules and business logic from determining the number and kind of pushups or rest for a given card, to managing the game timer.  At the time I misunderstood the division of responsibilities in MCV and called this class GameController.  If I was doing it again today I would name it GameModel.  Architecting Prison Pushups this way helped to centralize logic and abstract the game rules from the user interface.

In one of my current client project’s I’ve adopted a similar strategy.  I can’t say much about the project now so I’ll just refer to it as ProjectF.  In this case I’ve been more deliberate and thoughtful about the design.  In Prison Pushups there was a real game involved and there was a natural abstraction to build the game rules into a model.  But, in ProjectF collecting business logic together into a single class is solely motivated by the desire for clean software abstraction.  Reading about Fat Models and Thin Controllers has taught me that this is a better organization. And I’m seeing opportunity to reuse  models in different scenes in the app.  Along the way, I’ve also tried to keep the Model objects relatively small and simple.  I have Model objects that model data for the app.  Separate from the data models, I’m building classes that model the behavior of scenes, or parts of scenes, in the app.  I’ve kept the data and behavior classes separate to keep either from growing out of hand.

Modeling Behavior and TDD

As I’ve recently adopted TDD practices I have test driven the design and development of my behavior models.  I find this has made this business logic in the application much easier to test than if it had been a part of the control or more tightly coupled with either the user interface or with the data.  Testing in this way has also given me a better appreciation of the boundaries of the behavior classes from an API standpoint.  I see the behavior model as sitting between the controller and the data models and the tests test both ends of this interface.  That is, I stub out the data models to feed controlled data into the behavior model and then test that the right corresponding data is returned the public interface (as the controller will expect).  This experience has given me a better understanding of API from both a testing and design perspective.  I’m very excited to continue doing development in this way.

I contrast all of this with another project that I have in the background that I will refer to as ProjectQ.  ProjectQ has not been using TDD or thin controllers.  And it’s design has suffered because of.  The project has become very difficult to work with as the business logic is not well contained and has overly coupled to the interface.  When I go back to this project I feel it might make sense to add tests such that I can refactor and extract its business logic into behavior models.  Doing so may help get the project moving faster as well as teach me more about extracting and abstracting logic from existing code.

Subcontrollers

While working on ProjectF I decided that one of my interface scenes had two very distinct parts.  In fact, one half of the interface can be completely disabled at times.  To simplify the view controller for this scene I decided to break the logic into two controllers.  One controller managed the main part of the scene and a second controller, which I called a SubController, managed the second (often disabled) part of the scene. This subsection of the scene is composed of a UITableView which requires a data source and delegate.  Using a subcontroller lets me keep the tableview data source and delegate methods out of the main view controller.  The subcontroller lets me focus on the table view code when I’m working on populating the table view and when I’m working on populating the rest of the interface I can focus on the main ViewController.  The two controllers make use of different data models though they are currently sharing a single behavior model that describes the whole scene.  I’m not sure yet if I should have separated the behavior into two models or not.  There is some behavior shared between the two halves of the interface.  Perhaps extracting the subscene’s behavior into a subbehavior model might make sense.

Next Steps

So far these two design decisions of behavior modeling and sub controllers has worked out very well for me.  I hope to continue to using and adapting these strategies.


Viewing all articles
Browse latest Browse all 12

Trending Articles