Happy Monday to you all and happy October. I hope you have a good week. My goal: to develop a data model simpler than this one.
Here's what we have this week:
- Exploring modern C#
- Custom deployment layouts for Blazor WebAssembly apps
- Last week in the .NET world
Exploring modern C#
With the official release of .NET 6 next month, we'll see the release of C# 10. Much like the .NET platform as a whole, the language is beginning to adopt incremental, annual releases going forward. The C# 10 release brings us features like record structs, global using directives, extended property patterns, file-scoped namespaces, and so on. Richard Lander's .NET 6 RC2 announcement will be looking into some of these.
As C# has shifted over the years from a strict OO language to a more general-purpose one, it's experienced some pushback on how heavy it's become. We tend to go in circles in the .NET community: yes, there's a lot—it needs to evolve to be a modern language, but it also can't break people who rely on the older features. Right on time, the newsletter Twitter account posted a link to an article asking: is C# too complex? It spawned an interesting discussion, both about the article itself and of C#.
I like what Kathleen Dollard, a Microsoft PM for .NET Core CLI and Languages, had to say:
Still, I don't think it's realistic to expect a single way to do things, but it can get out of hand. As a simple example, there are at least a half dozen ways to check if a string is empty. It's that there are so many ways to do a single thing: some are modern and some best practices, some not—all the while, we know the language will never take anything away for backward compatibility reasons.
For us experienced developers, we can say the language is evolving and just "use what works best for you." What if you don't, or don't want the mental weight of dealing with it all?
As I was listening to C# language designer Mads Torgersen on Bryan Hogan's No Dogma podcast, I found this following exchange quite interesting. (I know there's a lot in this exchange, but I wanted to post it all to avoid taking anything out of context.)
Q: All of these new features, feel like new ways of doing old things and I would imagine they could get confusing. A criticism about C# that's been around for a while is that there are so many ways to do one thing anyway, and now you've added a whole bunch of new ways to do things I could do already.
A: Yes. That's a real challenge. If you have a programming language and you want to keep it the best option for somebody making the next project, it has to be modern. It has to have ways of doing things that are as expressive, as sleek, as ergonomic, performant, fast, and efficient as the other languages. So we have to keep evolving to do that. Now at the same time, we don't like throwing things out because we break people's existing code. What's a programming language designer to do?
We've lived with this conundrum for a while. I think we're starting to circle in on at least a partial solution to it. I can't say for sure that we're going to do this or how we're going to do it, but ... someone like Bill Wagner, who is doing our documentation and working on the C# Standard ...he's very essential in this discussion, said: "How about we try to define modern C#?" If you're coming to C# fresh or even as an existing C# programmer in general—if you have a pretty clean slate, this is the subset that you should be using. If you're outside of that subset it's either because you're trying something fancy like using
Span<T>to do efficiency stuff or unsafe code, or it's because you're doing some legacy things. Otherwise, these are the ways you should be doing things.
And then we could reinforce that from the documentation point of view, from a learning point of view, and also from a tooling point of view—we would take these templates and take those little suggestions and say: "Hey, that's kind of an old fashioned thing you're doing there, it would be sleeker to use pattern matching here, why don't you?" In fact, we have plenty of those in place already. We just don't have a coordinated set of features that are like "this is modern C#."
Then that evolves with the language, like when usings come in and some other things fall out of what modern C# is. And now there's a better way to do things. Now, we don't tell you to put usings on top of the file anymore, and we don't have guidelines about whether to prune or not ... that's just gone out of modern C# and now a modern C# programmer doesn't do that anymore. A sliding window that's current C# might help as long as we don't make it a worse experience to use all of the language. But maybe we can make it an even better experience to use the modern part of the language and can give you more guidance if you're not a veteran or if you don't want to chase down all the reasons for doing one or the other and you just want a recommendation—how should I be doing this? This is what we're currently working on.
I found this very interesting. A C# subset is not a new idea but I think Microsoft working on it is. In the past, I've seen some Microsoft resistance to that idea. It's early days but promising for the future of C#.
Custom deployment layouts for Blazor Web Assembly apps
This week, on the ASP.NET Blog, Javier Calvarro Nelson wrote about new .NET 6 extensibility points that will allow development teams to customize which files to package and publish with Blazor WebAssembly apps. The idea is that you could reuse this as a NuGet package. As Javier notes, this is important because some environments block and download the execution of DLLs from the network for security reasons.
The article lays out how to build the package yourself, but you don't have to. According to Daniel Roth, you can use a prebuilt experimental NuGet package to try it out. To use it, add a reference from your client project, update the server project to add the endpoint, and then publish your app. This is a good first step—hopefully, the end goal is to provide this out of the box.
🌎 Last week in the .NET world
- Michael Staib releases Hot Chocolate 12.
- Jiachen Jiang writes about the new nuget.org package details page.
- JetBrains launches the EAP for Resharper 2021.3 and also for Rider 2021.3.
- Javier Calvarro Nelson writes about custom deployment layouts for Blazor WebAssembly apps.
📅 Community and events
- Rodney Littles II writes a difficult, but important, post about his experience on the .NET Foundation board.
- Carol Smith announces Azure credits for open source projects.
- Beau Carnes launches a free Git for Professionals course.
- Henning Dieterichs writes about how the VS Code team made bracket pair colorization 1000x faster.
- Austin Lamb introduces SizeBench, a new tool for analyzing Windows binary size.
- Jeremy Miller writes about how to build efficient web services with Marten v4.
🌎 Web development
- Kristoffer Strube uses Blazor AoT compilation.
- Jon Hilton writes about how he organizes his Blazor components.
- Nancy Young writes about the pros and cons of Tailwind.
- Andrew Lock explores the code behind WebApplicationBuilder in .NET 6.
⛅ The cloud
- Tomasz Pęczek handles transient errors in Azure Durable Functions.
- Mark Heath asks: is it time to start creating C# Azure Functions in isolated mode?.
- Steve Smith writes about running GitHub Actions on demand.
- Michael Moreno asks: is C# getting too complex?
- Vladimir Pecanac explores events in C#.
- Scott Hanselman writes about implicit usings in .NET 6.
- Khalid Abuhakmeh compresses strings with .NET and C#.
- Jeff Fritz introduces LINQ in C#.
- Thomas Claudius Huber uses global using directives in C# 10.
- The Kubernetes Blog discusses how to handle data duplication.
- Davide Bellone tests HttpClientFactory with Moq.
- David Ramel writes how GitHub Copilot AI is spawning OSS Alternatives.
- Christian Gunderman avoids memory leaks in Visual Studio editor extensions.
- Mike Melanson writes about Docker defending their new Docker Desktop pricing, and the Docker Desktop PR campaign continues.
- Tobias Günther creates the perfect commit in Git.
- Milan Milanović writes about CI/CD with Azure DevOps.
🏗 Design, testing, and best practices
- Derek Comartin talks about an always valid domain model.
- Steve Smith groups assertions in tests.
- Thomas Maurer writes about how GitHub partitions its relational databases.
- Jimmy Bogard continues his DDD series with a write-up on encapsulating collections.
- Peter Vogel continues his series on unit testing legacy code.
🎤 Podcasts and videos
- The Coding Blocks Podcast talks about transactions in distributed systems.
- .NET Rocks talks to Mark Seemann about code that fits in your head.
- Software Engineering Daily talks about scaling Git for monorepos.
- The ASP.NET Monsters discuss new LINQ methods in .NET 6.
- Azure Friday walks through CosmosDB.
- The Azure DevOps Podcast talks to Anna Hoffman about Azure SQL.