Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save softinio/2fde25dd5a4a6e13c02acadf961e2bbf to your computer and use it in GitHub Desktop.
Save softinio/2fde25dd5a4a6e13c02acadf961e2bbf to your computer and use it in GitHub Desktop.

Revisions

  1. @Gabriella439 Gabriella439 created this gist Feb 5, 2020.
    275 changes: 275 additions & 0 deletions open-source-contributions.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,275 @@
    These are my rough notes when preparing for a Haskell livestream that I
    thought would be worth sharing. Some things are general comments on
    contributing to the open source ecosystem whereas other notes are specific
    to the stream (e.g. Haskell and the `streamly` package)

    How things look from a maintainer's point of view (for highly active projects):

    * Reactive

    As projects become more active the maintainer's "inbox" gets pretty large. A
    significant part of their routine is triaging their inbox.

    In this situation, maintainers commonly forget about the "big picture" of the
    project, including major deficiencies in user experience, due to this reactive
    workflow. Usually once a maintainer gets through their inbox their willpower
    is drained, so they don't take initiative to make any further improvements
    beyond what users requested.

    * Oversubscribed

    Most project authors bite off more than they can chew, and they eventually
    have to start deciding which requests to skip (either explicitly or by
    ghosting the request).

    * Bottlenecks

    If maintainers don't document/automate workflows or process then they have to
    put work into shepherding outside contributions and the maintainer becomes a
    bottleneck to outside contributors. If the situation is really bad the
    maintainer puts more work into shepherding outside contributions than it would
    have taken to do things themselves, which is an unfortunate situation for
    everybody involved.

    Given that, how can you help contribute to another person's repository:

    * Start by contributing small changes to "test the waters"

    This helps guage how open the maintainers are to outside contributions.
    (In my opinion) Good maintainers will entrust you with authority early on.

    Great example: Haskell's `lens` library (Edward Kmett freely shares commit
    bit for all of his projects)

    Opposite example: Nix (authority is rarely delegated, as far as I can tell)

    * Help improve the contribution or release process

    Study historical pull requests or releases and see if there is something
    that can be automated. For example, volunteer to contribute or improve CI
    pipelines or document processes (e.g. `.github/CONTRIBUTING.md`). Anything
    that makes it easier for new contributors will relieve the maintainer's
    burden and increase the leverage of outside contributions.

    Sometimes this can be as simple as writing down "How do I get permission to
    X" where X is:

    * "get the commit bit"
    * "get maintainer privilege on some community infrastructure"
    * "cut new releases"
    * "tweet or blog about the project in an official capacity"

    Also, "DevOps" experience is in high demand in the open source ecosystem and
    can make a huge impact on project adoption. For example, projects that
    release pre-built binaries for multiple platforms have a significant
    competitive edge over projects that require building from source.

    * Use the package and fix what you find

    As a new user of the package, you see it with fresh eyes and all the warts
    of the user experience are clear. Fix those warts!

    As a new contributor you have a large advantage over the maintainer that you
    might not yet appreciate: you have plenty of time to carefully think through
    and improve the holistic user experience. You're not distracted by the
    process of triaging incoming issues, so take advantage of that space and
    creative freedom.

    Example project we'll use for livestream: `streamly`, a stream processing
    package for Haskell

    I picked this package because it's already in very good shape and illustrates a
    lot of good open source practices

    There are two experiences we could potentially improve:

    * The experience of new users
    * The experience of new contributors

    We'll focus on improving the experience for new users

    Let's think through the entire "experience" of how a user might use `streamly`

    * Motivation

    How does a user even know that they even need a streaming library in the first
    place?

    For example, a lot of Haskell users will just write an explicit recursive
    loop without a second thought that they even should be using a streaming
    library.

    Or maybe they don't need a streaming library! How do they know what is the
    threshold for using a streaming library? This is a very common question that
    novice Haskell users struggle with.

    Some ways to improve this are:

    * Answering Stack Overflow questions where a streaming solution is an
    appropriate solution (i.e. not overkill)

    * Writing blog posts about the package to raise awareness that this class of
    problems and solutions exist

    * Discoverability

    How do people find out about your package specifically?

    * Adding the package to various catalogs of recommended solutions

    * Word of mouth

    * Search keywords (e.g. Hackage categories, search engine optimization)

    * Project website

    * Evaluation

    How do people select your package against competing solutions?

    * Comparative evaluations with other packages (e.g. benchmarks)

    * Ranking systems (e.g. Hackage votes, slant.co)

    * Skimming documentation/tutorials/blog-posts

    * Activity and/or reputation of authors / maintainers

    * Overall perception of quality

    * Word of mouth

    * Simple self-contained example

    * Probably the most common step that projects forget to do

    * Is there an example program?

    * Where is the example program? In the README? In the generated
    documentation? In an `./examples` directory on GitHub?

    * How to build the example

    * Yes, you may have to teach users to use their compiler or build tools even
    though it's technically not your project's responsibility

    Most novice users are struggling with their build tools, across all
    programming languages, and most of your users are novice users

    * How to integrate your package into an existing project

    * `cabal` vs `stack` vs Nix instructions

    * Again, technically not your job, but helps to spell it out anyway

    * Poor example: `reflex`, since you have to integrate with their project
    instead of the other way around

    * How reliably does your package build?

    * Is your package on Stackage?

    Easily the most important thing you can do to reduce build failures for your
    users

    This also gives you Nix support for free. Nix ecosystem closely tracks
    Stackage

    * Are your dependency bounds correct?

    Upper bounds are more work to maintain, but bounds failures are a better
    end-user experience than build failures and easy to amend via Hackage
    revisions.

    * Does your package have non-Haskell (e.g. C) dependencies?

    You can declare these as required dependencies in your `.cabal` file

    Some common dependencies that people can be unexpectedly missing from user
    systems:

    * `zlib`
    * `iconv`
    * `ncurses`

    * Documentation coverage

    * 100% haddocks?

    * Doctests?

    * @since annotations?

    * For each type, it's often useful to document these three things:

    * How to create that type
    * How to transform/combine that type
    * How to consume that type

    * API

    * Are the right things public / private?

    * Are the module names well-chosen? (e.g. `Control.Monad.Trans.State` vs
    `Streamly`)

    * Should internal modules be made available?

    * Okay, now to get to the actual code 😅

    Most things that are code-specific will be covered in the issue tracker

    Just browse open issues and take a crack at fixing them

    * https://github.com/composewell/streamly/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22
    * https://github.com/composewell/streamly/issues/11
    * https://github.com/composewell/streamly/issues/293

    There are still some generic improvements to the code you can make, too

    * Error messages

    Levels of error messages:

    * No error (silently transform a failure into a fake success)
    * One-liner (`Exception: Prelude.head: empty list`)
    * Expected: … / Actual: …
    * Here's what went wrong: …
    * Here's what you should do: …
    * I automated away what you should do
    * The invalid state is no longer representable (i.e. now a type error)

    * Type-level experience?

    * Are inferred types good?

    * Are type errors good?

    * You can add custom type errors in Haskell! This is a light-weight and
    high-value contribution!

    * How do users get help?

    * Issue tracker (e.g. GitHub)
    * Stack Overflow
    * Discourse
    * Gitter
    * Discord?
    * Twitter?

    Is it an easy and enjoyable process for them?

    Is the support process or forum discoverable?

    Are users left hanging or ghosted by maintainers?

    Do they know what is expected from them when they file bug reports?

    Is it clear if the ball is in their court or in maintainer's court for any
    given issue?

    * For frameworks (e.g. Yesod, Cloud Haskell, or Reflex): how to deploy the
    application to production

    Again, not your job, but your users expect *somebody* to hold their hand and
    tell them how to do this and that *somebody* is probably you