| ▲ | WorldMaker 5 hours ago | ||||||||||||||||||||||||||||||||||
> As a total beginner to the functional programming world, something I've never seen mentioned at length is that OOP actually makes a ton of sense for CRUD and database operations. I've heard this a lot in my career. I can agree that most object-oriented languages have had to do a lot of work to make CRUD and database operations easy to do, because they are common needs. ORM libraries are common because mapping between objects and relations (SQL) is a common need. It doesn't necessarily mean that object-oriented programming is the best for CRUD because ORMs exist. You can find just as many complaints that ORMs obfuscate how database operations really work/think. The reason you need to map from the relational world to the object world is because they are different worlds. SQL is not an object-oriented language and doesn't follow object-oriented ideals. (At least, not out of the box as a standardized language; many practical database systems have object-oriented underpinnings and/or present object-oriented scripting language extensions to SQL.) > it's super hard without an ORM or at least some kind of object layer This seems like you might have got caught in something of a tautological loop situation that because you were working in a language with "object layers" it seemed easiest to work in one, and thus work with an ORM. It might also be confusing the concepts of "data structure" and "object". Which most object-oriented languages generally do, and have good reason to. A good OOP language wants every data structure to be an object. The functional programming world still makes heavy use of data structures. It's hard to program in any language without data structures. FP CRUD can be as simple as four functions `create`, 'read`, `update`, and `delete`, but still needs some mapping to data structures/data types. That may still sound object-oriented if you are used to thinking of all data structures as "objects". But beyond that, it should still sound relatively "easy" from an FP perspective: CRUD is just functions that take data structures and make database operations or make database operations and return data structures. A difference between FP and OOP's view of data structures is where "behaviors" live. An object is a data structure with "attached" behaviors which often modify a data structure in place. FP generally relies on functions that take one data structure and return the next data structure. If you aren't using much in the way of class inheritance, if your "objects" out of your ORM have few methods of their own, you may be closer to FP than you think. (The boundary is slippery.) | |||||||||||||||||||||||||||||||||||
| ▲ | javcasas 3 hours ago | parent | next [-] | ||||||||||||||||||||||||||||||||||
> OOP actually makes a ton of sense for CRUD and database operations. OOP is nothing but trouble when you try to do some advanced database operations. Select some columns, aggregate them. That is hard in OOP. Throw in window functions and OOP just decides you don't exist. | |||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||
| ▲ | sroerick 4 hours ago | parent | prev [-] | ||||||||||||||||||||||||||||||||||
> This seems like you might have got caught in something of a tautological loop situation that because you were working in a language with "object layers" it seemed easiest to work in one, and thus work with an ORM. I mean, I think this is likely the case. So, I tried this, for example in Go, which is not really a proper functional programming language as I understand it, but is definitely not object-oriented. So for my use case, I wanted to be able to take a database schema and programmatically create a set of CRUD endpoints in a TUI. Based on my pretty limited knowledge of Go, I found this to be pretty challenging. At first, I built it with Soda / Pop, the ORM from Buffalo framework. It worked fairly well. Then I got frustrated with using Soda outside Buffalo, and yoinked the ORM to try and remove a layer. Using vanilla Go, it seems like the accepted pattern is that you create separate functions for C R U and D, as you referred to. However, it seems like this is pretty challenging to do programmatically, particularly without sophisticated metaprogramming, and even if you had a language which had complex macros or something, that is objectively significantly harder than object.get() and object.save(). Finally, I put GORM back in, and it worked fine. And GORM is a nice library, even though I think having an ORM is not the "Go" way of doing things in the first place. But also, Gorm is basically using function magic to feel like OOP. And maybe the problem with this idea is that it's not "Proper Go" to make a thing like this, it would be better to just code it. There's an admin panel in the Pagoda go stack which relies on ent ORM to function as well. I can only assume the developer motivations but I assume they are along the same lines as my experience. I certainly don't think any of this requires insane class inheritance, and maybe that's all people are talking about with OOP. But I still think methods go a long way in this scenario. In the real world, in business logic, objects do things. They aren't just data structures. To summarize, CRUD seems pretty easy in any language, programmatically doing CRUD seems super hard in FP. Classes make that a lot easier. Maybe we shouldn't do that ever, and that's fine, but I'm a Django guy, I love my admin panels. Just my experience. | |||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||