Therefore, thank you for making this. Automapping is a sign of incorrect abstractions and unarguably bad solution architecture but since we are still forced to deal with such, doing so with speed and without reflection is always welcome.
Therefore, thank you for making this. Automapping is a sign of incorrect abstractions and unarguably bad solution architecture but since we are still forced to deal with such, doing so with speed and without reflection is always welcome.
But if there are little of those, no need to make them prematurely. Field mapping is something for EF Core mapper configuration or repository implementation to worry about, no need to do the job twice.
You often don't need separate "Host" and "Core" projects either. And if you ever need to migrate to a new hosting solution, it happens maybe once during application lifecycle, and even then it requires some effort.
Replace-all and IDE tools work just as fine if not better for this, no need to inflict easily avoidable pain simply because it looks consistent with "other" solutions that were written 10 years ago.
Yeah mate, let's create a generic repository over the top of EF's perfectly decent DbSet<T>, just in case we ever decide to switch ORMs!
Why would the customer need to know about the cruft? The view/UI shouldn’t be exposing what’s not needed. Same with the DB, frameworks like MyBatis put the mapping where it belongs.
While manual handling is required when you have proper domain models with controlled creation and change operations, these tools can be useful for other matters.
Then that pattern can be extremely effective - in fact, that is exactly the reason that some of us were pushing the patterns you see today. It was especially effective back before we had strong typing in frontends as it saved a lot of time otherwise wasted on QA or typo's in the frontend.
> without reflection
Source generators are not reflection.
In such cases, having an extra abstraction is both redundant and an anti-pattern that made sense in the age of large monoliths where the scopes/contexts/features where segregated by modules.
Today, where modularity and protection of abstractions is no longer of concern because many teams can easily maintain up to 10 or even 15 (micro)services, the bias towards a certain solution style/architecture that is full of unnecessary abstraction layers, boilerplate and patterns that violate locality of behavior like there is no tomorrow is something that makes using C# much less attractive than warranted.
Ultimately, it comes down to the fact that unlike Go, C# is more than 20 years old, and while it builds upon ideas that were ahead of its time back then like async/await, LINQ and some other, it also suffers from "tradition" which can be easily seen in community resistance to rely on top-level statements (aka Python-style Program.cs), religiously following the rule "one file = one class" (even if it's just 'record User(string Name);') or simply overall creating 5-project solutions for something expressible in 3 .cs files.
Keeping in mind Chesterson's fence, I do acknowledge that the above is a result of likely reasonable and well-thought-out choices at the time, but it does not mean the circumstances haven't changed either.
You see in C# and Java that people love splitting classes into files (and are forced to by automated auditing tools - my last big project suffered from that, even as Lead I had my hands tied). Navigating such projects is horrible outside of tooling (such as in github) but fine if you always work within the IDE.
In Python I'm used to wading through classes of >1k LOC which are only slightly related because they have the opposite habit. I've yet to find a way to work around this.
Honestly I'm not sure what I find worst: it really depends on the project or the domain. If I had to chose I think that I'd prefer "too many small files" to "one huge file" as the latter has an extremely high risk of turning into a "big ball of mud" and it's what the clueless beginners do. That and trauma of having to maintain some old Visual Basic system where that was the norm.
Although to be completely honest: I would much rather that the AST was the main interface for code. The fact that our tools are based on text is a relic of the past.
Your arguments reject complexity, then, in the next breath, endorse it. Micro-services are the enterprise bloat of our time (and likely the worst example of all the bad ideas that have circulated in that space). Small departmental apps used by 15 people require 34 micro-services (all hitting the same db tables of course).
To give a better example, recently on HN there was a discussion on self-hosting Bitwarden and its respective implementations. The official one[0] is written in C# and uses 15ish containers. The alternative one[1] is written in Rust and is a one application. I think both have their merits, since the former is used to serve possibly millions of users at this point, while the latter is best utilized in self-hosted home or SMB scenarios.
In the right hands - so with strong progressive leadership - it wipes the floor with other ecosystems.
Also changing the app back to old format is "Ctrl + ." -> "Change to Program.Main" away.
Developers would find a gripe with one new feature or another, even if it makes achieving a particular goal easier and less painful, simply because change is very uncomfortable to many.
What exactly does Go do here, besides being grossly more verbose and less expressive than C# (and even Java)?
Sure, there are edge cases to nominative typing systems, and some of these particular cases may be better expressible with a structural one, but that’s another discussion to have.