关于iOS代码重构
之前刚好有时间,简单的读了一下《重构:改善既有代码的设计》这本书,重构是一门艺术,这门艺术必须要结合实践才能产生美感。如果经常逛虎扑的话,会发现一些段子手会把楼主很长的描述编成打油诗,这就是类似于初步的代码重构。
简单整理下自己的总结吧,当前由于工作进度问题,不能有大的改动,只能针对自己模块的代码进行简单重构,以下是自己用到的地方。
重构的三次法则:
第一次做某件事时只管去做;第二次做类似的事会产生反感,但无论如何还是可以去做;第三次再做类似的事,你就应该重构;
1.修改定义不明确的方法名和属性名;
方法一:可以使用com+f查找替换;
方法二:利用xcode工具:
1.1.选中需要修改的部分,Edit-Refacter-Rename
1.2.勾选Raname related files ,点击Preview,系统会展示出.h和.m文件中所有需要修改的地方,确定之后就OK了;
2.标注弃用方法
如果由于修改接口,不得不产生新旧两个接口,可以在旧接口方法名后标注DEPRECATED_ATTRIBUTE,运行后会产生方法弃用的告警
也可用NS_DEPRECATED_IOS(3_0, 7_0)等标注;
3.抽象
Extract:将代码抽取为一个单独的方法或函数
选中一段代码后(可以包括注释),选择Extract,会分析你选择的代码段后自动生成方法签名。你可以修改方法名,如果参数、返回值不正确也可以自己再修改。
如果选择了function,就是另外一种格式:
在预览时如果发现有些需要调整,可以直接在预览框编辑。
下面是抽出一个doubleValue方法的预览:
4.Create Superclass:创建父类
这个很好理解了,就是创建一个当前类的父类。要注意的是要选中类名的时候才能成功触发。
需要注意的是预览界面最左边的导航区,选择中间一个是这次重构会影响到文件列表。可以点击到这个tab下查看其它类的改动。
如果有警告,会默认显示警告的tab。
5.Move Up & Move Down
Move
Up:可以将一个方法、实例变量移动到父类中去。触发时和重命名一样,要选中实例名或者方法名后才能正常使用。在category中不适用。
Move
Down:相反,将选中的实例变量移动到子类中。是的,方法就不能移到子类了。逻辑上很难理解为什么是这样。但是苹果爸爸就是这么任性。
6.关于 手写代码 or Xib
国内iOS界的大神唐巧和喵神对这个问题也都有自己的见解,大家可以移步到他们的博客看看:
唐巧:http://blog.devtang.com/blog/2015/03/22/ios-dev-controversy-2/
喵神:http://onevcat.com/2013/12/code-vs-xib-vs-storyboard/
可以通过这两篇文章,选择合适方式构建界面;
总之:
对于复杂的、动态生成的界面,建议使用手工编写界面。
对于需要统一风格的按钮或UI控件,建议使用手工用代码来构造。方便之后的修改和复用。
对于需要有继承或组合关系的 UIView 类或 UIViewController 类,建议用代码手工编写界面。
对于那些简单的、静态的、非核心功能界面,可以考虑使用 xib 或 storyboard 来完成。
7.多用类型常量,少用#define
一个庞大的项目中,常常使用了大量的宏定义。宏定义的初衷之一是提高了程序的可读性,同时也方便进行修改。可是过度的宏定义往往违背了它的初衷。
例如
#define ANIMATION_DURATION 0.3
我们并不能很直观的理解它其中的时间含义,而
staticconst NSTimeInterval kAnimationDuration = 0.3;
就很好的描述了常量的含义。
此外,为什么要加一个static和const来同时命名?因为static意味着该变量仅在定义此变量的编译单元中可见。编译器每收到一个编译单元,就会相应的输出一份目标文件(object
file即.o文件)。假如我们不声明static,编译器就会为它创建一个“外部符号”。此时如果另一个编译单元也声明了一个同名变量,那么编译器就会抛出一条错误消息。事实上,如果同时用static和const命名,编译器根本不会创建符号,而是会像#define预处理指令一样,把所有遇到的变量都替换为常值。不过还是有一点区别的,用这种方式定义的常量是带有类型信息的。
不管是#define还是static const都不应该在头文件里声明,因为常量名称很有可能互相冲突,如果一定要这么做的话,要加上前缀,表明它输入哪个类。
再延伸的说一下extern:
extern常用于NSNotification中等,供外部使用,extern常量放在“全局符号表”中,以便可以在定义该常量的编译单元之外使用。这也是不用使用#import引入其所在头文件的原因,需注意,此类常量必须要定义,而且只能定义一次。
以上是目前情况下自己针对代码做的简单调整,后续继续记录;