Skip to content
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

docs(rfc): add api access modifiers style-guide RFC for v9 #23577

Merged
merged 6 commits into from
Aug 17, 2022

Conversation

Hotell
Copy link
Contributor

@Hotell Hotell commented Jun 16, 2022

This RFC introduces style guide/ common approach for our packages API access modifiers that will be enforced by tooling.

Preview 📖 👀

Tooling implementation PR 🛠

📣 Call to action to all teams

To be able to not delay v9 stable release any further we need all teams to review their packages by the end of Wednesday 22nd of June and apply following:

  • if you use @internal modifier already, please verify that it is not exposed from package public API. If that's the case please remove it - BREAKING CHANGE in RC
  • mark your package APIs with @internal modifier where necessary taking into consideration former bullet point

Why is this needed?

As/If we introduce this style-guide/workflow, with aforementioned tooling PR being merged and packages migrated to that new behavior, our packages will trim away @internal.

if we won't catch this now, we will introduce BREAKING CHANGES in stable release which is a NO GO.

@github-actions github-actions bot added this to the June Project Cycle Q2 2022 milestone Jun 16, 2022
@github-actions github-actions bot added the Type: RFC Request for Feedback label Jun 16, 2022
@fabricteam
Copy link
Collaborator

fabricteam commented Jun 16, 2022

📊 Bundle size report

🤖 This report was generated against 02a6a76a3350adfb4fd95cdfc178864801c8e2bf

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jun 16, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 121875e:

Sandbox Source
@fluentui/react 8 starter Configuration
@fluentui/react-components 9 starter Configuration

@size-auditor
Copy link

size-auditor bot commented Jun 16, 2022

Asset size changes

Size Auditor did not detect a change in bundle size for any component!

Baseline commit: 02a6a76a3350adfb4fd95cdfc178864801c8e2bf (build)

@Hotell Hotell changed the title docs(rfc): add api acessors rfc docs(rfc): add api access modifiers style-guide RFC for v9 Jun 16, 2022
@Hotell Hotell marked this pull request as ready for review June 16, 2022 14:52
@miroslavstastny miroslavstastny requested a review from a team June 16, 2022 14:59
@andrefcdias andrefcdias self-requested a review June 16, 2022 15:15
export declare function hello(): void;
```

#### `@alpha`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure how useful the prerelease stage modifiers will be since it's harder for partners to be aware of these tags, not all IDEs will render tsdoc the same way. For the scenarios that the prerelease modifiers cover, IMO /unstable entrypoint + _unstable suffix would be more impactful

Copy link
Contributor Author

@Hotell Hotell Jun 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure how useful the prerelease stage modifiers will be since it's harder for partners to be aware of these tags, not all IDEs will render tsdoc the same way

good point, lemme provide a visual for the usage

graph TD
A["@alpha,@beta"] --> U["@fluentui/pacakge-name/unstable"]
B["@public"] --> S["@fluentui/pacakge-name"]
C["@internal"] --> E((X))
Loading

these access modifiers will:

  • enforce us to not expose public/beta/internal by accident as part of public API
  • guard us from exposing public/beta shipped from package /unstable api to be shipped in consuming package as stable API

additional context: if needed we can allow @beta to be shipped from stable and only @alpha from unstable but I'd leave that to team decisions ( IMO we should not do that ).

Is that more clear now ? If yes I'll add the graphics to RFC. ty!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

additional context: if needed we can allow @beta to be shipped from stable and only @Alpha from unstable but I'd leave that to team decisions ( IMO we should not do that ).

As @beta packages could have breaking changes IMO we should not ship them under stable.

To check my understanding: we have following chain for packages alpha -> beta -> rc. If we follow the same for APIs in comments, we should have also @rc comment, right? 👾

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean that @fluentui/new-component will only be usable from @fluentui/new-component/unstable while the component is in alpha and beta stages ?

Copy link
Contributor Author

@Hotell Hotell Jun 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean that @fluentui/new-component will only be usable from @fluentui/new-component/unstable while the component is in alpha and beta stages ?

yes that's the idea (from TS api POV )

Copy link
Member

@ling1726 ling1726 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not fully convinced about the prerelease modifiers, but they are fully usable withour existing practices.

What I love is the ability to completely strip dts for fully internal APIs

rfcs/shared/build-system/package-public-api.md Outdated Show resolved Hide resolved
It indicates that an API item has been officially released, and is now part of the supported contract for a package. Semver versioning is used and enforced thus the API signature cannot be changed without a MAJOR version increment.

- tooling will NOT trim the declaration from a public API surface.
- CANNOT be exposed from `/unstable` API surface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the only reason to use @public. Based on the other examples it seems that everything is implicitly public unless otherwise annotated. Do we need this annotation? When would I use it?

Copy link
Contributor Author

@Hotell Hotell Jun 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems that everything is implicitly public unless otherwise annotated.?

yeah, API without annotation is implicitly considered as public ->
image

We can enforce it with tooling, so missing annotation will fail on CI/build

image

Do we need this annotation? When would I use it?

It might feel like unnecessary churn for some devs to add this annotation all the time, on the other hand:

  • it will force to provide reasonable amount of documentation to public APIs which is what we should be doing anyways
  • consistency of using modifiers

personally I have no strong opinions on this, besides having consistency

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we should enforce it via ESLint to be sure that all APIs are properly annotated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation. That really helped.

As you said, it is an extra bit of typing/work but I like the fact that everything would then always be explicit. We uncovered quite a few accidentally public APIs during bug bash so I think it's worth being strict about.

@Hotell Hotell requested review from a team June 17, 2022 08:14
export declare function hello(): void;
```

#### `@beta`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any difference between in @alpha & @beta except semantics, is correct? As we export them as under unstable is there a sense to use @unstable instead?

IMO it will reduce maintenance cost as with current proposal we should ensure that @alpha will be changed to @beta when a package will be promoted. And we don't have any automation for it...

Copy link
Contributor Author

@Hotell Hotell Jun 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any difference between in @Alpha & @beta except semantics, is correct

correct. I added more context to one of Lings comments

image

As we export them as under unstable is there a sense to use @unstable instead?

that's great idea ! we would need to get this implemented to api-extractor as it has limited support for access modifiers stripping / or eventually introduce custom tooling

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking more into custom annotations and api-extractor support and there might be some possibilities to do this. api-extractor documenter already supports tsdoc that allows custom annotation definitions. similar implementation would be needed for dts stripping mechanism. I'll create issue on Rush repo to add this support.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


### Proposed access modifiers:

#### `@internal`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could have @public be the modifier and have the tooling make all things @internal by default. This would force us to be explicit in what is exposed. If we forget the attribute, the method or type can't get published.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually agree with this 👍 how easy it is to implement might be a differnt story

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting idea indeed @GeoffCoxMSFT ! that would work only for stable API's though, which is not our use-case as we have various stages of API/packages that are being shipped to users.

how easy it is to implement might be a differnt story

haha YES

@andrefcdias andrefcdias removed the request for review from a team July 4, 2022 16:52
export declare function hello(): void;
```

### Summary
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check out the summary with Fufure work paragraph - based on our discussion if it makes sense to you and if we can proceed.

@layershifter @spmonahan @ling1726

cheers!

rfcs/shared/build-system/package-public-api.md Outdated Show resolved Hide resolved
rfcs/shared/build-system/package-public-api.md Outdated Show resolved Hide resolved
rfcs/shared/build-system/package-public-api.md Outdated Show resolved Hide resolved
rfcs/shared/build-system/package-public-api.md Outdated Show resolved Hide resolved
Co-authored-by: Tristan Watanabe <[email protected]>
@Hotell Hotell enabled auto-merge (squash) August 17, 2022 15:08
@Hotell Hotell merged commit 813f873 into microsoft:master Aug 17, 2022
@spmonahan
Copy link
Contributor

@Hotell In a recent discussion the possibility of an unstable API or feature for an otherwise stable component came up.

As a hypothetical let's say we need to add a new feature to SpinButton. Today SpinButton is stable in v9. We are unsure of either the exact API or the exact behavior (or perhaps both!) of this new feature but we want to be able to ship it so our users can test out the feature and provide feedback. How can we mark this feature as "unstable" so it's clear to users that it should be used with caution but available on an otherwise stable component?

I think this should be essentially the same flow as moving an unstable component to stable, just applied to individual features of a component.

I'm bringing this up now because it may be something we need in the future but I definitely don't think it should block this PR in any way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants