Skip to content

INV Signatures Wrapping

peasoupio edited this page Dec 27, 2020 · 1 revision

INV allows you to wrap signatures with interfaces.
Here's a quick example:

// inv1.groovy
inv {
    broadcast { Something } using {
        ready { new MyBroadcastedObject() }
    }
}

// Could be here OR inside a /src folder, if using a REPO file structure
// Visit for more info: https://github.com/peasoupio/inv/wiki/REPO-file-structure
class MyBroadcastedObject {
    String a() { return "a" }
    String b() { return "b" }
}
inv {
    require { Something }
    
    step {
        // As strange it seems, it is fully valid and usable.
        def something  = ($something as $Something)
        assert "a", something.a()
    }
}

// Here we are using an interface and it is starting with an $ per convention
interface $Something {
    String a()    
}
  1. We are broadcasting Something with a new instance of MyBroadcastedObject
  2. In another file, we are requiring Something. MyBroadcastedObject instance created previously is now accessible by the variable $something (See why here: https://github.com/peasoupio/inv/wiki/INV-groovy-syntax)
  3. We create a step to make sure $something is available outside the require statement.
    IMPORTANT: It is not required by the wrapping mechanism.
  4. We cast with the keyword as the MyBroadcastedObjectinstance using a valid signature, provided by the interface $Something
  5. We call the a() through the $Something to the "real" MyBroadcastedObject instance

So basically, this mechanism contractualize a consumer to its provider without outside the real implementation. Thus, it adds more validation before the usage of a broadcast instance.

Also, this mechanism helps IDEs to get an actual definition for a require statements variable - since we are wrapping it.
It is quite useful for troubleshooting and debugging.

What if the signature is not valid?

In a case like this:

// inv1.groovy
inv {
    broadcast { Something }
        ready { new MyBroadcastedObject()}
}

class MyBroadcastedObject {
    String a() { return "a" }
}
// inv2.groovy
inv {
    require { Something }
    
    ste {
        def something = ($something as $Something)
        assert null, something
    }
    
}

interface $Something {
    String c()
}

As the assert infer, the returned value from the wrapping mechanism is null because String c() is not a valid method signature to the matched broadcast value.