isValidの書き方

きっかけ

コードのネストを深くするな | anopara を読んで、 僕もネストは浅い方が好きだけどisValid…お前はダメだ。 - bufferings のコメント / はてなブックマーク って書いたら、@m_seki さんに"isValidダメなんだ。どう書けばいいの?"というツッコミを頂いたので。ちょい考えてみた。まぁ、元記事の主題とは関係ないところなので。ゆるりとね。

元々のんは、こんな感じ?

Groovyで書いてみた。

class Data {
  def Count
  def Error
  def Result
}

class Validator {
  boolean isValid(Data a)
  {
      if(a != null)
      {
          if(a.Count > 0)
          {
              if(a.Error == null)
              {
                  if (a.Result != null)
                      return true;
              }
          }
      }
      return false;
  }
}

で元記事のリファクタは

  boolean isValid(Data a)
  {
      if (a == null)
          return false;
   
      if (a.Count > 0)
          return false;
   
      if (a.Error == null)
          return false;
   
      if (a.Result != null)
          return true;
      else
          return false;
  }

イケてない。なにがって。。。

リファクタするならテスト書こうね

Spockで書いてみた。こうですか?

class isValidメソッドのテスト extends spock.lang.Specification {

  def sut = new Validator()

  def "Dataがnullのときはfalse"() {
    setup:
    def data = null

    expect:
    sut.isValid(data) == false
  }

  @Unroll
  def "Count:#count, Error:#error, Result:#result のときは #valid"() {
    setup:
    def data = new Data(Count:count, Error:error, Result:result)

    expect:
    sut.isValid(data) == valid

    where:
    count | error | result || valid
    0     | null  | null   || false
    0     | null  | "a"    || false
    0     | "a"   | null   || false
    0     | "a"   | "a"    || false
    1     | null  | null   || false
    1     | null  | "a"    || true
    1     | "a"   | null   || false
    1     | "a"   | "a"    || false
  }
}

Spock Web Console で実行すると。

こうなった。

isValidメソッドのテスト
 - Dataがnullのときはfalse
 - Count:0, Error:null, Result:null のときは false
 - Count:0, Error:null, Result:a のときは false
 - Count:0, Error:a, Result:null のときは false
 - Count:0, Error:a, Result:a のときは false
 - Count:1, Error:null, Result:null のときは false
 - Count:1, Error:null, Result:a のときは true
 - Count:1, Error:a, Result:null のときは false
 - Count:1, Error:a, Result:a のときは false

じゃ元記事のリファクタリング後のやつを

テストしてみようか。結果は。

isValidメソッドのテスト
 - Dataがnullのときはfalse
 - Count:0, Error:null, Result:null のときは false
 - Count:0, Error:null, Result:a のときは false
 - Count:0, Error:a, Result:null のときは false
 - Count:0, Error:a, Result:a のときは false   FAILED

   Condition not satisfied:
   
   sut.isValid(data) == valid
   |   |       |     |  |
   |   true    |     |  false
   |           |     false
   |           Data@441b9f
   Validator@112d0b5
   
   at isValidメソッドのテスト.Count:#count, Error:#error, Result:#result のときは #valid(Script1.groovy:61)

 - Count:1, Error:null, Result:null のときは false
 - Count:1, Error:null, Result:a のときは true   FAILED

   Condition not satisfied:
   
   sut.isValid(data) == valid
   |   |       |     |  |
   |   false   |     |  true
   |           |     false
   |           Data@e75bc7
   Validator@1f6c888
   
   at isValidメソッドのテスト.Count:#count, Error:#error, Result:#result のときは #valid(Script1.groovy:61)

 - Count:1, Error:a, Result:null のときは false
 - Count:1, Error:a, Result:a のときは false

ふむ。2こ失敗しとるね。じゃ、修正すると、こうかな。

  boolean isValid(Data a)
  {
      if (a == null)
          return false;
   
      if (a.Count <= 0)
          return false;
   
      if (a.Error != null)
          return false;
   
      if (a.Result != null)
          return true;
      else
          return false;
  }

テスト通った(∩´∀`)∩ワーイ

おまけ

テストがあるから安心して修正できるね!ってことで僕ならどう書くかなーって。

class Validator {
  boolean isValid(Data a) {
    return (a != null 
        && a.Count > 0
        && a.Error == null
        && a.Result != null)
  }
}

こうかなー。(そういうことじゃない

全部入り

class Data {
  def Count
  def Error
  def Result
}

class Validator {
  boolean isValid(Data a) {
    return (a != null 
        && a.Count > 0
        && a.Error == null
        && a.Result != null)
  }
}

class isValidメソッドのテスト extends spock.lang.Specification {

  def sut = new Validator()

  def "Dataがnullのときはfalse"() {
    setup:
    def data = null

    expect:
    sut.isValid(data) == false
  }

  @Unroll
  def "Count:#count, Error:#error, Result:#result のときは #valid"() {
    setup:
    def data = new Data(Count:count, Error:error, Result:result)

    expect:
    sut.isValid(data) == valid

    where:
    count | error | result || valid
    0     | null  | null   || false
    0     | null  | "a"    || false
    0     | "a"   | null   || false
    0     | "a"   | "a"    || false
    1     | null  | null   || false
    1     | null  | "a"    || true
    1     | "a"   | null   || false
    1     | "a"   | "a"    || false
  }
}