Language agnostic 是否有超缩进代码的替代方案?

Language agnostic 是否有超缩进代码的替代方案?,language-agnostic,coding-style,indentation,Language Agnostic,Coding Style,Indentation,我经常遇到需要执行大量检查的代码,在真正执行任何操作之前,代码至少会缩进五到六级。我想知道还有什么选择 下面我发布了一个我正在谈论的示例(它不是实际的生产代码,只是我头脑中突然想到的东西) 公共字符串myFunc(SomeClass输入) { 对象输出=null; 如果(输入!=null) { SomeClass2 obj2=input.getSomeClass2(); 如果(obj2!=null) { SomeClass3 obj3=obj2.getSomeClass3(); if(obj3!

我经常遇到需要执行大量检查的代码,在真正执行任何操作之前,代码至少会缩进五到六级。我想知道还有什么选择

下面我发布了一个我正在谈论的示例(它不是实际的生产代码,只是我头脑中突然想到的东西)

公共字符串myFunc(SomeClass输入)
{
对象输出=null;
如果(输入!=null)
{
SomeClass2 obj2=input.getSomeClass2();
如果(obj2!=null)
{
SomeClass3 obj3=obj2.getSomeClass3();
if(obj3!=null&&!BAD_OBJECT.equals(obj3.getSomeProperty())
{
SomeClass4=obj3.getSomeClass4();
如果(obj4!=null)
{
int myVal=obj4.getSomeValue();
如果(错误值!=myVal)
{
String message=this.getMessage(myVal);
如果(最小值,请参阅以获取帮助

  • 用防护罩替换条件 条款
  • 将条件块分解为 分离功能
  • 将否定支票转换为 阳性检查
  • 提早返回:

    if (input == null) {
        return output;
    }
    

    您可以通过使用保护子句来消除一些嵌套

    public String myFunc(SomeClass input)
    {
        Object output = null;
    
        if(input == null) return "";
    
        SomeClass2 obj2 = input.getSomeClass2();
        if(obj2 == null) return "";
    
        SomeClass3 obj3 = obj2.getSomeClass3();
        if(obj3 == null || BAD_OBJECT.equals(obj3.getSomeProperty()))
        {
            return "";
        }
    
        SomeClass4 = obj3.getSomeClass4();
        if(obj4 == null) return "";
    
        int myVal = obj4.getSomeValue();
        if(BAD_VALUE == myVal) return "";
    
        String message = this.getMessage(myVal);
        if(MIN_VALUE <= message.length() &&
               message.length() <= MAX_VALUE)
        {
             //now actually do stuff!
             message = result_of_stuff_actually_done;
        }
    
        return output;
    }
    
    公共字符串myFunc(SomeClass输入)
    {
    对象输出=null;
    如果(输入==null)返回“”;
    SomeClass2 obj2=input.getSomeClass2();
    如果(obj2==null)返回“”;
    SomeClass3 obj3=obj2.getSomeClass3();
    如果(obj3==null | | BAD_OBJECT.equals)(obj3.getSomeProperty())
    {
    返回“”;
    }
    SomeClass4=obj3.getSomeClass4();
    如果(obj4==null)返回“”;
    int myVal=obj4.getSomeValue();
    如果(BAD_VALUE==myVal)返回“”;
    String message=this.getMessage(myVal);
    
    如果(MIN_值是,您可以按如下方式删除缩进:

    基本上是按顺序进行检查,并与失败而不是成功进行比较。 它消除了嵌套并使其更易于遵循(IMO)

    公共字符串myFunc(SomeClass输入)
    {
    对象输出=null;
    如果(输入==null)
    {
    返回null;
    }
    SomeClass2 obj2=input.getSomeClass2();
    如果(obj2==null)
    { 
    返回null;
    }
    SomeClass3 obj3=obj2.getSomeClass3();
    如果(obj3==null | | BAD_OBJECT.equals)(obj3.getSomeProperty())
    {
    返回null;
    }
    SomeClass4=obj3.getSomeClass4();
    if(obj4==null)
    {
    返回null;
    }
    int myVal=obj4.getSomeValue();
    如果(坏值==myVal)
    {
    返回null;
    }
    String message=this.getMessage(myVal);
    
    如果(MIN_值如果不需要处理停止,则不嵌入

    例如,您可以执行以下操作:

    if(input == null && input.getSomeClass2() == null && ...)
        return null;
    
    // Do what you want.
    
    假设您使用的是像Java这样的语言,它对条件进行排序

    或者,您可以:

    if(input == null && input.getSomeClass2() == null)
        return null;
    
    SomeClass2 obj2 = input.getSomeClass2();
    if(obj2 == null)
        return null;
    
    ...
    
    // Do what you want.
    
    对于更复杂的情况


    如果不需要处理,可以从方法返回。嵌入大型嵌套if几乎不可能读取。

    如果只是可读性问题,可以通过将嵌套移动到另一个方法使其更清晰。如果愿意,还可以转换为保护样式

    public String myFunc(SomeClass input)
    {
        Object output = null;
    
        if (inputIsValid(input))
        {
          //now actually do stuff!
          message = result_of_stuff_actually_done;
        } 
    
        return output;
    }
    
    
    private bool inputIsValid(SomeClass input)
    {
    
        // *****************************************
        // convert these to guard style if you like   
        // ***************************************** 
        if(input != null)
        {
            SomeClass2 obj2 = input.getSomeClass2();
            if(obj2 != null)
            {
                SomeClass3 obj3 = obj2.getSomeClass3();
                if(obj3 != null && !BAD_OBJECT.equals(obj3.getSomeProperty()))
                {
                    SomeClass4 = obj3.getSomeClass4();
                    if(obj4 != null)
                    {
                        int myVal = obj4.getSomeValue();
                        if(BAD_VALUE != myVal)
                        {
                            String message = this.getMessage(myVal);
                            if(MIN_VALUE <= message.length() &&
                               message.length() <= MAX_VALUE)
                            {
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
    
    公共字符串myFunc(SomeClass输入)
    {
    对象输出=null;
    if(输入有效(输入))
    {
    //现在真的做点什么!
    消息=实际完成的工作的结果;
    } 
    返回输出;
    }
    私有布尔输入有效(SomeClass输入)
    {
    // *****************************************
    //如果愿意,可以将其转换为防护样式
    // ***************************************** 
    如果(输入!=null)
    {
    SomeClass2 obj2=input.getSomeClass2();
    如果(obj2!=null)
    {
    SomeClass3 obj3=obj2.getSomeClass3();
    if(obj3!=null&&!BAD_OBJECT.equals(obj3.getSomeProperty())
    {
    SomeClass4=obj3.getSomeClass4();
    如果(obj4!=null)
    {
    int myVal=obj4.getSomeValue();
    如果(错误值!=myVal)
    {
    String message=this.getMessage(myVal);
    如果(最小值)为“是”,则存在替代方案。
    请不要这样编写代码(除非您维护自己的代码)

    我不得不维护这样的代码,就像查尔斯·布朗森的电影一样糟糕(尽管有些人喜欢这些电影)

    这种代码通常来自过程语言,比如C(is C procedural:p)

    这就是ObjectOrientedProgrammng成为主流的原因。它允许您创建对象并向其添加状态。使用该状态创建操作。他们不仅仅是属性持有者

    我知道是你编造的,但大多数情况下,所有这些条件都是业务规则!!。大多数情况下,这些规则都会改变,如果原始开发人员不再在那里(或者几个月过去了)没有一种可行的方法来修改代码。规则很难阅读。这会带来很多痛苦

    你能做什么? 1.)使用private成员变量(又名属性、属性、实例变量等)将对象的状态保持在对象内部

    2.)将方法设置为私有(这就是访问级别的作用),这样就不会有人错误地调用它们,并将程序置于NullPointerException区域

    3.)创建定义条件的方法。这就是他们所谓的自文档代码

    所以不是

    // validates the user has amount
    if( amount > other && that != var || startsAligned() != false  ) {
    }
    
    创建一个方法

    if( isValidAmount() ) {
    }
    
    private boolean isValidAmount() {
       return ( amount > other && that != var || startsAligned() != false  );
    }
    
    我知道它看起来很冗长,但允许人们阅读代码。编译器不关心可读性

    那么,使用这种方法,您的超嵌套结构会是什么样子呢

    像这样

    // these are business rules
    // then it should be clear that those rules are
    // and what they do.
    
    // internal state of the object.
    private SomeClass2 obj2;
    private SomeClass3 obj3;
    private SomeClass4 obj4;
    
    //public String myFunc( SomeClass input ) {
    public String myComplicatedValidation( SomeClass input ) {
        this.input = input;
        if ( isValidInput() && 
            isRuleTwoReady() &&
            isRuleTreeDifferentOf( BAD_OBJECT ) &&
            isRuleFourDifferentOf( BAD_VALUE ) && 
            isMessageLengthInRenge( MIN_VALUE , MAX_VALUE ) ) { 
                    message = resultOfStuffActuallyDone();
        }
    }
    
    // These method names are self explaining what they do.
    private final boolean  isValidInput() {
        return  this.input != null;
    }
    private final boolean isRuleTwoReady() {
        obj2 = input.getSomeClass2();
        return obj2 != null ;
    }
    private final boolean isRuleTreeDifferentOf( Object badObject ) {
        obj3 = obj2.getSomeClass3();
        return obj3 != null && !badObject.equals( obj3.getSomeProperty() );
    }
    private final boolean isRuleFourDifferentOf( int badValue ) {
        obj4 = obj3.getSomeClass4();
        return obj4 != null && obj4.getSomeValue() != badValue;
    }
    private final boolean isMessageLengthInRenge( int min, int max ) {
        String message = getMessage( obj4.getSomeValue() );
        int length = message.length();
        return length >= min && length <= max;
    }
    
    几乎可以理解为

    if is valid input 
    and rule two is ready 
    and rule three is not BAD OBJECT 
    and rule four is no BAD_VALUE 
    and the message length is in range
    
    通过保持规则的小范围变化,编码人员可以非常容易地理解它们,而不必害怕某些事情

    很多
    // these are business rules
    // then it should be clear that those rules are
    // and what they do.
    
    // internal state of the object.
    private SomeClass2 obj2;
    private SomeClass3 obj3;
    private SomeClass4 obj4;
    
    //public String myFunc( SomeClass input ) {
    public String myComplicatedValidation( SomeClass input ) {
        this.input = input;
        if ( isValidInput() && 
            isRuleTwoReady() &&
            isRuleTreeDifferentOf( BAD_OBJECT ) &&
            isRuleFourDifferentOf( BAD_VALUE ) && 
            isMessageLengthInRenge( MIN_VALUE , MAX_VALUE ) ) { 
                    message = resultOfStuffActuallyDone();
        }
    }
    
    // These method names are self explaining what they do.
    private final boolean  isValidInput() {
        return  this.input != null;
    }
    private final boolean isRuleTwoReady() {
        obj2 = input.getSomeClass2();
        return obj2 != null ;
    }
    private final boolean isRuleTreeDifferentOf( Object badObject ) {
        obj3 = obj2.getSomeClass3();
        return obj3 != null && !badObject.equals( obj3.getSomeProperty() );
    }
    private final boolean isRuleFourDifferentOf( int badValue ) {
        obj4 = obj3.getSomeClass4();
        return obj4 != null && obj4.getSomeValue() != badValue;
    }
    private final boolean isMessageLengthInRenge( int min, int max ) {
        String message = getMessage( obj4.getSomeValue() );
        int length = message.length();
        return length >= min && length <= max;
    }
    
        if ( isValidInput() && 
            isRuleTwoReady() &&
            isRuleTreeDifferentOf( BAD_OBJECT ) &&
            isRuleFourDifferentOf( BAD_VALUE ) && 
            isMessageLengthInRenge( MIN_VALUE , MAX_VALUE ) ) { 
                    message = resultOfStuffActuallyDone();
        }
    
    if is valid input 
    and rule two is ready 
    and rule three is not BAD OBJECT 
    and rule four is no BAD_VALUE 
    and the message length is in range