APP项目的开发流程很多公司都有自己的见解和流程规范,有的可能甚至没有规范,横看成岭侧成峰,远近高低各不同,不能一概而论到底哪种流程是绝对正确的,小编阿飞就从产品立项->需求分析->UI设计->程序开发->测试验收->总结大会这个流程来给大家介绍一下APP项目开发过程中的一些设想和规划。
工作概述: 产品立项阶段亦称为准备阶段,该阶段主要基于需求大纲通过针对性的市场调研、用户访谈及竞品分析,尽可能的评估产品的核心功能,方向定位、目标用户群、成本投入和市场前景。在决策层评估通过的条件下,组建虚拟开发小组,协调资源,明确项目负责人及产品计划上线时间等事项。若为甲方需求的项目,可省略市场调研及商业价值评估的相关内容。
描绘远景,设定目标: 产品的远景是什么?计划需要做什么实现这个远景?明确各个阶段的产品目标,为什么设定这样的目标?
市场调研,竞品分析: 通过针对性的市场调研和充分的竞品分析,测算产品市场前景和风险成本。
收集需求,排优先级: 收集各业务市场部门反馈的需求意见,做典型用户的深度访谈,组相开发设计运营人员头脑风暴,明确产品核心功能和开发需求优先级。
组建团队,定负责人: 依据产品定位和投入资源,组建合适的虚拟开发小组,指定项目负责人,团队相互熟悉各个岗位人员。
定期碰头,制定计划: 商定项目相关人员定期碰头会,保持团队所有人最新需求信息同步,初步制定产品各个阶段完成时间节点。
成果: 《竞品分析报告》、《产品立项说明书》、《产品BRD文档》
工作概述: 基于产品定位和运营策略,与产品各需求方进行深度的需求沟通,将抽象繁杂的需求整理分析成可落地执行的方案,召开需求评审,排定各功能点的开发优先级,规划产品各个版本迭代的功能计划表,设计产品原型,撰写产品需求说明书,与设计开发团队沟通确定各阶段的完成时间节点,明确产品实际上线时间,与市场运营团队沟通上线运营计划方案等。
需求分析,原型设计: 与市场业务运营同事深度沟通,形成初步的需求大纲,功能列表,组织团队全员头脑风暴,分析需求的真伪及紧迫性,确定需求开发优先级,制定产品功能迭代计划表,设计产品原型初稿及页面结构图;
需求评审,确定方案: 由产品经理牵头召开需求评审会议,向开发团队详细讲解产品逻辑流程和交互细节,评估技术实现的可行性。对不明确的需求做二次需求更新;
需求文档,开发周期: 依据需求评审结果,修改设计最终版原型及交互,标注原型及撰写产品需求说明书,管理后台数据相关数据统计等需求,技术根据需求文档反馈每个阶段的完成时间节点。
成果: 《产品PRD文档》、《产品交互原型稿》(低/高保真)、《产品开发进度计划表》
工作概述: 基于原型交互稿及产品PRD文档设计产品页面效果图,与产品沟通确定详细的交互细节及效果。与需求业务方确定完善效果图设计最终版,依据开发需求进行效果图细节标注,设计产品icon及应用市场审核宣传材料,配合市场运营部门设计产品运营活动页面等。
用户分析,设计梳理: 收集相关资料分析目标用户的使用特征、情感、习惯、心理、需求等,基于3W法明确使用者,使用环境及使用方式;
素材收集,确定风格: 在深度熟悉产品整体业务流程和商业需求的基础上,确定页面主辅色,制定交互方式,操作与跳转流程、结构、布局、信息和其他元素;
界面设计,规范输出: 设计产品页面、图标、ICON,皮肤及一些界面交互的表现。与前端开发沟通,明确切图命名及标注规范,输出最终设计稿。
UE测试,整体复盘: 产品测试阶段包含UE测试,负责测试页面的还原度及交互的易用性,针对设计稿和需求文档提出测试反馈优化意见。产品上线发布后,全面复盘本次设计架构和细节,总结设计经验和优化迭代建议,并撰写相关的分析优化报告。
成果: 《PSD源文件》、《切图源文件》、《交互描述及标注细节规范说明》
工作概述: 分为用户端、服务端两类开发。其中用户端开发,主流有iOS和Android,依据需求文档和设计稿,实现前端页面的交互效果,与服务端确定数据交换接口协议。服务端开发依据需求文档,设计数据库表结构,评估核心复杂功能的实现方案,撰写开发设计概要文档及反馈重要功能的完成时间节点。
成果:《开发设计概要》、《接口协议文档》、《自测通过的产品1.0版》
工作概述: 参考产品需求文档和开发设计概要,撰写产品测试用例,召开用例讲解会,对产品全方位的进行测试,将测试不通过的内容反馈给开发,判定bug严重程度和跟进修复进度,评估产品上线发布的可行性,协助产品和业务人员撰写产品验收报告。
测试类型: 功能性测试、容错性测试、性能效率测试、易用性测试、兼容性测试、压力测试等
成果: 《测试bug反馈记录表》、《测试验收报告》
项目完成之后,需要发项目参与的所有人员组织起来,总结项目过程中的问题,避免以后再次发生,个人觉得这点很重要。
1、 基准库的封装不能马虎,包括各种基类,utils等,前期可能做不到完美,随着项目的开发过程中逐渐优化,有时间应该提交到jcenter上面,采用远程依赖的方式可以加快编译速度,并且能减少项目的冗余度。
2、 ui库一定要形成。ui库用于存放一些封装好的自定义view,需要根据项目的整体风格,封装一些app内使用的组合控件,避免造成布局臃肿。公用资源文件等和ui想关的东西。
3、 第一个版本不用考虑那么长远,做什么组件化之类的东西,但是相应的功能模块需要分开,尽量减少耦合度,为后面项目增大做组件化开发减少压力。
4、 框架的选择,例如:网络、图片加载、数据库、rxjava等,尽量选择比较新的,稳定的,灵活度高的框架,避免后面替换的麻烦。如即时通讯,消息推送等后期替换很费时间的第三方框架需要进行调研慎重选择,最好确定以后,后期不用替换,框架不用可以最新版,最重要的还是稳定性。
5、 时间允许最好写点单元测试,如果前期没写单元测试,一旦项目大了,后面你会更不想写了。
6、 不要放太多的library代码到项目中,导致最后一个项目有很多个moudle,导致编译时间很长,尽量提取你需要的功能放到基准库中,减少moudle的数量,如果整个moudle的功能基本都需要,可以考虑打包成aar的方式依赖,减少编译时间,项目的依赖逻辑一定要清晰,不能混乱。
7、 写完项目之后,回过头来欣赏下自己的项目,你会发现,可能有很多地方都有更好的方式实现,大部分看第三方库的代码比看自己写的代码多,多看自己写的代码,才能发现自己的问题所在,这点是提升自我的一个方法,个人觉得比较重要。
1. mutable的数据类型,不能声明为copy的属性,如@property(nonatomic, copy) NSMutableArray *array; @property(nonatomic, copy) NSMutableDictionary *dict;这样的声明,然后再初始化的时候会有问题,self.array = [[NSMutableArray alloc] init]; 其实它在内存中是NSArray的实例。所以一定得是mutablecopy.
2.如果用下面代码出现一个模态ui,这个模态ui中有UITextField或UITextView的成员,那么会出现keyboard, 如果发送resignFirstrRsponder键盘是不会消失的。
UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:searchVC]; nv.modalPresentationStyle = UIModalPresentationFormSheet; [self presentModalViewController:nv animated:YES];
UINavigationController必须用Category的方法实现如下方法,才可以让键盘消失
@interface UINavigationController (DismissKeyboard) - (BOOL)disablesAutomaticKeyboardDismissal; @end @implementation UINavigationController (DismissKeyboard) - (BOOL)disablesAutomaticKeyboardDismissal { return NO; } @end
3.关于NSURLConnection中的delegate,下面是官网的说明:
Note: During a download the connection maintains a strong reference to the delegate. It releases that strong reference when the connection finishes loading, fails, or is canceled.
也就是说,delegate会被NSURLConnection拥有,在非arc情况下,下面的代码也可以
//creates the handler object MyHandlerClass *handler = [[MyHandlerClass alloc] init]; //creates the connection with handler as an autorelease object [[NSURLConnection alloc] initWithRequest:request delegate:[handler autorelease]]; 或 //creates the handler object MyHandlerClass *handler = [[MyHandlerClass alloc] init]; //creates the connection with handler [[NSURLConnection alloc] initWithRequest:request delegate:handler]; //releases handler object [handler release];
MyHandlerClass中NSURLConnection的回调方法也会解发。
在arc情况下代码如下:
//creates the handler object MyHandlerClass *handler = [[MyHandlerClass alloc] init]; //creates the connection with handler [[NSURLConnection alloc] initWithRequest:request delegate:handler];
4. static library中如果用了category, 那么在引用库的时候在other Link中加入-all_load 或 -force_load参考
5. 如果项目工程中有c/c++的源码,那么在编写项目Prefix.pch的时候一定得注意,如果下面这样写,编译会出错:
#ifdef __OBJC__
#import
#import
#endif
#import "AppDelegate.h"
修改方法为如下就正确了:
#ifdef __OBJC__ #import#import #import "AppDelegate.h" #endif
因为这是一个预编译头文件,是全局的,所有源文件对其都是可见的,所以在c/c++源码中也会引入,在c/c++源码中引用objective_c的源码就会出错。
6. UIView 的addSubview:b方法,如果参数b是同一个指针,那么无论调用多少次,它的subview中只有一个b对象。 测试环境是iOS6, 记得iOS3好像没有这个限制。
7. NSNumber能表示的数字整数部份精度只有15位,其实是double的精度。如果需要更高的精度,请用NSDecimalNumber。
8. UITableView相关:
不要在- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath方法中调用
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell,会引起循环调用。
9. 发送crash log 到邮箱
void uncaughtExceptionHandler(NSException *exception) { NSLog(@"CRASH: %@", exception); NSLog(@"Stack Trace: %@", [exception callStackSymbols]); // Internal or email error reporting } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); // Normal launch stuff }
10.加MKAnnotation到MKMapView的时候,MKAnnotation的coord取值范围应是(-180, 180), 如果超出这个范围, 将不能加成功。将不影响MKMapView中数组annotations的个数。
11.用数组的时候一定要先check index是否超出数组大小,否则很容易crash.
12. 声明delegate请用weak类型,否则很容易memory leak.
13. 不要用NSManagedObject对像做为Model数库,即使数据结构一样的,也不要这样做。比如UI A显示查询出来的结果, UI B里delete了数据库,那回到UI A就悲剧了。
14. CFTypeRef是没有ARC的概念,所以需要自己管理内存。在一个方法中返回一个CFTypeRef一定要注意在外面释放内存,不然有内存leak.解决方法有两种,一是在方法面面release返回的CFTypeRef, 二是将方法返回的值改为ObjC的类型,这样就可以支持auto release.
15.在category方法中实现私有方法如- (void)viewDidAppear:(BOOL)animated, 然后在pushViewController
做动画的时候会出现Unbalanced calls to begin/end appearance transitions的错误
16.系统在做动画的时候尽量不要对UIWindow的subview进行操作。本人在pushViewController:vc的时候,在vc的viewDidLoad中对HUD进行了show/hide/show 操作,结果HUD不显示。
17.在UITableViewController这类开发中,UITableView的UITableViewDelegate与UITableViewDataSource要用单独的类来实现,这样可以减轻viewController的负担。UIViewController中是处理消息事件。在UITableView的UITableViewDataSource中千万不要指定第一行显示什么,第二行显示什么,要用数据源控制该显示什么,也就是说应跟据数据源的类型来显示。
18.重用机制一定要小心,比如UITableViewCell就可能是重用机制,所以在用UITableViewCell的时候,一定要恢复初始化再用。
19.不用的代码应毫不犹豫的删掉。
20.如果项目依赖两个库,一个需要在Other Link Flags加-ObjC, 别一个是C/C++的库,则不需要加,那么就需要加一个-licucore来解决问题。