一、概述
「账号」指的就是App的登录账号,如手机号码。你可以能会认为,账号不就一个手机号码,顶多加一个UserInfo
用户信息,这个有啥好讲的呢?确实,市面上大部分App确实如此,也能够满足业务需求了。
不过,实际中存在这样场景下:
- 一个用户的「账号」下面存在「子账号」;
- 用户基础数据多,含有多个用户数据类;
- 用户相关数据,多个接口返回;
- 服务器重构,接口迭代,返回数据字段变更;
- 一个App往往,是允许多个用户登录,有些App也希望缓存多个账号信息,等等。
这些场景下,不进行账号的管理治理,那么后续访问用户基础数据,更新用户基础数据,将会越发吃力,也是很容易出错的。
二、移动端账号需要考虑的问题
账号数据缓存和持久化
大部分的用户数据直接简单本地缓存和内存缓存即,但也存在数据流多访问频率极低的,需要查询的可以考虑持久化到数据库中,例如IM用户关系、通讯录等。账号数据安全性问题
核心数据尽可能不存放本地,例如银行卡号,密码等等。确有需求,则需要考虑安全加密机制,避免被破解泄露信息。账号数据访问接口设计
账号数据是整个App最基础的数据,它的访问频率无疑是最高,网络请求、key值、数据库字段等都需要它。因此,一套方便快捷的访问接口,无疑会让业务方调用更加舒心,无形也提高开发效率。移动端账号数据访问特点
多读少些是移动端账号数据的访问特点,往往是一次更新后续直接访问。对于数据同步方案,可以考虑加入读写锁进行保护。账号数据与服务器解耦
服务器往往因为重构、优化等导致接口数据字段变更,如果一开始直接使用接口数据Model的话,整个App所有相关都要进行修改,如果是跨App或者跨项目,更是无可接受的。
因此,有必要设计内部账号Model,与外部隔离开。
三、设计方案
3.1、账号模块架构设计图
可以大致分为以下几个部分:
BussinessLogic,专门负责账号业务逻辑处理,例如登录、退出、修改密码等,服务接口请求等。
同时负责将服务器接口数据ResponseData 转化为 账号模块需要的数据model。AccessInterface,针对高频账号数据提供的访问接口。
AccountCenter,账号数据管理核心类,
往往被设计成单例类,有此仅有一份,很符合单例特性。
负责账号数据组织,处理缓存逻辑、安全性逻辑。
负责多账号、多子账号管理
切换账号失败数据回滚。Storage,负责账号数据的存储
Security,负责安全加密算法相关。
3.2、账号的数据设计
账号使用独立的数据模型
将服务器接口返回的数据模型 转为 独立设计的账号数据模型。这样在服务器接口移动的时候,本地可以保持不变,业务层接口可以保持不变。账号的数据模型
所有的属性都为只读,避免外部轻易修改;只能通过方法接口修改更新。
@protocol AccountModelProtocol <NSObject>
- (void)updateModelWithData:(id)data;
@end
// userInfo
@interface UserInfo : NSObject <AccountModelProtocol>
@property (readonly) NSString *userId;
@property (readonly) NSString *userName;
@end
@interface UserInfo ()
@property (nonatomic, copy) NSString *userId;
@property (nonatomic, copy) NSString *userName;
@end
@implementation UserInfo
- (void)updateModelWithData:(id)data {
}
@end
- 账号的相关数据进行分类,大致可分为以下:
银行账号、身份证等敏感信息
基础用户信息:手机号码、用户名、性别、生日、区域等
第三方平台账号信息,例如IM、七牛云、阿里云等账号
账号动态变化信息,如登录sessionId、AccessToken信息等。
教育App,用户学校信息、用户班级信息、家长孩子信息。
用户等级信息、Vip信息等
@interface UserInfo : NSObject <AccountModelProtocol>
@end
@interface UserLevelInfo : NSObject <AccountModelProtocol>
@end
@interface SchoolInfo : NSObject <AccountModelProtocol>
@end
- 针对常用的数据,专门提供专门易用接口,方便上层使用。
同时, 对于提供接口,保证数据可用性,为空不返回nil,而是空字符。保证上层不需要判空直接使用,不会导致crash。
// 通过类方法简化
@protocol UserInfoAccessProtocol <NSObject>
+ (NSString *)userId;
@end
@protocol UserLevelAccessProtocol <NSObject>
+ (NSString *)userLevelName;
@end
// 易用接口访问层
@interface AccountCenter (Access) <UserInfoAccessProtocol, UserLevelAccessProtocol>
@end
@implementation AccountCenter (Access)
+ (NSString *)userId {
return accountSingleton.userInfo.UserId ? : @"";
}
+ (NSString *)userLevelName {
return accountSingleton.userLevelInfo.levelName ? : @"";
}
@end
数据完整性校验
针对保存进来的数据,需要进行完整性校验,保证数据的可用性。例如用户数据,userid、phone必须不为空;第三方账号account、appid必须不为空。账号访问接口建议提供同步接口
对于账号数据访问,都是要求快速且同步的;如果设计成异步,往往给业务调用者造成不必要麻烦。遇见过将其设计成异步,真的是无尽的深渊。根据账号访问特性,设计读写锁进行多线程同步。
可根据实际需要提供深拷贝的接口