mulesoft-labs / data-weave-rfc

RFC for the data weave language
11 stars 6 forks source link

Visibility + LifeCycle #14

Open machaval opened 4 years ago

machaval commented 4 years ago

We are trying to kill a long debt on how to make element visibility available on DW and I'm trying to make it without changing the lang. So my proposal is using annotations. If this doesn't feel correct then we may need to change the grammar.

%dw 2.0
@Internal(permits = [])
fun internalToModule(): String = ??? //Only available to the current module
@Internal(permits = ["acme::.*"])
fun iternalToOrg(): String = ??? //Only available to modules under acme::
@Deprecated(replacement = "MyModule::newFunction", since= "1.1.1")
fun deprecatedFunction(): String = internalToModule() //This function has been dprecated
@Experimental()
fun experimentalFunction(): String = ??? //This function is mark as experimental and it may be removed or change

My first concern is permits being a string that represents a regex. So I think that we should either make it just a string that is prefix or change it to regex type.

Deprecated and Expermiental are ok

jerneyio commented 4 years ago

I like these, it's immediately obvious what they mean and how to use them. I have a few questions around permits:

How do you see permits being used, to do module-level privacy over multiple files?

com/foo/bar/baz/module.dwl -

@Internal(permits = ["com::foo::.*", "io::jerney::.*"])
fun process(): String = ???

com/foo/module.dwl -

import process from com::foo::bar::baz::Module

fun runIt(): String = process()

I assume @Internal() is equivalent to @Internal(permits = [])

There may be situations where a function is deprecated, but there's no replacement for it. An attribute like comment might be useful. Example @Deprecated(comment = "Use com::acme modules instead"). Then that message could be shown in Anypoint Studio somehow.

machaval commented 4 years ago

Yes the idea of Internal is to allow only a set known domains to allow the access of a given function/variable etc or just say this is visible only in this module. By domains I mean "com::foo::" or ""io::jerney::" I end up removing the need of .* as I think it doesn't add value and people are going to forget to add it. So I think it is simpler to say that the permits represents that the given definition is going to be visible in all its subdomains.

I would add the comment on the Deprecated I think it is a good idea.

Thanks @jerneyio !

menduz commented 4 years ago

I think the most reasonable thing to do would be to specify the visibility as a regex.

Besides that, I've never seen a language where you specify an allow-list for the visibility what is the rationale behind it instead of validating a "private" "protected" or "package" modifiers from the importer's perspective? You will never know where you (or team or company) would like to use a function to allow it everywhere.

machaval commented 4 years ago

Hi @menduz Scala has something similar not a list but you can modify visibility https://alvinalexander.com/scala/how-to-control-scala-method-scope-object-private-package/

Also OSGI has the concept of x-friends http://blog.vogella.com/2010/05/25/x-friends-in-equinox/ that is basically the ones that can access internal stuff Though private makes sense protected it doesn't as is for hierarchy classes package I never use it. In my case the use case was we have a function call native and I only want this function to be used by known friends in this case "bat" and "dw"