#299 Exploring how constructors are used in current codebase

brian Fri 18 Jul 2008

We actually have a fairly decent body of code which includes over 500 classes. Below is a script which dumps how various constructors are used (the script is a lot shorter than the results). I'll be going thru these results more carefully and posting my thoughts. But my initial observations:

  • Over 30% of classes have a compiler generated synthetic make ctor
  • 56% of classes have a constructor with arguments (although many were designed before with-blocks)
  • Only 6% of code has multiple constructors, virtually all of those in compiler and haven, and almost about all of them are easily reworked
  • Err classes scream for parameter based constructors since all of them take Str, Err as their first two optional parameters (and also scream for the ArgErr("bad arg") syntax)
  • Location is a good example where multiple constructors are handy and where the constructor does a non-trivial transformation of File to a Str.
  • Compiler Exprs are probably the most extensive use of constructors in the code base using multiple constructors with subclass chaining that isn't just "pass-thru"
  • Pretty much every manually coded, no arg constructor only does initialization and validation
class Dumpctors
{
  Type[] synthetics := Type[,]
  Type[] privates := Type[,]
  Type[] errs := Type[,]
  Type[] singleNoArgs := Type[,]
  Type[] singles := Type[,]
  Type[] multiples := Type[,]

  Void main()
  {
    count := 0
    Pod.list.each |Pod p|
    {
      p.types.each |Type t|
      {
        if (t.isMixin || t.isEnum || t.isSynthetic || t.pod.name == "testSys") return
        count++
        ctors := t.methods.findAll |Method m->Bool| { return m.isCtor }
        if (ctors.size == 1)
        {
          ctor := ctors.first
          if (ctor.isPrivate) { privates.add(t); return }
          if (ctor.isSynthetic) { synthetics.add(t); return }
          if (ctor.params.isEmpty) { singleNoArgs.add(t); return }
          if (t.fits(Err.type)) { errs.add(t); return }
          singles.add(t)
        }
        else multiples.add(t)
      }
    }

    sum := 0
    type.fields.each |Field f|
    {
      Type[] list := f.get(this)
      echo("\n$f.name ($list.size)")
      list.each |Type t| { echo("  $t") }
      sum += list.size
    }
    echo("\nTotal: $count, Sum: $sum")
  }
}

JohnDG Fri 18 Jul 2008

If you tried to do that in Java it would be more than a thousand lines of code.

How often I've wanted to iterate through Java's notion of a Pod....

jodastephen Fri 18 Jul 2008

I'd be particularly interested in how many times (and in what circumstances) a construction-with-block sets a const field (or performs any other operation that is disallowed for a normal-with-block. Also how many times both a () constructor and construction-with-block are paired together.

Login or Signup to reply.