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

Solid code isn't flexible

Solid code isn't flexible

Chris Keathley

September 02, 2022
Tweet

More Decks by Chris Keathley

Other Decks in Programming

Transcript

  1. Chris Keathley / @ChrisKeathley / c@keathley.io SOLID code isn’t Flexible

  2. So, I’ve been taking a break

  3. None
  4. None
  5. Y o This Talk

  6. This talk isn’t really about SOLID

  7. This talk is about building systems with less stuff

  8. Single Responsibility Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle

    Dependency Inversion Principle
  9. Single Responsibility Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle

    Dependency Inversion Principle What is this in s er vice of?
  10. No one ever got fired for adopting an acronym

  11. Software Design is *really hard*.

  12. How do we make it easy to change software?

  13. How do we make it easy to change software? How

    do we add new functionality without changing any existing code?
  14. Lets Talk About: Fundamental Ideals Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  15. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  16. Premise 1 Software Design is about managing complexity

  17. HTTP Client

  18. HTTP Client Socket Management

  19. HTTP Client Socket Management SSL

  20. HTTP Client Socket Management SSL Connection Pooling

  21. HTTP Client Socket Management SSL Connection Pooling h1.1 vs h2

  22. HTTP Client Socket Management SSL Connection Pooling h1.1 vs h2

    Parsing http payloads
  23. HTTP Client Socket Management SSL Connection Pooling h1.1 vs h2

    Parsing http payloads Essential C om pl ex ity
  24. Total Complexity Sum(essential complexity * interaction points)

  25. Total Complexity Sum(essential complexity * interaction points) Most often in

    the f or m of dependent code
  26. Dependencies Change h er e… Module A Module B Means

    Change h er e
  27. Premise 2 All code has a cost. Anything we add

    to the system should add significant value.
  28. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  29. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  30. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  31. Total Complexity Sum(essential complexity * interaction points)

  32. Total Complexity Sum(essential complexity * 0)

  33. Encapsulation Not just f or y ou r state!

  34. Encapsulati o API

  35. Encapsulati o Shall ow lay e API

  36. Encapsulati o Deep er Lay e API

  37. Encapsulati o Best Case API

  38. HTTP Client

  39. HTTP Client TCP Y ou sh ou ld on ly

    have to see this stuff Not this…
  40. HTTP Client TCP MyOtherServiceClient Fuse Regulator

  41. HTTP Client TCP MyOtherServiceClient Fuse Regulator Gen er al Specific

  42. HTTP Client TCP MyOtherServiceClient Fuse Regulator Gen er al Specific

    M or e Reusable Less Reusable
  43. Examples MapSet Jason Network Protocols Persistent Term

  44. Red Flags Excessive passthrough or defdelegates Layered modules that share

    similar apis or functions Changes impacting multiple dependencies Pushing specific details into lower levels decreases reuse
  45. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  46. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  47. Handler Web Request Ecto Cache

  48. Handler Web Request Ecto Cache Wh er e do these

    go?
  49. How much of this is reusable?

  50. Who knows how to make these decisions?

  51. Handler Web Request Ecto Cache

  52. Handler Web Request Ecto Cache Is this still reusable?

  53. Handler Ecto Cache Can I use this functi on ?

    Background Task
  54. Handler Ecto Cache Are we g oi ng to need

    to tune this? Background Task
  55. Push specific logic upwards. Pull complexity downwards.

  56. Handler Ecto Cache Background Task

  57. Handler Ecto Cache Background Task

  58. Delete passthrough modules

  59. Handler Ecto Wrapper defmodule EctoWrapper do def one(query), do: Repo.one(query)

    def all(query), do: Repo.all(query) end
  60. Handler Ecto

  61. Remove modules that provide little value

  62. def get_posts(id) do case :fuse.check(:service) do :ok -> case call_service(id)

    do {:ok, result} -> :ok = Cache.put(id, result) {:ok, result} {:error, error} -> :fuse.melt(:service) {:error, error} end :blown -> cached = Cache.get(id) if cached do {:ok, result} else {:error, error} end end end
  63. def get_posts(id) do case :fuse.check(:service) do :ok -> case call_service(id)

    do {:ok, result} -> :ok = Cache.put(id, result) {:ok, result} {:error, error} -> :fuse.melt(:service) {:error, error} end :blown -> cached = Cache.get(id) if cached do {:ok, result} else {:error, error} end end end H ow does this s er vice int er act with the cache?
  64. def get_posts(id) do case :fuse.check(:service) do :ok -> case call_service(id)

    do {:ok, result} -> :ok = Cache.put(id, result) {:ok, result} {:error, error} -> :fuse.melt(:service) {:error, error} end :blown -> cached = Cache.get(id) if cached do {:ok, result} else {:error, error} end end end Finding a bug means reading the functi o
  65. def get_posts(id) do case :fuse.check(:service) do :ok -> case call_service(id)

    do {:ok, result} -> :ok = Cache.put(id, result) {:ok, result} {:error, error} -> :fuse.melt(:service) {:error, error} end :blown -> cached = Cache.get(id) if cached do {:ok, result} else {:error, error} end end end This is a “C om plete” Functi o
  66. Every function should do one thing and do it completely

  67. Each function should add value and provide reuse.

  68. A function’s signature should be much simpler than its implementation.

  69. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  70. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  71. Polymorphism Inversion of Control &

  72. Enum

  73. Enum S er i ou sly the best module ev

    e
  74. Enum Enum er able things go in Functi on s

    that op er ate on items
  75. Polymorphism in Elixir Functions Protocols Behaviours

  76. defmodule Animal do def speak(f) do f.() end end dog

    = fn -> "bark" end cat = fn -> "Worship me you lowly human" end Animal.speak(dog) Animal.speak(cat)
  77. Mentat.fetch(:posts_cache, :key, fn key -> case Service.get_posts(key) do {:ok, resp}

    -> {:commit, resp} {:error, e} -> {:ignore, e} end end)
  78. Polymorphism in Elixir Functions Protocols Behaviours

  79. Controller Web Request Other Service

  80. Controller Web Request Other Service Can we mock this ou

    t?
  81. defprotocol MyService do def get_posts(impl) end

  82. defprotocol MyService do def get_posts(impl) end defmodule MyService.HTTP do defstruct

    :url, :fuse defimpl MyService do def get_posts(%{url: url, fuse: fuse}) do case :fuse.check(fuse) do :ok -> Req.get(url) :blown -> {:error, Error.unavailable("Service is down")} end end end end
  83. defprotocol MyService do def get_posts(impl) end defmodule MyService.Mock do defstruct

    fake_response: %{} defimpl MyService do def get_posts(%{fake_response: fake_response}) do fake_response end end end
  84. real = %MyService.HTTP{} fake = %MyService.Mock{} MyService.get_posts(real)

  85. Controller Web Request Other Service

  86. Controller Web Request Other Service Inject the s tr uct

    into the plug c on n
  87. defmodule MyApp.Posts do def index(conn, _params) do service = conn.private[:service]

    MyService.get_posts(service) end end
  88. Polymorphism in Elixir Functions Protocols Behaviours

  89. Machinery Behaviour

  90. Machinery Behaviour Behavi ou rs ar e g oo d

    when y ou c on tr ol the machin er y arou nd them
  91. Lets Talk About: Fundamental Ideas Deep Layers vs Shallow Layers

    Things are better together Allowing for extension
  92. Don’t forget to ask “why”.

  93. Chris Keathley / @ChrisKeathley / c@keathley.io Thanks!