Abstraction in Elm: Conclusion

Matthew Buscemi
2 min readJan 16, 2018

--

Table of Contents

  1. Introduction
  2. One Expression to Rule Them All
  3. Introduce Comments
  4. Introduce Local Functions
  5. Utility-Based Modularization
  6. Domain-Based Modularization
  7. Wrappers and Generics for Everything
  8. Conclusion

Summary

Our code communicates implementation details (what the application does) best when we make it as concrete as it can possibly be.

Our code communicates our intent (why we made the implementation choices we did) best when we make it as abstract as it can possibly be.

When our code is perfectly concrete, intent in unclear, duplication is rampant, and change is hard because engineers attempting to read it experience detail-overload.

When our code is perfectly abstract, implementation details are unclear, meaningless partitions are rampant, and change is hard because engineers attempting to read it experience partition-overload.

When our code is perfectly concrete, the relationships between various parts of our code are unclear, because everything is in one enormous function, and so nothing exists to help distinguish the relationships.

When our code is perfectly abstract, the relationships between various parts of our code are unclear, because every single part is behind a partition. The partitions are therefore meaningless, and so nothing exists to help distinguish the relationships.

The relationships between various parts of our code are clear when we implement the best partitions for the given behavior, living within a given function, living within a given module, living within a given application, living within a given ecosystem. The definition of “best” will depend upon context, but it will always be somewhere between the two extremes of total concreteness and total abstraction, which are the least desirable configurations for any software project of significant size.

Takeaways for Elm

Component-based architecture forces the creation of partitions that are not tied to meaningful utilities or domains for a particular application. As a result, large component-based systems typically end up with some amount of abstraction that obscures clarity of detail without adding clarity of intent. One of the greatest aspects of programming in Elm as that the only abstractions we are beholden to are the signatures of the functions that we pass to Program.

However, I would love to see the Elm community discuss more openly which kinds of abstraction choices are good and which kinds of abstraction choices are bad, rather than urging individuals away from abstraction entirely. The time to start thinking about your application’s structure is not when it reaches six hundred lines. That time, in my experience, is always right now. Especially on a team, choosing any kind of arbitrary boundary, (for example, waiting until your data structures have such-and-such number of fields or until files become such-and-such lines long), is a recipe for engineers to proceed without thinking about structure. Then, the code will end up either overly concrete or overly abstract, and the team will have to deal with all the baggage that comes with that particular extreme.

--

--