scala-best practices (02)-code cleanliness

Code cleanliness

We write code for the computer to run, but it is not just the computer that reads the code, but also our comrades (colleagues) and future comrades.
We cannot be a pig teammate, so it is necessary to guarantee a common code specification.

Each line of code needs to have a reasonable length

Avoid having a long code from left to right, when understanding this line of code will occupy our thinking.

In printed products, the most reasonable length is 50-70 characters.

In the programming process, we use indented characters, 60 characters are too short.
80 characters is generally acceptable, but it cannot be used in Scala, because in Scala we use a lot of long and descriptive names of closure functions and classes, 80 characters are too short.

A balanced strategy:

  • We use 80 characters as a benchmark.
  • Generally not more than 100 characters.
  • If possible, switch function calls to one line.
  • It is better not to exceed 120 characters (IDEA prompts 120 characters by default)

Don't rely on SBT or IDE plugins to format code

The IDE will provide formatting plugins, but you must be careful when using them.

The IDE only provides a mandatory rule. It does not understand the developer's intention. The simple part can use automatic formatting. But try to use our own logic to add format.

Be sure not to adjust the code that others have carefully formatted! !

Code case:

    val dp = new DispatchPlan(new Set(filteredAssets), start = startDate, end = endDate, product, scheduleMap, availabilityMap, Set(activationIntervals.get), contractRepository, priceRepository)

In most cases, automatic formatting will have the following results:

    val dp = new DispatchPlan(Set(filteredAssets), start =
      startDate, end = endDate, product, scheduleMap, availabilityMap,
      Set(activationIntervals), contractRepository, priceRepository)

The above readability is not good, we can have the following format:

    val dp = new DispatchPlan(
      Set(filteredAssets),
      startDate,
      endDate,
      product,
      scheduleMap,
      availabilityMap,
      Set(activationIntervals),
      contractRepository,
      priceRepository
    )

The above looks much better, but in fact, for some scenarios, we need to disconnect a line:

   val result = service.something(param1, param2, param3, param4).map(transform)

The following two bad writing methods:

    // transform调用不爽
    val result = service.something(
      param1,
      param2,
      param3,
      param4).map(transform)

    // 打破的逻辑
    val result = service.something(
      param1,
      param2,
      param3,
      param4
    ).map(transform)

The following will be much better:

    val result = service
      .something(param1, param2, param3, param4)
      .map(transform)

It's much better now, isn't it? Of course, sometimes this line is too long, you need to ask for some kind of temporary value:

    val result = {
      val instance =
        object.something(
          myAwesomeParam1,
          otherParam2,
          someSeriousParam3,
          anEvenMoreSoParam4,
          lonelyParam5,
          catchSomeFn6,
          startDate7
        )

      for (x <- instance) yield
        transform(x)
    }
  • Of course, sometimes if the code is very bad, it needs to be refactored, for example, for a function, there are too many parameters.
  • Therefore, we strictly control the length of each line of code and avoid the use of automatic formatting plugins, which will cause many readability problems.

Avoid using long functions

The ideal function should have only a few lines. If the lines are too long, we need to break them down into smaller functions and name them.

Note that in Scala, we do not need to provide such intermediate functions in other scopes, the purpose here is mainly to help readability, so in Scala, we can use internal functions to break the logic into multiple parts.

Avoid typos

Pay more attention to the underline hint! Avoid spelling errors in English, typos in Chinese annotations, etc.

Declare meaningful names

* "There are only two difficult things in computer science: cache invalidation and naming."-Phil Karlton

Here we have three guiding principles:

  • Give a descriptive name, but do n’t go too far, the four words are already a bit too much
  • If the type / use can be easily inferred from the direct context, or a convention has been established, then it can be named succinctly
  • If it's descriptive, don't talk meaningless nonsense

The following example is acceptable: we can directly see from the context that p is a people, so a short letter name is enough.

for (p <- people) yield
  transformed(p)

The following example is acceptable: because "i" is a convention used as an index

for (i <- 0 until limit) yield ???

The following is generally unacceptable, because when using tuples, the naming of the collection does not reflect the content contained (if these elements are not named, then the collection itself will have a bad name):

someCollection.map(_._2)

The following implicit parameters are acceptable for short names, because when implicitly passed, we do not care about them unless they are lost:

def query(id: Long)(implicit ec: ExecutionContext, c: WSClient): Future[Response]

This is unacceptable because the name is completely meaningless, even if there is a clear descriptive attempt:

def processItems(people: Seq[Person]) = ???

This is unacceptable because the naming of this function indicates a side effect ("process" is a verb, meaning a command), but it does not describe what we do to these "people". The "Items" suffix is ​​meaningless, because we might say "processThingy", "processRows", "processStuff", but it will still say the exact same thing-absolutely nothing. It also adds visual confusion, because more words are more text, and meaningless words are just noise

Guess you like

Origin www.cnblogs.com/duchaoqun/p/32993d2e73464f160973a6e005f0a928.html