• 开发小结-设计类


    本文主要汇总了自己在软件设计方面的一些经验总结。

    设计评审

    对于一些基础组件的重构改进,在自己做完相关设计后,务必要请组内其他人一起评审下,不要以自我为中心,以为自己写的接口就是完美的。多与人讨论,不管讨论的对象是老手、还是小白,多个角度去审视已有设计,于人于己都是大有益处的。

    基础类接口的设计务必要慎重,一旦成型后,再想改动,难度就很大。举个例子,我之前负责的基类代码,其中有些接口以及内部实现写的不合理,外部用起来很别扭,但因前期使用范围较小,别扭就别扭的用了。随着时间的流逝,该基类被越来越多的人使用,吐嘈声不断,自己有过重构接口的想法和具体方案,但碍于改动牵涉到的面较大,就没有推动改进下去了。

    UI设计

    UI显示逻辑,显示数据来自后台响应,在后台响应数据之前,“当前界面的原始数据是否要清空,有两种看法:

    清空界面数据:优点每次不会看到旧数据,缺点是当网络不好时,显示界面会空白。

    不清空界面数据:优点是在网络尚未返回数据时,用户体验好。缺点是,看到的数据是旧数据。

    具体采用哪种措施,个人觉的取决于当前数据对用户的重要程度以及更新频率,如果数据很重要并且频繁更新,那最好在先清空界面数据,再往后台发送请求。如果不是那么重要,而且更新频率不高,那么不清空界面数据带来的体验较好。

    从开发流程一致性上来看,统一清空界面数据的心智负担较小。

    对于一个界面来说,进入和退出的处理,最好要有相互呼应的地方。怎么理解呢?比如说,打开的时候有清空、申请资源、发送请求、初始化操作的动作,那么退出也要有清空、释放资源、取消请求和卸载操作的动作。不管是某个界面,某个模块,子系统和整个系统,一致性操作要保证,否则就有潜在的泄露问题。

    解决方案设计

    在重新设计时,不要被已有的实现方案所束缚。假设这个模块是从0开始,你会怎么去组织和设计各种信息。

    脑子里面首先想出来的方案,往往不是最佳的,肯定有改进的空间。
    每一个设计方案,首先都有它的整体的设计思路,随后的铺陈展开,都围绕这个整体思路来做。

    任何一个需求或者功能的实现,都可以至少定出两三个方案,在开始具体编码之前,要分析各个方案在实现基本功能之外的优缺点。由团队一起来讨论,看看在这种场景下,使用哪种方案较好。

    将各个模块所使用到的全局数据可以集中汇总到全局类中,如要实现配置热更新功能,则可在配置改变时,只需要更新此类中的内容即可。外部赖该数据的模块,无需改变,只需在全局配置改变事件中重新初始化即可。

    如能够动态计算的内容,不需要额外用变量来保存,对外提供接口函数,在每次获取时,重新计算或者发消息获取。

    对于枚举类型和字符类型的相互转换,如果枚举类型只定义了4种,每一种有对应的数值,

    enum ETest
    {
    	TEST_1 = 1,
    	TEST_2 = 2
    };
    
    ETEst a = (ETEst)1;
    a = (ETEst)3;		 // 这句可以编译通过
    

    枚举类型的强制转换,如果cTemp的值来自于网络流,网络流数据又可能不在已有枚举范围内,会存在无效情况,而这在编译阶段时不会报错不会报错,在运行阶段,该枚举值就有潜在的隐患,为了消除该隐患,建议枚举类型统一通过函数来转换,对于不在枚举值中的转换,提示错误,返回错误类型的枚举值。

    高内聚低耦合

    什么样的功能需要高内聚在一起,在今天的讨论中,比如断线重连提示框的控制和提示框本身实现。

    就这两个功能来说,提示框本身作为一个较独立的功能,若要复用,那么提供的接口函数粒度就可以比较细,让外部使用者根据具体功能来调用各个接口,实现自己的功能。从提供方来说,是可以了。

    但在有些场景下,外部使用者只想设置它关心的数据,其他类型的配置它不想关心,但这些设置有是有必要的,比如位置、Logo等,这个时候,有两种做法:

    方法一:在提示框中,各类设置均有一个有意义的默认值,若外部不设置,则使用默认值。

    方法二: 若外部不想关心与它无关的设置,可在提示框外再提供一个初始化函数,内部设置好默认配置下提示框,提供给外部使用。外部只需要调用者一个初始化函数即可,若有其他的需求,接着调用其他接口就行。

    功能的提供者和功能的使用者关注点是不一样的,提供者提供的粒度可小可大,但从设计原则上来看,每个接口实现的功能要足够细化,而一些较复杂,需要组合各个接口实现的功能,可由使用者来安排,也增加一个中间层,由中间层来构造较高级的接口,高级接口的设计,按照接口一致性来,有create就一定有对应的destory

    高内聚的另一种角度的理解:

    代码被阅读的次数要远远大于它被修改的次数,因此,代码可读性决定了可维护性,代码定义的关联性(相关代码定义和对应辅助函数)要大于分散性。

    相同语意的语句要内聚到一起。具体表现为一组相关的数据类型定义,应该聚合在一起,方便一起阅读理解。比如和登录相关的,登录类型和认证类型就适合放在一起。相互关联的定义以及接口函数,应该或者说必须放在一起。

    颜色的复用

    在程序中涉及到颜色数值,肯定不会直接写死,而是用颜色ID映射具体颜色数值。这里有一个问题,相同的颜色数值,要不要对应同一个颜色ID呢?如果这两个相同的颜色数值用在两个不同的地方,那么他们就是两个不同的颜色ID,即使他们所映射的数值相同。假想未来某个地方颜色值有修改,那只修改对应颜色数值即可,不用影响其他界面。

    为了减少颜色的适配工作量,同时为以后的切换颜色方案打好基础,开发需要限制设计能够允许的颜色取值范围,不能让设计无休止的提各种不同的颜色需求,例如,每一类颜色只提供可选的10左右的ID段范围,可以有多类(12类)颜色,设计提供的总的颜色数值总量控制,具体数值可以自定。

    消息设计

    消息一般有操作系统原生消息,系统级别请求响应消息,系统级别订阅发布消息,还有各个子模块内部使用的自定义消息。每种层级的消息需要定义好使用界限,什么层级的代码使用什么类型范围的消息,在架构设计时,就需要有严格的定义。

    消息宏的定义要全局系统唯一,消息的定义唯一可避免不同模块定义了相同数值的不同功能的消息。要做成全局唯一,最佳实践是在同一层级目录下,定义全局消息,事先定义好各个业务的消息起始段和结束段。

    每一种消息的定义要清楚明确,比如显示用户信息,清除显示这两个功能,

    第一个功能可以定义 WM_SHOW_INFO ,带用户标识可。

    第二个功能的话,有两种做法:

    • 复用WM_SHOW_INFO,传空的用户标识代表清楚显示内容。

    • 单独定义清空界面显示消息,WM_CLEAR_INFO

    这两种做法,推荐使用第二种,它符合消息功能的唯一性。

    针对消息发送来说,不允许跨层消息传递,只允许向上一层发送消息,只响应本模块负责的消息,若不属于本模块的职责,向上继续传递消息。

    消息的命名规范,与现有工程中的消息命名规则保持一致,若不一致,则需要修改使其一致,同时,将本次修改作为单独提交。

    消息的使用场景、使用方法、入参说明以及正常的使用范例,至于消息负责人,可以从SVN的blame功能中推导出来,需要随着消息的定义一同清晰明确的给出。

    对于消息的定义和使用,一种消息带的参数,一定有明确定义,一般不建议传递可变长度的消息,例如如下这种:

    	 struct NMClickNum
    	 {
    		CString m_strName;
    		vector<CString> m_vInfo;
    	 };
    	
    

    在消息中传上述结构体,是有安全隐患的。因为接受者有额外的心智负担,需要考虑传递的顺序和对应的一致性,很容易用错。比如A界面vector里面塞3个数据,B界面塞3个数据,但不同顺序的数据含义不同,在消息接收端,首先判断消息的个数是否符合要求,即使是符合要求,也不能确保特定索引位置上的消息一定是想要的,因为无法判断错误。这种送不定长的消息只适用于网络流层面,在业务层是禁止使用。

    业务层面的消息的目的性要唯一,不能造一个通用层面的消息,携带各种数据,在各种组件之间穿梭。而是,针对特定的业务和界面,定义特定的消息,比如说

    A界面需要3个数据
    B界面需要另3个数据
    C组件产生这3个数据是A界面需要的
    D组件产生的3个数据是B界面需要的
    
    那么,在定义消息时,A-C之间定义一个消息,D-B之间定义另一个消息,不同消息携带的参数要有明显的区分定义,以防用错。
    
    
  • 相关阅读:
    Intent
    What should we do next in general after collecting relevant data
    NOTE FOR Secure Friend Discovery in Mobile Social Networks
    missing pcap.h
    after building Android Source code
    plot point(one column)
    When talking to someone else, don't infer that is has been talked with others at first. It may bring repulsion to the person who is talking with you.
    进程基本知识
    Python input和raw_input的区别
    强制 code review:reviewboard+svn 的方案
  • 原文地址:https://www.cnblogs.com/cherishui/p/10455029.html
Copyright © 2020-2023  润新知