Is ORM the only way or the right way to design and deal with data?

Hi guys so I have been trying to build is small library app - the app just will ultimately allow users to reserve study rooms or auditoriums. It will also allow users to book and expert(just a person that has a certain skill they need, like math…) to help them with whatever needs they have. The app reads a CSV file that has all the library branches from the city and it also contains all the rooms that each branch have.

Ok, now the real issue. Due to the new suggest way of building things in Phoenix 1.3 (context) I have been trying to build my little elixir app following the context rule. I originally decided to use processes to hold my states such User, Branch, Room, Availability, and Reservation. But, It felt like I was starting to rewriting ORM crud operations. Thus, I decided to find something that did not require me to use Ecto because I was getting really confused on where to put schema, models and so on. I found this repo Moebius, as I’m using it I found my defining functions such as from_model, to_model basically mapping DB to my structs. Why? Well, this is what I have always learned from java, .net, Ruby and jumping to Phoenix.

I would like to know, can I just create my app without relying on structs to define my data and just use… I guess modules to define how to transform my data or what type of operation can be done with the retrieve DB data?

Pretty what is the right way? Or what the advantages and disadvantages between ORM and Directly just querying to you DB without transforming your data to a model?(Ecto vs Moebius?)

Whats is the correct or approved way of designing when it comes to this subject?

If feel like I am lacking some basic knowledge here, can anyone help?

Thank you.

The right way to a degree is a matter of preference, on a large project that started with ORM you still will end up with direct queries especially for reporting (ORMs will not support window functions, CTEs etc.). They could also limit your ability to control a lot of things such as setting an isolation level or increasing work_mem for a particular query etc. (BTW using PG specific examples).

The main advantage I see to using an ORM over raw calls is static ‘typing’ (at least making sure the names are correct) as I have a habit of mis-typing something and I like the compiler to catch me instead of getting a wtf SQL error later. ^.^

2 Likes

Another important advantage of Ecto as a tool is that, as far as I know, it’s currently not possible to introduce, even by accident, an SQL injection vector using the query DSL - this is checked at compile-time.

3 Likes

Thanks alot for your answers. But, what I also want to know is if ORM(or because there are no SRM?) Is the only way? Because at this point to me the way things are being introduced based on other languages too is that you always need an ORM to deal with DB. Can I not just deal with the DB data itself and use specific modules to transform the data based on what ever context?

It seems like I am being told that ORM/Ecto is the only and right way.

No, it’s not. Postgrex is pretty good on it’s own and not difficult to use. You can extend it’s functionality with type casting etc. to the level that can be very much all you need.
Check out: https://github.com/elixir-ecto/postgrex/tree/master/lib

But I’m not advocating you do that, esp. if you just start with Elixir.

2 Likes

Do you mind elaborating on why you wouldn’t suggest one to develop in such way?

I think in most cases, it’s going to be considerably more work.

1 Like

The simplest way to think about contexts and ecto is as if you didn’t have an ORM. Think of the structs as the SELECT part of your query instead of thinking of a schema that has to be fully mapped to the database. IMHO is dramatically simpler.

1 Like

Am I picking nits if I say that before you can talk about an ORM, you have to have an “O”? ORMs are terrible ideas that make a relational database look like an object database, including stuff like inheritance, etcetera - I’ve yet to see them result in nicer code.

For Elixir, I think Ecto and similar tools are more geared towards lifting relational algebra up in the language, which I think is an decent idea - at least your not trying to plaster over the fact that there are huge impedance mismatches between the incompatible models you’re trying to bridge.

However, in every non-trivial project you end up writing custom SQL, and it turns out that the basic CRUD stuff doesn’t change that much over the lifetime of a project (often a reason people give for the “flexibility” of libraries to interface with an RDBMs without having to type SQL). Might as well go with SQL embedding everywhere so you only have one way to do things.

1 Like

In the end you typically end up writing a small (and imperfect) framework that takes care of most of the boilerplate for the functionality you want to use.

Once I found myself in a situation where I had to access the database from Java - and due to my “Business Component” certification I knew that EJBs where mostly dead weight at the best of times (and EJB-QL was too restrictive) but plain JDBC would have been extremely verbose - what I wanted to use was Spring’s JdbcTemplate. Unfortunately there were bureaucratic barriers to using it - so I “borrowed” the parts of the API that I needed and implemented the bare minimum to get it to work (not something I would actually recommend doing - for obvious reasons).

If you want to play around with the idea also have a look Erlang ODBC application Examples where you aren’t limited to PostgreSQL.

1 Like

Well, what I would like to know is do I have to bound the data that I retrieved from the database to a struct/object context? Because to me, it sounds like this is how you should be making your application but based on what @brightball said:

I think that it makes things a bit clearer. But doesn’t that make application tightly coupled to ecto? In another post that I made Process and Stateness are they object?, it was agreed that the database could be considered as a completely separate system that interacts with your app - so if i where to decide to change database it would be easy to accomplish such task.

I am just trying to break things down here while keeping the context approach in mind. so a structure should look like so:

lib/
some_context_folder/
schema.ex
schema.ex
some_context.ex ← this context handles all the request that neeeds to be done in the database?

When I say “the select statement” I just mean think of the context as what your application needs from the database for that part of your application, rather than a typical ORM layer where you would get back every field from a table as part of the object. A users table with 100 columns may only need 4 for th context that you are working in, so rather than SELECT * you are specifying those fields.

In the other topic I mentioned the repository - it’s essentially a Façade which wraps your persistent storage access technology - whether it’s something as low-level as ODBC or high level as a relational mapper like Ecto. The only thing the context contributes is the boundary for the functionality of that (context’s) repository (which is necessary to support the capabilities of the context).

The more significant issue in terms of coupling are the data types (shape of data; structs) which are used to interface with the repository - for example if the repository returns and accepts types that are generated with the assistance of Ecto.Schema for use with Ecto.ChangeSet then the repository has failed to decouple the application from Ecto. On the flip-side a lot of the value that Ecto can provide is lost if the application is successfully decoupled - you’d essentially have to implement your own Unit of Work.

Another perspective is to simply, deliberately accept the coupling between, for example, Ecto and the rest of the context’s capabilities - provided that the context is small enough to be easily replaced in it’s entirety when the persistent storage technology changes sometime in the future.

2 Likes