Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

the patterns can still be completely the same without OOP - pairing data and functions that operate on said data. enemy.damage() and Enemy::damage(enemy) are functionally and semantically equivalent. But in the latter case (where you separate data and code) you don't need to worry about object assembly/IoC, how to pass a reference to A all the way through the object graph to object B, composition over inheritance becomes the default (at least in my experience using TypeScript interfaces, YMMV with other languages). The benefits of OOP, primarily state encapsulation, stop looking like benefits when it turns out your state boundaries weren't quite right.

Of course I'm biased as I went through the same "procedural => OOP => case-by-case" learning curve as the GP. But I ended up spending a lot of time trying to satisfy vague rules when using OOP - with procedural/functional programming with schema'd data, I get to spend a lot more time on what I actually want to do. Not worrying about SRP, SOLID, object assembly, how to fix my object graph now that A needs to know about B, and so on.



> how to pass a reference to A all the way through the object graph to object B

you just end up replacing the object graph by the call graph, which makes all the business logic much messier as now every function call takes a "context" argument


That's not been true in my experience - what you do end up with is a global data structure, which is the shared state for all or most non-ephemeral top level concerns. Aside from recursive functions I find call stacks tend to be quite short.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: