Re: On database systems
Reply #1 –
Surely the whole point of adhering to MVC is that all the business logic is separate from the database handling, and that creating a new DB backend is essentially just to create a new set of Models?
As in the Controllers should have absolutely no idea how the data is gathered, merely that it is the data they are expecting to find.
Re: On database systems
Reply #2 –
Fully agree on controllers. Queries and such, how the data is gathered, indeed, are absolutely not the job of the controllers. That's one of the most important aspects of the separation we're targeting, and this is one of the many results of.
OTOH, I cannot support exactly the statement that: switching the db backend has to mean "a new set of Models". Conceptually, or architecture-wise, this statement is not true. It shouldn't change models either. :)
But there are at least two things that matter for Elk here:
1 - we don't have a database abstraction layer. We have a database layer, with some level of abstraction but I wouldn't call it abstraction layer. :) Sure, we could say it abstracts away an INET_ATON for PostgreSQL, for example, but that's not yet an abstraction layer. It does a job, but indeed I expect that for better behavior of a database backend, more than this layer needs change in Elk: some .subs need it or can benefit from it, too.
2 - we don't have exactly models yet. Not model classes - so an object oriented model. Nor a set of functions, "self-containing" enough (such as, a clear set for CRUD only). Not exactly; the files contain much more: any database work, built on our layer.
If we'd have at least one of two or both, then models would be self-contained units of behavior which use at their turn, some functions to trigger database updates; but models wouldn't use raw queries which may need change (or queries with still a bit too much raw SQL; ours isn't raw, but it isn't abstracted away either).
In that case, models would not need change, when implementing even a very different database backend.
In Elk, I'd like to see at least the second part of point 2. (and probably at some point, point 1). Personally, I disagree to even target object oriented models (at the very least, for timeline-related reasons), but the second part is becoming true with the current work: from .subs, I expect we'd have a set of functions which do the basic creation/reading/update/removal of some kind of 'entities'. Like createPost() exists since long. It's not a simple insert a row in the messages table, it contains its own logic: a model logic, a processing to create a thing we know as a post. (a complete enough post.)
There is already (and I expect it will be more) a difference, in .subs, between a simple utility function implemented around some query, and those functions which serve to build and manipulate the entities of the application: posts, topics, personal messages (with all updates, not just a row) etc. The latter become models. (in a more strict sense.)
For the purpose of this discussion, I'd say we can think of .subs as having at least two (or more) parts, conceptually. Some are [becoming] main functionality of models, others are serving specific database-work needs.
Why do I say this? Well, two reasons: on one side, personally I should be careful to call yet our .subs Models. I did on the wiki (well, I set quotes around the role of "model", lol, and maybe I should slightly update), and of course they're on the model-side of Elk. Yes: they're not routing, controllers, templating, sessions handling, etc. They're the model-type part of Elk. But they're different than standard strict design "Models", and that's ok, just need to make a difference.
And, on the other hand, models shouldn't change with db backend. That's partly the job of database abstraction, partly the job of implementing models such as they don't have (ideally) those queries which may change. (I'd argue they shouldn't have any queries at all, actually, but we're not aiming that.)
There are already proposals and PRs to refactor some .subs functions, to use the simpler .subs functions available. That might be a good idea, and go in the same direction: some more complex Model-ish behavior, may be implemented with the help of the simpler atomic pure-database-work functions.
Back to the database backend: I think some .subs functions (i.e. some simply-database-work functions in the subs files, such as the PostgreSQL example above or others) will always need to be re-implemented. Perhaps because of some SQL detail, perhaps because of performance. Even with a better abstraction layer, we will not get (IMO) to entirely abstract away the complexities of some queries. Not if we want to have the best behavior of the forum on another db system. For a forum, there are complex queries for which abstraction doesn't quite cut it. It isn't a blog - content, comments, users, pingback, done. O:-)
But not all, not even most. One shouldn't need to reimplement a new set of models. Along, of course, with controllers, templates, and the rest.
Re: On database systems
Reply #4 –
This is the fun of abstraction - you can abstract everything and not be right or wrong. It is all preference. You can add a data abstraction layer and then add a NoSQL layer and a SQL layer then add a Redis driver or an Oracle driver. You can add a class for every object and then add a class to access a specific table then add a class for tables that link to tables. You can add a SQL abstraction layer so you don't write out "SELECT * FROM table" anymore, now you write $db->getSQL()->select($columns->(a, b, c), $where->('1=1'));. You can do all of this and not be wrong in any of it. It is all "right" because you're removing coupling. In the end though, how much more development does that add and how much harder is it for you to find WTF you're looking for?
One tip: in removing joins, you make abstraction a hell of a lot easier. I like ZF2's table abstraction when you're not dealing with joins. I like having a function or a couple of functions in a central location that deal with the database. Then I can use those in different models.
I think it is stupid to abstract SQL. Takes way too much development and you never really test on the other platforms. I don't think anyone that says "supports MySQL, PostgreSQL, Oracle, and MSSQL" really supports it as well as whatever the developers usually use. If you really want to support them, stick with the ANSI standards and don't use any performance enhancements. Let the performance enhancements happen at the driver level (maybe give a hint if you can).
My models usually look something like this class myModel { constructor($dic); getFoo() { if !$dic->get('cache')->get('foo') ? $dic->get('db')->getTable('foo')->getAllById($id); $cache->set('foo', $result); } }
Re: On database systems
Reply #5 –
I see no distinction between "database abstraction layer" and "database layer." If you're implying what I think you are, I would call that a SQL abstraction layer.
The subs are far from being "models" yet. They are what I would still consider helper functions. Some are farther than others, but I wouldn't consider them a model until they handle an "object" (as any noun, not a class) as a single entity. So, you can have OOP without classes and you can have classes without OOP. You can't have OOP without dealing with a singular object. It can be a global variable (nasty) but it needs to have be in a single variable and not have 100 different ways it is editable in different locations. The easiest way to contain it is in a class then have that class delivered as a service. Some standard services would be: user (current), theme (current), database, cache, settings.
Re: On database systems
Reply #7 –
What's the difference between PersonalMessage::delete() and deleteMessages()? Seems like a huge waste to break them up. Seems like the model classes are just an interface with CRUD methods but not really where the object body is at.
PersonalMessage should be PersonalMessages since it is an object pool (even though you don't want it to be individual classes for each message, each message can still be considered an object).
Another way to make db abstraction really easy is by naming all of the requests and making sure everything is parameterized. Then anyone can use hooks to change the request/result.
Re: On database systems
Reply #9 –
Can the next version have a PSR compliant architecture - drop the .controller.php and other garbage?