In the technical community, it’s common to see blogs touting the various advanced features and advanced modes of programming languages and presenting elegant code that uses these features. So are learning and using these things good or bad, and what are the pros and cons? This article is intended to help you make your own judgments.

The cleverness and wisdom of skill

There are many people who are proud of the unpopular characteristics of using languages and frameworks. They use various obscure APIS to show their familiarity with frameworks, and then think that their programming ability and technical level are higher than those who write simple logic. Is this a reasonable view? Let’s use a few examples to make a corollary:

First of all, when recruiting and developing students, there is a very interesting phenomenon, that is, the more high-level candidates, the less the specific coding skills are examined, and the more the architectural ability, business understanding, engineering quality is examined. Please note that the understanding of architecture, business and engineering is not the soft qualities of general communication and management, but the solid professional skills of being an engineer.

On the other hand, some of the hottest things in the tech community are getting started with frameworks and libraries. From a variety of explosive [XXX from entry to mastery] to [hand to hand to teach you to learn XXX], the most popular content is still these API how to tune, how to set a class of technical knowledge.

Combining these phenomena and some common sense, we can obtain the following three conditions:

  • The more advanced the programmer, the smaller the proportion of technical knowledge in the ability tree.
  • The proportion of senior programmers is much smaller than that of junior programmers.
  • Most of the programmer community happens to focus on technical knowledge.

Based on these conditions, we can make a loose corollary: the people who are most interested in and obsessed with programming skills are probably the majority of entry-level programmers. ** In this way, showing off skills does not indicate a high level of skill.

To be clear, we’re not saying that programming skills aren’t important. In contrast, advanced programmers are far more familiar with techniques than their junior peers, and many of the more skillful code can optimize and solve problems at an order of magnitude. So how do we evaluate code like this?

Students who can use a variety of advanced characteristics are undoubtedly smart. But where to use it and how to use it requires the so-called wisdom of judgment. It’s like the Facebook and Google code specifications often say:

Use your best judgement.

It sounds nice, but it’s actually a very metaphysical concept. Below we’ll go into a more specific discussion and isolate some of the common gimmicks.

Common tricks of the trade

All happy families are like one another; each unhappy family is unhappy in its own way.

— Leo Tolstoy

Good code is all alike, and bad code is bad in its own way.

If we judge a piece of code by its quirks, the quality of the code is probably not much better. For code that uses a variety of techniques, we can also find a number of scenarios where the technique is badly used to point out the problems with each.

Using dangerous semantics

Many people read advanced Programming and show off their understanding of advanced features and apply them to real projects. Within the front-end category, these behaviors include but are not limited to:

  • Learn to= == = =In different occasions, different symbols are used to realize judgment logic.
  • Learn toVariable ascensionUse it to implement a particular code execution sequence.
  • Learn toprototypeconstructorFinally, they are used to realize various inheritance relationships.
  • Learn tothisUse special rules to bind the context after the various pointing rules.

Code that uses these features will certainly work, but the problem here is that the semantics are dangerous, or the language is a design problem. Why would ** use them to show their skill level when they know they are difficult to use and there are already mature alternatives? ** in the front-end community, this kind of behavior comes and goes. For example, just understanding the various this pointing rules would be enough to write a long article (which would already be nikkei boring in many tech communities). And == this kind of unspeakable characteristics, even a lot of people read the blog [in-depth grasp] to [reasonable use]. As for a completely counterintuitive design flaw like variable promotion, some people make up fancy interview questions.

Of course, there is nothing against understanding how these so-called “advanced features” work and why they lead to confusing behavior. It is important for every reliable student who wants to grow to learn them. The advice here is:

  1. Learn them at least once, to the point where you can point out what’s wrong with them.
  2. Learn the alternatives to these features and know how to avoid potholes.
  3. Never use them in your code unless you maintain the underlying base library.

Every programming language, in its own development process are unavoidably left behind problems. This problem is especially serious for JS, a language that was born over a weekend and requires very high forward compatibility. But as software engineering has evolved, the dangerous semantics of these design flaws have faded into history, and learning, mastering, and using them in depth is now as obsolete as delving into IE6 compatibility issues. If someone is giving you a hard time with these questions, you can say something like:

Yes, I know there are four ways to bind this, and I know there are four ways to write back.

Apply design patterns

In general, there are some “patterns” to be found in programs, if taken literally. Because you can always use previous experience to build new programs. You could call this experience a “pattern.” But since the publication in 1994 of a book called Design Patterns (commonly known as GoF, “The Gang of Four”), the term has taken on a new, distorted meaning. It becomes a dogma that leads to serious complexity and inefficiency in the organization.

— Deciphering design Patterns

Design patterns are also a very popular topic for technical articles. For example, there are quite a few articles will “design patterns” in more than a dozen patterns are moved to JS, with various advanced features 】 【 mentioned above to simulate this, realizing that, finally sublimation sentence said these patterns are 【 】 a good programmer must have, in this resume and add a line to master all kinds of design patterns can pretend bility 】 full!

Design patterns were created to complement static languages like Java. Many [classic] design patterns have long been part of the mechanics of programming languages. For example, export has built-in support for singleton patterns, wrapping content in a layer of function is a factory pattern, yield implements iterator patterns, and so on. For example, the dynamic nature of JS makes JSON much more flexible than reflection, and the design of first-class citizens of functions makes JS callback functions much more flexible than Java callback interfaces or Visitor patterns.

The pernicious nature of many articles advocating design patterns is not that they create unnecessary complexity, but that they create the illusion that you can’t do it without using patterns. At least in the good open source projects I’ve read, I don’t find any rote patterns, but rather a clear description of the problem the code is trying to solve, followed by an easy-to-read abstraction. You can certainly conclude with hindsight that they implement certain patterns, but I prefer to believe that the authors didn’t write the code in a [here to use] way of thinking. However, for many novice students who lack the ability to discriminate, without the experience of reading high-quality code, the old code of the company’s historical projects can also be influenced by the path of the pattern. Privately, I thought it was a pity.

Shrink lines of code

We all know that copy-pasting resulting in long, repetitive code is bad. However, copy-and-paste mostly happens when the schedule is too tight to optimize. Given the intensity of Chinese students’ work, this is understandable. At the other end of the spectrum, however, is the overcorrection of simplifying code in all sorts of bizarre ways to achieve minimalism.

For example, just the beginning of functional programming students, may have a preference for a(B (C (D, E (f, g)))) such code, think that through deep nested functions, can greatly reduce the intermediate variables, thus saving the amount of code; Again, for example, some of my classmates like to connect all kinds of judgment logic to use logical operators, high-altitude string into a | | b & c & d such judgment logic written in one line; Also, for utility functions, it is common to write more and more arguments, and then [pass all arguments in one line at a time].

Is this code really more readable? Deeply nested function calls bring a lot of close parentheses in the form of)))))), which has long been deprecated in Lisp; Single-line judgment logic is bad for debugging; The behavior of functions that pass in a large number of parameters tends to be complex and difficult to debug (think of all the tricks you can do with just F (x, y) on the gaokao, and how complex permutations and combinations of f(a, B, C, D, e) variables can be).

These coding practices are easily and painlessly replaced with more readable forms, and it’s not a big deal. However, deliberately creating such code will somewhat embarrass the maintainers behind it. For specific line breaking and indentation practices, a tool such as JavaScript Standard Style can handle most situations automatically.

Implicit rewriting common sense

Explicit is better than implicit.

— The Zen of Python

Modern engineering frameworks typically provide a number of custom interfaces through which developers can easily rewrite the behavior of the framework. React, for example, opens up context, and libraries like Redux and MobX take advantage of this interface, greatly optimizing the experience of deep-passing for props. However, there are a number of implicit conventions about frameworks that can be quite confusing when they are unreasonably customized in common business code. This kind of rewriting often happens in small places, but the impact is often large.

For example, in one project we maintained, there was an effort to rewrite the React.Component base class and replace it with its own xxx.basecomponent. The customized component has no changes related to the business logic, but rather some inexplicable initialization code. This invalidates the implicit common sense of the React component base class. When it comes to maintenance, replaced components may not look special at first, but can cause problems when replaced back. Moreover, there are no comments or documentation on the hack code, and it is not clear what problem it was originally added to solve. There is no more reasonable evaluation of such coding practices than smart-aleck.

Another clever practice in this project, for example, is to replace window.fetch with three or four different custom versions of the requested path (rest assured, it won’t tell you why!). . Isn’t it amazing that when a maintainer writes a new FETCH, he can’t use any pre-existing knowledge implicit in the fetch, but must trace it back to previous custom versions to debug it?

There are also implicit practices where the problem is [side effects]. For example, if you read user = getUser(id), you wouldn’t want the getUser function to not only query the user for you, but also silently pop up a prompt, send a request, and erase the current data. Of course, part of the complexity of the front end itself is managing a lot of UI, networking, and other side effects. However, if calling a function has many consequences, many maintainers may choose not to override it, adding further complexity.

Of course, there are many vendors who would love code with implicit side effects. For example, implicitly mount the whole family bucket 360.

Reinvent the wheel

Collections like The Most Commonly used Front-end utility functions are often seen in the tech community, and they tend to have high likes. However, 500 in one small Overlord game card, really more fun than Super Mary?

The authors have been able to read some of these articles and have noticed that these functions are often packaged without even a fixed topic: getCookie on the left, deepClone on the right, isEmail on the previous, scrollTop on the next. Each of these implementations, however, has just a few lines of annotations, no test cases, dependency configuration, or documentation, and is called small and beautiful.

Is this code worth copying into your project for reuse? To put it bluntly, they are simply the product of satisfying the “I can build wheels” sex drive. I certainly have full faith in the author’s ability to churn out an elegant deep copy, but a project is not an interview, and a stable, reliable wheel requires a lot more than a simple implementation that has nothing to do with code. According to the myth of the Man-month, only 1/6 of a software project’s actual coding time is spent, and the rest of the time is spent testing, documenting, and communicating. For higher-quality library code, is it really useful to write code by hand or copy and paste it from the web (no, inline, to put it nicely)?

When using a class library in a formal project, stable existing dependencies are the obvious first choice if they meet the requirements. If you’re going to have to build your own wheels, go out of your way to do five-sixths of a solid project outside of the code, and don’t reinvent a poor wheel.

Pursue higher-order abstractions

This last point is probably a bit of a niche, because it’s obviously against the grain for many people who can just copy and paste their requirements. But, for that reason, it is a more advanced form of trickery.

High Order sounds like the holy Grail of purity. Higher-order functions and higher-order components seem to be a perfect match for higher-order programmers. But what if you needed to maintain higher-order functions like this?

() = >() = > () = > () = > 123
Copy the code

A function that returns a function of a function of a function of a function of a function of 123, high order indeed, but really doesn’t confuse you…

conclusion

Some of you who have endured all the way to this point may have joked that these skills are important in complex, advanced and blahblah scenarios, so a few clarification points at the end:

  1. Most of the techniques that affect maintainability are not only not needed in the day-to-day writing of business logic, but should be avoided as much as possible. Especially when it comes to motivations like “here’s the API you learned yesterday”, think twice.
  2. In a serious, large open source project, there are inevitably a number of tricky hacks. At this point, you’ll probably find a lot of comments that tell you why you’re doing it, which is a good lesson to learn.
  3. This is not an objection to mastering advanced programming skills, but rather a hope that some “smart-alecky” code will not be carelessly introduced into the formal project, which will cause inconvenience later maintenance.
  4. If you want to get rid of the baggage of a business project and learn how to properly use your ingenuity, getting involved in an open source project might be a shortcut. Hopefully, this article’s zero-point guide to contributing to the open source community will help.

Finally, there are some simple toy wheels in the author’s personal Github, please feel free to make fun of them… 😅