modular rails presentation outline

Post on 21-Jul-2016

17 views 0 download

description

modular rails presentation outline

Transcript of modular rails presentation outline

Big Ball of MudKitchen SinkKerfuffle

We all know rails 1. its great because it is so fast and easy > rails new sweet_webapp # ship it! - simple, well known architectural pattern (MCV) - gems and plugins for everything (devise, etc.) - global access to every object in your system, so you never have to worry about loading or dependencies => This is an excellent pattern for quickly serving and persisting simple web forms in a database 2. but then it starts to slow down... each of those strengths come with a long shadow - MVC -> Big Ball of Mud - gems/plugins -> Kitchen Sink impossible to update dependancies, tied hands because generic solution no longer severs needs (monkey patch / extend the gem "make it work"), slow tests bc domain logic is tied to your gems (active record), large memory footprint - global access -> Kerfuffle - fragile, frightening, code 3. Why does this happen? MVC -> BBM - Violates core OO principals: Encapsulation, Knowledge hiding, Stable Dependency Ordering - Violation of DIP, Demeter, and Ask Don't tell - DIP DBSchema -> Model -> Controller -> View - assets: DRY, convention over configuration (great for simple form persistence - no domain logic) - liabilities: Changes to any lower layer ripple through higher layers (shotgun surgery), Out of control dependency graph Hides your Domain Logic: Domain logic is mixed with Service logic (ActiveRecord / Models, Controllers [if save then...]), Domain logic is hidden in Service logic (AR: validations, callbacks, save if; AC: before filters) Domain itself is hidden in the Framework (person.account.houses.first.bridge) Domain logic obscured framework life cycles (AR: after_find) => 1. Changes to or in Services / Frameworks ripple through your app (non-trival to upgrade rails) - shotgun surgery -- check for other smells 2. It is hard to know what the application is (still) supposed to do - long "spin up time" (recurring payment) - low "bus number" (why is it this way) - fear (we don't know what happens if we change this) - code silos / ownership 3. Domain Functionality is limited by technologies du jour -- adoption of new technology can be very difficult (imagine removing Active Rec

ord and Mysql to switch to Mongoid/Mongo) - Demeter AR: Global access, wide (almost infinite) interface for objects, can be performance penalty for acting otherwise - assets: Fast to code, easy to think of at the moment, fewer files / classes (not really a benefit) - liabilities: Relationships in Domain are exposed and repeated everywhere (not DRY), Global access encourages us to add responsibilities to existing objects rather than creating new ones - this ties the app together, key to implementing BBM - changing how an object is stored can break your application - entity relations are repeated all over the app, sometimes silently depended on - product.cart.customer.address means that a customer cannot have two carts -- ever. - Ask Dont Tell AR: Global access, auto-magic ? methods, confusion persistence mechanism with behavior (latch has the state i want) - assets: Fast to code, easy to think of at the moment, fewer files / classes (not really a benefit) - liabilities: spreads decision logic over n+1 objects where n objects are needed to make the decision - eg. door.open! vs. door.open! if door.latch.is_closed? (usually violation of LOD too) - obscures logic, ties app together - in fact, it violates all SOLID principals: SRP, Open/Close, Interface segregation, Liskov, DIP 4. What can we do about it? 1. Order Dependencies Stably - hexagonal - DIP layers 2. Separate Domain from dependencies: - Skinny Controller, Skinny Model, Smart PORO 3. Limit access - physical separation - Folders / namespaces in app/models, app/controllers, and /lib - Unbuilt gems - in rails project - out of rails project - Built gems - used across your enterprise - Tell Demeter to Obey 4. Use gems/plugins sparingly and limit where you use them - may be worth creating an adapter or an application service (Resque / Sidekiq)