-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider removing cloudformation namespace #878
Comments
We realized it's important to clearly separate between L1s and L2s and that's the reason we decided to namespace all L1 classes into a namespace. I understand that this is not an ideal situation but, since we hope that people will be able to mostly use L2s, I wonder if "littering" the module's namespace is worth it. |
I understand the goals. As a side note, I think there will always be power users who want direct access to the L1s, and I wanted to propose something other than namespaces before the API got locked in a V1 release; IIUC they are a legacy of Typescript from before ES6 modules were standardized. If you don't want the cloudformation types exported from the "root" module, perhaps the generated code could be placed in its own, "nested" module:
This would allow something like:
It retains the value of keeping the root namespace clean while providing explicit, convenient access when needed. I don't know how this would play with JSII, however. Another option would be to break out the generated code into their own modules, but that is probably more headache for you than it would be a convenience for me. |
You can actually do this today: import { FunctionResource } from "@aws-cdk/aws-lambda/lib/lambda.generated"; It's not pretty but it works :) |
And no, it does not translate across jsii, but that may not matter, since most languages have deep imports anyway?
|
True. I tend to view the contents of directories within modules as "private api" unless documented by the developer, preferring root-level imports.
That's an interesting point, and I suspect that JSII might have trouble with a module that publishes to both FWIW, In the span of options I provided, when I'm a maintainer I actually prefer the "isolate generated code into separate modules" approach. I find it's much simpler to reason about a module's contents when it is either all generated or all hand written. But this particular issue isn't about maintenance but API surface, and I can of course achieve my goals through additional aliasing:
Or any similar variation. So import style is partly a matter of taste; I just find the namespace mechanism awkward. |
I don't think we're going to change this, and the need for it is going to decrease as we're filling out or L2 library. Feel free to reopen if you strongly disagree. |
I am reopening this... There were a few conversations earlier around removing support for namespaces in jsii (since they are quite tricky to model in some programming languages). If we do end up removing support for namespaces, it means that we will need to find a solution for this. We could consider extracting the L1 modules to a separate library (i.e. We could also reconsider going back to the monolithic CFN package: Another option is to prefix all these types with something like @rix0rrr Thoughts? |
My vote would be back to But we'll still need SOME kind of namespacing even then, for property types |
I imagine that it's simpler to maintain, but I would discourage a monolith; the aws-sdk for JS does this and it has some associated headaches, and I generally prefer a "don't pay for what you don't use" model. |
Here are a few alternatives to consider. Let's add pros/cons to each (this is preliminary): (1a) Just remove the namespaceMove the L1 classes (e.g. BucketResource) to the root namespace of the package. This means that we are going to have both Pros:
Cons:
(1b) Remove the namespace and rename the classesSame as (1a) but also rename from (2) Another package per serviceMove the generated classes to another package per service. So we'll have Pros:
Cons:
(3) A single package for all generated resourcesSee "cons" below, but this option will actually not eliminate the need for namespaces. Pros:
Pro/Con:
Cons:
|
I am leaning towards 1b - any other options/feedback/preferences? |
Leaning towards Otherwise, I prefer 2 over 3 (everything in one bag is impractical), and 1 is a no-no from me (makes it hard for someone to know what class they should use when there is both L1 & L2 available). |
Regarding
|
The problem with 3 is that it exposes the entire CloudFormation spec to users/IDEs, when most of the time they'll only need a small fraction of it. It may inadvertently encourage using L1 APIs, instead of installing the relevant L2 API, given it's already available in the project. 1b sounds like the safer option, but it's not very concise. @RomainMuller's suggestion I think is the best. The "Cfn" prefix is a bit ugly, but that should trigger to end users that's it not the right thing to be using. |
I agree with most of the positive comments to 1b. I probably lean towards the longer name (1 it's clear and 2 I'm autocompleting anyway), but honestly either works for me. Out of curiosity 2 initially annoys me, but if we separated this into Worth any further investigation or did you guys consider this too and it didn't make the cut? |
There is no technical difference between There's another implication for this option, which is that it will basically mean that services that do not have L2s will have an empty library (with 0 exported types), or we will have to remove their library altogether. Some would say that's a good thing ("this service doesn't have L2s"), but I think in general, when someone needs a service, they would want a consistent experience, even if they would have to fall back to use L1s for that service. |
As an end user, (2) is still my preferred option, even with empty libraries, which I presume would still have a dependency on the cfn library. But I also understand that currently that imposes a high maintenance burden on you. (1b) has an unstated con that upgrading users would have to rename all of their classes. Given that I make heavy use of L1s for services that have missing or incomplete L2s, (1a) would be my second choice of the options given. |
@eladb -- I think the challenge for 2 is then this:
I think you are saying that in order to really accomplish 2 we would need to do the following
Does that sound right? If so how much headache does 1b solve right now vs separating this repo later or now? |
Rename generated CloudFormation resource constructs from `cloudformation.XxxResource` to `CfnXxx`. This fixes #878 and eliminates the use of namespaces in the CDK. This is done in a backwards compatible way, which means that we still generate the old resources under the `cloudformation` namespace so we can remove them in a subsequent release. Those resources also include a deprecation warning which is emitted upon `cdk synth`. Documentation updated to reflect changes. Related: aws/jsii#283 and aws/jsii#270
The cloudformation namespace creates some headaches when using ES6 imports. For example, if I need to import the L1 interfaces from two different modules (say, Lambda and API Gateway), I have to rename the namespaces so they don't conflict:
or, alternatively rename the import, and use additional qualification.
What I what I would like to do is import the L1 resources directly, but I cannot because of the namespace:
Typescript's manual discourages combining namespaces and modules.
The text was updated successfully, but these errors were encountered: