Pretty Good Practices (PGP for short) is a series focused on identifying practices that will improve your quality of life as a developer. Examples may be specific, but the ideas will trend towards being generally applicable. What makes them pretty good rather than best practices is that historically what developers consider best practices evolve dramatically over time.

Today we will take a look at publishing dart packages and what steps authors can take to ensure that they are producing quality packages that will attract usage and feedback. These are guidelines, not rules.

Provide MVP documentation

This is easily one of the most important steps. If your code is not well documented, then there's no way for consumers to understand how to use it. I cannot count the number of packages published to the store that still don't have adequate documentation beyond what is generated by Flutter. Delete it before you publish it, so it is clear what your package is missing. Publishing early, before adding documentation does not benefit anyone.

1. Tell your audience what the package does

We are developers - not salesmen. But just the act of publishing a project means that we want it to be used. You should always provide at least a sentence about the purpose of the package. This quickly provides potential users with context.

2. Provide a brief description of the differences, in loaded categories

State management may still be an unsolved problem in Flutter applications, but there are still a plethora of options available. Describing the differences between similar projects validates both your use case and that of your consumers.

3. Provide at least simple examples of usage

If I am on the pub site, the last thing I should be doing is reading source code to decipher how to use a package. It may be daunting to try and document every use case of an application, but it is even more daunting to not document any. If I cannot find one use case in a project's documentation, that is a clear indication that I should not be using it.

Provide decent test coverage

Testing is absolutely critical when publishing packages for consumption. Testing ensures the integrity and confidence in the package as it evolves. I absolutely love Kent C. Dodds article on the topic, so I'll reiterate some of his points.

1. Write tests

Whatever time it takes to write tests will be made up by the maintenance cost of maintaining your package. Tests are really about building confidence in the impact of changes to the package.

Automated tests allow contributors to make changes to your package and verify those changes. They also extend a contributor's understanding of the package. The strong typing of Dart is valuable, but it cannot ensure that your package's logic is free of bugs.

2. Not too many

I am not dogmatic in how much test coverage you should provide. There are diminishing returns on the road to 100% because you will inevitably end up testing things that do not need to be tested. Focus on areas that have logic - branching, platform usage, etc. "You should very rarely have to change tests when you refactor code."

3. Mostly integration

The test pyramid above indicates that you should spend more of your time on unit tests due to them being inexpensive to maintain and fast to write. But it doesn't capture the "confidence quotient" that each level provides. End to end tests provide high confidence but are expensive to write because they can break regularly and rely on the complexities of UI frameworks. Unit tests provide low confidence but are cheap. The most value comes from integration tests because they are not terribly expensive and allow you to verify that the components of your package work together.

Dodd's article and trophy graphic capture the value tradeoff a little better.

Here we can see that end to end tests are the highest reward because they find the big problems, compared to static typing which can let you catch things like typos. Integration tests hit that sweet spot of being high value with a decent investment.

pana is a great tool that analyzes projects for the bare necessities of what makes a good package. Things such as whether there's a description, whether URLs to the homepage or documentation are missing or invalid. I believe that pub.dev also uses pana to determine its scores, so running it regularly gives you a clear indication of how your package will be stored.

Extra Credit: Setup CI

Setting up automation to handle the testing and publishing of your packages will improve your productivity immensely. There is nothing more exciting than remembering the steps to publish a package or make a change: pulling down the pull request, analyzing the project, running tests on the project, bumping the version, and finally publishing. You could do that, or you could let the computer do the work for you and enjoy a beer (or coffee if that's your thing).

Conclusion

You can summarize all of this advice as just being a good steward to your community. These are suggestions (good practices not best ones) that will drastically improve the lives of your contributors and your consumers. And really, isn't that what open-source is about?