I recently had to take over an unfinished project. It was an AJAX control to select multiple friends as you can find it on Facebook.
“It’s 99% complete”, I was told. Yeah, right. I counted 2 story points (without looking at the code). Soon I knew I was too optimistic: Classes calling other classes without logic. Randomly named variables. Data, creation of DOM elements, AJAX calls spread all over the place:
That’s not going to be easy. To make things worse: I am a Javascript beginner. What I did up to now was procedural Javascript code.
I felt the urge to begin everything from scratch. But I remember Joel Spolsky saying that we should resist so I decided to go for a refactoring.
As I know the MVC pattern very well from Zend Framework I tried to apply this pattern. Separation of concern! Each class has a well defined purpose. Here’s the architecture I refactored the code to:
- Model: All operation on data (i.e. the friends to be selected) is in the classes “ModelFriendListItems” (which aggregates “ModelFriendListItem”). The Ajax request fetching the friend objects from the server is located ther as AJAX is about data.
- View: The three views for the panes “Parent container”, “All friends” and “selected friends”. DOM manipulation only in these classes.
- A controller in charge of instancing and controlling the model and the views. The controller handles all events. No AJAX.
Here’s the sum up of the concerns of the parts:
DOM manipulation | AJAX calls | Event and input handling | |
Model | No | Yes | No |
View | Yes | No | No |
Controller | No | No | Yes |
As every class has his well defined concern you quickly know where to look when you need to maintain or extend the control. The name of the class and files reflects the role (ViewAllFriends.js, ModelFriendsListItems.js). Logical event and data flows.
You can try it here. Here’s how the final version looks:
Well… It took much more than the 2 story points I counted in the beginning. But it feels much better having clean code! And my colleagues having to extend this control (Leo?) are surely happy for this clean up 🙂
I am sure there are other ways to model a Javascript control. What is your best practice?