面向对象分析(OOA)、面向对象设计(OOD)、面向对象编程(OOP),是面向对象开发的三个主要环节。
实际项目开发中,项目组长给我一个小功能开发,他说让我设计下。我怎么知道怎么设计?自从看完《代码整洁之道》,我只知道变量,函数,类命名规范,其他的也稀里糊涂。那怎么样才算是设计,怎么样分析,设计呀?
案例:给项目接入实时打点功能。
做成什么样(分析)?
用什么框架?有哪些合格指标?对于容灾兜底逻辑有无要求?性能要求?
很多需求都不明确,可能觉得我是小白,没有办法考虑很高的项目深度,现在就是要求我实现这个功能。 那我该怎么做呢?
面向对象分析主要的分析肯定也是要求需求进行分析,将一个需求拆解为可以具体到实现的小目标。 比如性能是这次就做,还是留到下次进行优化? 容灾逻辑需要现在就添加吗?
-
基础功能分析
第一步想的就是接入目前常用框架Pubsub,通过账号密码验证后就可以上报打点(当然这可能需要进行方案调研,成本分析等等工作)
-
优化:安全
代码安全性,不能将账号密码明文存储在代码里。选择native层密钥来进行存储。
-
优化:性能
代码不需要再主线程里,应该开穿行子线程进行打点,不需要影响主线程性能。
-
优化:隐私
打点之前要采集用户数据,并且用户状态是可能在采集数据的过程中改变,所以每次打点都需要检查开关状态。
-
优化:最后
代码可扩展,那就要重新优化代码,接口编程,对上层和调用打点工具进行抽象化处理。
最后一个优化,其实要在项目开始时就应该设计好,可是这怎么会是一个初级工程机就考虑到的呢?在代码整洁之道里,我们已经了解了,一个项目都是逐步优化的过程。并不是一蹴而就,我们设计的目的就是打开困境,不至于茫然不知道干嘛。
按照什么方案做(设计)?
- 划分职责进而识别出有哪些类;
- 定义类及其属性和方法;
- 定义类与类之间的交互关系;
- 将类组装起来并提供执行入口。
首先划分大模块:
1.初始化Pubsub打点工具
2.检查隐私状态
3.在对应的时机进行打点
继续拆分细节:
- 读取存储中的账号密码(账号密码)
- 初始化Pubsub参数(topic,参数等)
- 初始化Pubsub (构造打点工具)
- 检查隐私(个性化服务,用户隐私等开关)
- 寻打点时机打点(多个页面的展示以及点击)
- 标记页面状态(页面切换,开始计时)
- 初始化打点数据 (页面数据)
- 验证数据有效性 (数据判空)
- 数据类型转化为需要的类型map(需要转化为MAP)
- Pubsub将数据转上传
将上面几个实现点进行合并: 1.pubsub相关的功能点有以下几个
markdown
1. 读取存储中的账号密码(账号密码)
2. 初始化Pubsub参数(topic,参数等)
3. 初始化Pubsub (构造打点工具)
4. Pubsub将数据转上传
js
public class DataUploader {
private String username;
private String password;
private String pubsubTopic;
private int pubsubPort;
private PubsubClient pubsubClient;
private TelemetryTool telemetryTool;
// 构造方法,用于初始化对象时设置基本信息
public DataUploader(String username, String password, String pubsubTopic, int pubsubPort) {
this.username = username;
this.password = password;
this.pubsubTopic = pubsubTopic;
this.pubsubPort = pubsubPort;
}
// 初始化账号密码
public void initializeAccountCredentials() {
// 读取存储中的账号密码逻辑,示例中用到了伪代码
this.username = dataStorage.getUsername();
this.password = dataStorage.getPassword();
}
// 初始化 Pubsub 参数
public void initializePubsubParameters() {
// 初始化 Pubsub 参数逻辑,示例中用到了伪代码
this.pubsubTopic = "your_topic";
this.pubsubPort = 1234;
}
// 初始化 Pubsub
public void initializePubsub() {
// 初始化 Pubsub 逻辑,示例中用到了伪代码
this.pubsubClient = PubsubInitializer.initializePubsubClient();
this.telemetryTool = new TelemetryTool(pubsubClient);
}
// 上传数据到 Pubsub
public void uploadDataToPubsub(String eventData) {
// Pubsub 将数据转上传逻辑,示例中用到了伪代码
telemetryTool.publishEvent(eventData);
}
}
2.打点数据相关
markdown
7. 初始化打点数据 (页面数据)
8. 验证数据有效性 (数据判空)
9. 数据类型转化为需要的类型map(需要转化为MAP)
js
class PageDataInitializer {
fun initializePageData(rawData: Map<String, Any>?): Map<String, Any> {
// 8. 验证数据有效性(数据判空)
val validData = validateData(rawData)
// 9. 数据类型转化为需要的类型map(需要转化为MAP)
return convertDataTypes(validData)
}
private fun validateData(data: Map<String, Any>?): Map<String, Any> {
// 在这里执行您的数据验证逻辑
// 这里仅仅是一个简单的示例,验证数据非空
return data ?: emptyMap()
}
private fun convertDataTypes(data: Map<String, Any>): Map<String, Any> {
// 在这里执行您的数据类型转化逻辑
// 这里仅仅是一个简单的示例,不进行实际转换
return data
}
}
-
检查隐私以及隐私状态管理
- 检查隐私(个性化服务,用户隐私等开关)
-
页面状态和时机处理 5. 寻打点时机打点(多个页面的展示以及点击) 6. 标记页面状态(页面切换,开始计时)
大体的流程就是这样,将参数和功能封装到类里,这是不是很熟悉?
对这就是充血模型
,这样做的好处就是高内聚,并且通过多态使得功能组合起来,降低耦合。这一点还是要多加练习,我也是第一次按照这种方法来分析需求,设计需求,实现,有很多点还没有认识到精髓。