代码结构和可读性第2部分-类和结构

欢迎回来,在第1部分中,我们介绍了一些基础知识:变量,数据结构和函数。

代码结构和可读性第1部分—变量,数据结构和函数
如果您来自我的有关结构和可读性的Swift编程文章,那么您已经知道一些基本知识…… medium.com

我们学会了一些清理它们的方法,但是现在我们继续前进。 我计划这次对您轻松一点,因为我们在这里只讨论类和结构。 如果您不了解类或结构,建议您阅读我为Swift写的一篇文章。 不用担心Swift不是您的语言,如果您的语言支持它们,那么足够通俗易懂,足以让您掌握类和结构。

类和结构

让我们从那里抛出一个示例类开始。

 公共类动物{ 
命名:字符串
让收藏夹食物:字符串
变量年龄:整数
让countryOfOrigin:字符串
init(名称:字符串,最喜欢的食物:字符串,年龄:整数,
countryOfOrigin:字符串){
self.name =名称
self.favoriteFood =最喜欢的食物
自我年龄=年龄
self.countryOfOrigin = countryOfOrigin
}
}

当然,我们可以将其更改为struct并忘记初始化程序,但是我要使用一个类,因为让我们面对现实吧,即使您尝试使其具有可读性,也有点草率。

老实说,当结构可以使用时,我尽量不要使用类。 我不必担心初始化(除非我想),我不必担心参考周期(除非我要进行极端优化),并且我的代码库要小几行。

那么我们可以使用类来解决这个问题吗? 好吧,确定间距确实有帮助,所以让我们从这里开始:

 公共类动物{ 
 命名:字符串 
让收藏夹食物:字符串
var age =年龄
让countryOfOrigin:字符串
  init(名称:字符串,最喜欢的食物:字符串,年龄:整数, 
countryOfOrigin:字符串){
self.name =名称
self.favoriteFood =最喜欢的食物
自我年龄=年龄
self.countryOfOrigin = countryOfOrigin
}
  } 

一点间距与此很长的路要走。 但是我认为我们可以做得更好。 每当我的代码看起来像这样的部分难以阅读时:

  ... 
init(名称:字符串,最喜欢的食物:字符串,年龄:整数,
countryOfOrigin:字符串){
self.name =名称
self.favoriteFood =最喜欢的食物
...

我尝试添加一些额外的空间,以便可以看到我正在将name分配给类实例变量name 。 像这样:

  ... 
init(名称:字符串,最喜欢的食物:字符串,年龄:整数,
countryOfOrigin:字符串){
  self.name =名称 
self.favoriteFood =最喜欢的食物
...

这使得查看我的init声明在哪里结束和我的赋值开始变得容易得多。 让我们一起来看看。

 公共类动物{ 
 命名:字符串 
让收藏夹食物:字符串
var age =年龄
让countryOfOrigin:字符串
  init(名称:字符串,最喜欢的食物:字符串,年龄:整数, 
countryOfOrigin:字符串){
  self.name =名称 
self.favoriteFood =最喜欢的食物
自我年龄=年龄
self.countryOfOrigin = countryOfOrigin
}
  } 

看起来好一些,但现在又有一个问题。 init(name...行看起来不合适,我将添加另一个空格来区分属性和初始化。尽管如此,我也不喜欢我们如何将变量var与常量混合在一起, ,我也会修复该问题。

 公共类动物{ 
 命名:字符串 
让收藏夹食物:字符串
让countryOfOrigin:字符串
var age =年龄

  init(名称:字符串,最喜欢的食物:字符串, 
countryOfOrigin:字符串,年龄:整数){
  self.name =名称 
self.favoriteFood =最喜欢的食物
self.countryOfOrigin = countryOfOrigin
自我年龄=年龄
}
  } 

注意,我的初始化参数和初始化代码与属性保持相同的顺序。 这样,当我要更改班级内容或仅查看该班级的代码时,所有内容都很容易找到。

但是,我越看越容易惹恼我。 我们需要重构一点。 nameage是简短的变量名,但是favoriteFoodcountryOfOrigin似乎很长。 尽管它们是描述性名称,但我认为可以略微缩短这些名称,而又不会丢失每个属于Animal的上下文是安全的。

 公共类动物{ 
 命名:字符串 
let favFood:字符串
let origin:字符串
var age =年龄

  init(name:String,favFood:String,origin:String,age:Int){ 
  self.name =名称 
self.favFood = favFood
self.origin =起源
自我年龄=年龄
}
  } 

由于进行了这种重构,我们不仅使这些属性很好地结合在一起,而且还充分缩短了init函数,因此所有属性在一条直线上都可以很好地融合在一起。

即使对于独立的类,注释仍然很重要。 通常,我喜欢将我的课程分为几个部分。

  //类定义 
  //属性 
  //初始化 
  (//静态方法) 
  //公开(方法) 
  //私有(方法) 

括号中的所有内容均为可选文本或有意义的地方。 我倾向于做的另一件事是将最可见的属性和方法放在最不可见的属性和方法之前。 我总是将init函数直接插入最后一个属性之后以及所有方法之前。 我总是将静态函数直接放在init之后,因为大多数情况下它将在内部使用或作为公共API。 如果我没有一节,我将忽略整个评论。 因此,让我们再来看一次。 我还将通过公共获取方法将age更改为私有财产,因为我不能仅仅说Animal年龄已经10岁了,相反,我需要让Animal生日。

  //动物 
//定义动物的名称,喜爱的食物和国家/地区
//来源。
//
// name:获取或设置动物的名称
// favFood:获取或设置动物喜欢的食物
//起源:获取或设置动物的起源国
//年龄:获取动物的年龄
 公共类动物{ 
  //属性 
 命名:字符串 
let favFood:字符串
let origin:字符串
 私人变量年龄:整数 

  //初始化 
  init(name:String,favFood:String,origin:String,age:Int){ 
  self.name =名称 
self.favFood = favFood
self.origin =起源
自我年龄=年龄
 问好() 
}

// 上市
  func hadBirthday(){ 
自我年龄+ = 1
}
  func getAge()-> Int { 
返回自我
}

// 私人的
 私人功能sayHello(){ 
print(“ Hello,World!”)
}
  } 

在顶部,您将看到所谓的docstring 。 有时,这就像上面的Swift示例中的类声明一样。 有时,它将位于类声明(如Python)之下。

 动物类: 
“”
这是Python中的文档字符串。 最好不要超过80个字符
或PEP8会向您尖叫。
“”
...

PEP8希望您使用80个字符作为文档字符串,但我认为对于任何一种语言而言,这都是一个不错的数字。

这些用于提供快速文档的IDE。 这里有几个例子。

不要仅仅因为我说过而编写文档,而是为可怜的灵魂做的,那可怜的灵魂必须在您之后更改该代码。 它将发生,业务规则会发生变化,拥有适用于他们的文档可帮助他们了解它的作用,并使他们的生活变得更加轻松。 我敢肯定,如果您考虑一下您同意我使用的方法的参数时,是否会有所反思。 正如您在上面看到的那样,可获得的文档越多,您的生活就越轻松。 这可能不利于提高可读性,但有助于浏览全新的代码。 哦,那失踪了; 导致VS错误的错误将永远不会出现,但我保证在截屏后将其作为示例。 (世界上一切都正确)

抱歉,绕道而行,但这很重要! 让我们回头看看代码:

  //动物 
//定义动物的名称,喜爱的食物和国家/地区
//来源。
//
// name:获取或设置动物的名称
// favFood:获取或设置动物喜欢的食物
//起源:获取或设置动物的起源国
//年龄:获取动物的年龄
 公共类动物{ 
  //属性 
 命名:字符串 
let favFood:字符串
let origin:字符串
 私人变量年龄:整数 

//初始化
  init(name:String,favFood:String,origin:String,age:Int){ 
  self.name =名称 
self.favFood = favFood
self.origin =起源
自我年龄=年龄
 问好() 
}

// 上市
  func hadBirthday(){ 
自我年龄+ = 1
}
  func getAge()-> Int { 
返回自我
}

// 私人的
 私人功能sayHello(){ 
print(“ Hello,World!”)
}
  } 

在公共财产和私有财产之间,我将它们分开。 如果我拥有更多私有财产,则将所有私有财产合理地组合在一起即可。 如果有相关的属性,例如birthdayage ,我会将它们与其余的私有属性组合在一起。 由于在此示例中我所有的公共财产都不相关,因此将它们放在一起不会有任何伤害。 如有需要,请将其归档在其他属性下。

经过一秒钟的初始化(无论如何并没有太大变化),我们有公共和私有方法区域。 Public优先于private方法,因为您很有可能在私有方法之前更改public方法,仅仅是因为它们比您的private方法(在大多数情况下)被调用的频率更高,并且bug更加明显。 注意,这里我们实际上可以得到私有属性,这就是其他开发人员可以调用的使用该隐藏属性的语言。 我们不希望他们直接进入年龄。 如果您突然说他们75岁,并且全世界都同意您的话,那么没有人会喜欢,除非他们实际上是75岁或75岁以上。

现在我们有了一个私有财产,它的意思是“ Hello,World!”。

回到初始化,我们添加了此调用,但是如果您注意到了,我在底部添加了该调用。 有时,将其放置在顶部更有意义,例如在进行一些计算以自动实例化私有变量时,但在此处将其放置在底部是可以的。 我们只是称呼它,所以当类完全初始化时,它会通过欢迎您自己使用“ Hello,World!”来告知我们。

如果您仔细观察一下,我们不会失去任何可读性,代码很干净,并且其结构还不错。 是的,该文档字符串很大,但是在我们有了颜色之前,我们对此无能为力:

看看这看起来好多了? 定义明确的空格,引人注目的部分,这段代码看起来很干净。

摘要

因此,这是一篇简短的文章,但我希望它对如何构造类和结构使它们看起来比以前更好有帮助。 类和结构比这要大得多,通常您可以在GitHub上找到一些不错的干净代码。

微软通常有一些良好的编码习惯,但我也从Apple,Google和其他公司那里看到了非常好的编码。

在下一篇文章中,我们将介绍文件结构。

代码结构和可读性第3部分-文件结构
在上一篇文章中,我们研究了类和结构。 我们将通过… medium.com 扩大本文的视野