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

[skip-ci] Core conventions #52397

Merged
merged 7 commits into from
Jan 15, 2020
Merged

[skip-ci] Core conventions #52397

merged 7 commits into from
Jan 15, 2020

Conversation

rudolf
Copy link
Contributor

@rudolf rudolf commented Dec 6, 2019

Summary

Adds conventions adopted by the Platform team for src/core.

Checklist

Use strikethroughs to remove checklist items you don't feel are applicable to this PR.

For maintainers

@rudolf rudolf added Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc Feature:New Platform v8.0.0 release_note:skip Skip the PR/issue when compiling release notes labels Dec 6, 2019
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-platform (Team:Platform)

> internal types.

- 1.2 Classes must not be exposed directly. Instead, use a separate type,
prefixed with an 'I', to describe the public contract of the class.
Copy link
Contributor Author

@rudolf rudolf Dec 6, 2019

Choose a reason for hiding this comment

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

Discussed here #46668 (comment) and here #33396

};

// -- good (alternative) --
export interface IUiSettingsClient {
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'm not sure if there are cases where we prefer to have a dedicated interface instead of inferring a type from a class? If we don't have good examples of where this would be better, I can remove this from the conventions.

Copy link
Contributor

Choose a reason for hiding this comment

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

Pros having explicit interfaces:
There is a difference in that an interface is a source of truth when we define it explicitly. it means that we have control of what properties are a part of a public contract.
Better tooling, as there are no intermediate types. Whenever I click Go to definition on SavedObjectsClientContract it navigates to Pick type.

Cons:
It creates an additional burden to define contracts manually.
Separates docs for an interface and implementation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I prefer explicit interfaces. I'd rather be deliberate about choosing to expose a property or method rather than allowing it to happen without notice (though the api-extractor tooling may make it more obvious).

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'm not completely convinced by the benefit of a separate interface. Adding a public method to an interface doesn't make it more obvious that it will change the API contract than adding a public method to a class.

It seems like typescript support for private named fields will land in February https://github.com/microsoft/TypeScript/wiki/Roadmap#38-february-2020. If classes support real private fields/methods it will remove the need for an intermediate type (whether an explicit interface or PublicContractOf). I see real private fields as the best solution, source code and docs live next to each other, no intermediate types, no type duplication. When Kibana adopts TS 3.8 would we still prefer a separate interface?

Copy link
Contributor

Choose a reason for hiding this comment

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

When Kibana adopts TS 3.8 would we still prefer a separate interface?

Don't think so. IIRC public/private field separation was the main reason for an explicit interface introduction.

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 think it could be slightly easier to migrate from PublicContractOf to private fields, but it wouldn't be that much work to migrate away from separate interfaces either.

Since we're hopefully adopting a new convention soon, it probably doesn't matter too much that we have two alternatives. I can flesh out the comment section to mention the pro's and cons of both conventions and mention that we're hoping to adopt private fields once it's available.

Copy link
Contributor

Choose a reason for hiding this comment

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

Works for me. Agreed that in most use-cases real private fields works well.

> churn when we know related API methods will be introduced.

## 3. Tests and mocks
- 3.1 Declary Jest mocks with a temporary variable to ensure types are
Copy link
Contributor Author

Choose a reason for hiding this comment

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

> hovering over the type in a code editor.

## 2. API Structure and nesting
- 2.1 Nest API methods into their own namespace only if we expect we will be
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed here: #48431 (comment)

@rudolf rudolf marked this pull request as ready for review December 6, 2019 16:24
@rudolf rudolf requested a review from a team as a code owner December 6, 2019 16:24
@rudolf
Copy link
Contributor Author

rudolf commented Dec 6, 2019

@elastic/kibana-platform Are there other conventions you can think of that's worth documenting as part of this PR?

Comment on lines 113 to 115
> Why? Without the temporary variable, Jest types the `start` function as
> `jest<any, any>` and, as a result, doesn't typecheck the mock return
> value.
Copy link
Contributor

Choose a reason for hiding this comment

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

TIL

@joshdover joshdover self-requested a review December 17, 2019 15:34
};

// -- good (alternative) --
export interface IUiSettingsClient {
Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I prefer explicit interfaces. I'd rather be deliberate about choosing to expose a property or method rather than allowing it to happen without notice (though the api-extractor tooling may make it more obvious).

src/core/CORE_CONVENTIONS.md Outdated Show resolved Hide resolved
rudolf and others added 2 commits January 6, 2020 13:33
@joshdover joshdover self-requested a review January 14, 2020 16:09
@rudolf rudolf merged commit d10d628 into elastic:master Jan 15, 2020
@rudolf rudolf deleted the core-conventions branch January 15, 2020 13:30
jkelastic pushed a commit to jkelastic/kibana that referenced this pull request Jan 17, 2020
* Table of contents for conventions

* Add Core Conventions

* Add Tests and mocks section

* Update src/core/CORE_CONVENTIONS.md

Typo

Co-Authored-By: Josh Dover <me@joshdover.com>

* Add pro's/con's for alternatives to private fields support

Co-authored-by: Josh Dover <me@joshdover.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:New Platform release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants