5 ms·
I think splitting into projects with their own separate dependencies is/was actually one of the few advantages to C#, because it lets you replace an entire proj
by jaabe 8y ago
I think splitting into projects with their own separate dependencies is/was actually one of the few advantages to C#, because it lets you replace an entire project and it’s dependencies seamlessly.
This has been extremely handy for us as we’ve been slowly upgrading to .net core. Because we can literally do it one project at a time without even risking breaking anything. Before going to .Net core it made switching from Web Forns to MVC really, really painless because all the business logic lived in its own projects, allowing us to run and maintain the Web Forms project, while building its replacement within the same solution.
I guess it requires you to think about the architecture of your solution, but what stack doesn’t? I say “is/was” an advantage though, because it’s primary use cases are frankly mostly related to the past or really bad practices. It allows you to keep a single project running on some really old .Net version, to utilise something legacy. That’s bad, but sometimes it has real works value, even if it’s bad.
NUGET has been fairly terrible though, and despite its many improvements, frankly continues to be so.
- stult 8y agoMy experience has been the same. It's great when the code base is designed and maintained by people who view assemblies as isolated, fully separable entities. But many programmers walk into dotnet not understanding the approach and make a mess of it.
- james_s_tayler 8y agoIt's for exactly this reason that I think anything that makes the _technically_ optimal set of choices is actually a bad bet because the probability it is understood well enough to be used in the correct manner is low and it's possible to use it an an incorrect manner. So that's mostly what you see.
- tracker1 8y agoAgreed... imho, make the code as discoverable and simple as possible. It's easier to copy/paste or just replace classes as needed rather than make them composable or setting up huge injection profiles.
- jaabe 8y agoI don’t understand that though. I agree that C# certainly could be clearer on the intended purpose of project separation, maybe it could even be stricter, but the default way to build projects in C# is with a high amount of isolation. You can break this isolation, but you have to deviate from the standard. Hell breaking some parts of the project isolation in C# is even quite tricky. Ironically consolidating your packages cross projects while using NUGET is suggested by standard, but I’ve already shared my views on NUGET being terrible. Anyway, my point goes something like, if you’re not utilising OOP “correctly” in C#, then why would you be using OOP “correctly” in a language that is even less opinionated about isolation than C#? I say “correctly” in quotes because I personally like a high amount of isolation in my OOP, but I’m sure not every one does.
- crispyambulance 8y agoI like the idea of "isolated, fully separable" assemblies, but there's very little explicit advice on this topic and the tools themselves (visual studio and msbuild) are agnostic about that. I mean, there's nothing to prevent you from spreading out namespaces across multiple assemblies. You can specify namespace and assembly in the "properties" dialog for your project, and also in within the source for each cs file, etc. I've never understood this lack of "guard-rails" in the tooling to prevent these kinds of messes. It seems like that would be reasonable thing to expect?
- tracker1 8y agoI've seen it as a mess far more often than something clean that ever gets replaced. I once worked on a project where a relatively simple change meant changing/adding interfaces in over 36 files across 17 projects in 2 solutions. It took a week and a half to thread that noodle through the pile of spaghetti. My opinion today is that it's easier to have more understandable code than apply "Enterprise" patterns early on. Create classes and test from them instead of deep DI/IoC patterns and interfaces everywhere. In the end, build it like it's throw away code and have high code coverage requirements when in doubt. I do understand the various patterns, and have worked with them, and more often than not, the path leads to a big mess in practice. I tend to lean away from smarter classes and instead favor POCO + Utility Classes with Single Instances. YMMV of course.