-
Notifications
You must be signed in to change notification settings - Fork 83
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
RFC: 0192 Removal of the "constructs" compatibility layer #195
Conversation
Title does not follow the guidelines of Conventional Commits. Please adjust title before merge. |
|
||
To apply AWS tags to a scope, prefer `Tag.add(scope, name, value)`. | ||
|
||
> TODO: should we change to `Tags.of(scope).add(name, value)`? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kinda feel this would be more consistent with the Aspects
API and thus would incur less cognitive load to developers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I like it too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I agree, Tag.add
is the current API, as mentioned here we can consider changing to Tags.of(x).add()
, but it's not a breaking change nor required for this migration at this point.
|
||
- [x] Migrate to projen | ||
- [x] Branch to 4.x and release as @next | ||
- [x] Reintroduce `c.node` instead of `Node.of(c)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kinda liked Node.of(c)
because it keeps the API of Construct
/IConstruct
super clean. However I don't really love how IConstruct
is just a marker interface and it has no bearing in how Node.of(IConstruct)
achieves getting the Node
from there (which makes it unsafe).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly, and that's why I am reintroducing IConstruct.node
so it's not a marker interface anymore. Also, not having this.node
as a way to access the node is going to break a lot of CDK code.
@eladb Notice: aws/aws-cdk#8645 Should we really have the Can we move this to Im thinking this intermediate EDIT: I think we can disregard this as I see it was addressed in the RFC. I also agree that we should keep the composition model pure to |
|
||
To apply AWS tags to a scope, prefer `Tag.add(scope, name, value)`. | ||
|
||
> TODO: should we change to `Tags.of(scope).add(name, value)`? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I like it too.
stage.synth(); | ||
``` | ||
|
||
Consider a design where you mutate the tree in-band (preferable), or use `Lazy` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think an example for a Lazy
(or whatever we most recommend for "late" bound calculations) implementation of something that would normally be in prepare
would be nice.
Co-authored-by: Neta Nir <[email protected]>
Title does not follow the guidelines of Conventional Commits. Please adjust title before merge. |
* RFC: 0171 CloudFront Redesign - initial rough ideas * Iteration #2 of the API, sans the Lambda@Edge functionality. Still in draft state, but hopefully getting closer. * Lambda@Edge API v1, plus some of the open questions and other sections filled in. * Added detailed design section, including before/after examples * Proper namespacing in the examples, and updated the open questions * Minor update to force pull request refresh * Minor changes per feedback; removing the 'draft' tag * Distribution.for* syntactic sugar * Removing Distribution.behavior, keeping origin->behavior nesting consistent * Minor API updates per feedback and lessons learned from implementation * Added implementation note for capturing behavior ordering
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
To reduce the risk of naming conflicts (e.g. see [Terraform CDK | ||
issue](https://github.com/hashicorp/terraform-cdk/pull/230)) between `node` and | ||
domain-specific APIs, we propose to introduce this API under the name | ||
`construct` (of type `Node`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So... let me summarize this: all classes that extend Construct
will have a construct
property that returns an instance of Node
? I would naturally have expected construct
to return an instance of Construct
(basically, this
), and the naming you're proposing strikes me as surprising and counter-intuitive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The property name should be considered in the context of its usage rather than its type because the type is not part of the usage semantics.
Do you find this counterintuitive?
bucket.construct.addDependency(role);
As oppose to:
bucket.node.addDependency(role);
I actually think the former is much more intuitively and reads much better.
We actually have a naming guideline that says that names should not include the type name because it's redundant information in strongly typed environments.
Do you have an alternative suggestion?
Perhaps we can rename Node
to something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually have a naming guideline that says that names should not include the type name because it's redundant information in strongly typed environments.
The problem is the name is the base type name (of the receiver) as well as the coined term for sub-types of it. The reason I don't love it is precisely because of this guideline: it looks like redundant information (so why's it there?), but is not (so it's surprising in that sense).
As discussed... I don't feel extremely strong against this. It does feel counter-intuitive to me but I have no idea whether I'm representative of users or not in this respect.
For the record, I think this.construct.addDependency(role)
reads super good, but for some reason the magic weakens when the receiver is not this
.
Additionally, I cannot come up with a better suggestion for a name... so there's that, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's a little late, but I don't agree with this rename.
I would expect a field called construct
to point to an object that IS a Construct. I like what they did in TerraCDK, constructNode
seems like a good compromise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason we have this property is in order to group all the API of Construct
under a single namespace so it won't "pollute" the APIs of subclasses, which are oftentimes generated classes in CDKs.
The conceptual mental model is that this is "the construct API". The fact that the type is Node
is actually not in line with this mental model.
If I am looking at this from a usage point of view, I think construct
makes more sense:
this.construct.id
this.construct.path
this.construct.addDependency(other)
this.construct.addMetadata
This is actually more natural then:
this.node.id
this.node.path
...
Additionally, we actually have a guideline against using the type name in symbol names because type information is an intrinsic part of the API (we prefer handler: lambda.Function
over handlerFunction: lambda.Function
).
I would rather rename the Node
class (maybe ConstructApi
) instead of renaming this property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the record, after some discussion I think I would have preferred for this member to be called constructTree
, as this is the member that consumers use to access the features of the "construct tree" (which is a CDK concept that people are, or should be, familiar with which is distinct from the concept of a "construct").
We get things like:
// All perfectly natural
bucket.constructTree.findChild()
bucket.constructTree.removeChild()
bucket.constructTree.defaultChild
bucket.constructTree.findAll()
bucket.constructTree.children
bucket.constructTree.addWarning()
// Better than what we have now, this name emphasizes the tree traversal involved in these operations
bucket.constructTree.setContext()
bucket.constructTree.applyAspect()
bucket.constructTree.addDependency()
// These now have not such great names, because they apply to the "current node" and don't really have
// strong tree-ish connotations. Don't think any of them are *horrible* but they are certainly not fantastic.
bucket.constructTree.id
bucket.constructTree.path
bucket.constructTree.uniqueId
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think CDK users are required to understand the tree concept. In fact, we have traditionally tried to talk about "scopes" (I.e "the construct is created within the scope of another construct"). From a CS perspective this is indeed a tree, but I don't see how this adds much value to users.
As mentioned above, the primary reason for this property is to group all the construct APIs under an api namespace so they don't pollute or conflict the public api of subclasses, which is the primary programming pattern we use in CDKs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a difference between not needing to know that there is a tree structure involved (until you do), and pretending that the tree structure doesn't exist by studiously avoiding calling it a tree.
You might be under the impression that my argument is one about purity of CS concepts. It is not.
It is about acknowledging the fact that this structure exists, that it underpins the way the CDK works in a way which you can oftentimes ignore, but sometimes is quite relevant and requires people to understand it (see Stages, Stacks, Aspects, LogicalIDs, default children and escape hatches, see tree.json
and the VSCode plugin, ...) and that there is a term available which accurately describes the semantics, expectations, and the sort of API that people can expect from this structure that they are already intimately familiar with from other programming tasks.
I think being vague and coy and pretending there is no tree when we all full well know that there is, or using the word "construct" to refer to two distinct concepts, is not going to help users form a mental model.
I'm also not saying they won't be able to. Given enough exposure and enough examples, over time people are going to eventually be trained to write the right code. In that sense, ultimately it doesn't even matter what it's called, be it node
, construct
, or abc
, people will learn to cope.
I think I've laid out my reasoning for why I think it's advantageous to call the beast by its name. It's completely fine if you disagree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks for the effort in explaining.
The plan is to introduce construct
and deprecate node
over the 1.x
branch in short order. This will give us some "bake time" of a few months until we completely remove node
in 2.x. This will allow us to get feedback from users in case the mental model is confusing or insufficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just stumbled upon this - thanks for making the effort of changing the name 👍
Pull request has been modified.
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache-2.0 license