“This is the 25th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

preface

Dart code naming: Make your Dart code easier to read. This article describes how to design reasonable names, including variable names, function names, and so on. Good code is better than good comments, and good naming can make code easier to understand.

Rule 1: Keep naming consistent

Use the same names for the same things in your code, and you should follow user idioms. A lot of people write variable names and forget how they were named, so they get a new name. For example, an Image object might be called an Image in A file and A picture in B file, which would be confusing. The best way to do this is:

  • For entity objects at the product level, it is recommended that the front and back ends and data tables have the same entity object name.
  • It is recommended that development teams agree on entity object naming conventions for specific objects or components in their respective languages.
  • Don’t invent new nouns! Maybe you can understand it, but that doesn’t mean anyone else can.
  • ** Don’t use pinyin, and don’t abbreviate pinyin! ** When translating Chinese into English, choose words that are easy to understand.

Here are some naming comparisons:

// Correct example
pageCount         // A field representing the number of pages
updatePageCount() // Keep the same as the pageCount name
toSomething()     Iterable (toList()))
asSomething()     // Same as List toMap()
Point             // User usage
  
// Error example
renumberPages()   // The pageCount name is not consistent
convertToSomething()  // Inconsistent with the usual toX()
wrappedAsSomething()  // Not consistent with the usual asX()
Cartesian							// Is not a user idiom
Copy the code

Using familiar terms quickly lets the user know that the domain is involved, and avoids new or unfamiliar terms that add to the difficulty of understanding the code.

Rule 2: Avoid abbreviations

Don’t abbreviate unless it’s a well-known word. Even when using abbreviations, you should follow the customary rules of capitalization.

// Correct example
pageCount
buildRectangles
IOStream
HttpRequest
  
// Error example
numPages    // the num abbreviation is not appropriate
buildRects  // Rects is difficult to Rectangles
InputOutputStream  // Do not use simple abbreviations
HypertextTransferProtocolRequest // Do not use simple abbreviations
Copy the code

Rule 3: Put the noun that most accurately describes something last

When more than one noun is used to describe an object, place the noun that is closest to the object at the end so that it is semantically better to understand what the variable corresponds to.

// Correct example
pageCount             // Number of pages (count)
ConversionSink        // Sink for conversion
ChunkedConversionSink // A chunked Conversation Sink
CssFontFaceRule       // font rules in CSS
  
// Error example
numPages							   // Is not a collection of pages
CanvasRenderingContext2D // Not a 2D object
RuleFontFaceCss					 // 并不是 CSS
Copy the code

Rule 4: Make your code coherent like a statement

When you make your code coherent like a statement, you know what it means when you read it — no comments! In the following example, you can see what you’re doing when you look at the code.

// Correct example
if (errors.isEmpty) ...

subscription.cancel();

monsters.where((monster) => monster.hasClaws);
Copy the code

The next one is a little bit harder to understand.

// Check whether errors are empty.
if (errors.empty) ...

// Reverse what? What is the state after the reversal?
subscription.toggle();

// Does the filter include or exclude those that meet the criteria?
monsters.filter((monster) => monster.hasClaws);
Copy the code

But instead of forcing a sentence just to make it up, use simple phrases so that the reader can quickly and clearly understand what the code means. The following example is a bit excessive.

// Error example
if (theCollectionOfErrors.isEmpty) ...

monsters.producesANewSequenceWhereEach((monster) => monster.hasClaws);
Copy the code

Rule 5: Use nouns for attributes or variables that are not Boolean types

Because is an attribute, it would be an object if not a Boolean, using a noun makes it clearer to name what the attribute or variable corresponds to. At the same time, if you refer to things after operation, you should use the perfect tense of an adjective or verb (to indicate that it has been completed), rather than directly using a verb + noun, which will be mistaken for the action of operating an object.

// Correct example
list.length
context.lineWidth
quest.rampagingSwampBeast
sortedList
  
// Error example
list.deleteItems
sortList
Copy the code

Rule 6: For Boolean attributes that represent a class of operations that can be performed, use an energetic verb in preference

We often use Booleans to indicate what an object can do, whether it can be updated, whether it can be closed. It is recommended to use energetic verbs, which are more semantic. However, the meaning of the converted adjectives is not clear, and some words are not so intuitive.

// Correct example
if (widget.canUpdate) ...
if (window.canClose) ...
if (container.hasElements) ...
if (request.shouldResume) ...

// Error example
if (widget.updatable) ...
if (window.closeable) ...
if (container.withElements) ...
if (request.resumable) ...
Copy the code

Rule 7: Do not use verbs for Boolean arguments

For Boolean function arguments, it is easier to read adjectives instead of verbs.

// Correct example
Isolate.spawn(entryPoint, message, paused: false);
var copy = List.from(elements, growable: true);
var regExp = RegExp(pattern, caseSensitive: false);
Copy the code

Rule 8: For Boolean attributes and variables, use positive names

This is a little abstract, but you can see it in an example. When you use the reverse attribute name, assigning a Boolean value can be confusing. Such asisNotEmpty = true“You have to think about it for 1-2 seconds to understand what it means. In fact, when writing conditional expressions using reverse Booleans, it’s easy to get bugs in your brain!

// Correct example
bool isEmpty;

// Error example
bool isNotEmpty;
Copy the code

Of course, in some cases, the application will often use the reverse value directly, and then using the positive name will be counterproductive because you will need to reverse it again. Compare that to the ubiquitous fetch operator! It’s better to just use the negative name. For example, we need to intercept minors to be able to use a feature.

// Error example
bool isAdult;
if (! isAdult) {
  return 'Not Allowed for Non Adults'.}// Correct example
bool isNotAdult;
if (isNotAdult) {
  return 'Not Allowed for Non Adults'.}Copy the code

Rule 10: Use imperative verbs to name functions or methods that have other effects

When we use an imperative verb to describe a function, we clearly know that the function is to do something, sort of like a command. If the object is specified, the name or descriptor of the object may be added.

// Correct example
list.add('element');
queue.removeFirst();
controller.forward();
refreshController.loadMore();
Copy the code

Rule 11: Use nouns or non-imperative verbs in preference to functions whose primary purpose is to return a value

Such functions usually do little, but their main purpose is to return a value. If there are no arguments, it is usually a getter operation. But sometimes you need to pass a parameter, such as array subscript, data filtering criteria, etc. It’s better to use a noun or an adverb, while adding a verb feels redundant (usually get, find, etc.).

// Correct example
var element = list.elementAt(3);
var first = list.firstWhere(test);
var char = string.codeUnitAt(4);
Copy the code

Rule 12: Do not start method names with get

In most cases, get should be removed. For example, instead of using getBreakfastOrder, specify a getter property called breakfastOrder. If you do need a method to get an object, you should also avoid using get. Here are two tips:

  • If the caller is more concerned with the return value, you can simply drop get and use the noun as the method noun, for examplebreakfastOrder()Or use rule 11.
  • If the call cares about what the method does, it can use more precise descriptive verbs, such as create, Download, fetch, calculate, request, and so on.

Rule 13: Use the toX() form if the method is to copy an object into another representation

This may be a little hard to distinguish from rule 14 below, but what it means is that the operation transforms the object into a new representation of the object. The toJson, toString, toSet, toLocal forms are common. Most of this is irreversible.

Rule 14: If you return a different representation of the original object, use the asX() form

AsX is just like converting objects, we have the following code:

if ((object as String) = ='a') {... }Copy the code

The asX form is similar. The transformed object can also reflect the characteristics of the original object, that is, it can be converted back through certain means. For example:

var map = table.asMap();
var list = bytes.asFloat32List();
var future = subscription.asFuture();
Copy the code

Rule 15: Do not duplicate parameter names on method names

Parameter names can be read in conjunction with the method verb, so adding parameter names is a bit redundant.

// Correct example
list.add(element);
map.remove(key);

// Error example
list.addElement(element)
map.removeKey(key)
Copy the code

This is not absolute, for example, if adding arguments eliminates the meaning of different functions of the same class, as in the following example.

// Correct example
map.containsKey(key);
map.containsValue(value);
Copy the code

Rule 16: For generics, follow the common mnemonics

In general, we use the following mnemonics to represent different generic parameters in generics. This rule is needed to help us understand generics.

  • E: represents the generic parameter of the collection class, for example:
class IterableBase<E> {}
class List<E> {}
class HashSet<E> {}
class RedBlackTree<E> {}
Copy the code
  • K and V represent key and value generic parameters, such as:
class Map<K.V> {}
class Multimap<K.V> {}
class MapEntry<K.V> {}
Copy the code
  • R represents the return value generic parameter, for example:
abstract class ExpressionVisitor<R> {
  R visitBinary(BinaryExpression node);
  R visitLiteral(LiteralExpression node);
  R visitUnary(UnaryExpression node);
}
Copy the code
  • In other cases, it is common to use T, S, and U to identify generics. In practice, it is possible to use words (uppercase) as generic parameters if it is helpful. The following three examples are all fine.
class Future<T> {
  Future<S> then<S>(FutureOr<S> onValue(T value)) => ...
}

class Graph<N.E> {
  final List<N> nodes = [];
  final List<E> edges = [];
}

class Graph<Node.Edge> {
  final List<Node> nodes = [];
  final List<Edge> edges = [];
}
Copy the code

conclusion

We often struggle with comments and feel that they are a bit of a waste of time. In fact, if you name your code properly, you can save a lot of time writing comments. What really needs to be written is more documentation, which helps us and the team to sort out and develop business processes and logic. Therefore, the higher level of coding is to use good coding naming conventions and styles to understand functionality through code, to write fewer comments, and to make time to write documentation.

I am dao Code Farmer with the same name as my wechat official account. This is a column about the introduction and practice of Flutter, providing systematic learning articles about Flutter. See the corresponding source code here: The source code of Flutter Introduction and Practical column. If you have any questions, please add me to the wechat account: island-coder.

👍🏻 : feel the harvest please point a praise to encourage!

🌟 : Collect articles, easy to look back!

💬 : Comment exchange, mutual progress!