As we move forward with the Open Media Project, we've found ourselves in the "age old" debate of developing modules with functionality built on top of CCK or building a custom modules with full control over their tables and functionality. This was recently discussed here, but we have a different set of feature needs than davidm had so I'm bringing it up again.
For the Open Media Project, we know that the group of modules we include will be deployed (at least in part) by 7 locations. Each of these will have slightly different workflows, hardware, and features of the system they want to implement. We know we are developing for Drupal 6 and will likely be incorporating Media Mover and Rules. We know that we will be updating this collection of code fairly often over the the next 18 months. We know that some of the locations are going to have their own developers capable of modifying our work either through CCK's interfaces or by updating the modules themselves.
(Way) back in 2006, Nick Lewis' provocatively titled post 'Neutered Nodes: CCK's Dark Secret' generated a lot of discussion about the pros and cons of building on CCK in Drupal 4.7. After Drupal 5 was released, I posted a comment to the thread Nick's post generated to see if the changes made to CCK in Drupal 5 had changed anyone's opinion about building on CCK. Nick eventually updated the post saying he 'officially disagree with himself', but there were still others (including me) who thought custom modules were still the way to go if portability was a key feature. AjK's take on CCK in February of 2007..
"However, there is one area where realistically, only a module will do. We all have them. It's client that comes back wanting more and more features as their site grows (and are prepared to pay for it!). An example, custom searching. If you know your own module inside out then extending it and adding extra functionality is a breeze. With a CCK+Views deployment you have to start getting into the db construct for the site. If you want it generic across sites, you have a lot of settings admin work to do. Or hard code it for that site. Either way, it's sometimes a lot of work to retrofit custom work over CCK+Views."
In that same thread, PhilK adds this...
"A Drupal site is always evolving and when you're creating a custom node module you're relying on just 1 developer. i.e. You. As opposed to the large number of developers who have contributed and continue to contribute to the CCK and add on modules."
IMHO, these are still the best arguments for and against building on CCK.
I recognize the benefits to building on the contributions of the entire CCK community, but the flip side to that is if you find a limitation in CCK it could takes months (or even years) to resolve. Programmatic updates to a schema made with a module update is relatively easy. While the programmatic creation of CCK fields and programmatic population of CCK data is possible, these fields are still exposed through the CCK interface making it possible for users alter in unexpected ways. AFAICT, even in Drupal 6 there is no way to "protect" schemas programmatically generated through CCK from users altering them in a way that would negatively impact modules with a dependency on a field.
The code that drives Denver Open Media's current system contains several dependencies on CCK. When that code was originally written, implementing, supporting, and updating the codebase across multiple locations wasn't a key feature. Now it is. Moving the current code from one server to another took several hours and while I've streamlined the process and read about improvements in CCK on D6 that would make this even easier, I'm still reluctant to full embrace a dependency on CCK for key data fields. Even looking up the table location for CCK fields requires an additional (potentially performance hindering?) function/query since reusing the field changes the table it is found in.
Our current plan is to move forward with a hybrid approach. Cailin Nelson offered some good tips for this type of CCK and custom sub-module development in Drupal 5. We are hoping to generate the a more comprehensive list of best practices for this type of development in Drupal 6.
The question we are struggling with now is what determines whether a field is created/stored in a CCK field or a field found in a custom module table?
I tend to feel that anything that's part of the "core system" should be stored in the custom module's table. Core system are the fields that our workflow and the functionality enabled by another module depend on. But as PhilK has pointed out, we lose a lot of functionality that a small army of developers have contributed to CCK. Is this simply a case of weighing the CCK functionality vs. the overhead of developing everything else to deal with the flexibility CCK's allows?
We'd appreciate any advice on this topic and will roll any consensus from the resulting discussion into a Handbook page.

Comments
Excellent discussion. Difficult topic.
As one who has recently had his share of pain programmatically creating CCK fields, I can confirm that it leaves you wishing for a more portable and repeatable API. Your use case makes me think it would be nice to be able to turn off the admin UI for CCK altogether (similar to how Views UI can be turned off). This would at least be a small step in locking down a CCK installation into a predictable state.
My experience with importing CCK types and fields in an installation profile was mostly good. It took just a bit of code study to find the small blocking issues (some characters have to be escaped in eval'd code, for example), but once done you can launch a site that has the right content types, fields and tables.
It's a really hard call whether, over the long run, maintaining a custom module or maintaining CCK built types is more expensive. I usually opt for CCK, but it isn't a problem-free strategy, for sure.
The new API for the D6
The new API for the D6 version of CCK should help out with this, and there's been lots of discussion about moving the UI to a separate module so it can be turned off, but no one has actually tried to write a patch to do that. Someone should add a feature request to CCK to make the UI a separate module (or see if there is already one, there may be). Then someone needs to take time to write the patch, and that's the tricky part.
Or maybe just add a new permissions for who has access to the CCK UI so you can lock it down better. That would be a simpler patch.
Add an option of locking module generated content types/fields?
IMHO, CCK has matured to the point that turning off the UI (or even locking everyone else out of the UI) isn't an option. Rather move the UI to an additional module, what do you think of dmitrig01's suggestion to add a "locked" column to the CCK schema. Unless I'm missing something, it seems like a relatively minor patch to exclude locked content types/fields from CCK's UI.
Sub-modules could then leverage the power of CCK without worrying about a user inadvertently modifying/deleting a field that has dependencies.
Another nice feature would be if programatically created fields included the module name that created it in the prefix by default. This would prevent namespace conflicts from modules using generically named content types like "classes" or "projects".
locking in rules..
yep, I agree that locking fields would be a good approach.
In workflow-ng as well as in rules, rules can be provided by modules and they can be
* locked, which means they are completely hidden from the UI or
* default rules, which may be customized by the users and can be reverted to the original default.
I think analogous when a module provides some CCK fields there are two use cases
* provide useful defaults, that can be customized by users
* provide locked defaults, that can't be changed per UI
I think there are plenty of
I think there are plenty of good reasons of to split modules into UI and API components. However, the ability to turn off the UI is the least of these. Of more benefit is the separation of layers that allows other modules to use just the API as they see fit without having to fake user interaction.
The decision of whether to use CCK or a custom module for node fields should be influenced by what the fields interact with. As an example, Ubercart's product module programmatically creates an image field for its node types, but it specifically creates its own fields for price, SKU, and weight. The ideas of price and SKU are particular to the idea of a product, and the cart and order modules use them in particular ways because the price field is a price field. On the other hand, the image field is secondary to the idea of a product and the functioning of the module. It is up to the user how it should look and behave, so CCK is used to provide ways to let them.
That's the way things are now. There are plenty of features that CCK has that I wish I could use on my custom fields. I haven't looked at CCK for D6 yet, so I may already have some of my wish granted.
Übercart -- One cart to rule them all.
Ubercart -- One cart to rule them all.
Interaction determines where data should be stored
I tend to agree with the 'interaction determines where the data is stored' criteria, but your examples are simple text or numberic data types. While you are leveraging the image features of CCK, you (wisely) avoid building dependencies on that field.
So what do you do when your sub-modules have dependencies on with more complicated data types like Date, Embedded Media Field, or Fivestar?
Adding the lock and namespace feature to programatically generated content types and fields would solve the problem I think an increasing number of developers are going to run into where Client X created an interesting feature/workflow/application that started as a basic node extension using CCK. Over time that evolved into something more complicated to the point that sub-modules where created to extend functionality beyond CCK's limits.
This is the situation I find myself in. Both Denver Open Media and Manhattan Neighborhood Network have hired developers develop modules that add functionality that is absolutely dependent on a very specific CCK configuration. Now they want to share that work with other stations.
Improvements have been made to make CCK defined content types more portable, but the schemas created are still exposed to the CCK UI. Separating CCK into UI and API might be worthwhile for some other reason, but if simply adding the CCK UI module exposes schemas with dependencies won't any module utilizing the API have the same problem we have now?
Adding an option to "protect" specific content types and fields from the CCK UI will enable module developers to leverage CCK in their development. It will make it easier to move functionality "locked" into a specific CCK configuration into something that can shared with the community.
take a look at cck_create_install
kreynen, Please take a look at cck_create_install
http://drupal.org/project/cck_create_install
I created this module to solve this specific problem and would love feedback on it.
Basically it allows you to select any cck node type and it generates all of the install code for your module.
The module will also generate all of the taxonomy vocabularies and terms needed if your cck node uses the cck taxonomy module
Currently it does not handle field additions, but it is trivial to do using the generated install code.
Updates are also not handled, and these are less trivial, but I plan on adding this functionality
The basic usage is this.
1. Generate the node type as normal via cck (including taxonomies, widgets, settings etc.)
2. Generate views as normal using views module.
3. create a new module
4. add the dependencies for cck, views, taxonomy and any cck field modules to you modules.install file.
5. run cck_create_install, select the cck_content_type and press create install code.
6. copy the install code into your modules.install file.
Currently you have to run the devel clear cache method after installing your module, but that will be fixed shortly.
I am looking for feedback on this module.
Yched, Eaton, and I did a
Yched, Eaton, and I did a lot of emailing back and forth about what the CCK API should look like (and maybe moshe was involved in those emails, too -- at the time Eaton was planning to try to work on the API) and adding some options to 'lock' module-created fields was one of the things we discussed. I should go back and dig out those emails and post them somewhere since there are some good ideas about the development of the API in them. Not surprisingly, although it sounds like a good idea that we all agreed was important, as we dug into the implications of actually doing it we uncovered complications. Nothing in CCK is ever as easy as you think is should be :)
Not saying we shouldn't consider the suggestion, just pointing out that it's not necessarily a no-brainer.
Interesting
Currently I am manually locking cck fields required by modules I create that use cck.
In adding the functionality to cck_create_install to do field additions/updates I will need checkboxes for all of the cck fields.
Adding the option to lock a field makes sense and would generate the required hook_form api or validation code.
I am curious what options you came up with for locking fields via your discussion.
Lock field group (possible needed if your module is altering the cck form and not just doing it's work via the node_api hook)
Lock field options
Lock field options(default values) allow additions?
Lock field description
Seperate module to protect CCK schemas?
Benjamin Melançon suggested adding hook_form_alter to the modules that programmatically added the content types and fields. Unfortunately he's hasn't actually used this approach. Rather than include this protection in each module (we could have 10 doing this and some trying to protect the same fields), we're considering creating a separate module to handle this. This module would include a UI for locking and unlocking content types and fields so that it would be possible for someone who understands the dependencies to unlock a field and utilize the CCK UI to make changes.
Has anyone tried approach this before? I just can't believe we're the first group with a need to protect CCK schemas we've built dependencies on.
----> best practices = read the code and write patches <----
I love these you should or could with CCK do this thing... suggestions.... why not write a patch and post it to the queue instead of huffing and puffing your face red? Use the issue queue and a feature request and patch instead of bantering over here, where CCK maintainers only stumble by what you're talking about with google searches.
But you really want a best practice for hybrid modules that leverage CCK...
It seems what you have problems with in your update process is the storage model, so don't use the default storage model provided by CCK... Do not implement hook_field_settings op == database columns, and load your data in hook_field op = load... pretty simple eh.. I think Eaton's Amazon module is a good example... Imagefield and FileField load most of their data in hook_field...
These are some samples of adding fields with their own data stores. Keep in mind you have to provide your own views integration if you aren't letting CCK handle data storage for you.
Alternative to patch writing to get your itch scratched
Dropy,
I know you are a self-professed whiner/complainer, so I won't take this personally.
My goal is to allow users who understand the dependencies to extend our core Open Media content types, but prevent a change that is relatively easy to make in the CCK UI and impossible to reverse from breaking things. Giving stations, libraries, and other Open Media users the ability to build Views of this content is an important feature, so the approach Eaton took with the Amazon module is not going to work.
My approach to getting things done in Drupal might be a little different than yours, but I'd hardly consider it "huffing and puffing". I tend to do some research, read what other people have said on the topic, and compile that before requesting changes. Once I feel I understand why the feature isn't there (in this case, there wasn't a real need before programmatic creation of CCK content types), I'll ask some questions (in case I've missed something) before writing code. In this case I asked and according to Karen, adding a locked filed to the CCK schema was already considered and rejected. I'm still not sure why the feature was rejected, but how would investing the time writing a patch would help make the case for a feature that's already been rejected?
I don't have time to update a patch every time CCK is updated and continue making the case for lock in the issue queue. I just need the functionality.
So instead of taking your approach of posting a patch that the maintainers have already said they aren't interested in rolling into the module right now, I've taken Benjamin Melançon's advice and created CCK Schema Protector to hide the CCK content type and fields I want to protect from other users with access to the CCK UI. I should get a working alpha committed today. I really just wanted to make sure it was possible. Now that I know it is, I feel much more confident about building modules with dependencies on specific CCK fields.
CCK Schema Protector gets our itch scratched. If this approach becomes popular with other developers, maybe someone with more time can write the patch and make the case to get this rolled back into CCK.
CUSTOM NODE then add cck fields [vs] CCK NODE then use nodeapi
http://www.johnandcailin.com/blog/cailin/drupal-hooks-not-firing-cck-con... mentions:
Now I'm new to Drupal Development, but consider myself fairly versed in the code. I've missed all the previous debates about CCK vs. Custom Modules, so after about 4 months of developing on Drupal here's my favourite approach to this problem. Can someone please point out the downfalls.
I do the exact opposite of what John mentions. I create a custom module from a skeleton.module I've created. This is your standard blank module which provides just the default hooks. Then I add CCK fields to this module. This allows me all the node hooks with out having to use nodeapi (which I think just gets ugly). Why isn't this approach ever suggested?
Now I'm sure people will say....how can you be sure all your CCK fields will be added onto your node? Truth is, right now I can't. Currently, I'm the only developer and this is for a particular site, so that's not important to me at the moment...but as a solution to this problem, one could add all the fields in an .install file. This is what I plan to do when I need more portability for my custom modules.
Personally I prefer working with custom modules with out CCK. But things like Imagefields are just too complicated to create on my own, so I use the hybrid model. Life would be a lot simpler if one could simply use CCK field types as $form['field']['#type'] = 'cck_fieldimage'; types :D Not sure if you can do this yet, but why the hell not!
Freelance Web Design
Vancouver Events & Music community
Drupal & Commerce Themes
sounds reasonable
this sounds about right - and is, i think, how i'm about to proceed on a custom module that i'm working on. i'm new to module development, though, and it would be so helpful to see your module so i can see an example of exactly how you're implementing this. would you be willing to send it to me so i can just look at it for an example?
thanks!
(le@elly.org)
Any progress?
I ran into the same issue today and need to solve it. Is there any progress on implementing this feature or any idea how this could be accomplished?