SlideShare a Scribd company logo
1 of 27
Estructurar y
mantener
aplicaciones Rails
sin morir en el
intento
by @moises_macia
MADRID · NOV 18-19 · 2016
MADRID · NOV 18-19 · 2016
Hola
●
Moisès Macià (@moises_macia)
●
Actualmente CTO en @samyroad
●
~15 años desarrollando software (C++, PHP, Java, ...)
●
~5 años desarrollando en Ruby/Rails.
MADRID · NOV 18-19 · 2016
MADRID · NOV 18-19 · 2016
MADRID · NOV 18-19 · 2016
MADRID · NOV 18-19 · 2016
Hay una nueva versión de Rails
MADRID · NOV 18-19 · 2016
Sistema conectado Vs modular
To Design or Not To Design? A Third Good Question
MADRID · NOV 18-19 · 2016
Sistema conectado Vs modular
● Rails no es mi aplicación.
● Mi aplicación es mi lógica de negocio.
● Mi aplicación debe ser independiente.
● Idependiente del contexto.
● Independiente de como se accede a ella.
● Independiente de las herramientas que se usan para contruirla.
MADRID · NOV 18-19 · 2016
Problemas: Gems
● Gemas que añaden poco valor y hay que mantener.
● Gemas que se acoplan demasiado a ActiveRecord.
● Gemas con toneladas de dependencias.
● Gemas sin mantenimiento.
$ bundle list | wc -l
341
MADRID · NOV 18-19 · 2016
Problemas: God objects
● User.rb
● LOC > 1000
● Derivado de la politica “Fat
models”
MADRID · NOV 18-19 · 2016
Problemas: ActiveRecord
●
Acoplamiento entre persistencia y lógica de negocio.
●
Demasiadas responsabilidades en una sola clase.
●
Callbacks.
irb> User.new.methods.count
=> 2307
MADRID · NOV 18-19 · 2016
Problemas: Rails way
●
Fat controllers.
●
Fat Models.
●
Concerns.
●
Imposibilita hacer Unit testing.
MADRID · NOV 18-19 · 2016
Refactor: Gem diet
●
Gemas que aporten valor real.
●
Gemas mantenidas.
●
Gemas para conectar con servicios externos (S3, Mailchimp, etc.).
●
Bundle groups.
MADRID · NOV 18-19 · 2016
Refactor: Form objects
●
Contienen validación de datos.
●
Un formulario por cada caso de uso.
●
Un formulario puede contener datos de varios modelos.
MADRID · NOV 18-19 · 2016
Refactor: Form objects
# app/forms/users/create_form.rb
module Users
class RegisterForm
include ActiveModel::Model
include Virtus.model
attribute :nickname, String
attribute :email, String
attribute :password, String
validates :nickname, presence: true
validates :email, presence: true, format: RFC_2822
validates :password, presence: true, length: { within: 8..50 }
def persisted?
false
end
end
end
MADRID · NOV 18-19 · 2016
Refactor: Service objects
●
Un servicio por cada caso de uso.
●
Inyección de dependencias.
●
Interfaz común (.execute)
●
Contienen:
– Lógica de negocio.
– Llamadas a servicios externos.
– Llamadas a servicios internos.
●
Los servicios delegan la persistencia a ActiveRecord.
MADRID · NOV 18-19 · 2016
Refactor: Service Object
# app/services/users/create_form.rb
module Users
class RegisterService
class RegisterError < StandardError; end
def initialize(form)
@attrs = form.data
end
def execute
user = User.new(@attrs)
raise RegisterError, user.errors unless user.save
welcome_email
add_to_newsletter if user.newsletter_subscription?
suggest_followings
# ...
end
end
end
MADRID · NOV 18-19 · 2016
Refactor: Model
# app/models/user.rb
class User < ActiveRecord::Base
has_many :items
has_many :roles
def newsletter_subscription?
# ...
end
end
MADRID · NOV 18-19 · 2016
Refactor: Controller (1)
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
authorize User
if register_form.valid?
user = register_form.execute
render user, status: :created
else
render register_form, status: :unprocessable_entity
end
end
def update
authorize user
if profile_update_form.valid?
updated_user = profile_update_service.execute
render updated_user, status: :ok
else
render profile_update_form, status: :unprocessable_entity
end
end
end
MADRID · NOV 18-19 · 2016
Refactor: Controller (2)
# app/controllers/users_controller.rb
class UsersController < ApplicationController
private
def user
@user ||= policy_scope(User).find_by!(nickname: params[:nickname])
end
def register_form
@register_form ||= Users::RegisterForm.new(params)
end
def user_create_service
@register_service ||= Users::RegisterService.new(register_form)
end
end
MADRID · NOV 18-19 · 2016
Refactor: Controller (3)
# app/controllers/users_controller.rb
class UsersController < ApplicationController
private
def profile_update_form
Users::ProfilepdateForm.new(params).tap do |form|
form.resource = user
end
end
def profile_update_service
@profile_update_service ||= Users::ProfilepdateService.new(
user,
profile_update_form
)
end
end
MADRID · NOV 18-19 · 2016
Refactor: Unit testing
●
Service/Form objects faciles de testear al no estar acoplados a Rails.
●
Muy rápidos.
●
Tests unitarios.
●
Mocks de la persistencia.
MADRID · NOV 18-19 · 2016
Unit testing: Form Object
# spec/unit/forms/users/create_form_spec.rb
describe Users::RegisterForm type: [:form, :unit] do
let(:form) { described_class.new(nickname: 'codemotion', # ...) }
describe '.valid?' do
context 'when nickname is not valid' do
it 'should return false if it is too short' do
form.nickname 'xx'
expect(form).not_to be_valid
expect(form.errors).to include(:nickname)
end
# ...
end
# ...
end
end
MADRID · NOV 18-19 · 2016
Unit testing: Controller
# spec/unit/controllers/users_controller_spec.rb
describe UsersController, type: [:controller, :unit] do
describe 'create an user' do
subject { process :create, method: :post, params: params }
before(:each) do
expect_any_instance_of(described_class).to receive(:register_service) { register_service_double }
expect_any_instance_of(described_class).to receive(:register_form) { register_form_double }
end
it 'return created with valid data' do
expect_any_instance_of(described_class).to receive(:authorize).with(User)
expect(subject).to have_http_status(:created)
end
end
end
MADRID · NOV 18-19 · 2016
Integration testing: Service Object
# spec/integration/services/users/create_service_spec.rb
describe Users::RegisterService type: [:service, :integration] do
let(:user_attributes) { attributes_for :user }
subject { described_class.new(Users::RegisterForm.new(user_attributes)) }
describe '.execute' do
it 'should create a new user' do
new_user = subject.execute
expect(new_user).to be_an_instance_of(User)
end
end
end
MADRID · NOV 18-19 · 2016
Refactor
●
¿Son necesarias todas estas clases y divisiones?
●
Hay que ser pragmatico ante todo.
MADRID · NOV 18-19 · 2016
Recursos

More Related Content

Similar to Estructurar y mantener aplicaciones Rails sin morir en el intento

API Design Best Practices by Igor Miniailo
API Design Best Practices by Igor MiniailoAPI Design Best Practices by Igor Miniailo
API Design Best Practices by Igor MiniailoMagecom UK Limited
 
Backward Compatibility Developer's Guide in Magento 2
Backward Compatibility Developer's Guide in Magento 2Backward Compatibility Developer's Guide in Magento 2
Backward Compatibility Developer's Guide in Magento 2Igor Miniailo
 
VSSML16 L7. REST API, Bindings, and Basic Workflows
VSSML16 L7. REST API, Bindings, and Basic WorkflowsVSSML16 L7. REST API, Bindings, and Basic Workflows
VSSML16 L7. REST API, Bindings, and Basic WorkflowsBigML, Inc
 
Christoforos zolotas cloudmde2015 presentation - camera ready
Christoforos zolotas  cloudmde2015 presentation - camera readyChristoforos zolotas  cloudmde2015 presentation - camera ready
Christoforos zolotas cloudmde2015 presentation - camera readyISSEL
 
Backward Compatibility Developer's Guide Webinar
Backward Compatibility Developer's Guide WebinarBackward Compatibility Developer's Guide Webinar
Backward Compatibility Developer's Guide WebinarIgor Miniailo
 
Deploying your Predictive Models as a Service via
 Domino API Endpoints
Deploying your Predictive Models as a Service via
 Domino API EndpointsDeploying your Predictive Models as a Service via
 Domino API Endpoints
Deploying your Predictive Models as a Service via
 Domino API EndpointsDomino Data Lab
 
Mongo db improve the performance of your application codemotion2016
Mongo db improve the performance of your application codemotion2016Mongo db improve the performance of your application codemotion2016
Mongo db improve the performance of your application codemotion2016Juan Antonio Roy Couto
 
Unifying Frontend and Backend Development with Scala - ScalaCon 2021
Unifying Frontend and Backend Development with Scala - ScalaCon 2021Unifying Frontend and Backend Development with Scala - ScalaCon 2021
Unifying Frontend and Backend Development with Scala - ScalaCon 2021Taro L. Saito
 
Custom Forms and Configuration Forms in Drupal 8
Custom Forms and Configuration Forms in Drupal 8Custom Forms and Configuration Forms in Drupal 8
Custom Forms and Configuration Forms in Drupal 8Italo Mairo
 
JSFest 2019: Technology agnostic microservices at SPA frontend
JSFest 2019: Technology agnostic microservices at SPA frontendJSFest 2019: Technology agnostic microservices at SPA frontend
JSFest 2019: Technology agnostic microservices at SPA frontendVlad Fedosov
 
01. lab instructions starting project
01. lab instructions   starting project01. lab instructions   starting project
01. lab instructions starting projectrajul14
 
Reactive Application Using METEOR
Reactive Application Using METEORReactive Application Using METEOR
Reactive Application Using METEORNodeXperts
 
MongoDB .local London 2019: The Tech Behind Connected Car
MongoDB .local London 2019: The Tech Behind Connected CarMongoDB .local London 2019: The Tech Behind Connected Car
MongoDB .local London 2019: The Tech Behind Connected CarMongoDB
 
Magnolia & Angular JS - an Approach for Javascript RIAs Delivered by a CMS
Magnolia & Angular JS - an Approach for Javascript RIAs Delivered by a CMSMagnolia & Angular JS - an Approach for Javascript RIAs Delivered by a CMS
Magnolia & Angular JS - an Approach for Javascript RIAs Delivered by a CMSMagnolia
 
Presentation on angular 5
Presentation on angular 5Presentation on angular 5
Presentation on angular 5Ramesh Adhikari
 
API design best practices
API design best practicesAPI design best practices
API design best practicesIgor Miniailo
 
Deploying your Predictive Models as a Service via Domino
Deploying your Predictive Models as a Service via DominoDeploying your Predictive Models as a Service via Domino
Deploying your Predictive Models as a Service via DominoJo-fai Chow
 

Similar to Estructurar y mantener aplicaciones Rails sin morir en el intento (20)

API Design Best Practices by Igor Miniailo
API Design Best Practices by Igor MiniailoAPI Design Best Practices by Igor Miniailo
API Design Best Practices by Igor Miniailo
 
Backward Compatibility Developer's Guide in Magento 2
Backward Compatibility Developer's Guide in Magento 2Backward Compatibility Developer's Guide in Magento 2
Backward Compatibility Developer's Guide in Magento 2
 
VSSML16 L7. REST API, Bindings, and Basic Workflows
VSSML16 L7. REST API, Bindings, and Basic WorkflowsVSSML16 L7. REST API, Bindings, and Basic Workflows
VSSML16 L7. REST API, Bindings, and Basic Workflows
 
Christoforos zolotas cloudmde2015 presentation - camera ready
Christoforos zolotas  cloudmde2015 presentation - camera readyChristoforos zolotas  cloudmde2015 presentation - camera ready
Christoforos zolotas cloudmde2015 presentation - camera ready
 
Backward Compatibility Developer's Guide Webinar
Backward Compatibility Developer's Guide WebinarBackward Compatibility Developer's Guide Webinar
Backward Compatibility Developer's Guide Webinar
 
Deploying your Predictive Models as a Service via
 Domino API Endpoints
Deploying your Predictive Models as a Service via
 Domino API EndpointsDeploying your Predictive Models as a Service via
 Domino API Endpoints
Deploying your Predictive Models as a Service via
 Domino API Endpoints
 
Microservicios, en qué lío me he metido
Microservicios, en qué lío me he metidoMicroservicios, en qué lío me he metido
Microservicios, en qué lío me he metido
 
Mongo db improve the performance of your application codemotion2016
Mongo db improve the performance of your application codemotion2016Mongo db improve the performance of your application codemotion2016
Mongo db improve the performance of your application codemotion2016
 
Software Development with PHP & Laravel
Software Development  with PHP & LaravelSoftware Development  with PHP & Laravel
Software Development with PHP & Laravel
 
Unifying Frontend and Backend Development with Scala - ScalaCon 2021
Unifying Frontend and Backend Development with Scala - ScalaCon 2021Unifying Frontend and Backend Development with Scala - ScalaCon 2021
Unifying Frontend and Backend Development with Scala - ScalaCon 2021
 
Custom Forms and Configuration Forms in Drupal 8
Custom Forms and Configuration Forms in Drupal 8Custom Forms and Configuration Forms in Drupal 8
Custom Forms and Configuration Forms in Drupal 8
 
JSFest 2019: Technology agnostic microservices at SPA frontend
JSFest 2019: Technology agnostic microservices at SPA frontendJSFest 2019: Technology agnostic microservices at SPA frontend
JSFest 2019: Technology agnostic microservices at SPA frontend
 
01. lab instructions starting project
01. lab instructions   starting project01. lab instructions   starting project
01. lab instructions starting project
 
Reactive Application Using METEOR
Reactive Application Using METEORReactive Application Using METEOR
Reactive Application Using METEOR
 
angular2.0
angular2.0angular2.0
angular2.0
 
MongoDB .local London 2019: The Tech Behind Connected Car
MongoDB .local London 2019: The Tech Behind Connected CarMongoDB .local London 2019: The Tech Behind Connected Car
MongoDB .local London 2019: The Tech Behind Connected Car
 
Magnolia & Angular JS - an Approach for Javascript RIAs Delivered by a CMS
Magnolia & Angular JS - an Approach for Javascript RIAs Delivered by a CMSMagnolia & Angular JS - an Approach for Javascript RIAs Delivered by a CMS
Magnolia & Angular JS - an Approach for Javascript RIAs Delivered by a CMS
 
Presentation on angular 5
Presentation on angular 5Presentation on angular 5
Presentation on angular 5
 
API design best practices
API design best practicesAPI design best practices
API design best practices
 
Deploying your Predictive Models as a Service via Domino
Deploying your Predictive Models as a Service via DominoDeploying your Predictive Models as a Service via Domino
Deploying your Predictive Models as a Service via Domino
 

Recently uploaded

Independent Solar-Powered Electric Vehicle Charging Station
Independent Solar-Powered Electric Vehicle Charging StationIndependent Solar-Powered Electric Vehicle Charging Station
Independent Solar-Powered Electric Vehicle Charging Stationsiddharthteach18
 
Seismic Hazard Assessment Software in Python by Prof. Dr. Costas Sachpazis
Seismic Hazard Assessment Software in Python by Prof. Dr. Costas SachpazisSeismic Hazard Assessment Software in Python by Prof. Dr. Costas Sachpazis
Seismic Hazard Assessment Software in Python by Prof. Dr. Costas SachpazisDr.Costas Sachpazis
 
Artificial Intelligence in due diligence
Artificial Intelligence in due diligenceArtificial Intelligence in due diligence
Artificial Intelligence in due diligencemahaffeycheryld
 
Passive Air Cooling System and Solar Water Heater.ppt
Passive Air Cooling System and Solar Water Heater.pptPassive Air Cooling System and Solar Water Heater.ppt
Passive Air Cooling System and Solar Water Heater.pptamrabdallah9
 
Autodesk Construction Cloud (Autodesk Build).pptx
Autodesk Construction Cloud (Autodesk Build).pptxAutodesk Construction Cloud (Autodesk Build).pptx
Autodesk Construction Cloud (Autodesk Build).pptxMustafa Ahmed
 
The Entity-Relationship Model(ER Diagram).pptx
The Entity-Relationship Model(ER Diagram).pptxThe Entity-Relationship Model(ER Diagram).pptx
The Entity-Relationship Model(ER Diagram).pptxMANASINANDKISHORDEOR
 
Filters for Electromagnetic Compatibility Applications
Filters for Electromagnetic Compatibility ApplicationsFilters for Electromagnetic Compatibility Applications
Filters for Electromagnetic Compatibility ApplicationsMathias Magdowski
 
Worksharing and 3D Modeling with Revit.pptx
Worksharing and 3D Modeling with Revit.pptxWorksharing and 3D Modeling with Revit.pptx
Worksharing and 3D Modeling with Revit.pptxMustafa Ahmed
 
Fuzzy logic method-based stress detector with blood pressure and body tempera...
Fuzzy logic method-based stress detector with blood pressure and body tempera...Fuzzy logic method-based stress detector with blood pressure and body tempera...
Fuzzy logic method-based stress detector with blood pressure and body tempera...IJECEIAES
 
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdflitvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdfAlexander Litvinenko
 
Adsorption (mass transfer operations 2) ppt
Adsorption (mass transfer operations 2) pptAdsorption (mass transfer operations 2) ppt
Adsorption (mass transfer operations 2) pptjigup7320
 
History of Indian Railways - the story of Growth & Modernization
History of Indian Railways - the story of Growth & ModernizationHistory of Indian Railways - the story of Growth & Modernization
History of Indian Railways - the story of Growth & ModernizationEmaan Sharma
 
Interfacing Analog to Digital Data Converters ee3404.pdf
Interfacing Analog to Digital Data Converters ee3404.pdfInterfacing Analog to Digital Data Converters ee3404.pdf
Interfacing Analog to Digital Data Converters ee3404.pdfragupathi90
 
UNIT 4 PTRP final Convergence in probability.pptx
UNIT 4 PTRP final Convergence in probability.pptxUNIT 4 PTRP final Convergence in probability.pptx
UNIT 4 PTRP final Convergence in probability.pptxkalpana413121
 
Working Principle of Echo Sounder and Doppler Effect.pdf
Working Principle of Echo Sounder and Doppler Effect.pdfWorking Principle of Echo Sounder and Doppler Effect.pdf
Working Principle of Echo Sounder and Doppler Effect.pdfSkNahidulIslamShrabo
 
Diploma Engineering Drawing Qp-2024 Ece .pdf
Diploma Engineering Drawing Qp-2024 Ece .pdfDiploma Engineering Drawing Qp-2024 Ece .pdf
Diploma Engineering Drawing Qp-2024 Ece .pdfJNTUA
 
CLOUD COMPUTING SERVICES - Cloud Reference Modal
CLOUD COMPUTING SERVICES - Cloud Reference ModalCLOUD COMPUTING SERVICES - Cloud Reference Modal
CLOUD COMPUTING SERVICES - Cloud Reference ModalSwarnaSLcse
 
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdfInstruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdfEr.Sonali Nasikkar
 
What is Coordinate Measuring Machine? CMM Types, Features, Functions
What is Coordinate Measuring Machine? CMM Types, Features, FunctionsWhat is Coordinate Measuring Machine? CMM Types, Features, Functions
What is Coordinate Measuring Machine? CMM Types, Features, FunctionsVIEW
 
Artificial intelligence presentation2-171219131633.pdf
Artificial intelligence presentation2-171219131633.pdfArtificial intelligence presentation2-171219131633.pdf
Artificial intelligence presentation2-171219131633.pdfKira Dess
 

Recently uploaded (20)

Independent Solar-Powered Electric Vehicle Charging Station
Independent Solar-Powered Electric Vehicle Charging StationIndependent Solar-Powered Electric Vehicle Charging Station
Independent Solar-Powered Electric Vehicle Charging Station
 
Seismic Hazard Assessment Software in Python by Prof. Dr. Costas Sachpazis
Seismic Hazard Assessment Software in Python by Prof. Dr. Costas SachpazisSeismic Hazard Assessment Software in Python by Prof. Dr. Costas Sachpazis
Seismic Hazard Assessment Software in Python by Prof. Dr. Costas Sachpazis
 
Artificial Intelligence in due diligence
Artificial Intelligence in due diligenceArtificial Intelligence in due diligence
Artificial Intelligence in due diligence
 
Passive Air Cooling System and Solar Water Heater.ppt
Passive Air Cooling System and Solar Water Heater.pptPassive Air Cooling System and Solar Water Heater.ppt
Passive Air Cooling System and Solar Water Heater.ppt
 
Autodesk Construction Cloud (Autodesk Build).pptx
Autodesk Construction Cloud (Autodesk Build).pptxAutodesk Construction Cloud (Autodesk Build).pptx
Autodesk Construction Cloud (Autodesk Build).pptx
 
The Entity-Relationship Model(ER Diagram).pptx
The Entity-Relationship Model(ER Diagram).pptxThe Entity-Relationship Model(ER Diagram).pptx
The Entity-Relationship Model(ER Diagram).pptx
 
Filters for Electromagnetic Compatibility Applications
Filters for Electromagnetic Compatibility ApplicationsFilters for Electromagnetic Compatibility Applications
Filters for Electromagnetic Compatibility Applications
 
Worksharing and 3D Modeling with Revit.pptx
Worksharing and 3D Modeling with Revit.pptxWorksharing and 3D Modeling with Revit.pptx
Worksharing and 3D Modeling with Revit.pptx
 
Fuzzy logic method-based stress detector with blood pressure and body tempera...
Fuzzy logic method-based stress detector with blood pressure and body tempera...Fuzzy logic method-based stress detector with blood pressure and body tempera...
Fuzzy logic method-based stress detector with blood pressure and body tempera...
 
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdflitvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
 
Adsorption (mass transfer operations 2) ppt
Adsorption (mass transfer operations 2) pptAdsorption (mass transfer operations 2) ppt
Adsorption (mass transfer operations 2) ppt
 
History of Indian Railways - the story of Growth & Modernization
History of Indian Railways - the story of Growth & ModernizationHistory of Indian Railways - the story of Growth & Modernization
History of Indian Railways - the story of Growth & Modernization
 
Interfacing Analog to Digital Data Converters ee3404.pdf
Interfacing Analog to Digital Data Converters ee3404.pdfInterfacing Analog to Digital Data Converters ee3404.pdf
Interfacing Analog to Digital Data Converters ee3404.pdf
 
UNIT 4 PTRP final Convergence in probability.pptx
UNIT 4 PTRP final Convergence in probability.pptxUNIT 4 PTRP final Convergence in probability.pptx
UNIT 4 PTRP final Convergence in probability.pptx
 
Working Principle of Echo Sounder and Doppler Effect.pdf
Working Principle of Echo Sounder and Doppler Effect.pdfWorking Principle of Echo Sounder and Doppler Effect.pdf
Working Principle of Echo Sounder and Doppler Effect.pdf
 
Diploma Engineering Drawing Qp-2024 Ece .pdf
Diploma Engineering Drawing Qp-2024 Ece .pdfDiploma Engineering Drawing Qp-2024 Ece .pdf
Diploma Engineering Drawing Qp-2024 Ece .pdf
 
CLOUD COMPUTING SERVICES - Cloud Reference Modal
CLOUD COMPUTING SERVICES - Cloud Reference ModalCLOUD COMPUTING SERVICES - Cloud Reference Modal
CLOUD COMPUTING SERVICES - Cloud Reference Modal
 
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdfInstruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
 
What is Coordinate Measuring Machine? CMM Types, Features, Functions
What is Coordinate Measuring Machine? CMM Types, Features, FunctionsWhat is Coordinate Measuring Machine? CMM Types, Features, Functions
What is Coordinate Measuring Machine? CMM Types, Features, Functions
 
Artificial intelligence presentation2-171219131633.pdf
Artificial intelligence presentation2-171219131633.pdfArtificial intelligence presentation2-171219131633.pdf
Artificial intelligence presentation2-171219131633.pdf
 

Estructurar y mantener aplicaciones Rails sin morir en el intento

  • 1. Estructurar y mantener aplicaciones Rails sin morir en el intento by @moises_macia MADRID · NOV 18-19 · 2016
  • 2. MADRID · NOV 18-19 · 2016 Hola ● Moisès Macià (@moises_macia) ● Actualmente CTO en @samyroad ● ~15 años desarrollando software (C++, PHP, Java, ...) ● ~5 años desarrollando en Ruby/Rails.
  • 3. MADRID · NOV 18-19 · 2016
  • 4. MADRID · NOV 18-19 · 2016
  • 5. MADRID · NOV 18-19 · 2016
  • 6. MADRID · NOV 18-19 · 2016 Hay una nueva versión de Rails
  • 7. MADRID · NOV 18-19 · 2016 Sistema conectado Vs modular To Design or Not To Design? A Third Good Question
  • 8. MADRID · NOV 18-19 · 2016 Sistema conectado Vs modular ● Rails no es mi aplicación. ● Mi aplicación es mi lógica de negocio. ● Mi aplicación debe ser independiente. ● Idependiente del contexto. ● Independiente de como se accede a ella. ● Independiente de las herramientas que se usan para contruirla.
  • 9. MADRID · NOV 18-19 · 2016 Problemas: Gems ● Gemas que añaden poco valor y hay que mantener. ● Gemas que se acoplan demasiado a ActiveRecord. ● Gemas con toneladas de dependencias. ● Gemas sin mantenimiento. $ bundle list | wc -l 341
  • 10. MADRID · NOV 18-19 · 2016 Problemas: God objects ● User.rb ● LOC > 1000 ● Derivado de la politica “Fat models”
  • 11. MADRID · NOV 18-19 · 2016 Problemas: ActiveRecord ● Acoplamiento entre persistencia y lógica de negocio. ● Demasiadas responsabilidades en una sola clase. ● Callbacks. irb> User.new.methods.count => 2307
  • 12. MADRID · NOV 18-19 · 2016 Problemas: Rails way ● Fat controllers. ● Fat Models. ● Concerns. ● Imposibilita hacer Unit testing.
  • 13. MADRID · NOV 18-19 · 2016 Refactor: Gem diet ● Gemas que aporten valor real. ● Gemas mantenidas. ● Gemas para conectar con servicios externos (S3, Mailchimp, etc.). ● Bundle groups.
  • 14. MADRID · NOV 18-19 · 2016 Refactor: Form objects ● Contienen validación de datos. ● Un formulario por cada caso de uso. ● Un formulario puede contener datos de varios modelos.
  • 15. MADRID · NOV 18-19 · 2016 Refactor: Form objects # app/forms/users/create_form.rb module Users class RegisterForm include ActiveModel::Model include Virtus.model attribute :nickname, String attribute :email, String attribute :password, String validates :nickname, presence: true validates :email, presence: true, format: RFC_2822 validates :password, presence: true, length: { within: 8..50 } def persisted? false end end end
  • 16. MADRID · NOV 18-19 · 2016 Refactor: Service objects ● Un servicio por cada caso de uso. ● Inyección de dependencias. ● Interfaz común (.execute) ● Contienen: – Lógica de negocio. – Llamadas a servicios externos. – Llamadas a servicios internos. ● Los servicios delegan la persistencia a ActiveRecord.
  • 17. MADRID · NOV 18-19 · 2016 Refactor: Service Object # app/services/users/create_form.rb module Users class RegisterService class RegisterError < StandardError; end def initialize(form) @attrs = form.data end def execute user = User.new(@attrs) raise RegisterError, user.errors unless user.save welcome_email add_to_newsletter if user.newsletter_subscription? suggest_followings # ... end end end
  • 18. MADRID · NOV 18-19 · 2016 Refactor: Model # app/models/user.rb class User < ActiveRecord::Base has_many :items has_many :roles def newsletter_subscription? # ... end end
  • 19. MADRID · NOV 18-19 · 2016 Refactor: Controller (1) # app/controllers/users_controller.rb class UsersController < ApplicationController def create authorize User if register_form.valid? user = register_form.execute render user, status: :created else render register_form, status: :unprocessable_entity end end def update authorize user if profile_update_form.valid? updated_user = profile_update_service.execute render updated_user, status: :ok else render profile_update_form, status: :unprocessable_entity end end end
  • 20. MADRID · NOV 18-19 · 2016 Refactor: Controller (2) # app/controllers/users_controller.rb class UsersController < ApplicationController private def user @user ||= policy_scope(User).find_by!(nickname: params[:nickname]) end def register_form @register_form ||= Users::RegisterForm.new(params) end def user_create_service @register_service ||= Users::RegisterService.new(register_form) end end
  • 21. MADRID · NOV 18-19 · 2016 Refactor: Controller (3) # app/controllers/users_controller.rb class UsersController < ApplicationController private def profile_update_form Users::ProfilepdateForm.new(params).tap do |form| form.resource = user end end def profile_update_service @profile_update_service ||= Users::ProfilepdateService.new( user, profile_update_form ) end end
  • 22. MADRID · NOV 18-19 · 2016 Refactor: Unit testing ● Service/Form objects faciles de testear al no estar acoplados a Rails. ● Muy rápidos. ● Tests unitarios. ● Mocks de la persistencia.
  • 23. MADRID · NOV 18-19 · 2016 Unit testing: Form Object # spec/unit/forms/users/create_form_spec.rb describe Users::RegisterForm type: [:form, :unit] do let(:form) { described_class.new(nickname: 'codemotion', # ...) } describe '.valid?' do context 'when nickname is not valid' do it 'should return false if it is too short' do form.nickname 'xx' expect(form).not_to be_valid expect(form.errors).to include(:nickname) end # ... end # ... end end
  • 24. MADRID · NOV 18-19 · 2016 Unit testing: Controller # spec/unit/controllers/users_controller_spec.rb describe UsersController, type: [:controller, :unit] do describe 'create an user' do subject { process :create, method: :post, params: params } before(:each) do expect_any_instance_of(described_class).to receive(:register_service) { register_service_double } expect_any_instance_of(described_class).to receive(:register_form) { register_form_double } end it 'return created with valid data' do expect_any_instance_of(described_class).to receive(:authorize).with(User) expect(subject).to have_http_status(:created) end end end
  • 25. MADRID · NOV 18-19 · 2016 Integration testing: Service Object # spec/integration/services/users/create_service_spec.rb describe Users::RegisterService type: [:service, :integration] do let(:user_attributes) { attributes_for :user } subject { described_class.new(Users::RegisterForm.new(user_attributes)) } describe '.execute' do it 'should create a new user' do new_user = subject.execute expect(new_user).to be_an_instance_of(User) end end end
  • 26. MADRID · NOV 18-19 · 2016 Refactor ● ¿Son necesarias todas estas clases y divisiones? ● Hay que ser pragmatico ante todo.
  • 27. MADRID · NOV 18-19 · 2016 Recursos

Editor's Notes

  1. asdasdasd