Upload
marsbased
View
218
Download
2
Embed Size (px)
Citation preview
BUILDING LARGE WEB APPLICATIONS
That won’t be a pain to maintain
FIRST MONTHS BUILDING THE NEXT BIG THING ®
ONE YEAR LATER
–Henning Koch - Makandra CEO and author of Growing Rails Applications
“Large applications are large.”
AN INCONVENIENT SECRET
WHAT DO YOU THINK THAT MAKES AN APP MORE MAINTAINABLE?
3 STEPS TO GLORY
• Follow conventions
• Write code for human beings
• Always test
–Arthur Forman
“Not everyone thinks the way you think, knows the things you know, believes the things you believe, nor acts the way you would act. Remember this and you will go a long way in getting along with people.”
FOLLOW CONVENTIONS
THE EASY ONE: CODING STYLEif current_user redirect_to user_tasks_path(current_user, format: 'json') end !if(current_user) redirect_to(user_tasks_path(current_user, :format => ‘json')) end !unless current_user.nil? redirect_to( user_tasks_path( current_user, format: 'json' ) ) end !redirect_to(user_tasks_path(current_user, :format => 'json') if current_user !current_user && redirect_to(user_tasks_path(current_user, :format => 'json') !current_user and redirect_to(user_tasks_path(current_user, :format => 'json')
• It is very easy to start doing it.
• You’ll be faster reading code that follows a certain style.
• Saves time avoiding trivial discussions.
• When your team grows, you want to maintain coherence amongst your codebase.
WHY YOU SHOULD BE ADOPTING A CODING STYLE?
• Almost every Ruby on Rails company use and recommend a Style Guide:
• Thoughtbot: https://github.com/thoughtbot/guides/tree/master/style
• Plataformatec: http://guidelines.plataformatec.com.br/ruby.html
• MarsBased: Coming soon!
• If you can’t afford to build yours. Use the community ones!!
• https://github.com/bbatsov/ruby-style-guide
• https://github.com/bbatsov/rails-style-guide
WHY SHOULD YOU BE ADOPTING A CODING STYLE?
FRAMEWORK CONVENTIONS• Model View Controller architecture
• CRUD centric RESTFUL approach
• ActiveRecord pattern
• Convention over configuration
• Unobtrusive Javascript
• DRY (Don’t repeat yourself)
• Concerns and modules to extend functionality
• etc.
resources :projects !!class ProjectsController < ApplicationController ! def index end ! def show end ! def new end ! def create end ! def edit end ! def update end ! def destroy end end
EXAMPLE: RAILS CRUD BASED RESTFUL APPROACH
resources :projects !!class ProjectsController < ApplicationController ! def index end ! def show end ! def new end ! def create end ! def edit end ! def update end ! def destroy end end
Publishing feature
EXAMPLE: RAILS CRUD BASED RESTFUL APPROACH
resources :projects !!class ProjectsController < ApplicationController ! def index end ! def show end ! def new end ! def create end ! def edit end ! def update end ! def destroy end end
resources :projects do member do patch :publish patch :unpublish end end !!class TasksController < ApplicationController def index end ! def show end ! def new end ! def create end ! def edit end ! def update end ! def destroy end ! def publish end ! def unpublish end end
Publishing feature
EXAMPLE: RAILS CRUD BASED RESTFUL APPROACH
resources :projects do member do patch :publish patch :unpublish end end
resources :projects do member do patch :publish patch :unpublish post :duplicate patch :add_collaborator patch :remove_collaborator end ! collection do get :search end end
Lots of features
EXAMPLE: RAILS CRUD BASED RESTFUL APPROACH
A TRULY RAILS RESTFUL APPROACH
resources :projects !namespace :projects do resources :publishings, only: [:create, :destroy] resources :duplications, only: [:new, :create] resources :collaborator_addings, only: [:create, :destroy] resources :searches, only: [:create] end
EXAMPLE: RAILS CRUD BASED RESTFUL APPROACH
DEVELOPERS CONVENTIONS: DESIGN PATTERNS
Context Strategy
Concrete Strategy 1
Concrete Strategy 2
Concrete Strategy 3
YOUR OWN CONVENTIONS
• Your team is going to naturally develop a coding style and a set of conventions.
• Embrace them, document them and use them in all your projects.
• It’s part of your company’s culture.
YOUR OWN CONVENTIONS
Don’t change your conventions every 2
months
–David Heinemeier Hansson (@dhh) - Ruby on Rails creator
“We are not computer scientists. We are software writers.”
WRITE CODE FOR HUMAN BEINGS
Ruby programming language
WHY IS IT IMPORTANT?
BrainFuck programming language
USE INTENTION REVEALING METHOD NAMES
aka: Let your code speak to you
INTENTION REVEALING METHOD NAMESclass SearchUsersService def search_users(params) # TODO: refactor conditions = {} conditions["hireable"] = params[:hireable] unless params[:hireable].nil? conditions["availability"] = params[:availability] unless params[:availability].nil? conditions["profile.tags_array"] = params[:tags].split(",") if params[:tags] conditions["category_ids"] = params[:category_ids].split(",") if params[:category_ids] ! if params[:location] filter = { :multi_match => { :query => params[:location], :fields => ["profile.country","profile.state","profile.city"] } } end ! if params[:q].present? || !conditions.empty? query = User.search(params[:q], where: conditions, execute: false) query.body[:query][:bool][:must] << filter if params[:location].present? query.execute.results else User.active.ordered_for_directory(params[:order]) end end end
class SearchUsersService ! def search_users(params) conditions = extract_conditions_from(params) filter = extract_filters_from(params) ! if query_term_for?(params) || conditions.any? query = build_users_search_query(params, conditions, filter) query.execute.results else User.active.ordered_for_directory(params[:order]) end end !end
INTENTION REVEALING METHOD NAMES
KISS: KEEP IT SIMPLE STUPID
HOW DO YOU ACHIEVE SIMPLICITY?
Create reusable components only when you detect duplication.
Apply a design pattern to a problem only when simplifies your code and improves code readability.
Prefer being explicit than being implicit.
Maintain the abstraction low.
KISS: KEEP IT SIMPLE STUPIDIt also applies to the 3rd party software you are using
HOW TO BE SURE YOU ARE WRITING UNDERSTANDABLE CODE?
Pair programming
Git workflow based on pull requests and code revisions
Reading, reading and reading open-source applications and libraries
ALWAYS TEST
– Anonymous
“The principle objective of software testing is to give confidence in the software.”
WHY TESTING?
Bring confidence and peace of mind.
Discover hidden bugs in your application.
Save lots of time avoiding manual tests.
Allow you to refactor code.
# TODO: It needs refactoring. Replace conditionals with # polymorphism and delegate responsibilities. def author_information if author.kind_of?(Teacher) if author.male? "Mr. #{author.full_name} - Dpt #{author.department}" elsif author.female? "Ms. #{author.full_name} - Dpt #{author.department}" end elsif author.kind_of?(Student) "Student of #{author.degree}" end end
DON’T FORGET TO REFACTORA green test is not the final step
WHY DO CODERS STOP TESTING?
Testing require a different set of skills.
Some tests are hard to write (e.g. integration).
Tests also need maintenance.
Customers don’t mind if you test or not.
BONUS TRACK
Model
Controller
View
Decorators Presenters
Service Objects
Policy Objects
Facade