Skip to content

go design: SOLID vs functional options #18

@AmitKumarDas

Description

@AmitKumarDas

Use functional options when:

  • The behaviour needs to be tweaked
    • E.g.: DryRun, Debug, UseHttp, IgnoreChecks, etc.
    • E.g.: Support reuse a cached build as well as build always features
  • TIP: API needs boolean flags & optional features
  • TIP: Remember functional options is often used with variadic arguments
    • I.e.: There can be no args or a bunch of them & both of these should be perfectly valid
  • TIP: It is wrong if clients have to remember which functional option is mandatory vs. optional

Do not use functional options when:

  • Multiple behaviours are desired
    • Github release vs Gitlab release
  • Main actor / entity changes or requires additional entities/actors
    • Running on Mac vs Running on Windows
  • More examples:
    • Save file to Database vs. Publish file to CDN
    • Build using make vs. Build using make inside container
    • Build inside container vs. Build inside K8s Pod
    • Build inside Gitlab runner vs. Build inside Jenkins runner
  • Use of functional options in above case leads to:
    • [1] A single structure that caters to all possible requirements
    • [2] Explosion in the number of functions exposed from a single package
    • Most importantly the Single Responsibility Pattern (i.e. S in SOLID) is violated due to [1]
  • Summary: Functional options is not right if it breaks any of the SOLID principles
  • Remedy: Stick to old school patterns, idiomatic & effective practices
  • Test: Keep verifying the implementations against SOLID principles

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions