Slide 1

Slide 1 text

$ git clone https://github.com/shageman/sportsball.git $ cd sportsball $ ./build.sh

Slide 2

Slide 2 text

What brings you here?

Slide 3

Slide 3 text

Getting started with #cbra Component-Based Rails Applications RailsConf 2015, Labs Workshop

Slide 4

Slide 4 text

Stephan Hagemann @shageman shagemann@pivotal.io Pivotal Labs

Slide 5

Slide 5 text

Why #cbra?

Slide 6

Slide 6 text

Improved Communication Improved Collaboration Improved Creation Improved Maintenance Improved Comprehension

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Communication

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

Collaboration

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

Creation

Slide 14

Slide 14 text

graphs on/off

Slide 15

Slide 15 text

Maintenance

Slide 16

Slide 16 text

reports2

Slide 17

Slide 17 text

Comprehension

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

$ git clone https://github.com/shageman/sportsball.git $ cd sportsball $ ./build.sh

Slide 21

Slide 21 text

Sportsball - what does it do?

Slide 22

Slide 22 text

Status Quo

Slide 23

Slide 23 text

Sportsball App Rails Engine Gem

Slide 24

Slide 24 text

Code Review!

Slide 25

Slide 25 text

Code Review Recap ● No app folder! ● App gem loaded through path (Gemfile) ● App is an engine (engine.rb) ● App is mounted (config/routes.rb) ● App routes defined in engine (app/config/routes.rb) ● App defines and loads migrations (app/db/migrate/, engine. rb) ● Non-published gems are funky (both Gemfiles) ● Tests are at the appropriate levels and aggregated via scripts (build.sh, test.sh) ● Deployment is unchanged

Slide 26

Slide 26 text

Finding Components

Slide 27

Slide 27 text

What should be extracted first?

Slide 28

Slide 28 text

Sportsball App Rails Engine Gem

Slide 29

Slide 29 text

What is the intrinsic structure of this app?

Slide 30

Slide 30 text

1st Refactor Extract Domain Gem

Slide 31

Slide 31 text

Sportsball App Rails Engine Gem

Slide 32

Slide 32 text

Sportsball App Rails Engine Gem Predictor

Slide 33

Slide 33 text

bundle gem predictor #answer questions rm -rf predictor/.git* Move classes, move tests Rename module (in gem) Fix tests (in gem) Load gem (in engine) Fix tests (in engine) Check build (in main app) DIY - Extract Predictor Gem

Slide 34

Slide 34 text

Code Review!

Slide 35

Slide 35 text

Code Review Recap ● path … do (Gemfile) ● Require gem in (lib/app.rb) ● Non-test code changes only in Module names (prediction_controller.rb) ● OpenStruct App::Team and App::Game (predictor_spec.rb) ● Test runner is simplified (predictor/test.sh)

Slide 36

Slide 36 text

Lessons Learned ● Have good tests around the refactor ● Keep running those tests! ● Run tests inside out (up the dependency graph) ● Reduce component dependencies as much as possible ○ Simplifies component ○ Fewest possible reasons to change ○ Keeps dependency graph flat

Slide 37

Slide 37 text

Sportsball App Rails Engine Gem predictor

Slide 38

Slide 38 text

What else is in this app?

Slide 39

Slide 39 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games

Slide 40

Slide 40 text

2nd & 3rd Refactor Push Persistence Down

Slide 41

Slide 41 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games AR Engine

Slide 42

Slide 42 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games AR Engine

Slide 43

Slide 43 text

rails plugin new --help rails plugin new teams -BGVSJT --mountable \ --dummy-path=spec/dummy Move classes, move tests, move migration Create table renaming migration (in teams engine) Rename module (in teams engine) Fix tests (in teams engine) Load gem (in app engine) Create testhelper (in teams engine) and use (in app engine) Fix tests (in app engine) Check build (in main app) DIY - Push Teams Persistence Down

Slide 44

Slide 44 text

Code Review!

Slide 45

Slide 45 text

Code Review Recap ● Dummy app (teams/spec/dummy) ● String renames of AR associations! (app/game.rb) ● Teams test helper ○ Create test helper (teams/spec/support/object_creation_methods.rb) ○ Expose test helper (teams/lib/teams/test_helpers.rb) ○ Use teams test helper (app/spec/spec_helper.rb)

Slide 46

Slide 46 text

Lessons Learned ● Two ways of engine-out-of-engine extraction ○ Create fresh + move + rename ○ Duplicate + delete + rename ● Don’t mess with existing migrations! ○ Move affected existing migrations ○ Create new migration for table rename ● Test helpers nice for ActiveRecord models ● “App” is a terrible name to refactor away from

Slide 47

Slide 47 text

4th Refactor Better Naming of Component

Slide 48

Slide 48 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games Layout WebUI AR Engine

Slide 49

Slide 49 text

Common Base Misc General Lib Side note: If you feel like naming your engine...

Slide 50

Slide 50 text

Everything Cruft Random Don’t Know Don’t Care Duh Here are some alternatives

Slide 51

Slide 51 text

Everything Cruft Random DontKnow DontCare Duh Here are some alternatives (Proper module names)

Slide 52

Slide 52 text

Give the most specific name you can think of refactor a lot continue the conversation

Slide 53

Slide 53 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games AR Engine

Slide 54

Slide 54 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games AR Engine Can we split up WebUI?

Slide 55

Slide 55 text

5th Refactor Extract Layout and Style

Slide 56

Slide 56 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games WebStyle AR Engine UI Engine

Slide 57

Slide 57 text

Copy WebUI into WebStyle Remove everything but assets/layout - don’t forget vendor! (in WebStyle) Remove assets (in WebUI) Fix asset loading (in WebUI) Check build (in main app) DIY - Extract WebStyle

Slide 58

Slide 58 text

Code Review!

Slide 59

Slide 59 text

Code Review Recap ● No tests in WebStyle ● Application layout (web_style/application.html.slim) ● Layout selection (web_ui/application_controller.rb)

Slide 60

Slide 60 text

Lessons Learned ● You won’t know what components you will need to extract until you try to extract something

Slide 61

Slide 61 text

6th, 7th, 8th Refactor Separate independent UIs

Slide 62

Slide 62 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games WebStyle AR Engine UI Engine

Slide 63

Slide 63 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games WebStyle AR Engine UI Engine

Slide 64

Slide 64 text

Sportsball Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games WebStyle AR Engine UI Engine

Slide 65

Slide 65 text

Sportsball Welcome UI Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games WebStyle AR Engine UI Engine

Slide 66

Slide 66 text

Pick any one of the potential UI engines DIY - Split off a UI Engine

Slide 67

Slide 67 text

Code Review!

Slide 68

Slide 68 text

Code Review Recap ● Rerouting necessary ○ App routes (config/routes.rb) ○ Engine routes (*_ui/config/routes.rb) ○ Tests

Slide 69

Slide 69 text

Lessons Learned

Slide 70

Slide 70 text

Sportsball Welcome UI Rails Engine Gem Predictor Team UI Game UI Prediction UI Teams Games WebStyle AR Engine UI Engine That’s it!

Slide 71

Slide 71 text

Now - Your App!

Slide 72

Slide 72 text

leanpub.com/cbra/c/railsconf

Slide 73

Slide 73 text

cbra.info