76 lines
5.9 KiB
Markdown
76 lines
5.9 KiB
Markdown
|
# C# Language Design Meeting for December 2nd, 2020
|
||
|
|
||
|
## Agenda
|
||
|
|
||
|
1. [Partner scenarios in roles and extensions](#partner-scenarios-in-roles-and-extensions)
|
||
|
|
||
|
## Quote(s) of the Day
|
||
|
|
||
|
- "Have you noticed how similar what you just said is to function pointers?"
|
||
|
- "This is a modern version of COM aggregation." "But in a good way."
|
||
|
|
||
|
## Discussion
|
||
|
|
||
|
### Partner scenarios in roles and extensions
|
||
|
|
||
|
Today, we heard from partner teams on the Azure SDK and on ASP.NET, talking about friction they currently encounter
|
||
|
with some scenarios that might be addressable through roles, extension everything, or potentially some other solution.
|
||
|
|
||
|
#### ASP.NET Feature Collections
|
||
|
|
||
|
ASP.NET models contexts through an aggregation system that allows different services to be composed onto a single `HttpContext`.
|
||
|
For example, adding TLS to a session involves creating a TLS connection, wrapping the existing connection, and adding it
|
||
|
as an available feature to the context. This underlying connection could be one of several types connections: it could be
|
||
|
routed through a socket, or it could be in-process, or any of a number of other connection mechanisms, each with its own set
|
||
|
of properties. It is possible to retrieve each of these sets of features from a `Get` method on the context, but this is
|
||
|
cumbersome and not generally extensible: for their users, it would be nice to be able to expose a view over a context or
|
||
|
connection that exposed the underlying properties.
|
||
|
|
||
|
This scenario seems like a clear-cut use case for roles and extension-everything as we last discussed them. A role could be
|
||
|
used to expose a grouping of properties on an upper layer from a lower layer. In fact, the ASP.NET architecture was designed
|
||
|
with the eventual intention of using extension properties to remove a number of extension methods that they have in place
|
||
|
today to expose these underlying properties from a decorated type. Of the 3 scenarios we discussed today, this seems the
|
||
|
most obviously-addressed by the existing proposal.
|
||
|
|
||
|
#### Azure SDKs
|
||
|
|
||
|
The Azure SDK scenario presents a more interesting challenge. Feature collections were designed with C# in mind, meaning
|
||
|
that both types and type names were thoughtfully designed when creating the API. The Azure SDK (and by extension many
|
||
|
web APIs), by comparison, are designed in a web-first manner. In this context, property _names_ are important, and general
|
||
|
structures of an API are important, but names of these structures are _not_ important. These APIs are often described and
|
||
|
generated using Swagger, which uses JSON to describe the structure of a response. JSON structures can be strongly typed,
|
||
|
of course: the structure itself is the type. But the nested properties of a JSON object, which can be nested objects
|
||
|
themselves, are described entirely in a structural manner, not in a nominal manner as we do in C#. Here, C#'s paradigms
|
||
|
break down, and the SDK teams run into trouble when creating a C# API to wrap this structure. All of these nested structures
|
||
|
need to be named, so that C# can talk about them. This leads to an explosion of types, which can be made even more difficult
|
||
|
when you consider identical structures developed by different teams (perhaps even different companies). By necessity, each
|
||
|
team will need to create their own "named" data structure to give C# an ability to talk about the object, but these names
|
||
|
are really meaningless. The JSON didn't have this name, and the structures cannot unify. There are also scenarios with
|
||
|
very similar objects (perhaps one object has an extra field that the former does not have). This necessitates an entirely
|
||
|
new object to be created, and users often end up needing to write boilerplate methods that just translate objects from
|
||
|
representation A to B, changing nothing about the data other than making sure the type's name lines up.
|
||
|
|
||
|
This set of scenarios is not addressed by roles and extension methods, as they currently stand. We theorized that teams
|
||
|
might be able to a combination of `dynamic` and a custom completion provider/analyzer, to give users help in writing and
|
||
|
validating code that is, in essence, a set of dynamic calls to nested properties of unnamed types that does have a structure,
|
||
|
but this is a complicated solution to the scenario that is likely not generally-leverageable. There are more IDEs than just
|
||
|
VS, and more IDE scenarios than just completion: what would go-to-def do on these, or quick info on hover?
|
||
|
|
||
|
#### Data Processing
|
||
|
|
||
|
Finally, we took a look at a small proof-of-concept library exploring what replicating parts of the popular Python library
|
||
|
Pandas could be like in C#, with stronger typing around the data generated from a given input. This scenario is very
|
||
|
reminiscent of F# type providers, allowing users to simply dot into a data structure. However, it suffers from the same
|
||
|
set of issues that affect the Azure SDK scenarios above. In order to talk about nested data structures, they have to be
|
||
|
named. And while the Azure examples entirely focus on the types of structures representable in JSON, Pandas is far more
|
||
|
flexible. Additionally, Pandas allows you create new objects as they flow through a pipeline, adding or removing properties
|
||
|
as they are manipulated.
|
||
|
|
||
|
Looking at these last two examples, it seems that there are some scenarios not served well by C# today, involving JSON or
|
||
|
other structured but unnamed data. These scenarios care deeply about the names of properties, and the structure attached to
|
||
|
each property name, but the domains these scenarios interact with do not care about naming these structures. Further, adding
|
||
|
names to these structures in C# can be harmful, because it locks out scenarios that can be accomplished in the original
|
||
|
domain and forces a naming structure where none was intended, which can result in confusing or badly-named types that can
|
||
|
then never be changed because of backwards compatibility concerns. As we continue to evolve the roles and extension
|
||
|
everything proposals, we should look at these scenarios and see if there are ways to improve the experience for them.
|