The Basics: CRUD
CRUD stands for Create, Retrieve, Update, and Delete. These are the most basic actions you will perform on a database table. They are INSERT, SELECT, UPDATE, and DELETE respectively. CRUD is very easy to implement as opposed to the Active Record (although, it is still possible to use Active Record with CRUD and most of the time it is better to do so).
I think the problem with CRUD, is that the different patterns aren’t very useful when you are actually developing. For instance, in more advanced database table schemes, where you have joins and inserts need to flow into multiple tables, CRUD becomes interestingly limiting. You are in fact still playing with raw data and the developers using the API have to know exactly what they are handling, even if there are methods or parameters to let them know.
Furthermore, often the CRUD methods are placed in the same object, which coupled with helper methods can easily grow in an God / Blob object. It just doesn’t seem all that clean. I tend to think that the whole process could be easily implemented as a single class that contains the getter and setter magic methods, with the CRUD methods. I was close to implementing it, but it isn’t too useful and really just masks the bigger problem.
I’m starting to think that BREAD (Browse, Read, Edit, Add, Delete) is not really any better in the terms of overall object design either. CRUD and BREAD might work great for simpler table designs, but it is again limiting.
Asking the Question: What you are Handling?
The problem with CRUD and BREAD is from the architecture standpoint, you are working with the foundation and attempting to live in the building with no structure. Sure, you can throw a canvas over the person or people living there. In the terms of Getting Stuff Done, it is right up there. However, I’m starting to think that a better way is deconstruction of the actions instead.
I believe the reason the center of thought is around CRUD or BREAD for tables is, because that is what all of the examples are of. It takes a while to realize that just because an example is a certain way, doesn’t mean you have to conform to that always.
I believe it is more of a journey, than I had anticipated and I’m sure I haven’t reached the end. The “best” way to do this seems some much more than I had originally thought and it will take practice and experience to get to the destination. I plan on experimenting some more with the different styles and implementations to see where I can improve on the Active Record and incorporating CRUD, BREAD, and custom helpers.
That is not to say that building CRUD or BREAD off of actions is any better. Sometimes it makes sense to create an Active Record CRUD class for a table, because it is simple and is all you need. When you get up to the tables that require joins, inserting or updating into multiple tables, or more complex actions, then I think the complexity calls for an implementation a bit more complex.
Well, the usage of the API should not be complex, just the implementation might be more than a simple CRUD class might handle. The goal should always to allow the user of the API to figure out what the class is for and how to use it. The problem is that if there are many tables for a single class, then confusion will be inherit in which class should be used in each instance.
No Be All, End All Solutions
I think what CRUD and BREAD attempt to be or what people tend to think of it as a “Be All, End All” solution to the DB table API problem. That thinking doesn’t take in account the more complex usages of their API and what people will attempt to accomplish. Sure, you can force it to work, just like any number of solutions, but it doesn’t appear to be the best way to approach the problem.
It isn’t as if developers will know every possible usage of their API they will need to develop for and provide. Providing CRUD or BREAD seems to be the easy way out for the implementers of the library. If you force the majority of the work on to the developers using the library, then you lose conformity and force the developer to spend time implementing what should have already been part of the API.
Real Life Example: CodeIgniter
An epiphany came to me while writing this article; I have been approaching the Models in CodeIgniter all wrong. The goal wasn’t to implement CRUD and pass data to the methods, it was to create an Active Record pattern. The main point that I failed to realize was that people can call the db variable from outside the object, so I never thought to allow that usage.
Well, I’m contradicting myself. On one hand I don’t want to force the user of my API to do the work I should have done. The point is that I can provide for most usage and still allow for the developer to extend the API in a more advanced construct.
Possibly Related Posts:
- Game Engine Development and Open Source
- Plans for Base CMS
- Project Plans
- Calibre Improvements Part 2
- Usability Testing Software Development
All I know is now I’m hungry for bread.