PPPan's 平凡之路

非宁静无以致远

做一个互联网内容的贡献者。


iOS项目架构 - 规范

记得刚工作的时候,我的Mentor带我参加某银行业务系统研发成果交流分享会。会议让我印象很深的一点,是关于规范。发言人在说规范的时候,举了他见过的这么一个例子:

<div class="div1" ...>
  <div class="div2" ...>
    <div class="div3" ...>
     ...
    </div>
  </div>
</div>

“只有鬼才知道他的div1是什么!”

没有规范的代码,增加了代码的阅读成本,也因此大大降低了团队合作的效率。当产品上线后,出了BUG需要修复,而负责维护的却不是当初的开发团队,这是看混乱的代码成了一个噩梦。我们不只一次地听别的程序猿哀嚎过:“嗷,又要看别人的代码”。不规范的代码也是一方面的成因。

为了提高生产效率,同时也是本着对自己产出的代码,以及对他人负责的理念,在公司内部(如果客观条件做不到,至少在团队内部)需要践行代码的规范。一般来说,各司有各司的代码规范,基本的代码规范在此就不赘述了。然而,有一些原则是通用的,在此略作梳理:

1. 首先是为人编写程序,其次才是计算机。 软件的生命周期贯穿产品的开发,测试,生产,用户使用,版本升级和后期维护等过程,只有易读,易维护的软件代码才具有生命力。

2. 保持代码的简明清晰,避免过分的编程技巧。 简单是最美。不要过分追求技巧,否则会降低程序的可读性。

3. 编程时首先达到正确性,其次考虑效率。 编程首先考虑的是满足正确性,健壮性,可维护性,可移植性等质量因素。

4. 编写代码时需要考虑到代码的可测试性。 不可以测试的代码是无法保障质量的。实现设计功能的同时,要提供可以测试、验证的方法。

5. 函数(方法)是为一特定功能而编写,不是万能工具箱。 方法是一个处理单元,是由特定功能的,所以应该很好地规划方法,不能是所有东西都放在一个方法里实现

6. 鼓励多注释。

一些较为实用的iOS规范小Tips

在项目实战中,我总结出了一些比较实用的小点,在此分享一下,希望对大家有所帮助。

1.所创建项目的文件夹目录结构和Xcode中的虚拟Group文件夹的结构须一致,便于代码文件的维护。

规范的文件目录结构如下:

文件夹结构

推荐划分文件夹的时候按功能模块划分,便于修改BUG的时候寻找。

不规范的文件夹目录结构如下:

不规范的文件夹结构

资源文件、源码文件、第三方库全部混合放置,每个文件引用次数未知,稍微移动便会造成引用错误编译失败,都是因为文件夹目录结构不规范T T。

2. 胖Model瘦Controller。

大部分业务逻辑放在Model中做,Controller只负责Model和View的调配。Model和View不可直接沟通。Model->Controller,使用NSNotification传递消息。View->Controller采用Targt-action或者Delegate传递消息。ViewController终于从上千行代码的困境中解放出来了!

这条规范为什么我们会在MVC的文章中详细讨论。

3.标注方法块

同类方法写在一起,并用#pragma mark做标注。一个.m文件的方法至上而下应该是这样的:

#pragma mark - Life cycle

- (void)viewDidLoad {...}
- (void)viewWillAppear:(BOOL)animated {...}

#pragma mark - Private Method

-(void)setContentofScrollView {...}

#pragma mark - Notification

- (void)userDidLogin:(NSNotification *)notification {...}
- (void)mainViewPicsDownloaded:(NSNotification *)notification {...}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {...}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {...}

#pragma mark - Navigation

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {...}

#pragma mark - Getter and Setter

- (MainViewModel *)model{...}

在标注Delegate的时候,把Delegate名称直接做作为标注,比如UITableViewDelegate,UITableViewDataSource。这样的好处是,当这个Delegate是自定义的时候,别人在看代码的时候可以直接command+左键点击跳转到Delegate,便于他人阅读和寻找自定的Delegate。

Getter 和 Setter放在最后。

另外,尽可能地减少Controller中的私有方法。私有方法大多可以在Model中实现。

4.所有属性都使用Getter and Setter

不要在viewDidLoad里面初始化view然后再add,这样代码就很难看。在viewDidload里面只做addSubview的事情,然后在viewWillAppear里面做布局的事情,最后在viewDidAppear里面做Notification的监听之类的事情监听也同时放在ViewWillAppear中,在某些特殊的情况下,在ViewDidAppear中注册的监听会导致无法removeObserver。至于属性的初始化,则交给getter去做。

不要:

- (void)viewDidLoad
{
   [super viewDidLoad];
   self.textLabel = [[UILabel alloc] init];
   self.textLabel.textColor = [UIColor blackColor];
   self.textLabel ... ...
   self.textLabel ... ...
   self.textLabel ... ...
   [self.view addSubview:self.textLabel];
}

而是:

- (UILabel *)textLabel
{
    if (!_textLabel)
    {
        _textLabel = [[UILabel alloc] init];
        _textLabel.textColor = [UIColor blackColor];
        _textLabel ... ...
        _textLabel ... ...
        _textLabel ... ...
    }
    return _textLabel;
}

5.注释你的公有方法

使用这个工具规范注释.h头文件中的属性和方法。十分直白的方法和属性可以不注释。

That's all.Hope u enjoy it. : )