心法 | 功能模块的封装
功能模块,就是大家项目中都有的xxxManager
、xxxTool
诸如这种实现某个功能的一个 class 或一组 class。
封装功能模块是日常开发的重头戏之一,认真对待每一次功能模块的封装,你的编程能力将得到稳步提升。
工作的这几年我封装了若干功能模块,收获了一些一手经验。以下是我的心法:
1. 考虑真正可能的情况
多问几个“如果”,将问题考虑全面,有疑问立即找 PM、UI 确定。
另一方面,也不要脑洞大开。需要适当考虑扩展性,但也没必要深谋远虑。有些功能是近期显然不需要的、有些特殊情况是显然不会出现的,就不用考虑它的实现了。
2. 把接口想好
既然是功能模块,那接口就是它的门面,使用某个功能模块,其实就是跟这个功能模块的接口打交道,所以如果连接口都凌乱繁琐,那必定会遭到使用者的嫌弃。
我的实践是:在确保功能完备的情况下,尽可能减少接口的数量,尽可能减少参数的数量,尽可能只返回需要的东西,尽可能让接口的使用简单方便。
很多时候可以参考系统接口或优秀三方接口,看下别人是怎么定义的。但是参考终归是参考,要写出最适合自己项目的接口,终归要有自己的思考。比如说show
一个弹窗(或者 action sheet),系统的两种弹窗接口可以参考:
// UIAlertView
let alertView = UIAlertView(title: "title", message: "detail", delegate: self, cancelButtonTitle: "取消", otherButtonTitles: "确定")
alertView.show()
// UIAlertController
let alertController = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "确定", style: .default) { (action) in
print("确定")
}
let cancelAction = UIAlertAction(title: "确定", style: .cancel) { (action) in
print("确定")
}
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
我完全可以取其精华然后写个更加简单易用的接口:
let action1 = DSAlertAction(title: "第一个") {
print("点击了第一个")
}
let action2 = DSAlertAction(title: "第二个") {
print("点击了第二个")
}
let action3 = DSAlertAction(title: "删除", titleColor: .red, titleFont: .boldSystemFont(ofSize: 15)) {
print("点击了删除")
}
DSActionSheet.show(title: "title", message: "详情", actions: [action1, action2, action3])
3. 拼尽全力将代码写到最好
OOP or POP?
是否可以采用xx设计模式?
传值用哪种方式好?
代码是否规范?
注释是否清晰?
。。。
平时看的技术博客、经典书籍、优秀框架,学到的知识,这个时候就要拿出来了。
只有当你努力写出自己当前最高水平代码的时候,才有机会将编码能力提升到另一个层次。
4. 立即复盘
我个人很喜欢封装功能模块,只要不是太难搞的,都会亲自动手完成,自认还算是比较有经验的。但即使这样,依旧不敢保证一次性就写出令自己完全满意的代码。
所以,当按照前三步将功能完成的时候,我会立即复盘,从头到尾。虽然不会有大的改动,但基本上都会有小的调整。
必要的时候,让同事 code review 一波。
以上就是我封装功能模块的心法,核心就两点:
思考 + 实践
最重要的还是要自己思考自己写,如果抱着有轮子绝不自己造的思想,那什么心法都是纸上谈兵。