干净的代码——一种实用的方法
Posted 禅与计算机程序设计艺术
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干净的代码——一种实用的方法相关的知识,希望对你有一定的参考价值。
在对干净代码进行了一些讨论之后,我决定在一篇文章中总结最重要的事情。因为网上有很多关于清洁代码的帖子和信息,我认为一篇新的文章谈论它只是解释一些原则是不值得的。
在本文中,我将尝试为您提供清洁代码的实用方法。我不会深入理论,我想展示我是如何编写 Clean Code的。
什么是清洁代码,我们为什么要关心?
起源和定义
必须谈论罗伯特·C·马丁(Robert C. Martin)在 2008 年写的同名书。但是在本书第一次发布之前,有更多的书籍和经验丰富的开发人员讨论了类似的概念。
我已经建立了一种清洁代码的定义,加入了几位作者和来源的意见,我得到的是清洁代码具有以下特征:
它很重要,至少与性能、涵盖功能、避免错误等其他概念一样重要……
任何开发人员都很容易阅读。
任何开发人员都可以轻松修改.
它是由关心它的人写的。
它做了预期的事情。代码不会骗你,没有惊喜。
为什么要编写干净的代码
我真的相信编写干净的代码很重要,因为它是涵盖任何架构的主要目标的第一步:最大限度地减少创建和维护所需系统所需的人力。
当我们编码时,我们习惯于花更多时间(更多时间)阅读代码而不是编写代码。我们阅读了遗留代码、库代码、您的团队成员代码、您几个月前编写的代码(您不记得了)、离开公司的人编写的代码、Stack Overflow 中的代码……Robert Martin 对此给出了一些数字:
“事实上,阅读与写作的时间比例远远超过 10 比 1”——Robert C. Martin,Clean Code
考虑到这一点,不值得付出一点额外的写作努力吗?您花费在清理代码上的额外时间将获得数倍的回报。下次你要提交一段代码时考虑一下。
关于我们为什么要关心我们的代码的最后一个想法是,作为开发人员,我们编写的代码不仅仅是为了由机器解释。我们编写供人类阅读的代码。假设我们是作家,就像记者在报纸上写作或作家创作小说一样。
一些原则
关于什么是干净的什么不是干净的,有很多原则和想法。你可以在书中找到它们,也可以在网上找到它们。但是因为我需要一些基本的原则来玩一些东西,所以我将介绍其中的一些。如果您已经了解它们,您可以跳到下一部分,如果不是,我认为它们将使您了解其余理论的风格,也许还有了解更多信息的动机。
那么,让我们看看代码的一些原则。
命名(Naming):
当我们编码时,我们到处都在决定名称:变量、函数、类、包、文件……认真对待它是拥有干净代码的第一步。
获得干净名称的一些提示:
使用意图暴露的名称:
关于选择好名字还有许多其他技巧。可能使用暴露意图的名称是最重要的,但真正重要的是认真对待命名。
花点时间选择好名字。如果您认为更改后代码将更具可读性,请不要害怕更改现有名称。
函数(Function)
在所有关于干净函数的想法中,我将在这篇文章中强调三个。
1、第一条规则是基本且容易记住的:函数应该做一件事,它们应该做好并且应该只做。此处无需过多解释:避免副作用,如果您注意到它们同时在做几件事,请拆分您的函数。
2、函数要小而美。好的,但是它们应该有多短?如何测量它?让我们强制我们的函数有不超过 2 级的缩进。如果这对您来说很难,您可以开始设置更高的限制(例如 3 个级别),但请限制您允许的缩进级别。
3、关于参数......函数的参数越少,它就越干净。为什么?争论需要大量的上下文知识。在每次调用中,读者必须有上下文来理解每个参数。更多论点→更多您需要了解的上下文。从测试的角度来看,争论也很难。更多参数,更多测试用例,以确保所有参数组合正常工作。
注释
当我在 90 年代学习编码时,我的老师曾经要求我到处写评论。通常听到他们说“如果你不评论你的代码,我就不会纠正你的考试…… ”。这些注释的目的是使我们的代码更易于阅读。这也是我们在编写 Clean Code 时的一个目标,但也许注释并不是实现它的最佳方式。
“评论弥补了我们无法用代码表达自己的不足。评论总是失败”——Robert C. Martin,Clean Code
在这一点上我同意马丁的观点。他还说评论撒谎,我相信我们都发现旧评论说一些过时的东西。因为代码被维护了,但是没有什么可以强制注释也被维护。还有什么比虚假评论更糟糕的吗?
真相只在代码中。当您认为需要写评论时,请始终考虑是否没有更好的方式来使用代码来表达这一点。
最重要的想法是尽量避免使用注释来解释代码。例如:
避免使用注释来解释变量。相反,为这个变量选择一个好名字,你就不需要注释了
避免使用注释来解释功能。相反,强制你的函数只做一件事,有几个参数,并为它和它的参数选择一个好名字,你不需要注释
我们来看一个实际案例:
想一想未来的读者在发现这一点时会想知道if
什么。他们会很想知道这if
是检查年份是否是闰年,但他们可能不会对我们如何得到它感兴趣。如果他们好奇,他们可以导航到这个名字很酷的方法的实现。无意中,通过避免注释,我们在代码中分离了不同的抽象级别。
所以,一般来说,避免使用注释来解释代码。而且,因为您将使用 GIT 或任何其他分布式版本控制系统,请避免注释掉的代码(删除它!)、署名和署名,以及这类东西。
评论是不被禁止的,有些情况下评论是有意义的:
法律意见
所有评论
放大代码中某事的重要性或具体决定的原因
公共 API 中的强制注释(JavaDocs,……)(但是,在非公共代码中避免这种情况……不要强迫团队对所有类的所有功能进行注释!!!)
更多原则
正如我之前所说,我将仅评论一些原则,以对清洁代码理论有一个基本的了解。所以,这些只是关于清洁代码的一些最基本的想法。如果您觉得它们很有趣并且想了解更多信息,请在网上寻找更多资源,或者直接阅读 Martin 的书。
如何清理你的代码?重构是关键
嗯,好的命名,小的功能,没有注释来解释代码……明白了。但是,我该怎么做呢?我怎样才能按照这些想法编写代码?
我们的工作本身就很难。编写代码并让它工作已经是足够的挑战。而且不用担心让它保持清洁。
所以,这里的关键字可以是 Refactor。一个好的方法是编写代码而不用过多担心清洁度,然后,当我们让代码做我们想做的事情时,用重构来清理它。
重构的定义
代码重构是在不改变其外部行为的情况下重构现有代码的过程。这意味着重构前后的代码必须完全相同。
不是重构的东西:
更改算法
用另一种类型的循环替换
提升一段代码的性能
重构的东西:
将一段代码提取到一个函数中
重命名事物
将几个函数提取到一个新类。
创建一个常量来存储硬编码值
…
安全重构
也许你在想“我不想破坏代码,它工作正常!”。是的当然。让代码工作可能非常困难,我们不想在重构时破坏它。这就是人们主张不要更改非常糟糕的代码的典型原因。但别担心,有安全的方法。
我们可以依靠两件事来毫无畏惧地进行重构:
测试:出于多种原因,我们应该对我们的代码进行良好的自动化测试。但很明显,这将有助于我们在不破坏任何东西的情况下进行重构。每次重构后,您可以检查所有测试是否仍为绿色。我不会在这篇文章中写关于测试的内容,也许以后会再写一篇。如果你不知道测试,你应该。网络上有很多信息。如果你不知道从哪里开始,问我:)。
重构工具:现代 IDE 具有自动执行一些最常见的重构操作的工具。如果我们使用它们,我们将减少在更改代码时破坏某些东西的可能性。我将在本文末尾介绍它们;)。
你什么时候应该重构你的代码?
每时每刻。我的意思是,您应该致力于以下开发周期:
编写代码
编写测试
重构
而且不一定按这个顺序。您可以使用 TDD 进行开发,在这种情况下,您将在代码之前编写测试。但无论如何,每次你有一段工作代码时,你都应该重构。换句话说:您应该在每个周期结束时进行重构。而且这些周期应该很小。
因为如果你在一个小的开发迭代中工作,它会很容易重构,以确保一切都是干净的,你不会破坏任何东西等等……你通常会花几天的时间来完成大量的交付吗?几个文件中的代码行数?也许不是最好的习惯。
附录:重构工具
对于本附录,我选择了一个我很熟悉的 IDE,例如JetBrains 的 IntelliJ for Java。但是您将能够在您用于首选语言的 IDE 中找到此类工具。如果没有,也许你应该尝试另一个 IDE。
改名
可能最简单的重构工具是 Rename。您有一个名称不喜欢的实体,并且您想更改它。当然,您可以手动编辑它......但这不会是微不足道的,因为这个实体可以在很多地方使用。
例如:我想更改班级的名称Input
。我想叫它WordFrequency
。
因为它是一个类,所以我应该在很多潜在的地方更改Input
标识符。手动,我应该寻找所有这些。但是我们有重命名重构工具:
该工具将重命名实体,它将负责重命名我们需要的所有内容:其他用途、文件名、测试……甚至可能与实体相关的变量名:
提取方法
这可能是我使用最多的工具。让我们看一个例子:
我有这段代码,它是我想要重构的一个非常大的函数的一部分。我认为其中一些行正在做一些独特的事情,可能是一个私有函数。所以我决定提取。
2.我使用提取方法工具。这个工具为我提供了几个关于新方法将如何发展的选项:
3. 现在代码被提取到一个方法中,这里我们有调用。该工具将负责创建方法、移动代码并通过一次调用更改我们拥有相同代码的所有位置(因为它会找到重复项)。
其他工具
有许多重构工具可用于您可以用来重构代码的最常见操作。谈到 IntelliJ Idea,我们可以查看有关代码重构的文档,或者您可以查找您首选 IDE 的文档。我鼓励您发现 IDE 中的所有重构工具并使用它们来了解它们的工作原理以及您是否发现它们有用。
最后一个论点
如果您不完全相信,还有最后一个参数可以清理您的代码
始终编写代码,就好像最终维护您的代码的人是一个知道您住在哪里的暴力精神病患者——约翰·F·伍兹。
一些感谢
给你。如果您已经走到了这一步,非常感谢您阅读我的帖子。
Clean Code — A practical approach
After giving some talks about Clean Code I have decided to summarize the most important things in an article. Because there is a lot of posts and information in the net about Clean Code, I think that a new article talking about it simply explaining some the principles is not going to be very worthy.
In this article I will try to give you a practical approach to Clean Code. I will not go deep into the theory, I want to show how I write Clean Code.
Drawing: I want to clean code!
I want t̷o̷ ̷b̷r̷e̷a̷k̷ ̷f̷r̷e̷e my code clean!
What is Clean Code and why should we care?
Origin and a definition
It’s mandatory to talk about the book written by Robert C. Martin in 2008 with the same name. But there are more books and experienced developers talking about similar concepts before the first release of the book.
I have built a kind of definition of Clean Code joining the opinions of several authors and sources and what I get is that Clean Code has these features:
It is important, at least as important as other concepts like performance, cover the functionality, avoid bugs, …
It is easy for any developer to read.
It is easy for any developer to modify.
It was written by someone who cares it.
It does what is expected. The code does not fool you, no surprises.
Why you should write clean code
I really believe that writing Clean Code is important because it’s the first step to cover the main goal of any architecture: minimize the human effort needed to create and maintain the required system.
When we are coding, we use to spend more time (much more time) reading code than writing. We read legacy code, libraries code, your team mates code, code written by you several months ago (that you don’t remember), code written by someone who left the company, code in Stack Overflow… Robert Martin puts some numbers to this:
“Indeed, the ratio of time spent reading versus writing is well over 10 to 1” — Robert C. Martin, Clean Code
Taking this in consideration, is not it worth a little extra writing effort? You will get back several times the extra time you spend cleaning your code. Think about it the next time you are going to commit a piece of code.
Last thought about why we should care our code is that we, the developers, do not write code solely to be interpreted by machines. We write code to be read by humans. Let’s think that we are authors, in the same way that a journalist writes in a newspaper or a writer creates a novel.
Some principles
There are many principles and ideas about what is clean and what is not. You can find them in the book and also on the net. But because I need some basic principles to have something to play with, I am going to introduce some of them. If you already know them you can skip to the next section, if not I think they will allow you to get an idea of the style of the rest of the theory and, perhaps, the motivation to know more.
So, let’s see some principles with code.
Let’s practice with code!
Naming
We are deciding names everywhere when we are coding: variables, functions, classes, packages, files… Taking it seriously is a first step to having Clean Code.
Some tips to get clean names:
Use intention-revealing names:
Use intention-revealing names example
If you find this “s” entity later you get nothing about its purpose
Choose pronounceable names:
Use pronounceable names example
It’s not easy to talk with a colleague about the red variable without losing face
Use searchable names:
Seachable names example
If you try to find the “r” variable with your IDE’s search tool, probably you will find more than you want
Avoid prefixes and suffixes and abbreviations
Avoid abbreviations
What the hell is ‘hp’: hypotenuse, high point…? Spanish speakers could have more proposals.
There are many other tips about choosing good names. Probably use intention-revealing names is the most important but what is really important is to take the naming seriously.
Take your time to choose good names. And don’t be afraid to change an existing name if you think that the code is going to be more readable after the change.
Functions
Between all the ideas about clean functions I am going to highlight three for this post.
First rule is basic and easy to remember: Functions should do one thing, they should do it well and they should do it only. Not too much to explain here: avoid side effects, split your functions if you notice that they are doing several things at the same time.
Functions should do one thing
Functions should be small. Ok, but how short they should be? How to measure it? Let’s force our functions to have no more than 2 levels of indentation. If this is hard for you, you can start setting a higher limit (3 levels, for example), but please put a limit on the levels of indentation you allow.
Regarding the arguments… The fewer arguments a function has, the cleaner it is. Why? Arguments need a lot of context knowledge. In each call a reader must have context to understand each argument. More arguments→ more context you need to understand. Arguments are also hard from a testing point of view. More arguments, more test cases to ensure that all the combinations of arguments work properly
Function classification by the number of arguments. More than 2 not recommended
You must have a good reason for having more than 2 arguments in a function
Comments
When I learned to code in the 90's, my teachers used to ask me to write comments everywhere. It was typical to hear them say things like “If you don’t comment your code, I’m not going to correct your exam…”. The goal of those comments was to make our code easier to read. This is a goal that we also have when writing Clean Code, but maybe comments are not the best way to achieve it.
“Comments compensate for our failure to express ourselves in code. Comments are always failures” — Robert C. Martin, Clean Code
I agree with Martin in this point. He also says that comments lie, and I am sure that we have all found old comments saying something outdated. Because the code is maintained, but there is nothing that forces the comments to be maintained as well. Is there anything worse than a fake comment?
The truth is only in the code. When you think you need to write a comment, always think if there is not a better way to express this using the code.
The most important idea is to try to avoid comments to explain the code. For example:
Avoid comments to explain a variable. Instead, choose a good name for this variable and you won’t need a comment
Avoid comments to explain a function. Instead, force your function to do only one thing, have few arguments and choose a good name for it and its arguments and you won’t need a comment
Let’s see a practical case:
1. We have something complex. We feel that is going to be hard to understand in the future:
A complex piece of code
What is happening here? Did you get it? Cool, but maybe not trivial for everyone
2. We can add a comment to make it easier to understand:
Complex code with a comment
I have put a comment. Now I can sleep better. But, is this the best solution?
3. Let’s try another option, let’s extract the complex code to a method with a cool name:
Complex code extracted to a function with a cool name.
Definitively now it’s clean!
Think about what a future reader will want to know when they find this if. They will be interested to know that this if is checking if the year is a leap year, but probably they will not be interested in how we are getting it. If they are curious, they can navigate to the implementation of this coolly named method. Unintentionally, by avoiding a comment we are separating different levels of abstraction in our code.
So, in general, avoid comments to explain code. And, because you will be using GIT or any other distributed version control system, avoid commented-out code (delete it!), attributions and bylines, and this kind of stuff.
Comments are not forbidden, there are situations where comments make sense:
Legal comments
TODO comments
Amplifications about the importance of something or the reason of a concrete decision in the code
Mandated comments (JavaDocs, …) in public APIs (but, avoid this in non-public code… don’t force a team to comment the all the functions of all your classes!!!)
More principles
As I told before, I was going to comment just a few principles to get a basic understanding of the Clean Code theory. So, these are only some of the most basic ideas about Clean Code. If you find them interesting and you want to know more, look for more resources on the net or, directly, read Martin’s book.
How to clean your code? Refactor is the key
Well, good naming, small functions, no comment to explain the code… got it. But, how can I do it? How can I write code following these ideas?
Our job is hard in itself. Writing code and getting it to work can already be enough challenge. And that without worrying about leaving it clean.
Drawing: Writing code is hard
Writing code was already difficult without having to think about its cleanliness
So, the keyword here can be Refactor. A good way can be to write code without worrying too much about cleanliness, and later, when we have the code doing what we want, clean it up with a refactor.
Definition of Refactor
Code refactoring is the process of restructuring existing code without changing its external behavior. It means that the code before and after the refactor must do exactly the same.
Things that are not refactors:
Change an algorithm
Replace one type of loop with another
Upgrade the performance of a piece of code
Things that are refactors:
Extract a piece of code to a Function
Rename things
Extract several functions to a new Class.
Create a constant to store a hardcoded value
…
Safe Refactoring
Maybe you are thinking that “I don’t want to break the code, it’s working fine!”. Yes, of course. It could have been quite difficult to get the code working, we don’t want to break it when refactoring. And this is the typical reason people argue for not changing very bad code. But don’t worry, there is safe way.
We can rely on two things to refactor without fear:
Safe Refactor relying on Tests and Refactoring Tools
Refactoring can be a joy if we have good tests and use cool Refactoring tools
Testing: we should have good automated tests for our code for many reasons. But it is obvious that this is something that will help us refactor without breaking nothing. After each refactoring you can check if all the tests are still green. I am not going to write about testing in this post, maybe in another one in the future. If you don’t know about testing, you should. There is a lot of information on the net. If you don’t know where to start, ask me :).
Tests running in green
Everything is green. It seems that we haven’t broken anything.
Refactoring tools: modern IDEs have tools that do some of the most common refactoring actions automatically. If we use them we will be reducing the possibilities of breaking something when making changes to the code. I am going to introduce them at the end of this post ;).
When should you Refactor your code?
All the time. I mean, you should be working on development cycles of:
Write code
Write tests
Refactor
And not necessarily in this order. You can develop using TDD and, in this case, you will write your tests before the code. But anyway, you should refactor each time you have a piece of working code. In other words: you should refactor at the end of each cycle. And these cycles should be small.
Because if you work inside a small iteration of development it will be very easy to refactor, to ensure that everything is clean, that you are not breaking things, etc… Do you usually spend several days writing to end up making a delivery with a lot of lines of code in several files? Maybe not the best habit.
Appendix: Refactoring tools
For this appendix I have chosen an IDE that I am comfortable with, such as JetBrains’ IntelliJ for Java. But you will be able to find these kind of tools in the IDE you use for your preferred language. If not, maybe you should try another IDE.
Rename
Probably the simplest refactoring tool is Rename. You have an entity with a name that you don’t like and you want to change it. Of course, you can edit it manually... but this won’t be trivial because this entity can be used in a lot of places.
For example: I want to change the name of the class Input. I want to call it WordFrequency.
Because it is a Class, there are a lot of potential places where I should change Input identifier. Manually, I should look for all of them. But we have Rename refactoring tool:
Rename refactoring tool
Rename tool with all its options to rename an entity safely
This tool will rename the entity and it will be in charge of rename everything we need: other usages, the file name, tests… even variable names that could have relation with out entity:
It has realized that I had several variables that I might like to change. Thanks IDE!
Extract method
This is probably the tool I use the most. Let’s see an example:
I have this piece of code that is part of a very big function that I want to refactor. I think that some of these lines are doing something unique that could be a private function. So I decide to extract.
I want to extract the creation of wordFrequencyList to a method
2. I use the extract method tool. This tool offers me several options about how the new method is going to be:
Extract method tool
Extract method tool even dares to propose a cool name…
3. Now the code is extracted to a method and here we have the call. The tool will take care of creating the method, moving the code and changing all the places where we had that same code with one call (because it finds duplicates).
Cleaner, isn’t it?
Other tools
There are many Refactoring Tools for the most common actions you can want to do to restructure your code. Talking about IntelliJ Idea we can take a look to the documentation about Code Refactoring or you can look for the documentation of your preferred IDE. I encourage you to discover all the Refactoring Tools in your IDE and play with them to understand how they work and if you find them useful.
List of refactoring tools
A lot of refactoring tools!
In fact, in my IDE I can select a piece of code and get the “Refactor This” menu that will show me all the Refactoring Tools I can apply to this concrete case:
Tell me, kind IDE, what can I do with this?
One last argument
There is a final argument to clean your code if you are not completely convinced
Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live — John F. Woods.
Some thanks
To you. If you have come this far, thank you very much for reading my post.
【更多阅读:禅与计算机程序设计艺术】
以上是关于干净的代码——一种实用的方法的主要内容,如果未能解决你的问题,请参考以下文章
在不淹没客户端的情况下推送更新事件。干净的方式来做到这一点?
如何提高编程能力?写更多代码是最显著的方法,但是本文这一种与写代码完全相反,一起来看看吧
清洁代码之道:一份实用关于如何编写和维护干净整洁的好代码的的方法 The Art Of Clean Code...