Improvements to C# Ergonomics #3019
Labels
enhancement
New feature or request
help wanted
Community contributions welcome as the core team is unlikely to work on this soon
language/c#
C# language issues
needs-research
priority/awaiting-more-evidence
Lowest priority. Unlikely to be worked on unless/until it gets a lot more upvotes.
ux/configuration
Description
I raise this issue with constructive intent, and I realize it may not align with the priority or direction for the overall project, but since C# is a supported language, and this is the internet afterall, I wanted to share my thoughts.
I think it's prudent to note that the C# developer experience is not great, but there are some quality of life changes that could be made to improve it. I am not sure if these improvements need to be made in cdktf or some of the dependent libraries like
constructs or jsii. I'll happily open issues in all locations where appropriate and contribute where supported.
Overall, the topics discussed below come from the following mindset:
If cdktf is a development oriented approach to managing terraform resources, it makes sense to align with the typical developer experience in the target language.
To contextualize my opinions below, I have been using terraform since 0.11 and devloping in C# for 15 years. My organization controls all of our infrastructure with terraform and we've done a few experiments with cdktf in TypeScript, Python, and C#. I
am not saying this to brag. I don't think it's that special. I just want to share that I do have relevant experience using the tooling.
Linting
# pragma warning disable CA1806
is required in order to avoid warnings about new'ing up objects without assignment. I know this has been reported and is part of the underlying pattern for constructs. However, I think this warning exists for a goodreason and ignoring it feels off for the developer experience.
A quick fix would be to provide a default suppression of the warning with the project template. I don't think this is the only solution, and I'll touch upon that in other sections.
Incomplete Typing
A lot of the types are incomplete or incorrect, which looks to be a side effect of IResolvable as from what I have seen, these properties in TypeScript are all unions of
<someType> | cdktf.IResolvable
There are no unions in C# so maybe object is the only choice if this capability is needed. If it's possible to make
IResolvable
a generic interface, that might allow you to translate into C# with something like:The above keeps the desired type visible and gives the developer a reasonable chance at knowing allowed values without digging into any external documentation.
It could be less verbose if there's a concrete expression type that could be used for properties. That would allow for an implict cast:
Namespaces
The namespacing is pretty verbose. I read the pinned issue about how this was changed in cdktf 0.13 and understand the reasoning around performance.
In addition to pulling the schema from the provider, would it make sense to use the registry api to pull the doc navigation and use the subcategory field to drive the namespacing? It seems like there is some existing metadata that could be used to scope the nodes within a namespace without requiring lots of effort.
Surprising Implementations
For example List types don't implement list semantics. If we look at
AcmCertificate
, it has a propertyDomainValidationOptions
which is of the typeAcmCertificateDomainValidationOptionsList
. This is indeed a list in terraform, where a common pattern of consumption is to use a for expression to create corresponding route53 records to validate the domains on the cert, as in the example from the tf docs.This is not a list in C#. I can't get a count, I can't use any of the
System.Linq
extension methods, and I can't evaluate it in a loop. I can only index into it via theGet
method:Ideally this would implement
IList<AcmCertificateDomainValidationOptionsOutputReference>
, and we could use it like a typical list in C#.Interfaces for Configs
I understand that the interfaces make sense in TypeScript since they are evaluated against an anonymous object. This is not the case in C#, which makes the resource creation more explicit. This could be better if the resource constructors used the
concrete type, e.g.:
Newer versions of C# allow you to omit the class when the type is inferred. So that would allow us to do:
Admitidly, the above syntax is controversial in terms of readability, but it's nice to have the option to take advantage of the language features.
Patterns
Coming back to the pattern of new'ing up resources...
It seems more natural to think of the stack as an object to which you are adding resources. Likewise, I would expect to add stacks to an App. I think the inversion of control in place right now drives the awkward experience. I realize this is just
following the Constructs library but I it could be masked with a little syntax:
If you read this far, I appreciate it and I hope you consider some of the feedback above. As I mentioned at the beginning of the post, I'm happy to contribute if any of this is possible/acceptable to do within the scope of the project.
References
No response
Help Wanted
Community Note
The text was updated successfully, but these errors were encountered: