Skip to content

Instantly share code, notes, and snippets.

@thieux
Last active September 27, 2016 21:07
Show Gist options
  • Save thieux/6ff4c982ca323f44bc618c7914c8c75d to your computer and use it in GitHub Desktop.
Save thieux/6ff4c982ca323f44bc618c7914c8c75d to your computer and use it in GitHub Desktop.

Method or constructor parameters?

Consider passing parameter through a method:

class Fibo {
  int fibo(int n) {...}
}

Versus passing through a constructor:

class Fibo {
  int n;
  Fibo(int n) {
    this.n = n;
  }
  int fibo() {...}
}

Observe how names are wrong. In the first case (method) we tend to have the name in the method.

class Math {
  int fibo(int n) {...}
}

In the second (constructor) we tend to have the name in the class.

class Fibo
  int n;
  Fibo(int n) {
     this.n = n;
  }
  int compute() {...}
}

As an exercise we can design a service that takes 2 parameters to do its job.

Consider all variations of method/constructor initialisation of those 2 parameters.

Construct(a, b); m();
Construct(); m(a, b);
Construct(a); m(b);
Construct(b); m(a);

There is obviously no good design in itself. We should choose depending on consumer responsability, lifecycle and LSP (Liskov substitution principle).

Lifecycle

class Echo {
  void echo() {
    while (true) {
      String line = reader.readLine();
      writer.write(line);
    }
  }
}

class PdfWriter {
  File output;
  void write(String text) {...}
}

Here we choose output as a field, because it has a longer lifecycle (the same for each iteration). But text has a shorter lifecycle (change for each iteration).

Liskov

class Main {
  void extractErrors(Path errorFile) {
    ExactSearcher searcher = ...
    for (String line: Files.readAll(errorFile)) {
      if (searcher.matches("[ERROR]")) {
        extract(line);
      }
    }
  }
}

class RegexSearcher {
  boolean matches(String regex) {
    text.matches(regex);
  }
}

class ExactSearcher {
  boolean matches(String exact) {
    text.equals(exact);
  }
}

In this case, something is wrong with method matches(String). In one case the contract is that regex should conform to Pattern.compile(String). In the second case there is no such constraint.

Here we violate LSP because we cannot substitute ExactSearcher by RegexSearcher. Notice that LSP rely on the usage ("the programs").

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment