dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.29k stars 9.96k forks source link

Epic: Eventing Framework in .NET 9 #53219

Open captainsafia opened 8 months ago

captainsafia commented 8 months ago

This issue captures issues related to the "eventing framework" work area in .NET 9. Issues and categorizations are subject to change as design and prototyping is underway.

This eventing framework will allow developers to write applications that support processing messages from various queue providers in their application.

Major categories of work include:

More details here:

https://github.com/dotnet/aspnetcore/issues/53219#issuecomment-1921960530

Blackclaws commented 8 months ago

I'd like to chime in here a bit because I think a couple of points might be relevant to consider.

Right now there exist a couple of message handler frameworks. Some that come to mind are:

And many more exist.

Given that this is supposed to become a first party implementation of similar capabilities, is there going to be a call for usage scenarios so we can give feedback on which capabilities are used and how or is this going to be handled entirely internally?

I expect that this implementation will at least in part leverage source generation similar to how https://github.com/martinothamar/Mediator and https://github.com/JasperFx/wolverine do it. Albeit the difference between those two is that Wolverine does runtime source generation vs. Mediator using Roslyn source generators.

If it does use source generation I'd like to point out that special care should be taken looking at the integration with existing other source generators. Specifically because there still is no way to chain them together. It would be great if the capability to create MessageHandlers on the fly using Source generation would still allow them to be used from within whatever you're going to build. I'd love for the aspnetcore team to champion changes in Roslyn that lead to us being able to chain Source Generators :wink: . Given that the Razor generator already presents similar issues. Runtime code generation will likely not work that well together with AOT unless you do a two-pass system similar to how Wolverine handles it.

All in all I think having a first party implementation as something people can fall back on or that other libraries can expand on is a good thing. I'd just like it to be as usable as possible in the end :)

rogeralsing commented 8 months ago

IsnΒ΄t this exactly what you already tried with WCF when it came out? A unified platform for uni and bidirectional communication.

What will you do differently this time around to prevent the mess that WCF was for, especially for one-way messaging?

codymullins commented 8 months ago

I would request and highly recommend that in building this you introduce a common abstraction layer that can be used by third party tools, much like the ILogger abstraction introduced in previous versions of .NET.

Badabum commented 8 months ago

Why not support existing OSS tools like Wolverine or MediatR or smth else instead of building smth from scratch in-house?

smstuebe commented 8 months ago

One question pops into my mind: How are schema registries covered?

Is "Expose APIs for serializing and deserializing messages resolved from providers" meant to support schema registries out of the box, or is is meant to provide an interface to integrate a schema registry on your own?

oluatte commented 8 months ago

This is interesting. Some thoughts from experience with existing libraries in the space.

voroninp commented 8 months ago

With outbox feature, please.

eglauko commented 8 months ago

Why not support existing OSS tools like Wolverine or MediatR or smth else instead of building smth from scratch in-house?

One man library. The tools are designed to promote their creators. The design and functionality depend on the owner. When someone is dissatisfied, they create another very similar tool to fulfil their needs.

Create APIs and Layers to standardise these tools seems much better to me.

Badabum commented 8 months ago

Why not support existing OSS tools like Wolverine or MediatR or smth else instead of building smth from scratch in-house?

One man library. The tools are designed to promote their creators. The design and functionality depend on the owner. When someone is dissatisfied, they create another very similar tool to fulfil their needs.

Create APIs and Layers to standardise these tools seems much better to me.

Imo, that's exactly against the spirit and nature of OSS. Tools are not designed to promote developers(while this might be a good side effect). Those tools are built to solve problems, and people collaborate together to solve them. Now, MS looks at the existing ecosystem selects popular areas, and develops tools that essentially replace existing OSS alternatives. So what happens next? Use of those tools will obviously drop, and eventually, they will disappear. Why maintain some OSS tool when you can just sit, wait, and hope MS will be kind enough to develop the thing that solves your problem? This is not OSS.

jbogard commented 8 months ago

Just as a point of clarification, MediatR is NOT comparable to this feature set, nor would plug in to a common event bus interface.

MediatR is strictly in-process and in-memory. Not for durable async message queues.

And also evidently MediatR exists solely to promote myself.

I like this idea though. It should be easier to adopt event-driven architectures. It would be nice if it were like DI, logging, even EF Core where there is some default implementation but you can add your own 3rd party implementation.

kijanawoodard commented 8 months ago

The risk is that, similar to what happened with DI, the "common interface" effectively defines the implementation and stifles innovation. There was a great thread many moons ago where the author of Simple Injector was trying to explain why the DI interface was hostile to the fundamental premise of Simple Injector. IIRC the conclusion was ~"this is a solved problem that doesn't need innovation" which was off base considering Simple Injector was a reasonably popular project that was taking a different tack that wasn't achievable with the "common interface".

Not sure how that all finally resolved in the end.

My desire would be to always be able to opt out and also to be able to rebuild whatever is given from smaller bits of the framework.

jeremydmiller commented 8 months ago

One man library. The tools are designed to promote their creators. The design and functionality depend on the owner. When someone is dissatisfied, they create another very similar tool to fulfil their needs.

FWIW, there's a company behind Wolverine (JasperFx), with similar commercial support offerings behind NServiceBus, MassTransit, and Rebus to name a few others. That argument doesn't really fly. Even Wolverine as the newest kid on the block has technical roots going back a decade. NServiceBus and MassTransit are ~15 years old at least.

iancooper commented 8 months ago

Worth noting if you find this exciting, that we already offer all the features described in Brighter (and more @voroninp we have your outbox and inbox already):

https://github.com/BrighterCommand/Brighter

So if you are looking to work with a mature messaging framework, battle-tested at scale, (that also supports .NET Framework) feel free to check us out and start using events today instead of waiting.

We have been doing this for 10+ years, so our offering comes with a wealth of experience.

iancooper commented 8 months ago

But to the larger point. The .NET space is perhaps more richly served than any other ecosystem with messaging tools, both commercial, commercial support and solely OSS. Competition amongst those projects has created a strength in offerings that other languages don't have.

When MS enters the space that diversity and competition will be crushed, leading to less innovation and choice.

There is no argument that MS needed to enter this space, .NET developers were more richly served than any other ecosystem.

Instead this is just the usual MS playbook - crush successful OSS - own all the things.

When I spoke about a .NET Renaissance many years ago I was clear that MS had a duty of care as the 500lbs gorilla in the room not to do this.

But whilst previous flattening of .NET OSS could be seen as ignorance or lack of care, they know well enough by now, that this can only be seen as malice.

jeremydmiller commented 8 months ago

FWIW, I'm voting hard against any set of common abstractions for the entry point to messaging, and even more so to any kind of standardized interface signature for message handlers. That's a recipe for a mediocre developer experience that won't make .NET "the best platform for cloud native applications". This isn't a place for a "Conforming Container" kind of approach.

to11mtm commented 8 months ago

Please, No.

We are thankfully blessed with a lot of good libraries at various layers for event-ish type stuff:

Again, all of the above are extremely useful in the context of eventing or event driven systems.

I don't see how one could make a sane abstraction however, since many of them are context dependent yet cannot be easily simplified. They mostly have enough different but unique semantics to where a common abstraction could easily be either of little utility or just dangerous.

My apologies for any firmness here, I have concerns that another 'conforming container' across all of these paradigms would risk turning the story of event driven systems in .NET into a cautionary tale about good intentions stifling innovation and flexibility, potentially at the benefit of specific vendors despite the unique opportunities each of the above mentioned cases would handle.

I hope the community does not decide to add a 'conforming container, but for events', especially if it happens to conform best to a brand new system without clear benefit compared to existing ones aside from 'being first party' or 'well you need it anyway because ASPNETCORE'.

If we wanted to fix eventing at a better level, I would suggest:

Points One and Three, I think are fairly easy, it's just a matter of putting them where people can get to them.

That middle point, It actually solves a lot of other problems in the .NET space...

More Importantly, It helps the authors of all of the above things give better results to the community, as they have done for so long.

If you -do- choose to go down the route of a common abstraction, I would hope that it is a public process and you involve the above mentioned parties as well as others.

niemyjski commented 8 months ago

Just keeping an eye on this as a maintainer / co-creator of https://github.com/FoundatioFx/Foundatio. I just hope this doesn't follow the path of IDistributedCacheClient that I've seen used by very few. Please engage early and often with leaders who have been in this space a long time.

iancooper commented 8 months ago

Providing a first party abstraction to get as close to I want everything directly written in this async method to execute on a dedicated thread (or within a limited priority pool) as possible.

That is definitely an interesting one. Brighter uses a reactor/proactive model (depending on whether you use async) and has a single threaded message pump to preserve ordering (which you scale out). This also means we don't run into problems with thread pool exhaustion, or blocking on semaphores trying to limit work in flight at high scale. We use a custom SerializationContext based on an article by Stephen Toub to have async callbacks use that thread. But is a little gnarly and a framework solution to that problem would have re-usable value.

TeddyAlbina commented 8 months ago

Just keeping an eye on this as a maintainer / co-creator of https://github.com/FoundatioFx/Foundatio. I just hope this doesn't follow the path of IDistributedCacheClient that I've seen used by very few. Please engage early and often with leaders who have been in this space a long time.

I love foundatio ❀️❀️❀️

chrisfcarroll commented 8 months ago

Maybe one could compare the amount of money & effort that would be needed to develop a de novo fit-for-use eventing platform against the money & effort needed to create a set of template projects?

For Event Driven Architectures, having the right set of templates may be 80% of the developer win.

StephenCleary commented 8 months ago

If this does move forward, please also add:

With some solutions, it can be hard to even figure out what the DLQ is named...

niemyjski commented 8 months ago

Also, Kafka should be considered as it greatly impacts design.

jbogard commented 8 months ago

Also, Kafka should be considered as it greatly impacts design.

This proposal is about message queues. Kafka is not a queue, I don't think it should be considered.

voroninp commented 8 months ago

Good article about Kafka and message buses: https://particular.net/blog/lets-talk-about-kafka

iancooper commented 8 months ago

Queues vs Streams: https://youtu.be/RVmDU1QJmAs?si=zNA2EJslnvX23-mg

niemyjski commented 8 months ago

This more just comes down to messaging.. and I'm leaving this here https://x.com/BdKozlovski/status/1735344274655592685?s=20

Wanna use Kafka as a simple Queue?

With the new KIP-932: Queues for Kafka, you soon may be able to!

davidfowl commented 8 months ago

First, apologies for the confusion and concern we caused with this issue.

The idea was to focus on small subset of event handling, effectively "WebJobs v2" (https://github.com/Azure/azure-webjobs-sdk), principally for the Azure Functions folks but generic enough for everyone (like WebJobs is today). The goal is to align the Functions programming model with ASP.NET Core Minimal APIs so the developer experience is consistent. We have no plans to implement the application-level patterns which the rich ecosystem of .NET messaging frameworks and libraries already implement, such as sagas, outbox, persistence, or DTC integration. Your feedback here is important to us, and we will do better to reduce ambiguity up-front in the future.

Here are some more details:

I want to be clear that this is not a work area that's been approached with malice towards or ignorance of the various libraries that exist in the ecosystem. Figuring out when we should integrate with/recommend/use/etc. an existing package when we're exploring a particular problem area is always complex, and we don't take that responsibility lightly. Our overarching goal here is always to be responsible towards our users and our community.

We're still prototyping and figuring out details, but this is what we sketched out:

var builder = Host.CreateApplicationBuilder();

builder.AddAzureQueueService("orders");

builder.Services
  .AddEvents()
  .AddAzureStorageQueueEventProvider("orders")
  .AddTimerEventProvider("cron", "*/5 * * * *");  

var app = builder.Build();

app.UseRouting();
app.UseExceptionHandler();

var orders = app.WithProvider("orders");
var cron = app.WithProvider("cron");

orders.MapEvent("order-received", (Order order, ILogger<Program> logger) =>
{
  // Handler logic here
});

cron.MapEvent((TimerInfo timer) =>
{
  // Handler logic here
});

app.Run();
iancooper commented 8 months ago

Thanks for the feedback @davidfowl it is helpful

iancooper commented 8 months ago

@davidfowl Would I be right in thinking then that you perceive this as closer in scope to Celery than a messaging framework? https://docs.celeryq.dev/en/stable/getting-started/introduction.html

mmisztal1980 commented 8 months ago

Why are you calling it eventing, when it's clearly about messaging? Think about the confusion you'll introduce with the DDD crowd

davidfowl commented 8 months ago

@davidfowl Would I be right in thinking then that you perceive this as closer in scope to Celery than a messaging framework? https://docs.celeryq.dev/en/stable/getting-started/introduction.html

I don't think so but I don't know celery deeply (though I am aware of it). The framework design is intended to be much like ASP.NET Core but for non-http events. Here's the mental model we're using:

image

Why are you calling it eventing, when it's clearly about messaging? Think about the confusion you'll introduce with the DDD crowd

That's good feedback. We're leaning into cloud events since that's the primitive everything is built on. Maybe "cloud event framework" πŸ˜„. If you look at the code sample there are also timer events. Nothing is set in stone yet but event from a .NET POV felt like the most generic thing (raise an event in response to this message from the network).

captainsafia commented 8 months ago

To add onto @davidfowl's diagram above, *I*EventProvider is an interface that can be implemented to support resolving events from a variety of sources. An application might contain multiple event providers, like the sample above which includes timer-based and Azure Storage Queue-based event providers.

jeremydmiller commented 8 months ago

@davidfowl Thank you for the clarification, and I respect that you're trying to defuse the obvious concerns that some of us will have with this effort. All the same though, this is absolutely a messaging framework -- if a minimal one -- and will absolutely overlap and take away support from existing community and 3rd party tooling that already exists in .NET today.

That aside, I'm a little curious if y'all can share anything about your intended middleware strategy? And offhand, I'd question that approach in terms of the testabillity right off the bat. A decent team can certainly take steps to detangle much of their code from the framework for testability, but you're dependent on developer discipline and practices for that rather than the tool promoting testability. Do y'all have some existing ideas about how you're going to deal with that? Guidance, or maybe an integration testing harness of some sort?

to11mtm commented 8 months ago

First, apologies for the confusion and concern we caused with this issue.

The idea was to focus on small subset of event handling, effectively "WebJobs v2" (https://github.com/Azure/azure-webjobs-sdk), principally for the Azure Functions folks but generic enough for everyone (like WebJobs is today). The goal is to align the Functions programming model with ASP.NET Core Minimal APIs so the developer experience is consistent. We have no plans to implement the application-level patterns which the rich ecosystem of .NET messaging frameworks and libraries already implement, such as sagas, outbox, persistence, or DTC integration. Your feedback here is important to us, and we will do better to reduce ambiguity up-front in the future.

No confusion from the .NET folks that have been around enough and knew this was about Microsoft.Extensions.IConformingAbstractionThatWillMapGreatToAzure from the get-go...

I want to be clear that this is not a work area that's been approached with malice towards or ignorance of the various libraries that exist in the ecosystem. Figuring out when we should integrate with/recommend/use/etc. an existing package when we're exploring a particular problem area is always complex, and we don't take that responsibility lightly. Our overarching goal here is always to be responsible towards our users and our community.

I'm already getting that Microsoft.Extensions.DependencyInjection vibe, hope that won't be the case...

Aaronontheweb commented 8 months ago

ASP.NET is an HTTP and WebSocket programming framework - why does it need to have generic handling for "cloud events"? I'm not questioning the market need for having this, I'm questioning why does this need to be added to a web framework?

davidfowl commented 8 months ago

@jeremydmiller

That aside, I'm a little curious if y'all can share anything about your intended middleware strategy? And offhand, I'd question that approach in terms of the testabillity right off the bat.

Just like ASP.NET Core, where you can fake the HttpContext, you can also fake the EventContext (which is just a CloudEvent and an IFeatureCollection).

A decent team can certainly take steps to detangle much of their code from the framework for testability, but you're dependent on developer discipline and practices for that rather than the tool promoting testability. Do y'all have some existing ideas about how you're going to deal with that? Guidance, or maybe an integration testing harness of some sort?

Initial thoughts were around in memory model we have AKA WebApplicationFactory (though with a less bad API πŸ˜„). TBH we haven't gotten that far yet. Like I said, the mental model is map to the primitives we've defined in ASP.NET Core and change it when it doesn't work.

PS: Some really early ideas on this looked at reusing ASP.NET Core itself and sending cloud events over HTTP (similar to how dapr works but in proc).

davidfowl commented 8 months ago

ASP.NET is an HTTP and WebSocket programming framework - why does it need to have generic handling for "cloud events"? I'm not questioning the market need for having this, I'm questioning why does this need to be added to a web framework?

I'm not sure it's part of ASP.NET Core, though the issue is on this repository, it's not clear that this framework is going to be a fundamental part of ASP.NET Core. We're not sure where it'll live in the overall architecture diagram yet.

jscarle commented 8 months ago

The risk is that, similar to what happened with DI, the "common interface" effectively defines the implementation and stifles innovation. There was a great thread many moons ago where the author of Simple Injector was trying to explain why the DI interface was hostile to the fundamental premise of Simple Injector. IIRC the conclusion was ~"this is a solved problem that doesn't need innovation" which was off base considering Simple Injector was a reasonably popular project that was taking a different tack that wasn't achievable with the "common interface".

Not sure how that all finally resolved in the end.

My desire would be to always be able to opt out and also to be able to rebuild whatever is given from smaller bits of the framework.

.NET is very much an opt-in model. Most of us simply prefer to use the out-of-the-box model because, as a whole, .NET's defaults bring a lot of value. But you can go the full IKEA route with things like CreateEmptyBuilder.

jscarle commented 8 months ago

ASP.NET is an HTTP and WebSocket programming framework - why does it need to have generic handling for "cloud events"? I'm not questioning the market need for having this, I'm questioning why does this need to be added to a web framework?

I'd argue that some things are hard to get right. Rate limiting is a good example of one of those things that was recently added to the SDK.

I'll take something that's built into the framework and battle tested by millions of developers over a roll my own implementation any day of the week.

ilmax commented 8 months ago

I was thinking that the ability to expose an http endpoint is missing in the webjob sdk and it would be appreciated here to expose the health checks over http rather than using a more convoluted approach.

damianh commented 8 months ago

Why are you calling it eventing, when it's clearly about messaging? Think about the confusion you'll introduce with the DDD crowd

πŸ‘ŽπŸ» For "events" πŸ‘πŸ» To "messages" (of which "events" are a subset).

Aaronontheweb commented 8 months ago

I'd argue that some things are hard to get right. Rate limiting is a good example of one of those things that was recently added to the SDK.

... But that's actually an argument for using MassTransit / NServiceBus / whatever? It has the tens of millions of users already.

jscarle commented 8 months ago

I'd argue that some things are hard to get right. Rate limiting is a good example of one of those things that was recently added to the SDK.

... But that's actually an argument for using MassTransit / NServiceBus / whatever? It has the tens of millions of users already.

I agree with you, however I see this feature in a different light. I prefer to look at it in the same way I view the rate limiting that was added in .NET 7.0:

to11mtm commented 8 months ago

And also evidently MediatR exists solely to promote myself.

NGL @jbogard I always assumed it was mandated community service for AutoMapper.


The risk is that, similar to what happened with DI, the "common interface" effectively defines the implementation and stifles innovation. There was a great thread many moons ago where the author of Simple Injector was trying to explain why the DI interface was hostile to the fundamental premise of Simple Injector. IIRC the conclusion was ~"this is a solved problem that doesn't need innovation" which was off base considering Simple Injector was a reasonably popular project that was taking a different tack that wasn't achievable with the "common interface".

Not sure how that all finally resolved in the end.

Well the guy who wrote the book on .NET DI also came in, unfortunately it didn't help and sometimes new pain gets dropped but folks have given up on trying to reason. (personally speaking, finally gave up after Keyed services)


.NET is very much an opt-in model. Most of us simply prefer to use the out-of-the-box model because, as a whole, .NET's defaults bring a lot of value. But you can go the full IKEA route with things like CreateEmptyBuilder.

But the way MSDI works, especially with ASPNETCORE, it's very painful to actually use it as an 'opt in' model. I actually did a work app with SI and the MS DI Extensions, SignalR+Akka.NET+ASPNETCore and frankly it was a lot more violence to get around the conforming container's quirks in a correct way, compared to how things worked when we got to bring our own DI and had sane provider abstractions for ASPNET and framework.


I agree with you, however I see this feature in a different light. I prefer to look at it in the same way I view the rate limiting that was added in .NET 7.0:

* It's available, you're not obliged to use it. Usage is opt-in, not opt-out.

Not sure if this argument is serious, '1st party opt in' typically becomes 'lock in' in MSFT space pretty easily.

* It's not meant to replace more advanced, complex, or important use cases.

Probably my fear; perhaps at least I can look forward to seeing some amusing attempts of advanced, complex, or important use cases.

* In some organizations, due to governance, things like MassTransit are not available, this could give those organizations an alternative.

Sounds like a governance issue, shouldn't be papered over like this. There are plenty of great tools out there that a sane org shouldn't have a problem with.

* Not every project needs a large scale distributed event system which requires a high level of complexity. Perhaps this could allow more developers to start doing events/messages earlier in their project's lifetime.

See above comment; my fear is we wind up in a situation like EFCore where I'm amazed at how many engineers can't do complex SQL without EF.

* It could be a great way to onboard developers that are new to the .NET ecosystem. I also see the use case that this could be great for quick proofs of concept.

Depends on how tightly it's tied to what Azure does....

jeremydmiller commented 8 months ago

It's available, you're not obliged to use it. Usage is opt-in, not opt-out.

Its very existence will stop .NET developers from even researching or considering other options

It's not meant to replace more advanced, complex, or important use cases.

You know full well that users will demand more use cases and it will grow over time to meet a larger subset of the functionality in existing tooling

Not every project needs a large scale distributed event system which requires a high level of complexity. Perhaps this could allow more developers to start doing events/messages earlier in their project's lifetime.

You're making an assumption that non-MS tools are all difficult to get started with, and I think I'm rejecting the premise of that basic assumption. I also think that you're making a massive leap of faith that a Microsoft team with no experience of building or using tools like this will automatically make something that's easier to use than the range of existing tooling

davidfowl commented 8 months ago

Its very existence will stop .NET developers from even researching or considering other options

WebJobs and Azure functions already exist and are open source. Do you consider those messaging frameworks? If this was part of that effort would you feel the same way? (improving the programming model for something that already exists in what I mean).

jbogard commented 8 months ago

Its very existence will stop .NET developers from even researching or considering other options

WebJobs and Azure functions already exist and are open source. Do you consider those messaging frameworks? If this was part of that effort would you feel the same way? (improving the programming model for something that already exists in what I mean).

No, I don't. Just because something can consume a message from a queue does not make it a messaging framework.

Consider Spring Integration, which supports the patterns in Enterprise Integration Patterns. Those are the primitives a messaging framework lives in.

davidfowl commented 8 months ago

No, I don't. Just because something can consume a message from a queue does not make it a messaging framework.

Can others chime in? What are the elements above that make this a messaging framework and azure functions not one? I'm trying to better understand the nuance.

jscarle commented 8 months ago

Not sure if this argument is serious, '1st party opt in' typically becomes 'lock in' in MSFT space pretty easily.

The fact that a developer chooses to opt-in to the huge amount of value the default implementation of ASP.NET brings does not in itself consitute lock in. Like I mentioned, you can create an empty builder and make your own defaults. Or use the slim builder. Or heck, forget the builder and just write your own HTTP server. Nothing in .NET is lock-in. I could write my own implementation of various things that are brought in by the defaults, but why would I want to?

my fear is we wind up in a situation like EFCore where I'm amazed at how many engineers can't do complex SQL without EF

These are the same type of arguments that were originally made against top-level statements. In my personal opinion, the Program class was just a bunch of useless ceremony that I'm glad they removed. There is a whole new generation of younger developers that simply do not understand the concept of, or even the words, Dynamic-Link Library Entry-Point Function.

There are discussions going on right now between developers wondering if we'll reach a point in the future where AI will become sufficiently proficient to the level that human language will be the next level of abstraction in software development.

Making the developer experience easier and simpler for developers does not in itself dilute our talent. Educating yourself to learn more advanced techniques is a personal choice to which everyone has different abilities and comfort levels. If you want to play life on hard mode, write assembler. For some developers, .NET is their hard mode. I chose to learn to write source generators and quite enjoy it, for others its their hard mode.

Making the conscious choice to learn how to write complex SQL queries is what differentiates a senior developer from a junior one.

I also think that you're making a massive leap of faith that a Microsoft team with no experience of building or using tools like this will automatically make something that's easier to use than the range of existing tooling

That's a just a general blanket statement that completely dismisses the experience and skill of a massive pool of incredibly talented engineers who have collectively as a whole brought a lot of great things into the SDK over the years.

codymullins commented 8 months ago

I also think that you're making a massive leap of faith that a Microsoft team with no experience of building or using tools like this will automatically make something that's easier to use than the range of existing tooling

This is a bizarre statement and pure nonsense. I don't see the need here to attack the capabilities & skills of the dev team. You could just as easily push for this to live outside the core repositories or help shape how this features looks.

Besides, if you think what they'll provide isn't going to be easier than existing tooling, why do you care? This seems to be a very basic use case, which let's be honest, most apps would benefit from having less options and complexity.