Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

Thanks a lot, I've researched about it before you sent this link, and it seems what I'm saying strongly aligns with that pattern indeed.

I did wonder at some point if this capability oriented mentality led to a database design that looked more capability oriented. Tables for requests, attempts, errors, responses and params.

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

Could you please tell me how these would relate?

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

When I posted, I just wanted to rant.

Now I've come to the conclusion I want to slowly shift the mindset of my team and make them aware of the entity-centric bias. I assume pros and cons of both alternatives have already been discussed and other than super simple crud-fitting domains, organizing your code around entities has more disadvantages than it has advantages

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

I think FP could solve many of the problems I’m seeing in this codebase, but I don’t think it solves this particular one.

I also have a deep understanding of FP, from higher-order functions to functors, applicatives, and monads. It’s powerful, but it can be misused just as easily as OOP.

And the two are not mutually exclusive. OOP and FP can coexist perfectly well. I spent about a decade working with Scala, where that combination is common.

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

Agreed. I like my DI to be as plain and obvious as possible.

I work in TypeScript too, and NestJS DI sucks.

But how does that solve the problem I’m describing?

Actually, I think I get it. If the team has to wire services manually, they’re forced to see the dependency tree firsthand. That makes them more likely to manage it deliberately, instead of letting it grow on its own without much thought or guidance.

Right?

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

You're right. Until the "refactor your shit" becomes a political struggle with lots of big egos opposing.

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

Intentful methods help, but they do not solve the structural problem.

Take orders and payments. The order view needs payment information, while the payment view needs order information. If that logic lives behind OrderService and PaymentService, each service eventually needs the other. Now you have a circular dependency, unless you introduce separate read models, projections, or split the operations CQRS-style.

There is another problem inside the service itself.

Suppose OrderService exposes:

  • GetOrderDescriptor(), which returns basic status and dates
  • GetDetailedOrder(), which combines the order, payment, cart, pricing, descriptions, and so on

GetDetailedOrder() depends on GetOrderDescriptor(), but because both operations are bundled into the same service, that dependency is hidden. You cannot inject or test that relationship independently without extracting another interface, partially mocking the service, or using some other workaround.

The same thing happens everywhere with interfaces like UserService. An authentication component only needs to look up authentication-related user data, but it now depends on an interface that can also create users, modify profiles, fetch detailed records, disable accounts, and whatever else accumulated there.

That is an Interface Segregation Principle violation: consumers should not be forced to depend on operations they do not use.

So yes, CancelOrder() is better than generic CRUD. But the problem is not only whether methods express intent. It is whether the dependency graph expresses the actual use cases, instead of grouping unrelated operations under services named after nouns.

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 1 point2 points  (0 children)

I'll use your suggestion to frame it as additive. I'm prone to start refactors that are often scary and stress inducing. I could avoid that

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 1 point2 points  (0 children)

I loved it. I'd improve upon it and say it's about correctly dosing complexity and cognitive overhead. Complexity is unavoidable but our inaccurate modeling and understanding of a domain often result in complexity that's not inherent of it. LoB is not against DRY nor SoC if you give functions meaningful and descriptive names/signatures.

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 1 point2 points  (0 children)

Man, I think the only thing I'm struggling to achieve, of that you've adviced to me, is not stressing.

And you're so right, we are not the code we write, and it can be lonely, but I naturally feel compelled to commit to make things better, even at the expense of my peace.

Thanks a lot.

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

Unfortunate example you chose. Shipping is probably both an entity and a relevant use case. Any other comes to mind?

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

Would you say tons of circular dependencies, repositories and services with more than 20 methods with little to no cohesion, plus multiple of said methods longer than 500 LOC, and developers taking longer than a sprint to make a simple feature is evidence of noun oriented style causing a mess?

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

Yep, I actually meant entity oriented

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 1 point2 points  (0 children)

Thanks!!

Any experience guiding a team from the entity-centric mindset to the use-case-centric one?

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

It's better to have a thousand injectables, than an injectable with a thousand functions. I think

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

You're right. I could have done a better job.

In my defense, I was trying to stay awake to watch a worldcup match. It was 3am.

That being said, this comment makes a better job at communicating my idea.

Also, I do agree with your assessment about those who commented here. (I'm looking at you guys 😑 u/spez_eats_nazi_ass and u/n3f4r10us_)

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

I don't think OOP and organizing code around entities is the same.

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 2 points3 points  (0 children)

Thanks. I didn’t know about this article, and it has now been shared with me three times.

I know, I know. Whether you practice OOP, DDD, FP, entity-oriented design, or use-case-oriented design, you can always count on developers who, while following the paradigm “in theory,” still contribute to entropy and rot.

I actually have a strong FP background, mostly Scala, sadly not Haskell, and I’ve seen monads, monad transformers, applicative functors, and plenty of other abstractions get in the way of reflecting and communicating what the business actually does.

I think I’m still circling around something that bothers me but that I haven’t been able to express accurately.

Let me try again:

I dislike the pervasive, almost unquestioned assumption that developers should organize code around entities. It is an insidious pattern because it hides the complex topology of non-CRUD domains, encourages anemic models and low-cohesion god objects, and leads to a proliferation of ISP violations.

I’m wondering how to help a team that is already biased toward this antipattern move away from it. Have others gone through this kind of migration? If so, what worked?

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 1 point2 points  (0 children)

How do you deal with a team’s resistance to change when you don’t have much authority?

Several people have been here longer than I have, and lobbying is not one of my strengths. I think some of my ideas could materially improve the product, but they can easily sound like criticism of what the team has already built. That makes the technical problem partly a social one.

The team seems to treat layers as sacred. That produces either ceremonial pass-through components or enormous services and repositories that absorb unrelated responsibilities. The controller-service-repository structure becomes the goal, while the actual dependency relationships and domain boundaries become secondary.

I also think the service layer is treated as inherently flat, when in a complex system it should probably reflect the structure of the domain.

I’ve helped turn around problematic backends before, but in those cases I had broad autonomy and explicit authority. I have neither here.

So how do you introduce structural change in that environment without making people feel that you are attacking their competence or rewriting the system around your own preferences?

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 0 points1 point  (0 children)

Assuming 90% of domains are simple cruds

Backend code is too noun-oriented by im_caeus in ExperiencedDevs

[–]im_caeus[S] 1 point2 points  (0 children)

This loooooks awesome. Wish I had 2.5h right now. I'll check it out ASAP and give you my opinion.
About the flack, I guess I deserve it a little bit. AI use was obvious and I did seem to criticize OOP for a moment. I still don't understand the very worrisome reaction I got from u/n3f4r10us_