Entity/Repository Model for Hubzilla
Some time ago we discussed how to proceed with refactoring/modernizing the Hubzilla codebase. AFAIK we came to the conclusion that the Entity/Repository model would be the most suitable to convert to. Please correct me if i am wrong @Harald Eilertsen.I think it would be good to have some sample code where devs (like me) will be able to look at to get this going.
I think i might be able to start with something but will sure need some help :slightly_smiling_face:
MR: https://framagit.org/hubzilla/core/-/merge_requests/2315
This is just an example, as a base for further discussion. I chose to implement an entity class for the
addontable, because it's small, and relatively easy to reason about.I have ignored some of the columns of the table, as they seem to be unused.
A few things to note:
Instead of constructing the object directly, they are created via the static initializer functions. I've just included a couple of examples, but more can of course be added.
readonly, this reduces the need for "getters" while keeping the class simple. It may seem a bit strange at first, but in cases where a changed object is needed, just create a new one instead. Also remember the lifetime of an object is for the current request only, at maximum.Other than that I think it should be fairly straight forward. I've added a few helper functions to make things a bit more readable, and reduce code duplication.
The basic premise is that all interaction with the database table should go through the entity class. The calling code does not need to know how it's stored, or even that the data is stored in a database.
Likewise, the object has all the information needed about itself, as well as the methods needed to interact with it or manipulate it.
Once constructed the object is valid! There's no need to check the validity of the object in code that receives one. This internal consistency should be maintained by the object itself. This is part of the reason we make the properties
readonly, orprivateifreadonlyis not a viable option.Looking at the other entity classes defined so far, they do none of these measures. Properties are public, so they can be manipulated by anyone without the object itself not even being aware. They provide getters and setters, but don't do any validation in any of them, and the same with the constructor.
I hope this can be a useful starting point for the discussion, despite it's not the most interesting we would need.
Wondering if DB stuff could live in a separate class/namespace without complicating everything too much to have entity and data separated.
See commit 8a79b5a3.
It's rough, but should give a general idea. I think it's possible to take it even further, making the entities themselves more declarative, apart from the actual functionality they bring.
I think which parts to split out, and how will become more obvious as we add a few of these classes.
Also, I forgot to mention. I completely disregarded error handling in the example to keep it simple and focused on the main issues.