• 叙利亚避谈战中国是否摆大巴 人员严重不整花式缺阵 2018-05-11
  • 男子嫖娼后恋上卖淫女 女子外出约会被其砍杀 2018-05-11
  • 郭家耀:料指数于23200至23800点水平徘徊 2018-05-05
  • 海外热身天津遭惨败 队长:跟高水平打才能学习 2018-05-05
  • 中国首个海外基地为何选吉布提?扼守全球最重要航道 2018-05-05
  • 张稀哲再示爱新婚妻子:遇到对的人 有你就知足 2018-05-04
  • 崔龙洙称为输球会做自我反省 解拉米为何没进首发 2018-05-04
  • 特朗普打破惯例 罕见“优待”中国记者 2018-05-04
  • 英国脱欧后都柏林能否成为欧洲新金融中心 2018-05-03
  • 英国明年3月底前将启动脱欧程序 脱欧时间表一览 2018-05-03
  • 加拿大“网红”柯基因病辞世 粉丝超70万 2018-05-03
  • BFS牛汇:菲律宾政局动荡 比索面临贬值压力 2018-05-02
  • 哈勃望远镜捕捉到垂死恒星:如蝴蝶蹁跹(图) 2018-05-02
  • 揭秘:小检察官如何替人“消灾” 买通公安法院 2018-05-02
  • 爱神罕见粗口回应外界质疑:老子一点都不在乎 2018-05-01
  • 36选7玩法 >iOS开发

    几个步骤,让你的 iOS 代码容易阅读

    2018-04-24 13:23 编辑: yyuuzhu 分类:iOS开发 来源:张嘉夫_Joseph

    1.jpg

    本文翻译自 Making your iOS application easy to read with these simple steps.


    优秀的程序员会用尽可能简单的方式来解释他们的代码,即使是物理学家都可以用一张白纸和一只铅笔来解释虫洞,我们又何尝不可?

    我会尽可能让代码写地简单、易读,包括选择合适的变量名、使用编码规范(code conventions)等等,但还是缺了点东西,理解代码不应该是去理解“如何”实现的,而是要理解想要“达成”什么。

    甚至可以说要让读代码像读小说一样,而不是一大堆代码。


    下面讨论三大主题:

    问题

    阅读其他人的代码可能会非常折磨,如果不提供合适的上下文,我们会迷失在寻找某个函数或属性的意义中。

    建议

    不论是二进制语言、低级语言还是高级语言,语法都在变得越来越友好,以便吸引更多开发者。而随着语法变得更接近英语,我们的代码也应该简明扼要、不言自明。

    结果

    写出良好的代码,读起来像小说一样,容易阅读和理解(即使没有给出上下文)。


    函数命名

    正确的方式是:

    我们写函数时都会假设阅读它的人拥有足够的上下文,能够理解函数想实现什么。用模糊的含义来命名函数,例如“handleRedView()”会引起很多问题,”RedView”是啥?这个函数主要是想干啥?

    所以在某些情况下函数的用途会很模糊,如果没有提供足够的上下文,阅读起来会非常困难

    我们可以把函数的用途分为四类:

    1. 通知(Informer)函数

    2. 管理(Management)函数

    3. 路由(Router)函数

    4. 执行(Execution)函数

    1. 通知函数

    通?;岽シ⒙酚?管理函数,例子如下:

    delegate.dataHasUpdated()
    
    func dataHasUpdated()
    {
      //通知某事的发生
     }
    
    // 通知函数
    override func engineStarted()
    {
      super.engineStarted()
      handleCarStarted()
     }

    回调函数,通知某事已经/即将发生,并给机会进行响应。

    大部分情况下用于被代理(delegate)触发的操作,或是通知(notification)处理函数。

    2. 管理函数

    用于联合多个函数以实现更高级的用途,不需要依赖参数,block 中的所有代码都会执行。

    // 管理函数
    func handleCarStarted()
    {
      turnLights(on: true)
      turnAC(on: true)
    }

    上面的函数包含所有需要的信息,汽车启动时执行这些函数,此时我们不关注这是“如何”实现的,而是关注它做了“什么”。

    3. 路由函数

    用于联合多个函数以实现更高级的用途,需要依赖一些参数,只在我们想执行的时候才执行。

    // 路由函数
    private func turnLights(on shouldTurnLightsOn: Bool)
    { if shouldTurnLightsOn
     {
       turnExteriorLightsOn()
       checkForBurnedBulbs()
     } else { turnExteriorLightsOff() }
     如果 if 语句只执行一件事,我喜欢把 "if" "else" 和执行语句写在同一行,这样代码读起来会更流畅。

    路由函数通常同于指向执行函数,但在某些情况下,如果逻辑代码不超过一行,也可以包含自己的逻辑。

    4. 执行函数

    函数名字的具体实现。

    // 执行函数
    private func turnExteriorLightsOn()
    {
      leftFrontLight.isOn = true rightFrontLight.isOn = true leftBackLight.isOn = true rightBackLight.isOn = true }
     private func checkForBurnedBulbs()
     { for lightBulb in bulbs where !lightBulb.isUseable
       {
         Dashboard.(errorType: .lights) break }
     }

    这样就能写出一个干净、简短的类,可读性强,容易维护。


    * 谨记一项原则,每个函数都应该只有一个责任。

    避免在函数名称里使用”and“: playAndMinimize() loadAndPlay() 这个坏习惯会打破单一责任原则,写出能够适应两种情况的代码。

    避免在函数名称里进行猜测: moveRedViewIfNeeded() 上面的例子会导致后面的程序员必须深入此函数,才能理解触发移动 Red View 的时机,这样不够清晰。

    不,layoutIfNeeded() 并不属于这种情况,因为我们知道如果某个 view 的 setNeedDisplay 为 true,就应该重新布局。这种情况在 Swift 语言里很普遍,因为函数基本上都是应用私有的。


    谈及代码可读性,我首先会想到编码规范(code convention),它们被普遍接受、应用广泛,但使用编码规范并不一定会提升代码质量,虽然有跨应用性但可读性更差。

    ”is“前缀应该用于布尔型变量和方法,以便解释返回值是布尔类型的。#编码规范

    既然”if“语句总是用于布尔值,那还有必要给每个布尔属性都加上”is“吗?为什么苹果要把 Swift 语法从 view.hidden 改成 view.isHidden?我只能想到一种答案……因为**“if view.isHidden”**看起来更自然。

    尝试以以下原则使用“is”前缀:

    • 如果类的某个布尔属性/方法用于该类(公开)的实例,就有正当理由使用“is”前缀。

    public var isHidden: Bool
    { return alpha == 0.0
     } if containerView.isHidden
    • 如果布尔属性在类内部(私有)使用,前缀就是多余的。

    private var positionedVerticaly: Bool
     { return view.frame.width/2 == centerX
     } if positionedVerticaly if positionedVerticaly && positionedHorizontally
     VS if isPositionedVerticaly if isPositionedVerticaly && isPositionedHorizontally
    • 如果布尔型属性/方法同时被私有公开使用,那么应该用计算属性来返回该私有属性值。

    public var isPositionedVerticaly: Bool
    { return positionedVerticaly
     } if containerView.isPositionedVerticaly

    虽然用私有 set 并公开使用该属性也是可以的,但上面这种方式可以实现封装(encapsulation)。

    封装用于隐藏类中结构化数据对象的值或状态,防止未授权方直接访问。

    en.wikipedia.org/wiki/Encaps…

    那如果不是自己直接处理的布尔型,如果如何命名呢?

    private var playerIsPlaying: Bool

    private var gridConstraintIsEnabled()

    “is” 需要指向某个东西:view.isHidden, “is”指向 view。上面的例子里使用了此原则,playerIsPlaying,“is”指向 player。

    谨记:开发者通?;嵩谠亩潦粜陨髦跋仍亩梁诓康拇?,尝试搞明白这些属性的用途。

    /if playerIsPlaying { }/ 对比 /if isPlayerIsPlaying {}/

    哪个更自然?我想你已经有答案了。

    作者:张嘉夫_Joseph
    链接:https://juejin.im/post/5add93866fb9a07aa76744d9

    搜索CocoaChina微信公众号:CocoaChina
    微信扫一扫
    订阅每日移动开发及APP推广热点资讯
    公众号:
    CocoaChina
    我要投稿   收藏文章
    上一篇:Vue中使用Sortable
    我来说两句
    发表评论
    您还没有登录!请登录注册
    所有评论(0

    综合评论

    相关帖子

    sina weixin mail 回到顶部