月黑风高,好兄弟发给我一个重构需求,咨询我的定见。

一、 场景剖析

开发的产品是需求运行到不同的定制Android板子,不同板子有对应的不同SDK供给的API,现在的事务端,事务流程基本是确定的,比方有事务流程为翻开板子的某项开关(需求便是翻开开关),对应在板子中或许存在A、B、C三个板子或者更多,其间板子都供给了翻开开关S的办法,可是办法称号各不相同,现在在代码中的运用办法都是,创立一个服务于事务的东西类,在东西类中判别板子类型创立不同的SDK,并运用不同SDK的API完结这个需求。

关于商业SDK的开发及多SDK运用,我有丰厚的规划经历,面临这个问题,立马能说出这个描绘中存在的问题有多少,所以定见是重构!必须重构。

1.1 存在问题

我从来都是以理服人,必须要着说明为什么重构,怎么重构,成果是什么.

规划形式巡礼:多板适配事例解析与深度重构

1.2 复原代码,暴露问题

剖析上述问题,其间的重点有以下几处:

  1. 多板子(开发平台多,第一反响便是要适配(描绘紊乱的原因之一便是适配导致的))
  2. 事务概念一致(什么是事务概念一致呢?举个例子,关于产品而言,在产品需求发布的时候说,当用户点击按钮1时,红灯亮,这便是一个一致的事务概念,因为咱们是多板子的开发,咱们立马,应该考虑的便是分散性的思考)
  3. 不同板子都供给了SDK,可是API并不相同(此处可以这样剖析一下,关于定制开发的场景中,特别是这种场景下,需求的完结与否只与板子的供给需求是否相吻合(供给需求便是板子自身对外的开放功用))

经过这三点可以看出,这个需求其实很简略,很明晰,可是关于上述的描绘的完结办法,肯定是不行的。

为了好解决问题,咱们要引进几个实体板子称号(在开发中,领域模型非常重要,事关需求的成功与否、事关团队的配合度凹凸), 假定现在面临的板子有例如树莓派(Raspberry Pi)、小米开发板、华为开发板。然后复原一下代码

假定东西类称号为ControlBroadUtil, 复原代码如下

规划形式巡礼:多板适配事例解析与深度重构

这大约便是描绘复原的代码,这问题就很明晰了。

  1. 硬编码板子类型判别: 现在的完结办法中,经过在事务东西类中硬编码板子类型判别,这会导致代码的脆弱性。一旦有新的板子类型加入,就需求修正代码,或许引进新的错误。
  2. SDK办法称号不一致: 不同板子的SDK供给了相同功用的办法,但办法称号却不同。这种状况或许会导致紊乱,使得代码变得难以了解和保护。
  3. 紧耦合的事务东西类: 现在的规划中,事务东西类担任判别板子类型并挑选相应的SDK。这样的紧耦合规划违反了单一职责准则,使得代码难以测验和扩展。
  4. 可保护性差: 跟着板子类型的增多,事务东西类会变得越来越巨大,难以保护。任何一次修正都或许引发意外的问题。
  5. 扩展性问题: 当需求支持新的板子类型时,现在的规划需求修正现有代码,而不是简略地增加新的板子类型的完结。这降低了体系的可扩展性。
  6. 缺少笼统层: 现在的完结没有明确的笼统层,使得在引进新板子类型时无法简略地运用接口进行一致操作。这违反了面向目标规划的一些准则。
  7. 缺少文档和标准: 因为不同板子类型的办法称号不同,缺少明晰的文档和标准,团队成员或许难以了解和运用不同板子的SDK。

二、 谈谈重构思路,有哪些预留项

面临这类型的问题,其实内行第一眼就想到重构的办法了,我的主张是在给出重构定见时必须考虑后续的问题。

2.1 运用笼统工厂形式(意图便是简化、一致、别离创立流程,运用笼统工厂形式可以满意)

  • SDK的创立的独立互不影响,对应SDK的装备项都可以在自己的工厂中完结(为什么要用笼统工厂不必简略工厂?因为后续关于一个板子的改变维度或许超过两个(多套API))
  • 可以根据不同的板子进行合理的挑选
  • 在特定场景中可以自由切换,比方华为的不同版本板子,在晋级之后的切换场景。

2.2 类图结构如下

2.2.1 SDK创立UML

规划形式巡礼:多板适配事例解析与深度重构

其间:

ControlBoardFactory (笼统工厂):它声明晰一组用于创立一族产品的办法,每个办法对应一种产品,在这里便是每一种板子的SDK。

/**
*  
* @author: kpa  
* @date: 2024/2/7  
* @description: 它声明晰一组用于创立一族产品的办法,每个办法对应一种产品,在这里便是每一种板子的SDK。  
*/  
abstract class ControlBoardFactory<out T : ControlBoardService> {  
    abstract fun createControlBoard(): T  
}

HuaweiFactory等(详细工厂):它完结了在笼统工厂中声明的创立产品的办法,生成一组详细产品,这些产品构成了一个产品族,每种产品都位于某个产品等级结构中。

/**
*  
* @author: kpa  
* @date: 2024/2/7  
* @description:huawei 板子的创立工厂  
*/  
class HuaweiControlBoardFactory : ControlBoardFactory<HuaweiBoardServiceImpl>() {  
    override fun createControlBoard(): HuaweiBoardServiceImpl {  
        return HuaweiBoardServiceImpl()  
    }  
}

ControlBoardService(笼统产品):它为每种产品声明接口,在笼统产品中声明晰产品所具有的事务办法。

/**
*  
* @author: kpa  
* @date: 2024/2/7  
* @description: 笼统产品,对应事务,为需求接口  
*/  
interface ControlBoardService {  
    fun switch(switchValue: Int)  
}

HuaweiControlBordImpl等(详细产品):它定义详细工厂出产的详细产品目标,完结在笼统产品接口中声明的事务办法。

/**
*  
* @author: kpa  
* @date: 2024/2/7  
* @description:  
*/  
class HuaweiBoardServiceImpl : ControlBoardService {  
    override fun switch(switchValue: Int) {  
        TODO("Not yet implemented")  
    }  
}

2.2.2 SDK API运用UML

关于类中提的供给方接口将运用适配器形式完结与已知SDK API适配,此处规划的意图是:

  1. 需求开发中,不需求考虑详细的完结,咱们应该做到笼统的需求接口和产品需求是一致的。这样咱们即便撤走部分SDK或者增加n中SDK都不会影响咱们的事务。
  2. SDK的API咱们是不可以介入编程的,所以他在编码体系中只能是直接运用,可是直接运用就会导致代码的耦合性太高,对三方的依赖太强可不是什么好事

所以决议对笼统产品(ControlBoardService)部分运用适配器形式进行规划,要求是:

  1. 事务方无感SDK的调用但要调用
  2. 事务方可以多组合+自主完结

规划形式巡礼:多板适配事例解析与深度重构

组合办法:

class HuaweiBoardServiceImpl : ControlBoardService {
    private val huaweiBoardSDK: HuaweiBoardSDK by lazy { HuaweiBoardSDK() }  
    override fun switch(switchValue: Int) {  
        huaweiBoardSDK.huaweiOpenSwitch(switchValue)  
    }  
}

2.2.3 外观形式,保持事务掉用的整齐

规划形式巡礼:多板适配事例解析与深度重构

如果运用上述的代码,在一套体系中还是会出现调用紊乱的问题,呐,处理办法便是运用外观形式,右边部分为外观形式下的物理、逻辑结构。

外观形式相对简略。 类图就不画了代码如下:

/**
*  
* @author: kpa  
* @date: 2024/2/7  
* @description: 外观形式下的东西类  
*/  
object ControlBroadUtil {  
    private val huaweiBoardFactory: HuaweiControlBoardFactory by lazy { HuaweiControlBoardFactory() }  
    // 其他工厂  
    //...  
    // 需求接口,面相该接口编程  
    private var controlBoardService: ControlBoardService? = null  
    /**  
    * 供给商环境  
    */  
    private var supplierEnvironment = ""  
    private fun init() {  
    // 一致装备读取  
       supplierEnvironment = System.getProperty("")  
        controlBoardService = huaweiBoardFactory.createControlBoard()  
    }  
    /**  
    * 直接运用接口编程  
    */  
    public fun getControlBoardService(): ControlBoardService {  
        return controlBoardService ?: HuaweiControlBoardFactory().createControlBoard()  
    }  
}

三、重构成果剖析

经过以上的剖析和重构思路,可以得出以下重构成果剖析:

3.1 笼统工厂形式的长处

  1. 松耦合: 笼统工厂形式将产品的创立与运用别离,使得体系愈加灵活,减少了模块间的直接依赖,到达松耦合的效果。
  2. 可扩展性: 当需求增加新的板子类型时,只需增加新的详细工厂和产品类,无需修正已有代码,契合开闭准则,提高了体系的可扩展性。
  3. 一致接口: 笼统工厂形式供给了一组一致的接口,使得客户端无需关怀不同板子的详细完结细节,从而简化了客户端代码。
  4. 事务概念一致: 经过笼统工厂形式,可以将不同板子的SDK一致到一组接口中,使得事务概念愈加明晰和一致。

3.2 适配器形式的长处

  1. 解耦: 适配器形式将事务代码与SDK的详细完结解耦,事务方无需关怀底层SDK的细节,提高了代码的可保护性和可读性。
  2. 灵活性: 适配器形式使得事务方可以更灵活地挑选和切换不同的SDK,而无需修正事务代码,降低了对SDK的依赖性。
  3. 可扩展性: 当需求增加新的SDK时,只需完结适配器接口即可,无需修正已有代码,契合开闭准则,提高了体系的可扩展性。

四、总结

经过对现有代码的剖析和重构,咱们解决了原有代码存在的问题,提高了体系的可保护性、可扩展性和可读性。运用笼统工厂形式和适配器形式,使得体系愈加灵活,事务概念愈加一致,事务代码与底层SDK的完结解耦。这样的规划不仅适应了当时的事务需求,还为未来的扩展和改变供给了杰出的支持。

在实践开发中,重构是一个不断演进的进程,需求根据实践状况灵活运用规划形式和准则,不断优化和改善代码结构。一起,杰出的文档和标准也是团队协作的重要保障,可以使团队成员愈加容易了解和运用不同板子的SDK。