一个游戏程序员的代码书写观(一)

一个游戏程序员的代码书写观(一)

故事

游戏中基本都有MessageBox的需求,虽然可以使用OS层面的MessageBox,但是一般而言都不能满足游戏的需求,有鉴于此,我们实现了第一版的定制MessageBox:


public class MessageBoxManager
{
    public enum Mode
    {
        Confirm,
        ConfirmCancel,
    }

    public static void ShowMessageBox(
                                       string title, 
                                       string content, 
                                       Mode mode = Mode.Confirm,
                                       Action onConfirm = null,
                                       Action onCancel = null
                                     )


    // implementations

}

这个实现感觉还可以,虽然参数总共有5个,感觉有些略多,但是我们有预见性的提供了默认参数,同时我们提供了基本的MessageBox功能,可以设置标题,内容,显示模式以及可能的回调函数,基本不用编写什么使用文档,稍有经验的程序员都可以顺畅的写出使用代码:


MessageBoxManager.ShowMessageBox("Title", "My First Message Box !");

随着初版MessageBox的广泛使用,相关的需求也在不断升级,现在我们需要支持可以主动关闭的MessageBox了,分析需求后我们意识到这是一种新的MessageBox模式,经过一定扩展,我们有了第二版的MessageBox:


public class MessageBoxManager
{
    public enum Mode
    {
        Confirm,
        ConfirmClose,
        ConfirmCancel,
        ConfirmCancelClose,
    }

    public static void ShowMessageBox(
                                       string title, 
                                       string content, 
                                       Mode mode = Mode.Confirm,
                                       Action onConfirm = null,
                                       Action onCancel = null,
                                       Action onClose = null,
                                     )


    // implementations

}

Mode的类型增加了,并且接口参数也增加至6个,这里似乎已经有些坏味道了,但是毕竟只增加了一个参数,并且也提供了默认参数,使用上的复杂度似乎还可以接受~

很快的,更多的需求又接踵而至了,现在我们又需要定制MessageBox的按钮文字了,按照之前的思路,我们继续往接口中添加参数:


public class MessageBoxManager
{
    public enum Mode
    {
        Confirm,
        ConfirmClose,
        ConfirmCancel,
        ConfirmCancelClose,
    }

    public static void ShowMessageBox(
                                       string title, 
                                       string content, 
                                       Mode mode = Mode.Confirm,
                                       Action onConfirm = null,
                                       Action onCancel = null,
                                       Action onClose = null,
                                       string confirmText = null,
                                       string cancelText = null,
                                     )


    // implementations

}

还没等这版MessageBox实现完毕,我们又收到了新的需求:MessageBox需要支持超时!好吧,我们又不假思索的继续添加接口参数:


public class MessageBoxManager
{
    public enum Mode
    {
        Confirm,
        ConfirmClose,
        ConfirmCancel,
        ConfirmCancelClose,
    }

    public static void ShowMessageBox(
                                       string title, 
                                       string content, 
                                       Mode mode = Mode.Confirm,
                                       Action onConfirm = null,
                                       Action onCancel = null,
                                       Action onClose = null,
                                       string confirmText = null,
                                       string cancelText = null,
                                       float timeOut = 0,
                                       Action onTimeOut = null,
                                     )


    // implementations

}

现在,我们之前相对简洁的接口已经变的非常冗长,参数更是达到了惊人的10个,使用上也变得非常困难,虽然提供了默认参数,但是仍然容易产生误用,考虑我们使用新接口来定制确认按钮的文字


MessageBoxManager.ShowMessageBox("Title", 
                                 "My Customize Message Box !", 
                                 MessageBoxManager.Mode.Confirm, 
                                 null, 
                                 null, 
                                 null,
                                 null,
                                 "好的");

不仅长串的null参数让人心烦,而且接口的调用还是错误的:我们不小心将confirmText参数设置给了cancelText……

方法

放弃原接口的默认参数实现方式,转而使用重载的方式来提供多个接口已达到分解功能的目的,虽然仍然存在参数组合过多导致接口数量过多的问题,但是感谢二八原则,在实际的重载过程中,我们可以根据使用情况来达到相对平衡的封装程度,对于第三方的代码,如果遇到类似参数过多的问题,我们也可以借助外观模式等方法做类似的处理

据此我们实现的新版MessageBox:


public class MessageBoxManager
{
    public enum Mode
    {
        Confirm,
        ConfirmClose,
        ConfirmCancel,
        ConfirmCancelClose,
    }

    public static void ShowMessageBox(
                                       string title, 
                                       string content, 
                                       Mode mode = Mode.Confirm,
                                       Action onConfirm,
                                       Action onCancel,
                                       Action onClose,
                                       string confirmText,
                                       string cancelText,
                                       float timeOut,
                                       Action onTimeOut,
                                     )

    public static void ShowMessageBox(
                                       string title, 
                                       string content, 
                                       Action onConfirm,
                                     )
    {
        ShowMessageBox(title, content, Mode.Confirm, onConfirm, null, null, null, null, 0, null);    
    }

    public static void ShowMessageBox(
                                       string title, 
                                       string content, 
                                       Action onConfirm,
                                       Action onCancel,
                                     )
    {
        ShowMessageBox(title, content, Mode.ConfirmCancel, onConfirm, onCancel, null, null, null, 0, null);  
    }

    // other useful overrides

    // implementations

}

准则

函数的参数数量应该尽可能的控制(Rob大叔在《CleanCode》中描述过的一个观点是尽量减少函数参数的数量,最好不要超过三个),但是实际开发中因为需求增加、时间压力等情况,往往会出现函数参数数量增加甚至爆炸的情况,这种情况下可以考虑采取重载等方式进行进一步的封装,同时基于实际的使用情况来达到尽可能的平衡~

简单一句话:遇到复杂度偏高的代码,考虑进行平衡的封装吧!

猜你喜欢

转载自blog.csdn.net/tkokof1/article/details/70135846
今日推荐