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. "The goal of software architecture is to minimize the human

    resources required to build and maintain the required system." Robert C. Martin, "Clean Architecture"
  2. Architecture is about taking a step back, looking at a

    bigger picture and being aware of trade-offs when making decisions.
  3. Quality attributes Maintainability Reusability Availability Performance Reliability Scalability Security Supportability

    Testability Deployability Simplicity Development speed Composability Fault tolerance ...
  4. ‣ Isolation ‣ Separation of concerns ‣ Hiding of implementation

    details ‣ Good abstractions ISO/OSI model
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. "The single responsibility principle (...) states that every module or

    class should have responsibility over a single part of the functionality provided by the software. "
  15. EventService SalesService RatingService "Displays events near you" "Allows users to

    buy tickets for events" "Allows users to give rating to the event"
  16. "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/
  17. "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/
  18. Architecture is about taking a step back, looking at a

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

    bigger picture and being aware of trade-offs when making decisions.
  20. SalesService EventService • ticket_price • name • date • organizer

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

    { "name": "My Event", "organizer": {  }, "date": " ", "ticket_price": 200 }
  22. • Fetch both entities • Keep ticket price in both

    places • Keep everything only in events table • Use joins • ...
  23. ‣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
  24. ‣Small pieces ‣Loose coupling ‣Strong, well-defined, stable interfaces ‣Focusing on

    behaviour, not data ‣Knowing common problems & patterns What helps
  25. 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/
  26. ‣ "OO" patterns (SoC, SRP, SOLID, "Tell, don't ask") ‣

    Early Object Oriented ideas ‣ Microservices ‣ Domain Driven Design ‣ CQS, CQRS, Event Sourcing Extra