Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Embrace multi-model thinking

Embrace multi-model thinking

Ivan Nemytchenko

April 13, 2019
Tweet

More Decks by Ivan Nemytchenko

Other Decks in Programming

Transcript

  1. • Freelancing • Exploring apps architecture • Writing book •

    Teaching at Goodprogrammer.ru • Gitlabbing • Travelling Ivan Nemytchenko Omsk → Belgrade @inem http://inem.at
  2. Rubytrip! 40 days, 4 conferences, 8 countries - RubyConfBY Minsk

    - April 6 - RubyDay Verona - April 11 - RubyWine Kishinev - April 13 - RailsConf Minneapolis - April 30 - Saint P RubyConf - June 1-2
  3. Rubytrip! 40 days, 4 conferences, 8 countries - RubyConfBY Minsk

    - April 6 - RubyDay Verona - April 11 - RubyWine Kishinev - April 13 - RailsConf Minneapolis - April 30 - Saint P RubyConf - June 1-2
  4. System thinking Lifecycle Roles ISO/IEC/ IEEE 42010 Systems and software

    engineering — Architecture description coursera.org/learn/system-thinking
  5. 1.Invited 2.Registered 6.Deleted 3.Banned 5.Expired 4.Promoted User Invoice 1.Created 2.Sent

    3.Delivered 4.Paid 5.Expired Task 1.Created 2.Assigned 3.Sheduled 4.Completed 5.Archived
  6. - if current_organisation_subscribed? %p You are currently subscribed, using the

    following payment method: %p== #{@org.card_brand}: **** **** **** #{@org.card_last4} %p== Expires #{@org.card_exp_month} / #{@org.card_exp_year} - if @org.last_charge %p== The last payment of $#{@org.last_charge.amount/100} was taken on #{@org.last_charge.created_at.strftime("%d %b % %p== The next payment of $100 is due to be taken on #{(@org.last_charge.created_at + 1.month).strftime("%d %b %Y")} = link_to "Update credit card", edit_subscription_path, class: "btn btn-primary" %p = link_to "Cancel my subscription", subscription_path, method: "DELETE", class: "btn btn-danger", data: {confirm: 'Ar sure?'} - else - if @org.trial_ended? %h2 Thank you for trialing our product %h4 To continue using our product please subscribe to the following plan: - else %h2== Thank you for trialing our product (#{distance_of_time_in_words(@org.created_at, Time.zone.now)} left) %h4 To continue using our product after trial please subscribe to the following plan: %p $100/month %p Up to 500 devices and 200 users %p 3 admin users %p CSV/XLS upload = link_to "Subscribe", new_subscription_path, class: 'btn btn-primary'
  7. - if current_organisation_subscribed? #... - if @org.last_charge #... - elsif

    @org.last_charge_status != 'success' #... #... - if @org.expires_at #... - else - if @org.trial_ended? #... - else #... #...
  8. Flags can be hidden dates ranges, associations, status fields -

    if current_organisation_subscribed? #... - if @org.last_charge #... - elsif @org.last_charge_status != 'success' #... #... - if @org.expires_at #... - else - if @org.trial_ended? #... - else #... #...
  9. state_machine :state, initial: :trial do state :trial state :trial_ended state

    :subscribed state :cancelled_subscription state :not_subscribed state :payment_error event :subscribe do transition [:trial, :not_subscribed, :trial_ended] => :subscribed end event :disable_trial do transition :trial => :trial_ended end event :usage_period_ended do transition :cancelled_subscription => :not_subscribed end #... end
  10. - if current_org.trial? #... - elsif current_org.trial_ended? #... - elsif

    current_org.subscribed? #... - elsif current_org.cancelled_subscription? #... - elsif current_org.payment_error? #... - elsif current_org.not_subscribed? #... render partial: current_org.state
  11. Small scale respond_to do |format| format.html { render locals: {query:

    params[:q]} } format.json { @devices = @devices.first(5) @employees = @employees.first(3) } end
  12. larger scale (REDMINE) respond_to do |format| format.html { @issue_count =

    @query.issue_count @issue_pages = Paginator.new @issue_count, per_page_option, params['page'] @issues = @query.issues(:offset => @issue_pages.offset, :limit => @issue_pages.per_page) render :layout => !request.xhr? } format.api { @offset, @limit = api_offset_and_limit @query.column_names = %w(author) @issue_count = @query.issue_count @issues = @query.issues(:offset => @offset, :limit => @limit) Issue.load_visible_relations(@issues) if include_in_api_response?('relations') } format.atom { @issues = @query.issues(:limit => Setting.feeds_limit.to_i) render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") } format.csv { @issues = @query.issues(:limit => Setting.issues_export_limit.to_i) send_data(query_to_csv(@issues, @query, params[:csv]), :type => 'text/csv; header=present', :filename => 'issues.csv') } format.pdf { @issues = @query.issues(:limit => Setting.issues_export_limit.to_i) send_file_headers! :type => 'application/pdf', :filename => 'issues.pdf' } end
  13. HTML, JSON, PDF, RSS they all used in different ways

    different subsets of data different ways to generate results So it makes sense to create separate REST representations
  14. Hierarchy based on “BOUNDED CONTEXTS” scope module: :web do namespace

    :moderation do resources :articles, only: [:index, :edit, :update, :show] do member do patch :publish end end end resources :articles do member do patch :moderate end scope module: :articles do resources :comments do scope module: :comments do resources :likes, only: [:create] end end end end root 'welcome#index' end
  15. Painless Rails principles 1.Differentiate 'schema' from 'implementation' 2.Reduce entry point

    pressure 3.Control the number of degrees of freedom of the app 4.Don't mix layers of abstractions 5.Don't fight against the framework railshurts.com/rails-principles
  16. Sources SICP (Structure and Interpretation of Computer Programs) TAPL (Types

    and Programming Languages) by Benjamin C. Pierce DDD (Domain-driven design) by Eric J. Evans CC2e (Code Complete 2nd edition) by Steve McConnell railshurts.com/rails-principles ISO/IEC/ IEEE 42010 Systems and software engineering — Architecture description