Question about OO programming, functional programming, NoSQL, SQL databases and software architecture
I am an intermediate level self-taught programmer and I have been dying to get an answer to this general question about how to structure my applications. By not having a CS degree and only a few programmer friends, I have not been able to get a solid vision on what is the "right" or "best" way to address this type of problem.
This type of pattern appears everywhere in my current application, and I'm not sure what I should be doing. The pattern is:
I have a database model that is a type of container & # 39; container & # 39; or & # 39; father & # 39 ;, who has many elements that refer to him. For the sake of this, we can use a & # 39; Route & # 39 ;, model that represents a courier driver route for the day.
It has fields like:
- Created time - Assigned driver - Notes - isCompleted - isReconciled - serviceCount
I have another database model that is the & # 39; son & # 39; main that refers to the & # 39; father & # 39 ;, in this case, the route. In this case, it is a "service" and represents each one of the stops that the courier service driver must make as part of his route of the day. All services for the relevant route have a reference to the route. The relevant fields in a service are:
- Route <- id referring to the 'parent' model - Notes - isCompleted - isReconciled
In many of these cases, I have a situation in which if you change a service (the child), you may want to update some & # 39; higher level & # 39; or & # 39; summary value & # 39; on the road (the father).
- When all services are 'complete', update the route to be 'complete' - When all services are 'reconciled', update the route to be 'reconciled' - If you add a service to a route, update the 'service count' on the route
Currently, to handle this type of thing, I have functions that normally run after each mutation relevant to a service. It would be called something like updateRouteAfterServiceIsModified. Simply update the route after all modifications to the services, to update these summary values.
However, I understand that if you adopt a more object-oriented approach, you could have some kind of post-save link, or something similar, so if you ever modify a service, the route will be updated. I can see how this could improve code organization, but I can also see how it could be more complicated.
One of the things I have thought about doing is basically never calculating these summary values when making service mutations, since they can be determined on the fly, since they are basically inferred or computable properties. For example:
- To know if the route is complete, just check if all the services are complete - To know if the route is reconciled, just check if all the services are reconciled - To know the route count, simply count the number of services, as at the time you need to know
For me, the problem with computing them on the fly is that I will normally have some list of the & # 39; main & # 39; (routes) and I will want to do something like sort by these calculated fields. If the value is not saved in the parent, I have to calculate the value on the fly to sort the list.
I am using Mongo as my data warehouse, and aggregations in foreign fields become quite complicated quite quickly, and other relevant calculations to perform the desired type, and it seems a solution that is too complex and possibly not scalable. But I'm not a mongo expert, so I'm not sure.
I have never used SQL, p. PostgreSQL; I have a friend who has suggested that this kind of thing is much easier in Postgres. It may be possible that what is "normal" to be done in this situation with Postgres is never to keep these summary values in the parent, and simply calculate them at the time of classification, and that Postgres do it efficiently. Perhaps it is the case that the code does not become messy and that it scales well. If that is the case, although the application is primarily built, I would consider switching to Postgres, but I have simply never tried.
In summary, I think there may be 4 possible solutions to this type of problem:
Use a functional programming style and adjust or call functions properly when making mutations & # 39; secondary & # 39; to save all the data you want in the & # 39; main & # 39; model relevant.
Use an object-oriented programming style to maintain these summary / calculated values, saving them in the model & # 39; parent & # 39 ;.
It is not necessary to save these values, calculate them on the fly, Mongo is fine, aggregations can be very powerful, you just have to master them and create some abstractions where it would be useful or simplify your code.
It is not necessary to save these values, and the key to this is to use SQL, which facilitates the classification by a calculated value of strange field, it must change since it makes this type of process trivial.
I'm not sure if there is a "right" approach to this, but it seems such a common pattern in my experience that I would have thought there would be some consensus in the development community about what I should do.
Any help would be greatly appreciated, even if it only directs me to resources that can be useful!