I've been thinking for a while about reasons that prevent a lot of programmers — myself first of all — from writing clean, modular and expressive code while developing, for example, CocoaTouch apps.
What I discovered is that my top-three of reasons are following:
- UI code. Device-specific UI/UX, general clutter, 'quick fixes and workarounds' and so on.
- Poor Controller-View decoupling. Sometimes Controller ends up doing job that the View is responsible for.
- Sparse test harness.
Of course, those problems stem from lack of discipline or habit to write clean code. But it is difficult to discipline yourself if the environment allows you not to do that.
It is easy to sort laundry if you have a set of dedicated drawers, but if you have one drawer, it will slowly turn into mess — unless you are very disciplined.
And then I tried to apply that idea of 'sorting drawers' to address my code problems — and I thought that it is possible to sort MVP components as follows:
- Model is actually a framework of classes responsible for dealing with data. Model is reusable, as it is a set of routines to work with data.
- View is actually a framework of classes responsible for presenting information graphically. It doesn't depend that much on environment and it definitely can be reused.
- Controller is a framework of classes responsible for coordination of aforementioned layers and working with user interaction paths. Application itself is something like (?) a big controller. Since it glues together a defined set of models to a defined set of views, it is not reusable and depends heavily on those + platform etc.
So given the M and V are somewhat reusable, and C is not — maybe it makes sense to force separation of M and V? The best way to ensure they are separated is to put them in static libraries. After that they can be linked to the app, which contains only controller code.
This approach seems to me quite good because:
- only controller depends on something here
- developer can write separate test suites for those modules
- user interface classes can be reused in other apps easily
- model classes can be extracted to cross-platform codebase while maintaining the old facade
- commits are limited to three really distinct modules — what's more distinct than a separate library?
What do you think? Does this sound like an idea to follow?