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

Fighting Complexity in Elixir

722082f009c46a395182cc516fb620ca?s=47 Mrinal Wadhwa
September 19, 2020

Fighting Complexity in Elixir

This talk discusses how several ideas from John Ousterhout's book "A Philosophy of Software Design" can be applied to Elixir code.

722082f009c46a395182cc516fb620ca?s=128

Mrinal Wadhwa

September 19, 2020
Tweet

More Decks by Mrinal Wadhwa

Other Decks in Programming

Transcript

  1. Fighting Complexity

  2. Software has almost no constraints.

  3. Software has almost no constraints. We can make pigs fly,

    if we want to.
  4. If you can imagine a system, you can probably build

    it in software.
  5. The greatest limitation in software is our ability to understand

    the systems we are creating. — John Ousterhout, A Philosophy of Software Design
  6. As we add new features, our code evolves and naturally

    becomes more complicated. Subtle dependencies emerge.
  7. Over time, this complexity accumulates.

  8. It becomes harder and harder for us to keep all

    of the relevant information in our minds … Over time, this complexity accumulates.
  9. Because the system is becoming complex and we’re struggling to

    keep all the details in our minds:
  10. Because the system is becoming complex and we’re struggling to

    keep all the details in our minds: It becomes harder to add new features … it slows us down.
  11. Because the system is becoming complex and we’re struggling to

    keep all the details in our minds: We can easily miss some detail and create bugs … which further slows us down. It becomes harder to add new features … it slows us down.
  12. The effect multiplies and accelerates with every new contributor to

    our codebase.
  13. Progress starts to stagnate and costs start to grow rapidly.

  14. Fighting Complexity Its all about:

  15. Stamina Simpler, less complex, designs allow us to build larger

    more powerful systems before complexity becomes overwhelming. Its about building:
  16. Complexity Anything related to the structure of a codebase that

    makes it hard to understand or improve that codebase.
  17. Change Amplification Symptom 1: A seemingly simple change requires code

    modification in many places.
  18. Cognitive Load Symptom 2: How much information does a developer

    need to make a change to the system.
  19. Unknown unknowns Symptom 3: It’s not obvious which pieces of

    code must be modified to complete a task, or what information a developer must have to carry out the task successfully.
  20. Complexity is caused by two things dependencies and obscurity.

  21. Tactical Programming In the tactical approach, our main focus is

    to get something working. This is how systems become complicated - one small compromise at a time.
  22. Strategic Programming The first step towards becoming a good software

    designer is to realize that working code isn’t enough. It’s not acceptable to introduce unnecessary complexities in order to finish your current task faster. The most important thing is the long-term structure of the system. Our primary goal must be to produce a great design, which also happens to work. This is strategic programming. – John Ousterhout. A Philosophy of Software Design
  23. None
  24. The Tactical Tornado

  25. None
  26. The simple parts of reducing Cognitive Load … Good names,

    good comments, consistency, mix format, credo etc.
  27. Modular Design A developers only need to face a small

    fraction of the overall complexity at any given time.
  28. Does not mean more modules.

  29. Encapsulation Encapsulate complexity so our team can work on other

    parts of the system without being exposed to the complexity encapsulated in this module.
  30. In Elixir we can encapsulate at the function level and

    at the module level.
  31. Deep Modules The best modules are those that provide powerful

    functionality yet have simple interfaces.
  32. None
  33. None
  34. None
  35. With a sufficient number of users of an API, it

    does not matter what you promise in the contract: all observable behaviours of your system will be depended on by somebody. Hyrum's Law: Use defp.
  36. Loose Coupling Components in a loosely coupled system can be

    replaced with alternative implementations that provide the same services.
  37. Polymorphism The ability to present the same interface for differing

    underlying forms
  38. Messages Processes can send messages to other processes without needing

    to care what the receiver process is or does. The interface is Process IDs and Kernel.send/2
  39. Behaviors A module that defines a spec which other modules

    can implement.
  40. None
  41. Protocols A group of function headers that a data type

    must implement if it is considered to be implementing that protocol.
  42. None
  43. None
  44. Functions

  45. None
  46. Dependency Inversion High-level modules should not depend on low-level modules.

    Both should depend on abstractions (e.g. interfaces). Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions..
  47. github.com/ockam-network/ockam

  48. None
  49. github.com/ockam-network/ockam Mrinal Wadhwa twitter.com/mrinal CTO @ Ockam