mining gems in your existing codebase

36
Mining gems in your existing codebase @sanderhahn amsterdam ruby meetup 17th Dec 2014

Upload: sander-hahn

Post on 08-Aug-2015

134 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Mining gems in your existing codebase

Mining gems in your existing codebase

@sanderhahn amsterdam ruby meetup 17th Dec 2014

Page 2: Mining gems in your existing codebase

Agenda• Why extract gems?

• Prevent Rails apps to grow into monoliths

• How to design more modular apps?

• Railties, plugins, engines and mountables

• Ready for microservices?

• Just a perspective, open for discussion and your milage may vary

Page 3: Mining gems in your existing codebase

How Rails evolves

• Rails is a collection of separate gems living inside a single git repository (synchronised release planning and versions)

• Deprecation is done by including and extracting functionality into separate gems to allow managing technical debt (optional use of new and legacy gems)

Page 4: Mining gems in your existing codebase

Evolution by inclusion and extraction

• attr_accessible moved into protected_attributes gem, replaced by strong_parameters gem

• responds_with into responders gem

• cache_digests gem

• asset pipeline into sprockets-rails gem

• active_resource gem

Page 5: Mining gems in your existing codebase

Rails apps are structured by type

• app/assets

• app/controllers

• app/models

• app/views

• config/routes.rb

• db/migrate

Page 6: Mining gems in your existing codebase

Monolithic apps

• Rails development is very fast in greenfield projects but can become slower as your application and team grows

• Tests might require large fixtures of unrelated data and can take a long time to run

Page 7: Mining gems in your existing codebase

Engines enable apps to be structured by function

• Website Content

• Newsletter Subscription

• Lead Generation

• Webshop

• Public API

Page 8: Mining gems in your existing codebase

Advantages• Apps are build from logical separate modules

with explicit boundaries

• Distribute responsibility of code and work in a team

• Code reuse in client projects is possible

• Tests are more isolated and run faster

• Technical dept is easier to manage

Page 9: Mining gems in your existing codebase

Guiding principles

• Loosely coupled system is one in which each of its components has little or no knowledge of the definitions of other separate components

• High cohesion means to keep similar and related things together which share the same responsibility or goal

Page 10: Mining gems in your existing codebase

How to dissect apps into modular gems

• Railties (initialization)

• Plugins (extend Rails functionality)

• Engines (app composition)

• Mountable's (isolated namespace and route)

Page 11: Mining gems in your existing codebase

Foundation of Rails# rails/railtie.rb class Railtie

# rails/engine.rbclass Engine < Railtie

# rails/application.rb class Application < Engine

# config/application.rbclass Application < Rails::Application

Page 12: Mining gems in your existing codebase

Railtie provides several hooks to extend Rails and/or modify

the initialization process

Page 13: Mining gems in your existing codebase

Rails components are Railties

Page 14: Mining gems in your existing codebase

ActionMailer example

Page 15: Mining gems in your existing codebase

Plugin is an extension or a modification of the core

framework

Page 16: Mining gems in your existing codebase

Plugin structure$ rails plugin new gems/myplugin

Page 17: Mining gems in your existing codebase

Gem dependencies

Page 18: Mining gems in your existing codebase

Plugin config with Railtie

Page 19: Mining gems in your existing codebase

Engine is a miniature application that provides functionality to its

host application

Page 20: Mining gems in your existing codebase

Engine structure$ rails plugin new gems/myengine --full

Page 21: Mining gems in your existing codebase

Rails generate/destroy are available inside an engine

$ cd gems/myengine

$ rails generate scaffold user name:string

$ cd ../..

# add dependency in Gemfile

$ rake myengine:install:migrations

Page 22: Mining gems in your existing codebase

Mountable is a namespace-isolated engine

Page 23: Mining gems in your existing codebase

Mountable structure

$ rails plugin new gems/mymountable --mountable

Page 24: Mining gems in your existing codebase

Rails inside a mountable

$ cd gems/mymountable

$ rails generate scaffold post user:references title:string

$ cd ../..

# add dependency in Gemfile

$ rake mymountable:install:migrations

Page 25: Mining gems in your existing codebase

Engine vs mountables

Page 26: Mining gems in your existing codebase

Cross engine url_helpers

Page 27: Mining gems in your existing codebase

Testing an engine• At application runtime all engines are available

• Integration testing is done by creating a dummy app inside the test dir

• Other engines are only available if specified as a dependency

• Fake models and migrations can be created in the dummy app on engine boundaries

Page 28: Mining gems in your existing codebase

Dummy app for integration test in the devise gem

Page 29: Mining gems in your existing codebase

Example: Tolk gem is a Rails engine for translating your app to other languages

Page 30: Mining gems in your existing codebase

Tolk structure

Page 31: Mining gems in your existing codebase

Tolk generator

Page 32: Mining gems in your existing codebase

Thor and Generator actions

Page 33: Mining gems in your existing codebase

Breaking the Monolith @ Soundcloud

We decided to move towards what is now known as a microservices architecture. In this style, engineers separate domain logic into very small components. These components expose a well-defined API, and implement a Bounded Context — including its persistence layer and any other infrastructure needs. … In the end, the team decided to use Rails' features of engines to create an Internal API that is available only within our private network.

http://www.slideshare.net/pcalcado/from-a-monolithic-ruby-on-rails-app-to-the-jvm https://developers.soundcloud.com/blog/building-products-at-soundcloud-part-1-dealing-with-the-monolith https://developers.soundcloud.com/blog/building-products-at-soundcloud-part-2-breaking-the-monolith https://developers.soundcloud.com/blog/building-products-at-soundcloud-part-3-microservices-in-scala-and-finagle

Page 34: Mining gems in your existing codebase

Engines vs microservicesMicroservice architectural style: designing software applications as suites of independently deployable services

http://martinfowler.com/articles/microservices.html

Page 35: Mining gems in your existing codebase

Bounded Context helps guiding engine design

Domain-driven design (DDD) deals with large models by dividing them into different Bounded Contexts and being explicit about their interrelationships

http://martinfowler.com/bliki/BoundedContext.html

Page 36: Mining gems in your existing codebase

Thank you!