Summary of the proposed change
Make sure our code style is consistent in parts that are not covered in the Dart code style.
Link to supporting documentation, GitHub tickets, etc.
- Effective Dart is the main source for all code style, documentation, design and usage conventions.
What problem is this project solving?
As Dart has a great code style available that we use on this project we noticed that in some real-world cases there is no guidance, so here we collect all cases that we think important to clarify to make sure that the code style is consistent through the project.
Identify success metrics and measurable goals.
Have a document that can be used in code reviews to clarify code style issues and make sure that code style is consistent.
Identify what's not in scope.
- Other languages we might use (Bash scripts, JavaScript).
-
DO NOT end descriptions with a dot (.)
Good:
test(".fromJson() creates an instance from the json map", () {
Bad:
test('.fromJson() creates an instance from the json map.', () {
-
DO start Test Group descriptions with a Capital letter
Good:
group("DashboardPage", () {
-
DO start with a small letter test descriptions inside Test Groups
Good:
group("DashboardPage", () { test("throws ArgumentError trying to create an instance with null CI client",
-
DO start with a Capital letter test descriptions not inside Test Groups
Good:
testWidgets("Can't create widget without data",
-
DO start test descriptions with a dot (.) followed by a method name with an empty parenthesis (without parameters even if there are any) when a test is specific for a method (or named constructor)
Good:
test(".fromJson() creates an instance from the json map", () {
-
DO use Test Group descriptions with class under test name
Good:
group("ReceiveProjectMetricUpdates", () { ..... test("loads all fields in the performance metrics", () {
-
DO NOT use multiline test descriptions as such tests can't be started in Intellij
Good:
test(".fromJson() creates an instance from the json map", () {
Bad:
test('.fromJson() creates an instance' 'from the json map', () {
-
PREFER using double quotes in test descriptions
Good:
test(".fromJson() creates an instance from the json map", () {
-
DO NOT use "should" in test descriptions
Good:
test(".fromJson() creates an instance from the json map", () {
Bad:
test(".fromJson() should create an instance from the json map.", () {
Additional information:
-
DO NOT document Mock classes
Good:
class SourceClientMock extends Mock implements SourceClient {}
Bad:
/// This class mocks [SourceClient] to help with testing. class SourceClientMock extends Mock implements SourceClient {}
-
DO document Mock static fields
Though it is assumed that Mock classes do not have any fields, sometimes it appears to be very pragmatic to add some static fields to them in order to simplify code and tests structure, follow DRY or KISS, etc. (see Dart Mockito best practices)
Good:
class CoolClassMock extends Mock implements CoolClass { /// The really useful field that allows doing something extra-cool /// in order to prevent something very bad. static const String reallyUsefulField = 'Really Useful Value';
Bad:
class CoolClassMock extends Mock implements CoolClass { static const String reallyUsefulField = 'Really Useful Value';
-
DO NOT document Fake classes
Good:
class SignedInAuthStoreFake extends Fake implements AuthStore {
Bad:
/// Fake implementation of the [AuthStore] ensures that a user is already logged in into the app. class SignedInAuthStoreFake extends Fake implements AuthStore {
-
DO document Fake custom properties
Good:
class SignedInAuthStoreFake extends Fake implements AuthStore { /// Internal stream used to support [AuthStore] functionality. final BehaviorSubject<bool> _isLoggedInSubject = BehaviorSubject();
Bad:
class SignedInAuthStoreFake extends Fake implements AuthStore { final BehaviorSubject<bool> _isLoggedInSubject = BehaviorSubject();
-
DO document Testbeds, Stubs, etc. used in testing
Good:
/// A stub class for a [CiConfig] abstract class providing required /// implementations. class CiIntegrationStub extends CiIntegration {
Bad:
class CiIntegrationStub extends CiIntegration {
-
AVOID document fields of classes providing test data
Good:
/// A class containing a test data for the [JenkinsSourceConfig]. class JenkinsConfigTestData { static const String url = 'url';
Bad:
/// A class containing a test data for the [JenkinsSourceConfig]. class JenkinsConfigTestData { /// Test URL used for Jenkins configuration. static const String url = 'url';
-
PREFER using the
@immutable
annotation for immutable classes.Good:
/// A view model class with the build number metric data. @immutable class BuildNumberScorecardViewModel { /// A number of builds to display. final int numberOfBuilds; /// Creates the [BuildNumberScorecardViewModel] instance with /// the given [numberOfBuilds]. const BuildNumberScorecardViewModel({ this.numberOfBuilds, }); }
Bad:
/// A view model class with the build number metric data. class BuildNumberScorecardViewModel { /// A number of builds to display. final int numberOfBuilds; /// Creates the [BuildNumberScorecardViewModel] instance with /// the given [numberOfBuilds]. const BuildNumberScorecardViewModel({ this.numberOfBuilds, }); }
-
AVOID using the
@immutable
annotation when extending or implementing an immutable classes.Good:
/// A view model that contains the data for the percent displaying widgets. class PercentViewModel extends Equatable {
Bad:
/// A view model that contains the data for the percent displaying widgets. @immutable class PercentViewModel extends Equatable {
-
DO use the
immutable
collections in classes extendingEquatable
.Good:
/// A view model that represents the data of the performance metric to display. class PerformanceSparklineViewModel extends Equatable { /// A list of points representing the performance of the project builds. final UnmodifiableListView<Point<int>> performance;
Bad:
/// A view model that represents the data of the performance metric to display. class PerformanceSparklineViewModel extends Equatable { /// A list of points representing the performance of the project builds. final List<Point<int>> performance;
How will the project be tested?
The team will review the document and provide feedback.
Summarize alternative designs (pros & cons)
- Don't specify code style
- Pros:
- Save creating documentation and maintaining it.
- Cons:
- We'll notice different approaches used and code will be less readable due to the different styles used.
- Potential frustration due to unspecified style approaches.
Document milestones and deadlines.
DONE:
- Initial Unit testing documentation description rules.
NEXT:
- Add more Dart/Flutter style clarifications.
What was the outcome of the project?
Consistent code style used on all Dart codebases.