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

Domain Driven Design Kinda

Domain Driven Design Kinda

Explains how we kinda do Domain Driven Design in our Ruby on Rails at Product Hunt.

Radoslav Stankov

March 14, 2021
Tweet

More Decks by Radoslav Stankov

Other Decks in Technology

Transcript

  1. “Domain-driven design (DDD) is the concept that the structure and

    language of software code (classes, methods, functions, variables).” What is Domain Driven Design?
  2. What problems does DDD solve? “Developers are too wrapped up

    with technology and trying to solve problems using technology rather than careful thought and design” 1
  3. What problems does DDD solve? “The database is given too

    much priority, and most discussions about the solutions center around the database and a data model rather than business processes and operations.” 2
  4. What problems does DDD solve? “Developers don’t give proper emphasis

    to naming objects and operations according to the business purpose that they fi ll.” 3
  5. What problems does DDD solve? “Application logic is disjointed and

    hard to follow. It is hard to see an overview of the application features” 4
  6. What are the issues with traditional DDD? “In order to

    help maintain the model as a pure and helpful language construct, the team must typically implement a great deal of isolation and encapsulation within the domain model. Which overcomplicates the system.” 1
  7. What are the issues with traditional DDD? “Rails and Node

    doesn't fi t very well with DDD mindset. DDD comes from Java and similar languages.” 2
  8. What are the issues with traditional DDD? “A lot of

    DDD practices are focused on consultancy model and are used for model complicated business processes.” 3
  9. Ubiquitous Language “A language structured around the domain model and

    used by all team members to connect all the activities of the team with the software.”
  10. Ubiquitous Language “There are only two hard things in Computer

    Science: cache invalidation and naming things.” -- Phil Karlton
  11. Domains “A sphere of knowledge, in fl uence, or activity.

    The subject area to which the user applies a program is the domain of the software;”
  12. Domain Types 🎂 Core domain 
 🍰 Supporting sub domain

    
 🧁 Generic sub domain 
 🥮 Utilities (infrastructure) sub domain
  13. Domain Types 🎂 Core domain - Post, User, Ship 


    🍰 Supporting sub domain - Collections, Discussions 
 🧁 Generic sub domain - Votes, Comments, Seo 
 🥮 Utilities - External, ExecSQL, HandleRaceCondition
  14. Moderation Voting Comments Posts Collections Maker Goals Sharing Seo Discussions

    Ask Ship Mentors Founder Club Golden Kitty Maker Fest Topics Stories Spam Newsletter Noti fi cations Metrics Users Payments Activity Feed Jobs
  15. Moderation Voting Comments Posts Collections Maker Goals Sharing Seo Discussions

    Ask Ship Mentors Founder Club Golden Kitty Maker Fest Topics Stories Spam Newsletter Noti fi cations Metrics Users Payments Activity Feed Jobs Core Feature Generic Context Map
  16. Moderation Voting Comments Posts Collections Maker Goals Sharing Seo Discussions

    Ask Ship Mentors Founder Club Golden Kitty Maker Fest Topics Stories Spam Newsletter Noti fi cations Metrics Users Payments Activity Feed Jobs Core Feature Generic Context Map Utilities
  17. Bounded Context “A semantic contextual boundary. This means that within

    the boundary each component of the software model has a speci fi c meaning and does speci fi c things.”
  18. defmodule Hello.Accounts do @moduledoc """ The Accounts context. """ import

    Ecto.Query, warn: false alias Hello.Repo alias Hello.Accounts.User @doc """ Returns the list of users. ## Examples iex> list_users() [%User{}, ...] """ def list_users do Repo.all(User) end ... end
  19. FounderClub.join_waitlist(user:) 
 FounderClub.join(user:) FounderClub.request_access(user:, code:) FounderClub.deliver_waitlist_invite(invite:) FounderClub.plan_for(code:) 
 FounderClub.subscribe(user:, subscription_id:)

    FounderClub.claim_deal(user:, deal:) FounderClub.claimed_deals_by(user:) FounderClub.deals_available_to(user:) FounderClub.create_referral_code(user:, email:) FounderClub.destroy_referral_code(user:, email:) 
 FounderClub.referrals_of(user:) 
 
 FounderClub.active_subscription?(user) FounderClub.list_subscriptions 
 FounderClub.transfer_subscription(from:, to:)
  20. module FounderClub extend self 
 def admin_deal_form 
 FounderClub::Admin::DealForm 


    end 
 
 def policy 
 FounderClub::Policy 
 end 
 
 def mailer_info FounderClub::MailerInfo 
 end 
 end 🤔
  21. module Sharing extend self def text_for(subject, current_user: nil) generator =

    FindConst.call(Sharing::Text, subject) if generator.method(:call).arity == 1 generator.call(subject) else generator.call(subject, current_user: current_user) end end def image_for(subject) generator = FindConst.call(Sharing::ImageUrl, subject) generator.call(subject) end def image_for_comment(comment, highlighted_text:) Sharing::ImageUrl:Comment.call(comment, highlighted_text: highlighted_text) end endd
  22. Domain Event “A domain object that de fi nes an

    event (something that happens). A domain event is an event that domain experts care about.”
  23. Design Patterns 🚗 Entity 
 🚕 Value Object 
 🚙

    Aggregate 🚌 Repository 🚎 Facade 🚐 Factory 🚚 Service 
 🚛 Presenter
  24. Design Patterns 🚗 Entity 
 🚕 Value Object 
 🚙

    Aggregate 🚌 Repository 🚎 Facade 🚐 Factory 🚚 Service 
 🚛 Presenter
  25. Design Patterns 🚗 Entity 
 🚕 Value Object 
 🚙

    Aggregate 🚌 Repository 🚎 Facade 🚐 Factory 🚚 Service 
 🚛 Presenter
  26. module Share::Subject extend self def call(subject:, current_profile: ) subject_class =

    subject.class.name.tr('::', '' ) share = "Share::Subjects::#{subject_class}".constantiz e share.generate subject, current_profil e end end
  27. module Share extend self def message_for(subject, current_profile: nil ) subject_class

    = subject.class.name.tr('::', '' ) share = "Share::Subjects::#{subject_class}".constantiz e share.generate subject, current_profil e end end
  28. module Share extend self def message_for(subject, current_profile: nil ) subject_class

    = subject.class.name.tr('::', '' ) share = "Share::Message::#{subject_class}".constantiz e share.generate subject, current_profil e end end
  29. module Share extend self def message_for(subject, current_profile: nil ) share

    = Utils.module_for(subject, in: Share::Message ) share.generate subject, current_profil e end end 💡