modular rails presentation outline

2
Big Ball of Mud Kitchen Sink Kerfuffle 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 a bout loading or dependencies => This is an excellent pattern for quickly serving and persisting simple we b 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 gen eric solution no longer severs needs (monkey patch / extend the gem "make it work"), slow tests bc dom ain 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 Dep endency 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 laye rs (shotgun surgery), Out of control dependency graph Hides your Domain Logic: Domain logic is mixed with Service logic (ActiveRecor d / Models, Controllers [if save then...]), Domain logic is hidden in Service logic (AR: validati ons, callbacks, save if; AC: before filters) Domain itself is hidden in the Framework (person.acco unt.houses.first.bridge) Domain logic obscured framework life cycles (AR: afte r_find) => 1. Changes to or in Services / Frameworks ripple through your app (non-trival to upgrade rails) - shotgun surgery -- check for other smell s 2. It is hard to know what the application is (st ill) 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 technologie s du jour -- adoption of new technology can be very difficult (imagine removing Active Rec

description

modular rails presentation outline

Transcript of modular rails presentation outline

Page 1: 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

Page 2: modular rails presentation outline

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)