preface

What is a comment?

In programming languages, comments are explanations and descriptions of code that are intended to make it easier for people to understand the code.

Programmers hate two things: 1. People don’t write comments. 2. Write your own comments

More than once in the developer community, I’ve seen examples of people making fun of their ex-colleagues for not writing comments. It’s not just other people’s code, it’s even your own code, and when you look at it after a while, you’ll see: What was that about?

As developers, most of us know the importance of writing comments, but they often hold “can achieve the function is ok” this attitude to write code, completely follow one’s inclinations to be realized, the result is, of course, leave a pile of mess, form a vicious cycle of mentioned above, so at the time of writing code, please keep in mind that the code is written for people in the first place.

It only takes a few seconds to write concise, accurate comments, but it may save someone hours later trying to understand your code.

Write a comment

Is it easy to write comments? Simple. So is it easy to write comments?

The answers are just like writing articles, some articles are to keep a running list, others are thought-provoking and memorable.

The same is true for comments. In The Path to Better Code, we summarize three principles for writing comments:

  1. Accurate, incorrect comments are worse than no comments at all.
  2. Unnecessary comments waste the reader’s time.
  3. Clear, cluttered comments make your code even messier.

For example, never omit the word “programming” when talking about programming languages. Otherwise, it may be misinterpreted as natural language in everyday speech. That’s the requirement for accuracy.

bad:

String language = "Java"; // the language
Copy the code

better:

String language = "Java"; // the programming language
Copy the code

Comments that repeat code semantics are redundant if the code already expresses its semantics and logic clearly and simply. Annotation maintenance is time consuming and energy consuming, so don’t keep unnecessary comments. Code tells you How, Comments tell you Why.

bad:

// the programming language
String programmingLanguage = "Java";
Copy the code

better:

String programmingLanguage = "Java";
Copy the code

If comments and code are not visually distinct, comments destroy the readability of the code.

bad:

/* dump debug information if (hasDebug) { System.out.println("Programming language: Jave"); } * /
String programmingLanguage = "Java";
Copy the code

better:

// dump debug information
//
// if (hasDebug) {
// System.out.println("Programming language: Jave");
// }
String programmingLanguage = "Java";
Copy the code

Effective Dart also recommends clarity and accuracy in how to write comments, as well as brevity.

When writing a Flutter application using Dart, the view layer is pure Dart code with a lot of if.. else.. , different widgets need to be displayed based on conditions, so it is imperative to write good annotations while doing a good job of separating widgets.

Effective Dart documentation comments

In the process of learning and using the Flutter framework to develop apps, some developers do not pay much attention to the Dart language and start their Flutter journey after a cursory glance at the syntax. They still follow the previous syntax style of Java and Swift, which may cause unnecessary trouble in the future. For example, team members have different names, different comments, and so on.

Therefore, it is recommended that you first take a look at Effective Dart, which contains code style, documentation, best practices, and design guidelines. We are mainly concerned with the chapter of document comments. Here I summarize the following two points:

  1. use///To give up/ * *... * /

The reason is explained in Effective Dart

For historical reasons, dartdoc supports document comments in two formats: /// (” C# format “) and /**… */ (” JavaDoc format “). We recommend /// because it is more concise. /** and */ add two extra lines at the beginning and end of the multi-line comment. It is also easier to read in some cases, such as when a comment document contains list content marked with *.

If you are still using the JavaDoc style format, consider using a new one.

In the meantime, use /// document comments to annotate members and types.

Bad:

// The number of characters in this chunk when unsplit.
int get length => ...
Copy the code

better:

/// The number of characters in this chunk when unsplit.
int get length => ..
Copy the code

// is mainly used for annotation inside a method

greet(name) {
  // Assume we have a valid name.
  print('Hi, $name! ');
}
Copy the code
  1. Define the first statement as a paragraph and describe it in prose

The first paragraph in the comments document should be a succinct, user-oriented comment. The example below, for example, is usually not a complete statement.

bad:

/// Starts a new block as a child of the current chunk. Nested blocks are
/// handled using their own independent [LineWriter].
ChunkBuilder startBlock() { ... }
Copy the code

Better:

/// Defines a flag.
///
/// Throws an [ArgumentError] if there is already an option named [name] or
/// there is already an option using abbreviation [abbr]. Returns the new flag.
Flag addFlag(String name, String abbr) { ... }
Copy the code

This is just like writing a blog. You will write a general paragraph and then describe it in detail. This will make it easier for the reader to understand the main idea and save time.

It is also recommended to use prose to describe parameters, return values, and exception information.

Other languages, such as JavaDoc, use various tags and additional comments to describe parameters and return values.

bad:

/// Defines a flag with the given name and abbreviation.
///
/// @param name The name of the flag.
/// @param abbr The abbreviation for the flag.
/// @returns The new flag.
/// @throws ArgumentError If there is already an option with
///     the given name or abbreviation.
Flag addFlag(String name, String abbr) { ... }
Copy the code

Dart puts descriptions of parameters, return values, and so on in a document comment and uses square brackets to refer to and highlight the parameters and return values.

better:

/// Defines a flag.
///
/// Throws an [ArgumentError] if there is already an option named [name] or
/// there is already an option using abbreviation [abbr]. Returns the new flag.
Flag addFlag(String name, String abbr) { ... }
Copy the code

We focus on these two points, but see documentation notes for other specifications.

Practice in THE MVVM_FLUTTER project

Mvvm_flutter is an example of how I apply the MVVM architecture to Flutter.

Mvvm_flutter: github.com/ditclear/mv…

After the project is complete, we simply add a few JavaDoc comments on a few key methods, such as:

 /** * callthemodel layer 's method to login * doOnData : handle response when success * doOnError : Handle error when failure * doOnListen: show loading when listen start * doOnDone: hide loading when complete */
  Observable login() => _repo
      .login(username, password)
      .doOnData((r) => response = r.toString())
      .doOnError((e, stacktrace) {
        if (e is DioError) {
          response = e.response.data.toString();
        }
      })
      .doOnListen(() => loading = true)
      .doOnDone(() => loading = false);
Copy the code

Now let’s start converting it to the annotation style recommended by the Dart language. As follows:

  / / / login
  ///
  /// call the model layer [GithubRepo] login method to login
  // pass [username] and [password]
  /// Success: the returned information is displayed
  /// Failed: an error message is displayed
  /// Subscribe to start: loading = true
  /// Subscribe to end: loading = false
  /// returns [Observable] to the View layer
  Observable login() => _repo
      .login(username, password)
      .doOnData((r) => response = r.toString())
      .doOnError((e, stacktrace) {
        if (e is DioError) {
          response = e.response.data.toString();
        }
      })
      .doOnListen(() => loading = true)
      .doOnDone(() => loading = false);
Copy the code

Much cleaner than the previous code, we describe the method’s functionality in the first line of the comment, followed by a prose description of the method’s call, parameters, and return values.

This is the annotation for the ViewModel layer, so let’s do the annotation for the Model layer.

class GithubRepo {
    / / /...
  Observable login(String username, String password) {
    _sp.putString(KEY_TOKEN, "basic " + base64Encode(utf8.encode('$username:$password')));
    return_remote.login(); }}Copy the code

We annotate the login method as follows:

/ / / warehouse floor
class GithubRepo {
	
  / / / login
  ///
  // Process [username] and [password] as tokens and cache them with [_sp]
  /// Call the [login] method of [_remote] for network access
  /// returns [Observable] to the ViewModel layer
  Observable login(String username, String password) {
    _sp.putString(KEY_TOKEN, "basic " + base64Encode(utf8.encode('$username:$password')));
    return_remote.login(); }}Copy the code

The method here is simple, but for complex warehare-level methods, which may involve network, database, MethodChannel, SharedPreferences, and so on, Dart recommends annotations to better describe your code logic.

  /// get the article details
  ///
  /// 1. Run the [_local] database to check whether the articleId is [articleId]
  If there is cache, go to step 4; if there is no cache, go to step 3
  /// 3. Obtain the server data through [_remote] at the network layer and cache the server data. Go to Step 4
  /// 4. Return Observable to the ViewModel layer
  Observable getArticleDetail(int articleId) {
    return _local
        .getArticleById(articleId)
        .onErrorResumeNext(
        _remote.getArticleById(articleId)
            .doOnData((article) => _local.insertArticle(article)));
  }
Copy the code

In this way, we can easily disassemble the code logic, but also easier to write the corresponding test cases, convenient for unit testing.

Compared with the Model layer and the ViewModel layer, the View layer needs to pay extra attention to the fact that it is mixed with logical judgment and needs to display different widgets according to the conditions. When we extract the complex parts into methods, we also need to describe them in detail.

/// The widget inside the login button
///
/ / / when requests [value. Loading] is true, according to [CircularProgressIndicator]
Otherwise, normal login text is displayed
Widget buildLoginChild(HomeProvide value) {
  if (value.loading) {
    return const CircularProgressIndicator();
  } else {
    return const FittedBox(
      fit: BoxFit.scaleDown,
      child: const Text(
        'Login With Github Account',
        maxLines: 1,
        textAlign: TextAlign.center,
        overflow: TextOverflow.fade,
        style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0, color: Colors.white), ), ); }}Copy the code

With this improvement, you can also save yourself a lot of unnecessary annoyance when other developers read your code.

Write in the last

When you annotate a document using the Effective Dart annotation technique, you feel like you’re blogging because one of the benefits of blogging is memorization, which allows you to quickly understand things when you review them later, as well as comments.

I think even the best developers, if they don’t write comments for a long time, will forget, and have been lucky enough to see a Java file containing 30,000 + lines of code with no comments, and to this day no one wants to take on such a project, we are all programmers, so why should programmers bother programmers?

References:

Code Complete- Self-explanatory Code

The path to code refinement – Writing good comments is really a piece of cake?

Effective Dart – Documentation comments

==================== split line ======================

If you want to learn more about MVVM, Flutter, and responsive programming, please follow me.

You can find me at:

Jane: www.jianshu.com/u/117f1cf0c…

The Denver nuggets: juejin. Cn/user / 817692…

Github: github.com/ditclear