leontrolski - CMD-click manifesto

2 min read Original article ↗
  • Being able to CMD-click through code >> any other theoretical concerns.
  • CMD-clickability is the opposite of indirection - how does this function work? CMD-click it.
  • Non-CMD-clickable codebases are filled with non-meaningful abstractions and tend to be longer.
  • Static analysis tooling should be easy to write.
  • Stack traces should correspond with the structure of the code.
  • Higher order functions break the golden property, use them as a last resort.
    def do_something(data, f: Callable[...]):
        f(data)  # I can't CMD-click f
  • Trad Object Orientated code tends to break the golden property (this makes sense as objects are closures), use it as a last resort.
    def do_something(a: Animal):
        a.meow()  # I can't CMD-click meow
    This case it is ambiguous as meow() could be on any Cat, Lion, Tiger...
  • Use enum-like information to distinguish between otherwise similar data.
    class Cat(Animal): ...                # bad
    a = Animal(kind=AnimalKind.CAT, ...)  # good
  • Serializable enum-like discriminants in data can be trivially plonked into databases, regurgitated via JSON, etc.
  • Choose behaviour based on data, not class hierarchies:
    def do_something(data):
        if data.kind == Kind.A:
            g(data)  # I can CMD-click g
  • Say arbitrarily complicated things about data, rather than be constrained by inflexible heirarchies.
    class Cat(Animal, FourLegged): ...                  # bad
    def has_even_number_of_legs(a: AnimalKind) -> bool  # good
  • Strong typing aids CMD-clickability, this property of typing is more valuable than correctness.
  • Microservices in and of themselves are not bad, however:
    1. Construct your codebase such that CMD-clicking across a service boundary is as easy as within a service.
    2. Typecheck service boundaries as you would any other code.
    3. Use correlation ids and a Datadog-like tool to make cross-service stack traces comprehensible for debugging production.
  • Where you might have to fall back on grepping - make it easy, use full literals:
    @app.route(PREFIX + "/v1/add")          # bad
    @app.route("/payments/inbound/v1/add")  # good
  • Good code expresses the smallest possible state space the program could operate in - YAGNI.
    def do_something(data, f: Callable[...]):
        # f could be anything - big state space
        f(data)
    
    def do_something(data, kind: Kind):
        # we enumerate the specific things we can do - small state space
        if kind == Kind.A:
            g(data)
        ...
  • Lean in on language features, don't introduce unnecessary abstractions.
  • There exists deep library code where we want to allow consumers to do anything (extensibility). In application development, this is the exception - you have control over the whole codebase, the code by its nature is extensible.
  • Ignore this manifesto sooner than code anything outright barbarous.