Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Clean Architecture - Arena TOTVS 2015

01684ebe74590fa2d4c6f37e7a47c043?s=47 bezelga
November 25, 2015
130

Clean Architecture - Arena TOTVS 2015

01684ebe74590fa2d4c6f37e7a47c043?s=128

bezelga

November 25, 2015
Tweet

Transcript

  1. CLEAN ARCHITECTURE ON RAILS

  2. CHAPTER I What is Clean Architecture?

  3. None
  4. the PROBLEM

  5. None
  6. your top level structure is screaming the web FRAMEWORK

  7. The web is a delivery mechanism

  8. the web is a COMMODITY

  9. yet it DOMINATES your code

  10. image you’ve just joined a PROJECT

  11. None
  12. None
  13. what makes a GOOD architecture?

  14. it is not about frameworks and tools

  15. Fabiano Beselga CTO magnetis.com.br WRITER medium.com/@fbzga TWITTER @fbzga

  16. bit.ly/clean-rails

  17. IVAR JACOBSON

  18. business rules INTERACTORS (aka use cases)

  19. domain model ENTITIES

  20. communication interfaces BOUNDARIES

  21. diagrams: Robert C Martin

  22. None
  23. None
  24. None
  25. None
  26. None
  27. What about MVC?

  28. MVC as a Web architecture

  29. this is NOT WHAT I MEANT

  30. WEB FRAMEWORK APP

  31. CHAPTER II HOW to use it with Rails?

  32. BRAAVOS

  33. None
  34. WE ARE OPENING A BANK! WE NEED TO HIRE A

    GREAT DEVELOPER!
  35. None
  36. WHAT ABOUT THIS ONE?

  37. None
  38. None
  39. None
  40. HIRED!

  41. first day at WORK

  42. THE SYSTEM MUST TRANSFER MONEY BETWEEN THE FAMILIES ACCOUNTS

  43. OK! ANY EXCEPTION COURSES?

  44. WHEN THERE ISN’T ENOUGH MONEY TO TRANSFER.

  45. that’s easy, I can do it in 7 STEPS!

  46. GREAT! YOU HAVE 10 MINUTES!

  47. challenge accepted!

  48. 1 create the PROJECT

  49. rails new braavos

  50. mkdir core

  51. module Core end core.rb

  52. 2 define BOUNDARIES

  53. README Driven Development

  54. Usage Transfer money Core.transfer_money(amount: 10_000, source_account_id: 1, destination_account_id: 2) README

    => true # when transfer successful => false # when not enough balance
  55. 3 define behaviour Driven Development

  56. context 'enough money to transfer' do it 'responds true' do

    expect(transfer).to be true end it 'debits the source account' do expect{ transfer }.to change{ source_account_balance }.by(- amount) end it 'credits the destination account' do expect{ transfer }.to change{ destination_account_balance }.by(amount) end end PRIMARY course
  57. context 'not enough money to transfer' do it 'cancels the

    transfer and responds false' do expect(transfer).to be false end it 'does not change the accounts balance' do expect{ transfer }.to_not change{ source_account_balance } expect{ transfer }.to_not change{ destination_account_balance } end end EXCEPTION COURSE
  58. FFF

  59. define DATA MODEL 4

  60. CAN YOU TELL ME A LITTLE MORE ABOUT THE DOMAIN?

  61. EACH FAMILY HAS AN ACCOUNT. EACH ACCOUNT HAS A HISTORY

    OF TRADES MADE.
  62. rails g model account name rails g model trade account:references

    amount:decimal date:date
  63. trades debit: -1000 credit: +1000

  64. the ENTRY POINT 5

  65. module Core class << self delegate :transfer_money, to: TransferMoney end

    end core.rb
  66. the USE CASE 6

  67. module Core class TransferMoney def self.transfer_money(source_account_id:, destination_account_id:, amount:) balance =

    Core.get_balance(account_id: source_account_id) return false if balance < amount ActiveRecord::Base.transaction do Trade.create!(account_id: source_account_id, amount: -amount) Trade.create!(account_id: destination_account_id, amount: amount) end end end end core/transfer_money.rb
  68. REFACTOR!

  69. module Core class << self delegate :transfer_money, to: TransferMoney end

    end core.rb before
  70. CAZE DSL to elegantly declare use cases

  71. Gemfile gem 'caze'

  72. module Core include Caze has_use_case :transfer_money, TransferMoney end core.rb AFTER

  73. module Core include Caze has_use_case :transfer_money, TransferMoney, transactional: true end

    core.rb AFTER
  74. g github.com/magne/s/caze

  75. BREAKING NEWS! 
 WE HAVE MONEY TO HIRE AGAIN!

  76. WHAT ABOUT THIS SNOW?

  77. WHAT?

  78. None
  79. None
  80. Usage Transfer money Core.transfer_money(amount: 10_000, source_account_id: 1, destination_account_id: 2) README

    => true # when transfer successful => false # when not enough balance
  81. None
  82. expose it to the web 7

  83. let’s call it on a CONTROLLER

  84. class TransferMoneyController < ApplicationController before_action :load_balance def create if Core.transfer_money(source_account_id:

    source_account_id, destination_account_id: destination_account_id, amount: amount) redirect_to new_transfer_money_path else flash[:error] = 'Not enough money on the source account' render :new end end private def load_balance @balance = Core.get_balance(account_id: current_account_id) end end
  85. None
  86. bit.ly/braavos

  87. what just happened?

  88. Core represents WHAT THE SYSTEM Does CHANGES

  89. core/ get_balance.rb transfer_money.rb BEHAVIOUR CHANGES

  90. the models represent WHAT THE SYSTEM IS STABLE

  91. app/ models/ account.rb trade.rb DATA STABLE

  92. a key, longstanding hallmark of a good program is that

    it separates what is stable from what changes in the interest of good maintenance. - Trygve Reenskaug
  93. Models Core Rails delivery mechanism behaviour MODULE data #1

  94. the ALTERNATIVES

  95. Models Core Rails delivery mechanism behaviour RAILS ENGINE #2

  96. The database is a detail

  97. Isolate it!

  98. Models Core Rails delivery mechanism behaviour gem rails engine data

    API #3
  99. what about real life?

  100. magnetis.com.br

  101. ~ 4 years old codebase

  102. experimenting with clean architecture ~ 2 years

  103. None
  104. the first seeds magnetis core

  105. a module for each DOMAIN CONCEPT

  106. we have a module for investments recommendation Advisor

  107. Advisor.recommend_investments(params)

  108. None
  109. we have a module for accounting Accountant

  110. None
  111. magnetis/ domain/ accountant/ advisor/

  112. BOUNDED CONTEXTs Advisor Accountant Order Manager Account Manager Trader Pricing

    Backtesting
  113. why not MICROSERVICES?

  114. we also use the Rails WAY

  115. FINAL CHAPTER when to use it?

  116. YOUR PRODUCT

  117. core business your product rails way clean architecture

  118. Eric Evans Don’t try yo apply DDD to everything. Draw

    a context map and decide on where you will make a push for DDD and where you will not .
  119. THE distance from the view

  120. the domain logic is close to the view Rails way

  121. the domain logic is far from the view Clean architecture

  122. TIMING

  123. image: Kent Beck

  124. Lessons learned

  125. no good

  126. Over-engineering when the domain logic is close to the view

  127. getting out of the rails conventions may be hard

  128. the cool STUFF

  129. defer decisions until the last responsible moment

  130. it SCREAMS BEHAVIOR

  131. decoupled business rules

  132. tests RUNNING FASTER!

  133. what makes a GOOD architecture?

  134. CLEAN ARCHITECTURE HEXAGONAL ARCHITECTURE DOMAIN DRIVEN DESIGN DATA CONTEXT INTERACTION

    TRAILBLAZER
  135. all these architectures have SIMILAR OBJECTIVES

  136. Architecture is about Intent

  137. Intent = what the SYSTEM DOES

  138. reflect THE USER’S MENTAL MODEL in your architecture

  139. domain as a 1st class citizen

  140. ONE MORE THING…

  141. None
  142. None
  143. we are hiring fabiano@magne/s.com.br magne/s.com.br/dev

  144. Developer #1 Developer #2 The Boss The Mastermind Tio Roberto

    Domain Father Advisor Presenter CAST TYRION LANNISTER Jon SNOW SHERKLOCKS’ BROTHER IVAR JACOBSON UNCLE BOB ERIC EVANS ROBERT DUVAL FABIANO BESELGA by @fbzga