I got paid. That's all the good stuff I can say about it.
I got paid. That's all the good stuff I can say about it.
I wouldn't necessarily blame it on a lack of seniority or inexperience, it's a matter of not knowing the initial style, decisions, and limitations, as well as the vagaries of time. I find myself creating duplicate functions not because I wouldn't reuse the ones that exist, but because the original one was hidden away in a different place than I'd ever think to look for them. My approach is different and drifts even further over the years, I can't help it, so that the project starts to look stranger and stranger comparing the old code to the new. The original designers would find their style drifting too if they had to take care of a system for that long. They are just lucky enough that their style drift has project cut-offs, so each slice seems more cohesive.
I also don't know if this is a current maxim or not, but there should be a software principle that matches Peter's - every successful system will grow until it reaches a point where it's no longer successful. More and more requirements get added on, and unlike initial requirements where you could justify keeping scope tight due to staying lean, a system needs to grow beyond it's current limitations or it dies.
An additional side effect is that management fails to understand what/why is going on and overvalues the skills of the "experienced devs" and undervalues the skills of the maintenance devs because they don't understand the order-of-magnitude speed advantage enjoyed by devs when writing greenfield code.
"Experienced Developer A wrote the whole damn system in three months! Now Maintenance Developer B wants three months just to add a few buttons?!?"
I've been both the experienced person and the junior maintenance person.
The root issue is that management never seems to be able to grasp things on a technical level. I've tried to communicate this over the years, and have been praised for my communication skills in general, but I've never managed to bridge this particular gap.
Additionally: https://docs.microsoft.com/en-us/dotnet/architecture/porting...
Also the assistant doesn’t help with the numerous third party components which were never ported to core, the entire MVC stack internal changes or the changes that took place in NHibernate. So even if it did work it’d break everything in the process.
But I should mention that nhibernate is not even in the dotnet foundation and not supported for .net core ( I visited their site and it mentions dotnet framework).
I see this though: https://enterprisecraftsmanship.com/posts/nhibernate-now-sup...
So the issue is mostly nhibernate?
"c#" <--- this is not
Imagine what a 15 year old C++, Java, Javascript or Python project would look like. Not much different, I'm thinking...
You can possibly work with and update a C# program because of the incredible longevity/backward compatibility of the core libraries, and reasonable commitment to this in the culture of the ecosystem.
But in Javascript land this can easily or even typically hit a point where the errors from package churn are so much that economically the juice is not worth the squeeze, in a literal order of magnitude less than the typical C# system.
I agree that pretty much any 15 year old code base is going to get rough, but I think these languages have some clear footguns that aren't doing them favors either. I work on a codebase that isn't more than a few years old, and there's complexity issues from simple things like the language lacking good semantics for transforming data immutably, and that complexity spirals
I can attest that writing messy processes in languages that do address these concerns is absolutely possible, I've done so myself, but the mess is contained to a particular area and it's not as hard to follow which pieces of a system feed into another. Things as simple as making immutability the default and mutation explicit like Rust, and requiring modules be organized into a hierarchy like F# are huge wins. As much as I've gotten annoyed with F#'s project files hierarchy requirement because it requires some extra work/considerations for codependent types and codegen, it's amazing how much easier it is to jump into a new codebase where you can clearly see to understand behavior you start with the bottom of the file list, and to understand core logic/patterns you go to the top of the file list
One dark place some .NET devs got caught in the early days was some of the 3rd party ORMs. Nightmare of weird code, proprietary mapping tools and headaches.
I am still not sold on linq2sql either. Debugging that is never fun.
ORM-lites, such as Dapper, which only bind query results to objects, are an obvious exception thoug.
Every time I’ve seen a project use an ORM past the proof of concept phase, it ends up with some garbage layer to bypass or “trick” the ORM into doing something acceptable. (e.g. Complex materialized views presented as tables to the ORM so the ORM can just do straight selects without joins).
When I thought I needed better control and performance I wrote my first ORM. Which wasn't really all that ORM-y. It would use reflection to map to an object, but queries definitely weren't linq-able or using IQueryable and walking the predicates to dynamically generate queries. It was more like dataBase.TableName.First("id=@id", new {id = 1}); Which would generate "select * from TableName where id=@id" nothing earth shattering. Joins were done through dataBase.Join(new [] {"table1", "table2" }, new [] {"on table1.id=table2.table1_id"}, "table1.id=@id", new {id=1});
It was ugly and I eventually just replaced it with straight ADO.net.
I tried various other ORMs over the years, I eventually just settled on EF since it was not bad, and generates almost sane SQL most of the time.
It always made more sense to me to have a sanely-designed database first and then generate the mapping code from it, rather than the code-first style that seems to be popular with EF. You can do the database-first mode with entity framework, but it is less the happy path that the tooling and documentation tries to nudge you into.
I don't deny the value of the active record pattern where it works, but in almost every case I've used SQL over the past 5 years, I don't want a complex abstraction layer. I just want something to make it easy and safe to talk to the database for the 90% of straight forward queries we write.
With something like that, I feel as though I'd rather write my own active record system than use the configuration based systems we see with EF
I'm looking at you LLBLGen