🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 模型Model应该放什么代码 在以往开发中,对于模型层笔者存在这么几个疑惑: * 模型Model只是一个纯粹的数据结构 * 负责数据I/O操作的操作属于`C`还是`M` 第一个问题笔者认为原因在于认知错误,过往开发的过程中,笔者曾经一度认为数据和模型之间的转换属于业务操作,将这些处理放在控制器`Controller`层中执行: ~~~ - (void)analyseRequestJSON: (NSDictionary *)JSON { NSArray *modelsData = JSON[@"result"]; NSMutableArray *models = @[].mutableCopy; for (NSDictionary *data in modelsData) { LXDRecord *record = [[LXDRecord alloc] init]; record.content = data[@"content"]; record.recorder = data[@"recorder"]; record.createDate = data[@"createDate"]; record.updateDate = data[@"updateDate"]; [models addObject: record]; } } ~~~ 这是典型的认知错误引发的代码错误放置的错误,对于这种情况,直接常见的做法是在`Model`中直接加入全能构造器`Designed Initializer`来将这部分代码转移至`Model`中: ~~~ @interface LXDRecord: NSObject //properties - (instancetype)initWithCreateDate: (NSString *)createDate updateDate: (NSString *)updateDate content: (NSString *)content recorder: (NSString *)recorder; @end //Controller - (void)analyseRequestJSON: (NSDictionary *)JSON { NSArray *modelsData = JSON[@"result"]; NSMutableArray *models = @[].mutableCopy; for (NSDictionary *data in modelsData) { LXDRecord *record = [[LXDRecord alloc] initWithCreateDate: data[@"createDate"] updateDate: data[@"updateDate"] content: data[@"content"] recorder: data[@"recorder"]]; [models addObject: record]; } } ~~~ 在转移`数据->模型`这一逻辑处理之后数据层相对而言就充实的多,但这还不够。数据在完成抽象转换的工作之后,通常要展示到视图层面上。但往往模型还需要进行额外的加工才能展示,比如笔者曾经项目中的一个需求:`用户在缴纳宽带费用后将宽带办理期间显示出来`,这需求建立在服务器只有`办理时间`和`办理时长`两个字段。在`MVC`的结构下,将这部分代码放在`C`层会导致代码过多过于杂乱的后果,因此笔者将其放在`Model`中: ~~~ @interface YQBNetworkRecord: YQBModel @property (nonatomic, copy, readonly) NSString *dealDate; //办理时间 @property (nonatomic, copy, readonly) NSString *effectTime; //办理时长 - (NSString *)timeOfNetworkDuration; @end @implementation YQBNetworkRecord - (NSString *)timeOfNetworkDuration { NSTimeInterval effectInterval = [_effectTime stringToInterval]; return [_dealDate stringByAppendString: [_dealDate dateAfterInterval: effectInterval]]; } @end ~~~ 这一做法将一部分`C` 层次的逻辑放到了`M`中,由于这一部分的逻辑属于`弱业务`,属于几乎不会改动的业务逻辑,因此并不会影响`MVC`的整体结构。但同样也存在着风险: * 代码依赖于`Model`的差异化,复用性低 * 代码量取决于`Model`的数量,容易导致`胖Model`的情况 虽然存在着这些不足,但是如果是在`MVC`模式下对控制器进行减负的情况下,这种做法简单有效。另外,使用`category`将这些逻辑代码分离出去可以使得复用性变得不那么的糟。当然上面的`数据->模型`过程中也存在着因为数据类型变化而导致构造器失效的问题,这时候参考`YYModel`的做法可以减少或者解决这些问题的发生