Better OOD in Rails
Posted by Doug Thu, 23 Jun 2005 13:35:00 GMT
Honestly, Object Oriented Design is something I don’t get a chance to practice very often. Ruby on Rails encourages OOD with it’s fundamental MVC functionality split. What that’s typically meant to me is that every database table gets an ActiveRecord model, and every model has it’s own controller which drives some number of views. Reading Dave Thomas’ new Agile Web Development with Rails has broken that mold a little for me. Rather than focusing on a strict one model has one controller, Dave illustrates using controllers to group similar actions together. It seems obvious that’s what controllers are for; but, Dave’s book is the first place I’ve seen break the static tie between models and controllers. My project has an Image model. Users have many Images and Images belong to Users. I store Image filenames in the database associated with the User’s id. I also store the image file itself on the filesystem. Using Imlib2-Ruby bindings, I also parse the image to find things like width and height (to make proper image html tags) and scale the image to appropriate sizes. I’ve struggled with this object for not very good reasons. Yesterday I blogged about making progress on this at the sacrifice of tests. Last night was another “breaking the mold” learning experiences. I told MarkWindholtz about my testing struggles. He suggested we pair up to work on it together. What a valuable experience that was! He had me extract out the two main groups of non-database-specific Image functionality; ImageFiler, the part that deals with the filesystem; and (for a lack of a better name) Imager, that’s a simplified front-end to the Imlib2 functions. The original Image model contains these other two classes and delegates specific functions to them. This allowed me to test those other functions without having to worry about the database. I was struggling with what type of data fixtures to use when testing image scaling. I didn’t want to have to go through the work of making valid Image objects just so I could scale the image. With it broken apart it’s much easier to just test the individual pieces. It’s de-coupled. I had been lumping everything related to a given database table into a single ActiveRecord object. So far, it had worked out pretty well. The problem is when your models get more complex. It becomes hard to test the models with the database functionality in the way. I’m not exactly sure where the line is between adding functionality directly in the AR model and putting it in a aggregated class. I guess you can tell when it needs to be extracted by how ugly your testing ends up. To Dave Thomas’ credit, his Rails book also has an example of this. It’s not exactly the same, but his tutorial includes a primary model that’s not an ActiveRecord. One of the things that’s exciting about RubyOnRails? is that you actually get to do object oriented programming.