Characteristics of high quality code
Many code-cleaning programmers regard code readability as a sacrosanct truth, the most important characteristic of high-quality code, and have been put on the "altar". Unbeknownst to me, Uncle Bob's first chapter of Clean Code gives a name to what he calls "Clean Code" through the mouth of others: it's not just about being "clear".
According to Kent Beck's simple design rules, it's not really readability that comes first, it's "pass all tests". The latent meaning of this is to meet the right needs of the user, as the test can be seen as the user asking for it. This requirement is not just business, but also includes requirements for quality attributes, such as performance, security, and other attributes.
Elimination of duplication harmony Improving expressivenessThese two points, Sometimes they reinforce each other., Removal of redundant code, It will make the code much clearer; nevertheless, And sometimes they conflict with each other., Elimination of duplication The cost may be higher for, Resulting in the extraction of too many fine and tiny entities, Instead, it adds to the dyslexia。
That's why I often refer to Uncle Bob's "The first rule of functions is to keep them short. The second rule is to also be shorter. "Look at it as an overkill compulsion. For the kind of programmer who likes to write big functions, this principle does need to be kept in mind at all times, but remember not to consider it as a supreme guideline. There are prerequisites for ensuring that functions are short; read Kent Beck's simple design principles carefully, in order of importance.
Ability to pass all tests.
No duplicate codes.
Reflect the intent of the designer.
Do not add entities (methods, functions, classes, etc.) if they are not necessary.
If the program satisfies the customer's needs, there is no duplicate code, and the expression of the function is clear enough to reflect the designer's intent, why keep extracting functions and making them extremely short? The principle that really makes sense is " Let the function do only one thing”。
Because of this, the second refactoring of HtmlUtil.java in FitNesse, shown by Uncle Bob in the Clean Code book, is not necessary. After the first refactoring, the code looks like this.
public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception { boolean isTestPage = pageData.hasAttribute("Test"); if (isTestPage) { WikiPage testPage = pageData.getWikiPage(); StringBuffer newPageContent = new StringBuffer(); includeSetupPages(testPage, newPageContent, isSuite); newPageContent.append(pageData.getContent()); includeTeardownPages(testPage, newPageContent, isSuite); pageData.setContent(newPageContent.toString()); } return pageData.getHtml();}
The structure and hierarchy of this code is already very clear and does a reasonable enough job of encapsulating and hiding the implementation details. To say that it is inadequate, perhaps the following code could be made to do another method extraction so that it satisfies the SLAP principle (Single Level of Abstraction Principle).
newPageContent.append(pageData.getContent()); // extract as: includeTestContents(testPage, newPageContent)
And what exactly does the second refactoring done by Uncle Bob bring to the clarity of the code, other than making the methods shorter and hiding too much detail thus introducing more layers?
public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData)) includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml(); }
Too much is too little!
Sometimes, in order to remove repetition, it is necessary to find a pattern or some kind of abstraction from similar code, which in turn can be extracted. Excessive extraction can make the code hard to read, because the means of extraction often introduces "indirection". As Martin Fowler puts it, "Indirectness may be helpful, but non-essential indirectness is always uncomfortable." Unnecessary indirection often gets in the way of straightforward code harmony neat and tidy。If the only benefit of removing duplicates is to avoid a few private duplicates in a class, removing such duplicates really doesn't mean much.
I like clear code, but I think it's just as important to keep it correct and robust as it is efficient.
Because of code cleanliness, I used to see a lot of non-null judgments, illegal checks, and exception handling as a flood of interference with clear code, but if you don't do the "dirty work", the code can become unhealthy. In Java, if you really want to avoid these judgments, you can consider shifting responsibilities to the method caller by defining Checked Exception. However, the blind transfer of responsibilities is always irresponsible. Programmers implementing each method and each class should ensure that their code is self-governance The.
The following code.
@Override public void run() { if (isFromFile) { if (hasQuery) { throw new RuntimeException("both --execute and --file specified"); } try { query = Files.toString(new File(clientOptions.file), UTF_8); hasQuery = true; } catch (IOException e) { throw new RuntimeException(format("Error reading from file %s: %s", clientOptions.file, e.getMessage())); } } }
It's true that such code is not elegant, however enough judgement is made to ensure that the code is correct and robust. All I can say is that with those two points met, one can intelligently use things like defensive programming, Optional to circumvent redundant nesting or branching and thus improve the readability of the code.
Effective Java summarizes several characteristics of high-quality code. clearer、 properly、 available、 sturdy、 flexibly harmony maintainable . I think this summary is very pertinent. It's really important not to be too paranoid about writing code, and a fixation on code readability (clarity) regardless of any scenario, and a reiteration of DRY, are both irresponsible attitudes in my opinion.
Maybe it's because I'm getting old and I've become less idealistic; but more because I've seen too many programs that pursue so-called "neat code" and don't want to consider complex and tedious exotic cases that lead to unhealthy programs; because removing repetition unnecessarily indirectly affects the simplicity and cleanliness of the code, and even the performance of the code.
Neat code is a must, but not the only measure of code quality!