Skip to content

docs: use Reexport with SemVer #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,41 @@ using A
`@reexport @another_macro <import or using expression>` first expands `@another_macro` on the expression, making `@reexport` with other macros.

`@reexport begin ... end` will apply the reexport macro to every expression in the block.

## Use Reexport together with semantic versioning

Without restating [the semantic versioning](https://semver.org/) in complete details here's the
simplified version of it.

![semver_workflow](https://user-images.githubusercontent.com/8684355/140517399-91c1e7eb-8328-4fe5-aaab-d6da91864b9d.png)

If we adopt Reexport to PkgA, then `@reexport using PkgB` makes PkgB a reexported dependency of
PkgA. Assume that we have the following dependency graph:

![semver_example_package](https://user-images.githubusercontent.com/8684355/140514459-e460444d-a65f-481f-8520-964d605a851e.png)

This works pretty well if it's all about bug fixes and new features. But for breaking changes, say
PkgD makes a breaking release from v1.0.0 to v2.0.0, a natural question is: should we propagate the
changes from bottom to top? That is: should we make PkgB v1.0.1, v1.1.0 or v2.0.0 release? The
answer to this is: if the change is about the reexported symbol, then we have to make PkgB v2.0.0
release, and then do the same to PkgA. If it is not about the reexported symbol, then we should try
to absorb the PkgD breaking change as PkgB internal changes and only release PkgB v1.0.1 or v1.1.0.

![semver_solution](https://user-images.githubusercontent.com/8684355/140516220-573ceae9-e510-4d7d-9b7b-bae22f0fdf1a.png)

We need to do this because from a user's perspective he does not know whether the symbol is
reexported. Thus _if the bottom makes a breaking change to any exported symbols, not bumpping major
version on the top is a violation to the SemVer_.

The propagation of breaking changes in the left is definitely not ideal since it would trigger a lot
of [CompatHelper](https://github.com./JuliaRegistries/CompatHelper.jl) notifications. For this
reason, it is a better practice to be conservative on the choice of exported and reexported symbols.
Thus it is recommended to:

1. only reexport packages that is either stable enough, or that you have direct control of, and
2. use `@reexport using PkgD: funcA, TypeB` (requires Reexport at least v1.1) instead of `@reexport using PkgD`

This is just a recommendation so you don't need to follow this, but you need to know that Reexport
is not the silver bullet. Being lazy and blindly using `@reexport using A, B, C` means you still
need to pay for it if you care about the semantics that SemVer gaurentees. This is especially a
painful experience especially when you have a long dependency chain like `PkgD -> PkgB -> PkgA`.