Tuesday, November 24, 2009

Generalize everything pattern

Sometimes I 'am facing "generalize everything" pattern, when developer trying to invent a "racing car" for a trip for a few kilometers (or miles :) ). But as soon car is ready, it happens that car can be driven only on straight flat road, with no turns with constant speed only on 5th gear. Later, when you destinations changing you apply more and more hand-made solutions and hacks. Finally, after several month passed, car got a bit rusty and needs support, but is takes a lot of time (and money) even for clever mechanic to solve the problem. It's because car is full of "witty" and "smart" puzzles. Just take a walk, it's healthy.
A real life example: Customer required us to implement "read-only" feature for product, that we developing. After some discussion 2 possible solutions were found:
  1. Automate all processing of permissions. Base Presenter will automatically determine if user is read-only, call a special method in a Base View that is responsible for hiding all buttons, that is tagged with special marked (Save buttons).
  2. Move it's responsibility to concrete presenter and concrete view. View will have method, that hides edit buttons where buttons are defined explicitly. Presenter with call explicitly View.HideEditButtons() method if required.
Let's analyze pros and cons of each solution:

Maintainability

Using first approach - firstly, it seems that developers will produce less bugs during implementation of the each page. At least they need only to place properly annotated buttons on the page.  But when customer asks for a simple feature, like "please enable this button for read-only". Developer implements workaround on one page, on second, third and you have a bunch of pages with a different implementation of same feature. And finally when tester reports a bug, you need to analyze a markup (with annotation, do you remember), view implementation for hacks, base view implementation for hiding mechanism itself and presenter for an additional hacks.
In second approach, developer will modify a View.HideEditButtons method (remove or add hiding of buttons), or introduce new permission rule (if it's required). It's pretty easy now, because implementation is not coupled with "Base*" stuff and will not broke anything else in the system. Support team will need to analyze only 2 files – view and presenter, and all control hiding/showing are declared explicitly there.

Lines of code

It's nearly equal. On the left side there is a new-born framework and customizations for it. On the right side a lot of boilerplate permission checks and show/hide control code divided into methods.

Code complexity

General solution is full of polymorphism, default and implicit behavior, if branches, typeof-s. It's easy to forget a small thing, and here it is – a bug. Second solution is a set of flat methods with a rare branches like If(!Allowed){View.HideSomething();} that is easy to read even if you unfamiliar with a context.

Code duplication

Using 2nd approach, it's seems that you have written View/Hide methods and permissions check zillions of times. But that methods are completely different methods with the same pattern. Method is simple and contains only vital information that is differs from page to page. In 1st approach during simple tasks there is no code/pattern duplication at all, but later developers will invent their own hacks, that will do similar tasks in a different ways.

No comments:

Post a Comment