怎么写可读性强的代码

首先向大家推荐一个很有意思的website: http://coolshell.cn

怎么写可读性强的代码1. 1

类型命名(类,接口,和结构) 2

函数(方法和过程) 3

怎么写可读性强的代码2. 4

1.- 变量应该是尽可能的望文知意。千万不要使用教材中的命名方式。... 5

2.- 变量名不要太长,尽可能地简短... 5

3.- 可以使用缩写,但需要有一些注释... 5

4.- 使用合适的匈牙利命名规则... 6

5.- 不要使用反逻辑来命名... 6

6.- 保持一致性... 6

7.- 附和应用程序的领域术语... 6

8. 黄金法则- 花一些时间去思考去权衡一下你的变量名... 7

怎么写可读性强的代码3. 7

方法,类和变量... 7

Frameworks  Libraries. 9

数据库... 9

其它... 10

怎么写可读性强的代码0. 10

Naming Things in Code. 10

Types (Classes, Interfaces, Structs) 11

Functions (Methods, Procedures) 12

Does it Matter?. 13

 

怎么写可读性强的代码1

在我开始设计系统的时候,我会花去很多时间去设计命名,因为好的命名和好的设计是分不开的。

In the beginning was the Word, and the Word was with God, and the Word was God
太初有道。道与神同在,道就是神。 (约翰福音第一章,第一节)

在设计过程中给类,方法和函数好的命名会带来好的设计,虽然这不是一定成立,但是如果坏的命名那一定不会给你带来好的设计。在设计过程,如果你发现你很难命名某一个模块,某个方法时,可能你真正遇到的问题不是难命名的问题,而是这个设计是否真的合理,你或许应该花更多的时间来重新设计一下你的模块。

好的命名不仅会带来好的设计,好的命名还提高了程序的可读性,降低代码维护的成本。另一方面,如果糟糕的命名会给代码带来一堵无形的墙,让你必须深入代码去研究代码具有的行为,增加你理解代码的时间。

为此我总结了几条关于命名的指导原则,希望这几条原则能为你的命名设计带来帮助,我使用的是C++的语法,当然这些原则也很容易扩展到其他语言中去。

类型命名(类,接口,和结构)

 

名字应该尽量采用名词
Bad:           Happy
Good:          Happiness

不要使用类似名字空间的前缀
Bad:           SystemOnlineMessage
Good:          System::Online:Message

形容词不要用太多,能描述清楚就行
Bad:           IAbstractFactoryPatternBase
Good:          IFactory

在类型中不要使用Manager 或则 Helper 或则其他没意义的单词
如果你一定要在一个类型上加上ManagerHelper,那么这个类型要么就是命名的非常糟糕,要么就是设计的非常糟糕,如果是后则,那么这个类型就应该管理manage和帮助help一下自己了。
Bad:           ConnectionManager
               XmlHelper
Good:          Connection
               XmlDocument, XmlNode, etc.

如果某个类不能通过简单的命名来描述它具有的功能,可以考虑用类比的方式来命名
Bad:           IncomingMessageQueue
               CharacterArray
               SpatialOrganizer
Good:          Mailbox
               String
               Map

如果你使用类比,你就应该一致的使用它们
Bad:           Mailbox,DestinationID
Good:          Mailbox,Address

函数(方法和过程)

 

简洁
Bad:           list.GetNumberOfItems()
Good:          list.Count()

不要太简洁
Bad:           list.Verify()
Good:          list.ContainsNull()

避免缩写
Bad:           list.Srt()
Good:          list.Sort()

对于完成某件事情的函数使用动词
Bad:           obj.RefCount();
Good:          list.Clear();
               list.Sort();
               obj.AddReference();

对于返回布尔型的函数,使用类似提问的方式
Bad:           list.Empty();
Good:          list.IsEmpty();
               list.Contains(item);

对于只是返回属性,而不改变状态的函数则使用名词
Bad:           list.GetCount();
Good:          list.Count();

不要在函数名字中重复参数的名称
Bad:           list.AddItem(item);
               handler.ReceiveMessage(msg);
Good:          list.Add(item);
               handler.Receive(msg);

不要方法的名字中重复此方法的类的名称
Bad:           list.AddToList(item);
Good:          list.Add(item);

不要在函数的名字中加入返回类型,除非函数名必须以返回类型进行区别
Bad:           list.GetCountInt();
Good:          list.GetCount();
               message.GetIntValue();
               message.GetFloatValue();

不要名字中使用And 或则 Or
如果你使用一个连接词来连接函数名,那么这个函数肯定是做了太多的事情,更好的做法是将其分成更小的函数来处理(类似面向对象设计准则中的责任单一原则)
如果你想确保是这是一个原子的操作,那么你应该用一个名字来描述这个操作或一个类来封装他
Bad:           mail.VerifyAddressAndSendStatus();
Good:          mail.VerifyAddress();
               mail.SendStatus();

 

怎么写可读性强的代码2

 

前几天Neo写过《编程中的命名设计那点事》,这里也有另外一篇和程序命名的文章,可以从另一个角度看看。

1.- 变量应该是尽可能的望文知意。千万不要使用教材中的命名方式。

  • 好的变量 daysDateRange, flightNumber, carColor.
  • 坏的变量 days, dRange, temp, data, aux…

在我们的日常工作中,有很大数量的开发人员喜欢使用短的变量名,而不是有含义的变量名。这主要是因为我们大学教科书的那些示例所造成的,人都是先入为主,所以,教科书中的那些很抽象,带着演示的变量命名影响了我们一代又一代的程序员,并影响了他们很多年。虽然那些短的,教材式的变量名,可能会让你少打一些字,但其实,这是非常非常不好的。因为软件的维护成本远远大于了软件的开发成本,如果你不取一个好的一点的变量名,那么当进行代码评审时,当进行bug fixing时,当进行代码重构时,当进行代码维护时,你的某个变量名可能会让你一头雾水,不知道所措,还可以会让你走入陷阱,造成更大的时间成本。所以,一个可阅读的代码必然和那些不错的变量名分不开,而这也能让你的软件间接上有更好的质量。

2.- 变量名不要太长,尽可能地简短

只有简单和简短的变量名才是容易阅读的。因为你的变量名一定会用于程序语句中,所以,为了让你的程序语句看起来的简短,你的变量名也应该短一点,不然写出来的一个表达式就会显得很复杂。

当然,在有些时候,一个有含义的变量名和一个简短的变量名可能存在一些冲突。这相当锻炼我们的语言能力——如果有最精炼的词语来表达最丰富的含义。如果实在做不到,那么,取一个有含义的变量名要比取一个简短的变量名更好一些。不管怎么样,我们希望即简短又有丰富的含义,但如果不能两全,那有含义优先级更高一些。

  • 坏的变量howLonDoesItTakeToOpenTheDoor howBigIsTheMaterial…
  • 好的变量timeToOpenTheDoor MaterialSize.

3.- 可以使用缩写,但需要有一些注释

有一些时候,我们需要使用一些缩写来命名变量,比如:用usr来表示user,用gp来表示group,用conf来表示configuration,用cwd来表示current working directory,用ptr来代码point to reference,等等,等等。缩写一般要用在大家可以看得懂的,而不是为了缩写而缩短一个单词,当然,如果你把缩写后的变量名加上注释,那就更加稳妥了。关于一些约定俗成的缩写,可参看本文的附录一

4.- 使用合适的匈牙利命名规则

这里有一篇非常不错的英文文章告诉你 什么是合适的匈牙利命名 》,这篇文章同时还告诉你如何去用他。基本上来说,匈牙利命名法主要是为变量加上某种前缀以标识这个变量的类型,或是一种方法的功能。其基本原则是:变量名=属性+类型+对象描述。

比如:在描述类型方面:指针p,函数fn,长整型 l,布尔b,浮点型(有时也指文件)f,双字 dw,字符串 sz,短整型 n,双精度浮点 d,无符号 u……等等。关于更多的命名规范,请参见附录二

注意,匈牙利命名也是有不好的地方的,比如你要把一个整形改成一个浮点型,你除了要改变这个变量的类型,你还要改变这个变量的名字。这是相当麻烦的。而且,在某些时候,这种前缀式的命名可以反而让你不知所措。另外,在C++中,有了类以后,这种命名方法就显得不容易去实施了。所以,合适地使用匈牙利命名方式背后的思想是很关键的。

5.- 不要使用反逻辑来命名

  • 好的命名  IsEnabled.
  • 坏的命名: IsNotEnabled.

在阅读的时候,我们更喜欢正向的逻辑,而不是反向逻辑。这一规则不单单的命名,在条件语句中,我们也是要尽量不要使用这种反面的逻辑。如:if (! (isAdmin || isUser)),这样的语句很不符合人读代码的习惯,写成这样会更好一些——if (!isAdmin && !isUser)

6.- 保持一致性

保持所有代码的一致性。使用相同的命名规则。这外世界上没有最好的命名规范。但有一点是可以确认的,那就是在一个代码库中,应该使用一致的命名规则,即使这个规则不那么好,但整个团队使用一致的就是好的。

7.- 附和应用程序的领域术语

在不同的领域中,不同的观念会有非常特别和不同的意思。例如:单词“order”并不总是意味着次顺,有些时候,其意味着订单,有些时候,意味着命令,有些时候,意为着规则。所以,在某个领域中,某些单词会有不同的含义,所以,这需要我们的命令去附和这些领域。

 

8. 黄金法则- 花一些时间去思考去权衡一下你的变量名

当你设计好一个的变量名一个函数名的时候,别着急去使用他,停下来,想一想,这个变量名是否合适,是否还有更好的?也许你正在使用的是一个很不好的变量名。有些时候,需要我们权衡利弊一下,可能还要去和同事讨论一下。

总之,变量名是编程的第一步,第一步走好了,后面才走得好。试想,无论是你或你的同事在使用一些好的变量名编程是一件多么轻松的事啊。

 

 

 

 

怎么写可读性强的代码3

 

选择一个正确的名字是编程中最重要的事。以前酷壳向大家推荐过两篇文章《编程命名中的7+1个提示 和《编程中的命名设计那点事》,今天再向大家推荐一篇。一个正确的命名可以让你更容易地理解代码的程序,好的命名可以消除二义性,消除误解,并且说明真实的意图,甚至可以让你有清新的气息以让你更能吸引异性。;-)

方法,类和变量

正确的名字可以让你的程序顾名思义,下面是一些提示:

  • 不要使用ProcessData()这样的命名
    你如果在你的程序生涯中使用这样的函数名,那么这意味着你将是一个不合格的程序员而会被淘汰或解雇。请明确实际的功能。比如:ValidateUserLogin(验证用户登录)  EliminateDuplicateRequests(去除重复请求)  ComputeAverageAge(计算平均年龄),等等。
  • 让命名来帮你设计程序
    让我们假装有这么一条规则是——“任何的函数是有输入/输出的,那么,你需要思考的是所有的把input变成ouptut的步骤,然后,你可以选择一个简短的句了来说明你的这段程序,然后,把这个短句再精练一下,最终成为你的函数名,而那个短句则成了你程序的结构。
  • 命令不应该是模糊的
    如果你有一个类名叫:FilterCriteria ,但实际上其可用于文件过滤,那么这个类应该叫做: FileFilterCriteria ,就算是你真要想要用 FilterCriteria,那它也应该是抽象类。
  • 避免过多的工作
    这只是一个风格上的事情,但还是需要注意一下。在上面,我们使用到了 ValidateUserLogin  EliminateDuplicateRequests两个名字,这两个命令看上去需要做很多比较复杂的事。所以,让你的名字变简单一些也有利于你的程序更容易阅读和维护。一个软件本来就是由不同的模块拼成,而一个模块又是由更细小的函数和类拼成。编程中,我们都知道,一个函数的尺寸应该控制在200行以内,一个类的接口应该控制在20个以内。所以,从其名字上我们就不要让一个名字取得太大了。
  • 避免类名以 ”Manager” 结尾
    这样会让你类变成一个黑盒子,当然,有一些程序员喜欢使用这样的名字让那个类看起来好像更强大一些,但其实这样并不好。一般来说使用Manager这个字眼通常是使用工厂模式,或是一个容器,所以,对于一些最基本的算法或是数据结构的封装,最好是在其名字上体现这一算法或数据结构的名字,如: SortedList ConnectionPool
  • 为你的枚举类型使用单数名字
    一个枚举类型会列出所有可能的值,所以,叫animalType 会比 animalTypes 要好。
  • 匈牙利命名应该更多的关注名字的含义而不是类型
    匈牙利命名
    是一个以前很流行的命名方法,其给出了一整套的方法告诉你如何标记你的变量的类型,但可惜的是很多程序员过多的关注了变量了类型,而不是变量名的含义。而变量名的含义才是根本。
  • 不要让名字隐藏了内在
    比如,我们有段代码需要处理用户的输入,把其转成UTF-8,然后标准化(比如一些协议),最后再处理相应的转义字符。千万不要把这函数命名为Escape() ,因为你需要调用 ToUTF8() 以及NormalizeEntities() 最后才是 Escape() 函数。如果你希望使用一个函数名来做这三件事,那么,你宁可使用一个模糊的名字再加上充分的注释,而不是一个确切的名字。模糊的名字会让别人在阅读时想进去看看,而确切的名字则会让别人在阅读代码时忽略细节(这看起来和第一点有点矛盾,其实也是为了程序的易读)。比如:ProcessUserInput()
  • 一致性, 一致性, 一致性
    强调文章和代码的一致性,就算是文档写得再详细,我们也要去读代码,所以文档主要是体现思路和反映需求和设计。在程序上,我们的命令应当和文档中的术语保持一致,而程序中的命名也应该是用和文档相同的风格,这样,我们可以少很多理解上的成本。
  • 不要害怕改名
    有一些时候,你会觉得某具名字不合适,你需要改动一下。但你马上发现要改这个名字,需要修改很多的程序代码。在这里有一个原则,如果你的这个名字不是以API的方式发布时,那么你就应该不要害怕更改名字,就算是修改的工作量并不小,为了日后的更容易的阅读和维护,这是值得的。但是,如果这是一个API的名字,那我还是建议你不要改了,就算是你觉得这个名字烂得很。因为,当你的程序以API的形式发布后,会有N多的他人的程序依赖于这个名字,这个时候,兼容性和用户比什么都重要。

Frameworks  Libraries

你的用户是一个程序员,他需要使用你的代码进行二次开发。 Namespaces 将会是你重点需要注意的东西。

  • 使用namespaces 而不是类的前缀
    希望你的编程序语言支持namespace,这样,你就可以使用它而不是在类名前面加前缀了。如果你所使用的语言不支持namespace,那么你应该上网看看其它程序员使用什么样的方式来区分自己的代码和别人的代码名字空间。
  • 使用普通的namespace而不是使用公司名
    使用公司名做namespace并不是一个好的相法,因为公司名很容易变更,比如,公司因为被收购,被控告,合并,重组等原因需要更名。产品的名字同样也会改变。所以,使用一个普通的namespaces会好一些。如STLACE等。

数据库

Database Schemas 意为数据模型,所以,其名字应该和其领域是合乎逻辑的,而不是为了编程的方便。

  • 数据表应使用复数
    别使用单数形式,这是因为在远古的ORM 中需要使用单数的形式来定义类名。而且,一个表中包含了许多行数据,所以也应该是复数的。如,items“, “customers“, “journalEntries等等。,
  • 为那些包括派生数据或是日常处理的表使用aux_ meta_ 前缀
    这些表中的数据都是用来做为临时处理的,所以,你需要一个前缀或是后缀来使他们区别于实际的表。
  • 为主键加入表名
    如果你有一张表叫 ”driverLicensesID 列是主键,那么你应该把这个主键命名为driverLicense_id而不是”id”。这样做的好处是,当你在连接两个表的时候,你不需要为主键指定表名,如:driverLicense.idvehicle.id,也不需要为其取别名。
  • 使用后缀来标识类
    这样的例子很多,比如:ISBN Dewey Decimal numbersVIN等等.
    Joe Celko
    有一篇文章叫 SQL Programming Style提到了下面这样的风格:
    _id 主键
    _nbr 字符串型的数位(有严格的规则,如:车牌号,身份证号,手机号等)
    _code 标准化编码(如:邮编,ISO 国家编码)
    _cat 种类名
    _class 子集
    _type 稍不正式的类名,比如,驾照中的,摩托车”, “汽车”, and “出租车类型。

其它

  • 对于物理上的东西,命名其是什么,而不是做什么
    比如某些物理上的名字,姓名,性别,文件路径,网络链接,文件描述符,下标索引,类的属性,这些都是物理上的东西,所以,其名字应该是标识其是什么,而不是用来做什么。
  • 对于逻辑上的东西,命名其做什么,而不是是什么
    比如某些逻辑上的名字,函数名,数据结构,等。
  • 避免”Category” 问题
    千万别使用”Category” 作为你的属性名,因为,你会马上发现,这并不靠谱,因为这就等于什么没有说。与此相类似的还有”type” ”kind” ”variant” ”classification” ”subcategory” 等,对于这些名字,没人知道其是什么东西。而应该使用更为明确的分类,如: “FuelEfficiencyGrade”, “PackagingType”, “AgeGroup”, “Flamability”, “AllergenLevel”, 等等。

怎么写可读性强的代码0

 

Naming Things in Code

code | language 2009 / 06 / 05

When I’m designing software, I spend a lot of time thinking about names. For me, thinking about names is inseparable from the process of design. To name something is to define it.

In the beginning was the Word, and the Word was with God, and the Word was God.

The Gospel According to John

One of the ways I know a design has really clicked is when the names feel right. It may take some time for this to happen (I rename things a lot when I’m first putting them down in code), but that’s OK. Good design doesn’t happen fast.

Of course, good names alone don’t make a good design, but it’s been my experience that crappy names do prevent one. With that in mind, here’s the guidelines I try to follow when naming things. The examples here are in C++, but work more or less for any language.

Types (Classes, Interfaces, Structs)

The name should be a noun phrase.

  1. Bad:  Happy   
  2. Good: Happiness  

Bad:  Happy

Good: Happiness

Do not use namespace-like prefixes.

That’s what namespaces are for.

  1. Bad:  SystemOnlineMessage   
  2. Good: System::Online::Message  

Bad:  SystemOnlineMessage

Good: System::Online::Message

Use just enough adjectives to be clear.

  1. Bad:  IAbstractFactoryPatternBase   
  2. Good: IFactory  

Bad:  IAbstractFactoryPatternBase

Good: IFactory

Do not use “Manager” or “Helper” or other null words in a type name.

If you need to add “Manager” of “Helper” to a type name, the type is either poorly named or poorly designed. Likely the latter. Types should manage and help themselves.

  1. Bad:  ConnectionManager   
  2.       XmlHelper   
  3. Good: Connection   
  4.       XmlDocument, XmlNode, etc.  

Bad:  ConnectionManager

      XmlHelper

Good: Connection

      XmlDocument, XmlNode, etc.

If a class doesn’t represent something easily comprehensible, consider a concrete metaphor.

  1. Bad:  IncomingMessageQueue   
  2.       CharacterArray   
  3.       SpatialOrganizer   
  4. Good: Mailbox   
  5.       String   
  6.       Map  

Bad:  IncomingMessageQueue

      CharacterArray

      SpatialOrganizer

Good: Mailbox

      String

      Map

If you use a metaphor, use it consistently.

  1. Bad:  Mailbox, DestinationID   
  2. Good: Mailbox, Address  

Bad:  Mailbox, DestinationID

Good: Mailbox, Address

Functions (Methods, Procedures)

Be terse.

  1. Bad:  list.GetNumberOfItems();   
  2. Good: list.Count();  

Bad:  list.GetNumberOfItems();

Good: list.Count();

Don’t be too terse.

  1. Bad:  list.Verify();   
  2. Good: list.ContainsNull();  

Bad:  list.Verify();

Good: list.ContainsNull();

Avd abbrvtn.

  1. Bad:  list.Srt();   
  2. Good: list.Sort();  

Bad:  list.Srt();

Good: list.Sort();

Name functions that do things using verbs.

  1. Bad:  obj.RefCount();   
  2. Good: list.Clear();   
  3.       list.Sort();   
  4.       obj.AddReference();  

Bad:  obj.RefCount();

Good: list.Clear();

      list.Sort();

      obj.AddReference();

Name functions that return a boolean (i.e. predicates) like questions.

  1. Bad:  list.Empty();   
  2. Good: list.IsEmpty();   
  3.       list.Contains(item);  

Bad:  list.Empty();

Good: list.IsEmpty();

      list.Contains(item);

Name functions that just return a property and don’t change state using nouns.

  1. Bad:  list.GetCount();   
  2. Good: list.Count();  

Bad:  list.GetCount();

Good: list.Count();

(In C#, you’d actually use properties for this.)

Don’t make the name redundant with an argument.

  1. Bad:  list.AddItem(item);   
  2.       handler.ReceiveMessage(msg);   
  3. Good: list.Add(item);   
  4.       handler.Receive(msg);  

Bad:  list.AddItem(item);

      handler.ReceiveMessage(msg);

Good: list.Add(item);

      handler.Receive(msg);

Don’t make the name redundant with the object.

  1. Bad:  list.AddToList(item);   
  2. Good: list.Add(item);  

Bad:  list.AddToList(item);

Good: list.Add(item);

Only describe the return in the name if there are identical functions that return different types.

  1. Bad:  list.GetCountInt();   
  2. Good: list.GetCount();   
  3.       message.GetIntValue();   
  4.       mmessage.GetFloatValue();  

Bad:  list.GetCountInt();

Good: list.GetCount();

      message.GetIntValue();

      mmessage.GetFloatValue();

Don’t use “And” or “Or” in a function name.

If you’re using a conjunction in the name, the function is likely doing too much. Break it into smaller pieces and name accordingly.

If you want to ensure this is an atomic operation, consider creating a name for that entire operation, or possibly a class that encapsulates it.

  1. Bad:  mail.VerifyAddressAndSendStatus();   
  2. Good: mail.VerifyAddress();   
  3.       mail.SendStatus();  

Bad:  mail.VerifyAddressAndSendStatus();

Good: mail.VerifyAddress();

      mail.SendStatus();

Does it Matter?

Yes, I firmly believe it does. A module with well-named parts quickly teaches you what it does. By reading only a fraction of the code, the you’ll quickly build a complete mental model of the whole system. If it calls something a “Mailbox” you’ll expect to see “Mail”, and “Addresses” without having to read the code for them.

Well-named code is easier to talk about with other programmers, helping knowledge of the code to spread. No one wants to try to say “ISrvMgrInstanceDescriptorFactory” forty times in a meeting.

Over on the other side, poor names create an opaque wall of code, forcing you to painstakingly run the program in the your head, observe its behavior and then create your own private nomenclature. “Oh, DoCheck() looks like it’s iterating through the connections to see if they’re all live. I’ll call that ‘AreConnectionsLive()’.” Not only is this slow, it’s non-transferrable.

From the code I’ve seen, there’s a strong correspondence between a cohesive set of names in a module, and a cohesive module. When I have trouble naming something, there’s a good chance that what I’m trying to name is poorly designed. Maybe it’s trying to do too many things at once, or is missing a critical piece to make it complete.

It’s hard to tell if I’m designing well, but one of the surest guides I’ve found that I’m not doing it well is when the names don’t come easy. When I design now, I try to pay attention to that. Once I’m happy with the names, I’m usually happy with the design.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值