informalsystems / informalsystems/hermes

Separate internal and public crate APIs using explicit export list

Open
#2,188 4 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
505
Forks
399
PR merge metrics
No merged PRs in 30d

Description

Summary

Move implementation code into crate::internal, and explicitly export public APIs at the top level.

Problem Definition

Rust's approach for hiding private APIs and exposing public APIs is not very flexible when projects are split into multiple crates. The pub (crate) modifier only allows an internal interface to be exposed to other constructs within the same crate. But we cannot easily state that a certain API is accessible to an external crate managed by the same project.

This creates issues if we want to share internal APIs between different crates like ibc, ibc-relayer, and ibc-test-framework. While making the constructs public could solve the issue, this may potentially introduce maintenance burden if other projects decide to use the internal APIs.

A solution to this is to introduce an internal submodule that is public, but do not guarantee API stability. This way, crates within the same project can import constructs from the internal submodule, but external users will be adviced against importing the internal submodule.

At the top level, we then make explicit decision on which constructs from the internal crate should be exported. The explicit export list also makes it easier to conduct reviews. Reviewers can be aware of a new public API being added by just looking at lib.rs, instead of looking for the pub keyword scattered across many files.

The use of internal module is a common convention in Haskell. It also allows power users who are not afraid of API breakage to import internal constructs at the own risk, without affecting regular users who prefer stable APIs.

Proposal

Move all code into an internal module/subdirectory, and explicitly export public APIs in lib.rs.


For Admin Use
  • Not duplicate issue
  • Appropriate labels applied
  • Appropriate milestone (priority) applied
  • Appropriate contributors tagged
  • Contributor assigned/self-assigned

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by inspecting lib.rs and the ibc, ibc-relayer, and ibc-test-framework crate boundaries. Map current public items and determine the scope of moving code into internal modules. Done means implementation is under internal and top-level public APIs are explicitly exported in lib.rs.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design, blockchain
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.