避免if语句(avoiding if statements)

2019-08-02 17:32发布

我想着今天的面向对象的设计,我想知道你是否应该避免if语句。 我的想法是,在你需要的任何情况下,如果语句,您可以简单地创建一个实现了相同的方法两个对象。 这两种方法实现,简直是if语句原来的两个可能的分支。

我知道这似乎极端,但它好像你可以尝试,并认为在一定程度上。 在这个有什么想法?

编辑

哇,这没多久。 我想这是太极端。 是否有可能,虽然说是OOP下,你应该期望的方式不太if语句?

第二个编辑

这个怎么样:基于它的属性决定了它的方法实现的对象。 也就是说,你可以实现someMethod()两种方式,并指定一些限制。 在任何时候,一个对象会以正确的方法实现路径根据其性质。 所以在的情况下, if(x > 5)只是依赖于两种方法x属性

Answer 1:

我可以告诉你一两件事。 不管别人说什么,想简化和消除不必要的分支是你成熟的软件开发人员的一个标志。 有很多原因,分支是坏的,测试,维护,错误率较高等特点。 这是对的事情,我看采访的人,当针对一个,是一个很好的指标他们是作为一个开发者如何成熟。 我会鼓励你继续实验,通过使用更小的条件简化了您的代码和设计。 当我做这个开关,我发现少得多的时间调试我的代码,它只是简单的工作,然后,当我不得不改变一些东西,变化是超级容易做,因为大部分的代码是连续的。 我再次鼓励你100%继续做你正在做什么,不管别人说什么。 请记住,大多数开发商正在和思维的水平要低得多,只是遵循的规则。 因此,搞好提出这个问题。



Answer 2:

说明如何实现以下没有if语句或三元逻辑:

if ( x < 5 ) {
   x = 0
} else {
   print x;
}


Answer 3:

是它的真实,往往复杂的条件句可以用polymorphishm简化。 但它没有用所有的时间。 去阅读福勒的重构书时得到的一个想法。

http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html



Answer 4:

完全消除if语句是不现实的,我不认为这是大利是在暗示。 但是,他们往往使用多态来替代。 (因此可以在许多switch语句)。

弗朗切斯科奇里洛开始了反如果运动提出这个问题的认识。 他说:

知道如何使用对象让开发者消除基于类型的IF,那些最经常危及软件的灵活性和进化的能力。

您或您的团队还可以加入这项运动 。



Answer 5:

我的一位老师曾经说。 我倾向于认为,人们是如此教条之类的话,通常是做不计划。



Answer 6:

看一看反运动。如果我们的想法是不是要取代每一个如果与战略或国家模式的应用程序。 我们的想法是,当你有特别是基于类似的枚举复杂的分支逻辑,你应该看看重构的战略格局。

而这种情况下,你可以通过使用一个工厂如果一起删除。 这里是一个相对简单的例子。 当然,正如我在一个真实的案例说,在你的策略逻辑将不仅仅是打印出“我主动”多一点复杂。

public enum WorkflowState
{
  Ready,
  Active,
  Complete
}

public interface IWorkflowStrategy
{
  void Execute();
}

public class ActiveWorkflowStrategy:IWorkflowStrategy
{
  public void Execute()
  {
    Console.WriteLine("The Workflow is Active");
  }
}

public class ReadyWorkflowStrategy:IWorkflowStrategy
{
  public void Execute()
  {
    Console.WriteLine("The Workflow is Ready");
  }
}

public class CompleteWorkflowStrategy:IWorkflowStrategy
{
  public void Execute()
  {
    Console.WriteLine("The Workflow is Complete");
  }
}

public class WorkflowStrategyFactory
{
  private static Dictionary<WorkflowState, IWorkflowStrategy> _Strategies= 
    new Dictionary<WorkflowState, IWorkflowStrategy>();
  public WorkflowStrategyFactory()
  {
    _Strategies[WorkflowState.Ready]=new ReadyWorkflowStrategy();
    _Strategies[WorkflowState.Active]= new ActiveWorkflowStrategy();
    _Strategies[WorkflowState.Complete = new CompleteWorkflowStrategy();
  }
  public IWorkflowStrategy GetStrategy(WorkflowState state)
  {
    return _Strategies[state];
  }
}

public class Workflow
{
    public Workflow(WorkflowState state)
    {
        CurrentState = state;
    }
    public WorkflowState CurrentState { get; set; }
}

public class WorkflowEngine
{
    static void Main(string[] args)
    {
        var factory = new WorkflowStrategyFactory();
        var workflows =
            new List<Workflow>
                {
                    new Workflow(WorkflowState.Active),
                    new Workflow(WorkflowState.Complete),
                    new Workflow(WorkflowState.Ready)
                };
        foreach (var workflow in workflows)
        {
            factory.GetStrategy(workflow.CurrentState).
                Execute();
        }
    }
}   


Answer 7:

避免if语句:有很多方法可以做到,其中一人是下面:

int i=0;
if(i==1)
{
//Statement1
}

if(i==2)
{
//Statement2
}

if(i==3)
{
//Statement3
}

if(i==4)
{
//Statement4
}

使用字典和委托:

delegate void GetStatement ();

Dictionary<int,GetStatement > valuesDic=new Dictionary<int,GetStatement >();

void GetStatement1()
{
//Statement1
}
void GetStatement2()
{
//Statement2
}
void GetStatement3()
{
//Statement3
}


void GetStatement4()
{
//Statement4
}

void LoadValues()
{
valuesDic.Add(1,GetStatement1);
valuesDic.Add(2,GetStatement2);
valuesDic.Add(3,GetStatement3);
valuesDic.Add(4,GetStatement4);

}

如果更换的声明:

int i=0;
valuesDic[i].Invoke();


Answer 8:

在某些方面,这可能是一个好主意。 Swiching上的对象内的类型字段通常是一个坏主意时,你可以使用虚拟functtions代替。 但虚函数机制绝非为了取代如果()测试一般。



Answer 9:

你如何决定,而不if语句使用哪个对象的方法?



Answer 10:

这取决于什么原始语句进行比较。 我的经验法则是,如果它是一个switch或者if测试平等对抗的枚举,那么这就是一个单独的方法一个很好的候选人。 然而, switchif语句用于许多,许多其他类型的测试-有替换关系运算符(没有什么好办法<><= >= )有专门的方法,以及一些类型的列举的测试工作多更好地与标准语句。

所以,你应该只替换if ■如果他们是这样的:

if (obj.Name == "foo" || obj.Name == "bar") { obj.DoSomething(); }
else if (obj.Name == "baz") { obj.DoSomethingElse(); }
else { obj.DoDefault(); }


Answer 11:

在回答ifTrue的问题:

好吧,如果你有公开课和足够强的依赖型系统,它很容易,如果有点傻。 通俗地说,在任何特定的语言:

class Nat {
    def cond = {
        print this;
        return this;
    }
}

class NatLessThan<5:Nat> { // subclass of Nat
    override cond = {
        return 0;
    }
}

x = x.cond();

(继续...)

或者说,没有公开课,但假设多个调度和匿名类:

class MyCondFunctor {
    function branch(Nat n) {
        print n;
        return n;
    }

    function branch(n:NatLessThan<5:Nat>) {
        return 0;
    }
}

x = new MyCondFunctor.branch(x);

或者,像以前一样但匿名类:

x = new {
    function branch(Nat n) {
        print n;
        return n;
    }

    function branch(n:NatLessThan<5:Nat>) {
        return 0;
    }
}.branch(x);

你有一个更容易的时间,如果你重构这个逻辑,当然。 请记住,存在完全图灵完备型系统。



Answer 12:

创建为一个全新的类else ,而技术上是可行的,可能会导致代码很难阅读,维护,甚至被证明是正确的。



Answer 13:

Assume we have conditional values.

public void testMe(int i){

if(i=1){
somevalue=value1;
}


if(i=2){
 somevalue=value2;
}

if(i=3){
somevalue=value3;
}

}

//**$$$$$you can replace the boring IF blocks with Map.$$$$$**

// ================================================ ============

Same method would look like this:
--------------------------------
public void testMe(int i){

Map<Integer,String> map = new HashMap<Integer,String>();

map.put(1,value1);
map.put(2,value2);
map.put(3,value3);

}
This will avoid the complicated if conditions.

您可以使用工厂模式加载类时使用simliar解决方案。

public void loadAnimalsKingdom(String animalKingdomType)
    if(animalKingdomType="bird"){
    Bird b = new Bird();
    }
    if(animalKingdomType="animal"){
    Animal a= new Animal();
    }
    if(animalKingdomType="reptile"){
    Reptile r= new Reptile();
    }
  }

现在,使用地图:

   public void loadAnimalsKingdom(String animalKingdomType)
    {
       Map <String,String> map = new HashMap<String,String>();

       map.put("bird","com.animalworld.Bird.Class");
       map.put("animal","com.animalworld.Animal.Class");
       map.put("reptile","com.animalworld.Reptile.Class");

       map.get(animalKingdomType);

***Use class loader to load the classes on demand once you extract the required class from the map.***
}

像解决? 给竖起大拇指。 - VV



Answer 14:

这是一个有趣的想法。 我认为,理论上你就可以做到这一点,但它会在不专门用于支持其语言的巨大痛苦。 当然,我看不出有任何理由。



Answer 15:

我觉得他在说什么或者他的意思说的是,他认为这是最好的几个,以避免“标记”,并添加自定义功能的一类的过度滥用,如果当它更好地使语句意义的子类,或者重新考虑对象层次结构。



Answer 16:

这是极端的。 做你的建议是什么会引起很多不必要的重复代码,除非整个功能是完全不同的,基于单一如果周围; 如果是这样,如果可能应该已经对方法调用的另一边。

如果语句肯定有他们在面向对象的设计的地方。



Answer 17:

当然需要,无论你做什么,要作出某种形式的比较? 到底......相信你能避免if语句,但你会产生的代码,如果语句中使用的是相同的代码。

如果我错了有人纠正我,但我想不出一个时间,你可以得到任何形式的夺冠做这个。



Answer 18:

我觉得应用该参数的每一个if语句是非常极端的想法,但一些语言给你申请这个想法在某些情况下的能力。

下面是一个示例Python实现我过去写了一个固定大小的deque(双端队列)。 而不是创造一个“删除”的方法,并具有如果里面的语句,看看如果列表已满,你只是制造了两个方法,并根据需要重新分配给“删除”功能。

下面的例子只列出了“删除”的方法,但显然也有“追加”法等也。

class StaticDeque(collections.deque):

    def __init__(self, maxSize):

        collections.deque.__init__(self)
        self._maxSize = int(maxSize)
        self._setNotFull()

    def _setFull(self):

        self._full = True
        self.remove = self._full_remove

    def _setNotFull(self):

        self._full = False
        self.remove = self._not_full_remove

    def _not_full_remove(self,value):

        collections.deque.remove(self,value)

    def _full_remove(self,value):

        collections.deque.remove(self,value)
        if len(self) != self._maxSize and self._full:
            self._setNotFull()

在大多数情况下,它是没有多大用处的一个想法,但有时也可以是有帮助的。



Answer 19:

我会说,答案是肯定的隐约十岁上下。 特别是当语言允许一些重型功能的编程(即C#,F#,OCaml的)。

包含2如果声明,强烈夫妻两个业务规则,打破它的组件。

把它看作一个经验非常普遍的规则,但我会同意。 如果你有一大堆的if语句,也许你应该考虑的另一种方法。



Answer 20:

如果语句是相当核心编程等等,总之,你不能理智地避免它们。

然而,在面向对象的一个​​关键目标 - 事实上,“支柱”之一 - 封装。 旧的“封装什么变化”的规则可以帮助你去除,你正试图以说明你的对象的每一个选项的麻烦,如果和case语句。 一个更好的办法来处理分公司,特殊情况等,是使用类似的“工厂”设计模式(抽象工厂或工厂方法 - 根据需要,当然)。

例如,而不是你的主代码回路校验if语句,然后转移到创建每个操作系统不同的选项GUI窗口您使用何种操作系统,主代码会从工厂,它使用的操作系统,以确定哪些OS创建一个对象特异性具体对象进行。 在这一过程中,你正在服用的变化(和长的if-then-else子句)你的主代码回路,让子对象处理它 - 那么下一次你需要做出改变,如支持新的操作系统,你只是从工厂接口添加一个新类。



Answer 21:

我最近一直跟随反,如果谈话,听起来像是极端/夸张修辞给我。 但是我认为这是真理在此声明:if语句往往逻辑可以通过多态性更适当地实施。 我认为这是好事,每次都记住这一点,你正确的if语句。 话虽这么说,我觉得if语句仍是一个核心的逻辑结构,它不应该被恐惧或避免为宗旨。



Answer 22:

我在这里我的理解面向对象方法的两位 -

首先,在程序中哪些对象应该是直观的。 也就是说,我不应该试图创造一个“Arithmatic”类,以提供数学函数。 这是OOD的滥用。

其次,这是我的一个非常强烈的意见。 它不应该被称为面向对象的设计,但对象研究方法化设计! 如果对象的方法名称本身并不直观,然后继承的对象可能最终重新实现已经可用的方法。

面向对象的方法,据我,是不是程序性做法的替代品。 相反,它主要是针对两个主要的原因,语言的创造者 -

  1. 变量的作用域的性能更好。

  2. 垃圾收集,而比有太多的全局变量更好的能力。



Answer 23:

我与万斯同意,如果没有好,因为它增加了复杂条件和应避免成为可能。

多态性是在条件完全可行的解决方案它是用来意义,而不是“避免因”。

一个侧面说明,它不适合您的OOP的要求,但在数据化的方式也趋向于避免分支 。



Answer 24:

你必须明白什么(x > 5)的真正含义。 假设x代表一个数字,那么它基本上是“分类”大于五的所有号码。 因此,代码看起来像这样与Python语法语言:

class Number(Object):

    # ... Number implementation code ... #

    def doSomething():
        self = 0
        return self

    def doSomethingElse():
        pass

class GreaterThan5(Number):
    def doSomething():
        print "I am " + self

    def doSomethingElse():
        print "I like turtles!"

然后,我们可以运行类似下面的代码:

>>> type(3)
<class Number>
>>> type(3+3)
<class GreaterThan5>
>>> 3.doSomething()
0
>>> (3 + 3).doSomething()
I am 6
>>> (7 - 3).doSomethingElse()
>>>

这里的自动类型转换是非常重要的。 据我所知,没有任何语言的今天让你惹整数这么多。

最后,你可以在你的代码做。 只要人们读它可以实时了解。 因此,对整数或任何unordinary多态性调度必须有它背后真正的好理由。



文章来源: avoiding if statements