deft/notes/haskell_for_all_the_golden_rule_of_software_quality.org

139 lines
5.6 KiB
Org Mode
Raw Permalink Normal View History

2021-09-15 07:12:29 +00:00
:PROPERTIES:
:ID: f4975aa1-bd2e-46f5-9b9b-851677b39918
:ROAM_REFS: https://www.haskellforall.com/2020/07/the-golden-rule-of-software-quality.html
:END:
#+title: Haskell for all: The golden rule of software quality
Haskell for all
Monday, July 27, 2020
** The golden rule of software quality
This post summarizes a rule of thumb that I commonly cite in software
quality discussions, so that I can link to my own post to save time.
I have taken to calling this the “golden rule of software quality” because
the rule is succinct and generalizable.
The golden rule is:
#+begin_quote
Prefer to push fixes upstream instead of working around problems downstream
#+end_quote
and Ill explain implications of this rule for a few software engineering
tradeoffs (using examples from the Haskell community and ecosystem).
Disclaimer: The golden rule of software quality bears no relationship to
the golden rule of treating others as you want to be treated.
** Third-party dependencies
Most developers rely on third-party dependencies or tools for their
projects, but the same developers rarely give thought to fixing or
improving that same third-party code.
Instead, they tend to succumb to the bystander effect, meaning that the
more widely used a project, the more a person assumes that some other
developer will take care of any problems for them.
Consequently, these same developers tend to work around problems in widely
used tools.
For example, for the longest time Haskell did not support a “dot” syntax
for accessing record fields, something that the community worked around
downstream through a variety of packages (including lens) to simulate an
approximation of dot syntax within the language.
This approach had some upsides (accessors were first class), but several
downsides such as poor type inference, poor error messages, and lack of
editor support for field completions.
Only recently did Neil Mitchell and Shayne Fletcher upstream this feature
directly into the language via the RecordDotSyntax proposal, solving the
root of the problem.
The golden rule of software quality implies that you should prefer to
directly improve the tools and packages that you depend on (“push fixes
upstream”) instead of hacking around the problem locally (“working around
problems downstream”).
These sorts of upstream improvements can be made directly to:
- Your editor / IDE
- Your command-line shell
- Programming languages you use
- Packages that you depend on
Note that this is not always possible (especially if upstream is hostile to outside contributions), but dont give up before at least trying to do so.
** Typed APIs
Function types can also follow this same precept.
For example, there are two ways that one can assign a “safe” (total) type
to the head function for obtaining the first value in a list.
The first approach pushes error handling downstream:
#+begin_src haskell
-- Return the first value wrapped in a `Just` if present, `Nothing` otherwise
head :: [a] -> Maybe a
#+end_src
… and the second approach pushes the requirements upstream:
#+begin_src haskell
-- Return the first value of a list, which never fails if the list is `NonEmpty`
head :: NonEmpty a -> a
#+end_src
The golden rule states that you should prefer the latter type signature for
head (that requires a NonEmpty input) since this type pushes the fix
upstream by not allowing the user to supply an empty list in the first
place.
More generally, if you take this rule to its logical conclusion you end up
making illegal states unrepresentable.
Contrast this with the former type signature for head that works around a
potentially empty list by returning a Maybe.
This type promotes catching errors later in the process, which reduces
quality since we dont fail as quickly as we should.
You can improve quality by failing fast at the true upstream root of the
problem instead of debugging indirect downstream symptoms of the problem.
** Social divisions
Im a firm believer in Conways Law, which says:
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organizations communication structure.
Melvin E. Conway
… which I sometimes paraphrase as “social divisions lead to technical
divisions”.
If social issues are upstream of technical issues, the golden rule implies
that we should prefer fixing root causes (social friction) instead of
attempting to mask social disagreements with technical solutions.
The classic example of this within the Haskell community is the cabal vs.
stack divide, which originated out of divisions between FPComplete and
Cabal contributors (Corrected based on feedback from the Haskell
subreddit).
The failure to resolve the upstream friction between the paid and open
source contributors led to an attempt to work around the problem downstream
with a technical solution by creating a parallel install tool.
This in turn fragmented the Haskell community, leading to a poor and
confusing experience for first-time users.
Thats not to imply that the divide in the community could have been
resolved (maybe the differences between paid contributors and open source
volunteers were irreconcilable), but the example still illustrates the
marked impact on quality of failing to fix issues at the source.
** Conclusion
Carefully note that the golden rule of software quality does not mandate
that you have to fix problems upstream.
The rule advises that you should prefer to upstream fixes, all other things
equal.
Sometimes other considerations can prevent one from doing so (such as
limitations on time or money).
However, when quality is paramount then you should strive to observe the
rule!