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

Software Architecture

Software Architecture

Basics of software architecture

Maciej Kaszubowski

February 08, 2018
Tweet

More Decks by Maciej Kaszubowski

Other Decks in Programming

Transcript

  1. Poznan Elixir Meetup #6
    mkaszubowski94

    View full-size slide

  2. Time
    Development speed

    View full-size slide

  3. Time
    Software quality

    View full-size slide

  4. Time
    Developer happiness

    View full-size slide

  5. Time
    The big
    rewrite

    View full-size slide

  6. Software
    Architecture
    Poznan Elixir Meetup #6
    mkaszubowski94

    View full-size slide

  7. What is software
    architecture?

    View full-size slide

  8. "the important stuff
    Ralph Johnson

    View full-size slide

  9. "the important stuff (whatever that is)"
    Ralph Johnson

    View full-size slide

  10. "The goal of software architecture
    is to minimize the human resources
    required to build and maintain the
    required system."
    Robert C. Martin, "Clean Architecture"

    View full-size slide

  11. Architecture is about taking a step
    back, looking at a bigger picture
    and being aware of trade-offs when
    making decisions.

    View full-size slide

  12. Quality attributes
    (non-functional requirements)

    View full-size slide

  13. Quality attributes
    Maintainability
    Reusability
    Availability
    Performance
    Reliability
    Scalability
    Security
    Supportability
    Testability
    Deployability
    Simplicity
    Development
    speed
    Composability
    Fault tolerance
    ...

    View full-size slide

  14. Security
    Usability

    View full-size slide

  15. Common architecture
    patterns

    View full-size slide

  16. Monolith architecture

    View full-size slide

  17. Layered architecture

    View full-size slide

  18. Layered architecture

    View full-size slide

  19. Typical layered architecture

    View full-size slide

  20. Hexagonal architecture

    View full-size slide

  21. Clean architecture

    View full-size slide

  22. Clean architecture

    View full-size slide

  23. Microservices architecture

    View full-size slide

  24. Event-driven architecture

    View full-size slide

  25. Serverless architecture

    View full-size slide

  26. Of course you can mix them

    View full-size slide

  27. Example: ISO/OSI model

    View full-size slide

  28. ‣ Isolation
    ‣ Separation of concerns
    ‣ Hiding of implementation details
    ‣ Good abstractions
    ISO/OSI model

    View full-size slide

  29. Example: applying that lessons

    View full-size slide

  30. def release_expired_numbers() do
    expired_numbers = TwilioService.get_expired_numbers()
    Enum.map(expired_numbers, fn number 
    case Tesla.delete(@twilio_url, ) do
    {:ok, %Tesla.Env{status: 204}} 
    TwilioService.delete_phone_number(number)
    _error 
    :error
    end
    end)
    end

    View full-size slide

  31. def release_expired_numbers() do
    expired_numbers = TwilioService.get_expired_numbers()
    Enum.map(expired_numbers, fn number 
    case Tesla.delete(@twilio_url, ) do
    {:ok, %Tesla.Env{status: 204}} 
    TwilioService.delete_phone_number(number)
    _error 
    :error
    end
    end)
    end

    View full-size slide

  32. def release_expired_numbers() do
    expired_numbers = TwilioService.get_expired_numbers()
    Enum.map(expired_numbers, fn number 
    case Tesla.delete(@twilio_url, ) do
    {:ok, %Tesla.Env{status: 204}} 
    TwilioService.delete_phone_number(number)
    _error 
    :error
    end
    end)
    end

    View full-size slide

  33. def release_expired_numbers() do
    expired_numbers = PhoneNumberService.get_expired_numbers()
    Enum.map(expired_numbers, fn number 
    case PhoneNumberApi.release_expired_number(number) do
    :ok 
    PhoneNumberService.delete_phone_number(number)
    _error 
    # ?
    end
    end)
    end

    View full-size slide

  34. def release_expired_numbers() do
    expired_numbers = PhoneNumberService.get_expired_numbers()
    Enum.map(expired_numbers, fn number 
    case PhoneNumberApi.release_expired_number(number) do
    :ok 
    PhoneNumberService.delete_phone_number(number)
    _error 
    # ?
    end
    end)
    end

    View full-size slide

  35. def release_expired_numbers() do
    expired_numbers = PhoneNumberService.get_expired_numbers()
    Enum.map(expired_numbers, fn number 
    case PhoneNumberApi.release_expired_number(number) do
    :ok 
    PhoneNumberService.delete_phone_number(number)
    _error 
    # ?
    end
    end)
    end

    View full-size slide

  36. def release_expired_numbers() do
    expired_numbers = PhoneNumberService.get_expired_numbers()
    Enum.map(expired_numbers, fn number 
    case PhoneNumberApi.release_expired_number(number) do
    :ok 
    PhoneNumberService.delete_phone_number(number)
    _error 
    # ?
    end
    end)
    end

    View full-size slide

  37. Example: selling tickets

    View full-size slide

  38. defmodule MyApp.Event do
    schema "events" do
    field :name, :string
    field :start_date, :utc_datetime
    field :end_date, :utc_datetime
    field :description, :string
    field :tickets_count, :integer
    field :price, :integer
    field :location, Geo.Point
    belongs_to :host, MyApp.User
    has_many :tickets, MyApp.Ticket
    timestamps()
    end
    end

    View full-size slide

  39. defmodule MyApp.Event do
    schema "events" do
    field :name, :string
    field :start_date, :utc_datetime
    field :end_date, :utc_datetime
    field :description, :string
    field :tickets_count, :integer
    field :price, :integer
    field :location, Geo.Point
    belongs_to :host, MyApp.User
    has_many :tickets, MyApp.Ticket
    timestamps()
    end
    end

    View full-size slide

  40. Single Responsibility
    Principle

    View full-size slide

  41. "The single responsibility principle
    (...) states that every module or
    class should have responsibility
    over a single part of the
    functionality provided by the
    software. "

    View full-size slide

  42. "A class should have only one
    reason to change."

    View full-size slide

  43. EventService
    • Finding events
    Responsibilities:

    View full-size slide

  44. EventService
    • Finding events
    • Selling tickets
    Responsibilities:

    View full-size slide

  45. EventService
    • Finding events
    • Selling tickets
    • Ratings
    Responsibilities:

    View full-size slide

  46. EventService
    • Finding events
    • Selling tickets
    • Ratings
    • ...
    Responsibilities:

    View full-size slide

  47. How much would it take to rewrite
    entire EventService from scratch?

    View full-size slide

  48. EventService
    • Finding events
    • Selling tickets
    • Ratings
    • ...
    Responsibilities:

    View full-size slide

  49. EventService
    • Finding events
    • Selling tickets
    • ...
    Responsibilities:
    RatingService

    View full-size slide

  50. EventService
    • Finding events
    Responsibilities:
    RatingService
    SalesService

    View full-size slide

  51. EventService
    SalesService
    RatingService

    View full-size slide

  52. Nouns vs. Verbs

    View full-size slide

  53. EventService
    SalesService
    RatingService
    "Displays events
    near you"
    "Allows users to
    buy tickets for
    events"
    "Allows users to
    give rating to the
    event"

    View full-size slide

  54. "When you think about what a service
    knows, you always end up back at
    CRUD.
    http:/
    /www.michaelnygard.com/blog/2018/01/services-by-lifecycle/

    View full-size slide

  55. "When you think about what a service
    knows, you always end up back at
    CRUD. (...) Once you know what a
    service does, you can figure out what it
    needs to know. "
    http:/
    /www.michaelnygard.com/blog/2018/01/services-by-lifecycle/

    View full-size slide

  56. Database becomes just an
    implementation detail.

    View full-size slide

  57. SalesService
    API
    Stable interface
    Hidden
    implementation
    detail

    View full-size slide

  58. All great, right?

    View full-size slide

  59. Architecture is about taking a step
    back, looking at a bigger picture and
    being aware of trade-offs when
    making decisions.

    View full-size slide

  60. Architecture is about taking a step
    back, looking at a bigger picture and
    being aware of trade-offs when
    making decisions.

    View full-size slide

  61. SalesService
    EventService
    • ticket_price
    • name
    • date
    • organizer
    {
    "name": "My Event",
    "organizer": {  },
    "date": " ",
    "ticket_price": 200
    }

    View full-size slide

  62. SalesService
    EventService
    • ticket_price
    • name
    • date
    • organizer
    {
    "name": "My Event",
    "organizer": {  },
    "date": " ",
    "ticket_price": 200
    }

    View full-size slide

  63. • Fetch both entities
    • Keep ticket price in both places
    • Keep everything only in events table
    • Use joins
    • ...

    View full-size slide

  64. Maintainability
    Performance

    View full-size slide

  65. Easy to understand
    Easy to write

    View full-size slide

  66. This is hard

    View full-size slide

  67. ‣Trade-offs everywhere
    ‣There's no right answer
    ‣There's no way to predict the future
    ‣A lot of attributes to optimise for
    ‣It's easy to over-engineer
    ‣Not so much resources
    This is hard

    View full-size slide

  68. ‣Small pieces
    ‣Loose coupling
    ‣Strong, well-defined, stable interfaces
    ‣Focusing on behaviour, not data
    ‣Knowing common problems & patterns
    What helps

    View full-size slide

  69. Resources
    ‣ The art of destroying software - Greg Young
    ‣ Architecture the Lost Years - Robert C. Martin
    ‣ Modular monoliths - Simon Brown
    ‣ https:/
    /medium.com/@dan_manges/the-modular-monolith-rails-
    architecture-fb1023826fc4
    ‣ https:/
    /m.signalvnoise.com/the-majestic-monolith-29166d022228
    ‣ https:/
    /medium.com/appunite-edu-collection/whats-wrong-with-a-
    global-user-module-ed7ed013a519
    ‣ http:/
    /www.michaelnygard.com/blog/2018/01/services-by-
    lifecycle/

    View full-size slide

  70. ‣ "OO" patterns (SoC, SRP, SOLID, "Tell, don't ask")
    ‣ Early Object Oriented ideas
    ‣ Microservices
    ‣ Domain Driven Design
    ‣ CQS, CQRS, Event Sourcing
    Extra

    View full-size slide

  71. Thanks!
    Poznan Elixir Meetup #6
    mkaszubowski94

    View full-size slide