代码之家  ›  专栏  ›  技术社区  ›  BIBD

环球还是不好吗?

  •  3
  • BIBD  · 技术社区  · 15 年前

    我今天遇到了一些类似这样的代码;具有对整个类可见的流控制标志。我的直觉告诉我,这是处理流量控制需求的错误方法(这几乎就像C中的旧时代全局标志)。

    Public Class myClass
    
        Private bMyFlag As Boolean ''// <------
    
        private sub New
            bMyFlag = false
        end sub
    
        private sub mySub1
            bMyFlag = true
            mySub3()
            mySub4()
            mySubN()
        end sub
    
        private sub mySub2
            bMyFlag = false
            mySub3()
            mySub4()
            mySubN()
        end sub
    
        private sub mySub3
            if bMyFlag then
                DoSomething()
            else
                DoSomethingElse()
            end if
        end sub
    
        private sub mySub4
            if not bMyFlag then
                DoSomethingDifferent()
            else
                DoSomethingReallyDifferent()
            end if
        end sub
    
        private sub mySubN
            if not bMyFlag then
                DoNotPassGo()
            else
                DoNotCollect200Dollars()
            end if
        end sub
    end class
    

    对我来说很明显,这是事后移植的。我计划重新编写代码,使bMyFlag成为传递给mySub3、mySub4和mySuvN的参数。然而,在我这样做之前:

    是否有一个对类全局的流控制标志的有效原因?

    或者,如果不是,为什么这被认为是不好的做法?

    8 回复  |  直到 15 年前
        1
  •  12
  •   Matt Briggs    15 年前

    这不是一个全局(即应用程序范围)变量,它是实例级别(即作用于类)的变量。这没有什么错,只要这是预期的。

    因此,当该标志为真时,如果它对整个实例为真,则该标志应为真。如果它是某种通用的东西,每次都以完全不同的方式使用,那么就不应该在那里声明它。

        2
  •  9
  •   StingyJack    15 年前

    我不认为这是一个真正的“全球”。它只是一个成员级别的字段。这在大多数情况下都是完全可以接受的(但对于流控制来说并不是如此——看起来您真正需要的是一些类的重新设计)。

        3
  •  7
  •   Donut    15 年前

    bMyFlag 似乎引入了不必要的状态,这可能会使开发(调试等)复杂化。一些子例程修改其值,其他子例程根据其当前值执行不同的操作。这似乎引入了不必要的复杂性,可以通过一些重构来降低复杂性。为什么不直接将布尔值传递给 mySub1 mySub2 ,然后让这些子例程以该值作为参数调用其他函数?

        4
  •  4
  •   tvanfosson    15 年前

    从一个虚构的例子很难看出,但是你可能想考虑引入一种策略模式来处理基于对象状态的不同行为。通过这种方式,您可以将不同的Behvior实现为可互换的策略。这些策略将根据对象的状态进行交换。每个方法都只需为其行为调用当前策略。当然,我只会在策略复杂或众多的情况下这样做。

    对于一些合理简单的东西,您也可以使用继承,例如,我有两种状态:只读和可编辑。锁定对象将获取可编辑对象并返回该对象的只读版本。实际上,只有一个对象,但它周围有可编辑和只读包装器。行为上的差异内置于包装器中(如果您试图更改某些内容,readonly对象将引发异常)。

    如果它非常简单且不普及,我认为保持现状没有任何真正的问题。最终,if/else的东西会变得复杂难看,然后你可以重构成我上面描述的更干净的东西。

    使现代化 根据您的评论:

    听起来你有一个问题是可以通过继承来解决的。你想要一个LoggableObject。此LoggableObject有两个不同的变体:ScreenLoggable和FileLoggable。为ILogable定义一个接口,并定义一个包含任何公共代码的抽象基类。然后定义一个写入屏幕的ScreenLoggable类,它应该从基类继承并包含写入屏幕的代码的变体。定义写入文件的FileLoggable类。它还应该从基类继承,但包含写入文件的变量。使用工厂根据标记创建所需的iLogable类型。根据界面使用它,它将 做正确的事。

        5
  •  2
  •   Vinay Sajip    15 年前

    那里 通常情况下,你所指的模式是有效的。毕竟,对象是数据+操作,在您的示例中 bMyFlag 只是一些对象数据(状态)。如果其他方法不使用 ,而且只有 mySub3 , mySub4 mySubN 这样,你就可以把它作为他们的一个参数。否则,保持现状是合理的,并且 bMyFlag 是类的有效实例成员,如果它封装了实例的某些有用状态。

        6
  •  1
  •   giorgian    15 年前

        7
  •  1
  •   Cellfish    15 年前

    如果您的示例代码反映了真实的代码,我会说使用flag成员是一种糟糕的做法。Mysub3、mysub4等实际上是在做两件不同的事情,所以它们应该是不同的方法。因此根本不需要旗帜。

        8
  •  0
  •   Jon Spokes    15 年前

    如果您想将所有代码都保存在这个类的本地,您可以在其中嵌套这些类。类似以下内容(如果vb语法错误,很抱歉,已经有一段时间了)

    Public Class myClass
    
    Private bMyobj As iThing ' <------
    
    Private Sub New()
        bMyobj = null
    End Sub
    
    Private Sub mySub1()
        bMyobj = New Thing2()
        mySub3()
        mySub4()
        mySubN()
    End Sub
    
    Private Sub mySub2()
        bMyobj = New Thing1()
        mySub3()
        mySub4()
        mySubN()
    End Sub
    
    Private Sub mySub3()
        bMyObj.DoSomething()
    End Sub
    
    Private Sub mySub4()
        bMyObj.DoSomethingDifferent()
    End Sub
    
    Private Sub mySubN()
        bMyObj.PassGo()
    End Sub
    
    
     Public Interface iThing
         Sub DoSomething()
         Sub DoSomethingDifferent()
         Sub PassGo()
     End Interface
    
     Public Class Thing1
         Implements iThing
    
         Public Sub DoSomething()
             ' Implementation 1
         End Sub
         Public Sub DoSomethingDifferent()
             ' Implementation 1
         End Sub
         Public Sub PassGo()
             ' Don't do it
         End Sub
     End Class
     Public Class Thing2
         Implements iThing
         Public Sub DoSomething()
             ' Implementation 2
         End Sub
         Public Sub DoSomethingDifferent()
             ' Implementation 2
         End Sub
         Public Sub PassGo()
             ' Don't collect 200 dollars
         End Sub
     End Class
    
    End Class