I have been looking through a lot of code lately, looking for inspiration, and I am noticing something: practically every ColdFusion custom tag that I see is highly coupled to the parent application. I don't use custom tags all that often, so I have no great experience to feed off of here, but shouldn't all data required by a ColdFusion custom tag be passed in as an attribute of the tag?
I am looking at one custom tag right now from the CF Pet Market site application demos that uses:
- ATTRIBUTES-scoped variables
- APPLICATION-scoped variables
- REQUEST-scoped variables
- VARIABLES-scoped variables
Doesn't this seem a bit odd? Why the mixing and matching of all these scopes? Well, that's a poor question; the WHY is simply that it's easy this way. I guess the real question that I am driving at (and one that I would be very interested in getting answered) is "SHOULD" a custom tag use all these scopes? Doesn't this high degree of coupling to the parent application increase the maintenance costs and all that jazz? What are the best practices for ColdFusion custom tags?
I am not attacking about this - I really am interested as I am trying to figure out how I want to tackle a particular problem. I am also curious to see how people relate ColdFusion custom tags to ColdFusion components. People are all heated now about dependency injection and passing in data, low coupling and high cohesion and all that when it comes to ColdFusion components. Why such a huge change in standards for ColdFusion custom tags?
As I see it, there are two main types of custom tags:
One is library tags which are application neutral and do some task. For example, I have a 'tovar' tag that acts like CFSAVECONTENT but with the ability to append or override, as well as accept a VALUE attribute. I use it all over the place. Same interface, same functionality, same behaviour.
The other is application tags, which are tightly coupled to the application and serve to hold part of the application logic in a reusable component (other than a CFC). I usually use these for layout things, such as a 'link' tag which accepts an objectId to link to and translates it into an appropriate link (using some application-specific logic to compute the URL). I use a 'link' tag in multiple applications, but while the interfaces are all the same, each one's implementation is totally different, and depend heavily on environment (specially application-level singletons). Same interface, same functionality, application-specific behaviour.
There's definitely a place for both types of tags.
Great question and if you don't mind me asking what framework were you looking at from CFPetMarket that had that example?? I'm going to guess the SAM Methodology as I work with Simon Horwith and know his unquestionable passion for custom tags. ...And also for his heavy use of single quotes!! I'm pretty sure it has to be that one. :)
I personally use custom tags only for output. For example, my layout template, displaying a query with an XHTML table, pagination, etc. Many believe components shouldn't be used for output and I think its best to stick to that belief although it can depend on what you are trying to do. I do my best to encapsulate my components and I do the same for my custom tags. I definitely suggest both although don't beat yourself up trying to decide. Do what you best suits you.
I can totally appreciate what you are saying. I guess it's just something I am going to have to accept. I like the idea of application-specific tags and I think the idea of passing in ALL data required would be a daunting task.
That's funny :) I did have SAM open, but to be fair I have about 6 frameworks that I am flipping back and forth through looking for coding practices. Good hunch though!
Also, good suggestions. I am coming around. I just need to find a balance that makes me comfortable with the code.
You're right in thinking that components should be black boxes with wires going in and one wire going out. The single return value can be a structure and thus contain many results.
I think that since components are a relatively new phenom, some people are still using custom tags.
I use a custom tag to do a SELECT and then cfset FORM.variables that are in the Columnlist. But that's it's purpose.
I think the idea is: "If I were to post this to cfLib, is it written correctly?"
For expediency, most people don't write for cfLib support.
In fact, most people don't spend a lot of time looking through a lot of code for inspiration; so treasure these days where you see things through a student's perspective!
I appreciate the words... and hopefully the "Student" phase of my learning will be a life-long journey.
I love the smell of ColdFusion in the morning.... It smells like victory.
"In fact, most people don't spend a lot of time looking through a lot of code for inspiration; so treasure these days where you see things through a student's perspective!"
I totally disagree! I'm constantly digging through code for inspiration! I've really begun to love using Ben's programmatic configuration code and have always looked to others to see how it is they solve their problems to see what their approach was. It's probably more for implementation than inspiration but nonetheless you'd be amazed at how many developers still go digging through code.
Yeah, digging through code is a lot of fun.
I just got the urge to see a video of Christopher Walken talking about how exciting code viewing can be. Is it just me or is "anything" + Christopher Walken just more exciting???
I think a lot of the coupling you see in custom tags is because plenty of code using such tags is a little older and while OO devotees (who are particularly focused on minimizing unnecessary coupling) use custom tags, lots of NON OO programmers also use custom tags so it seems likely that you'd see more coupling in custom tags.
I think on the whole it is a bad thing to have a custom tag knowledgeable about its environment as it is not only less reusable, but also it makes the code less maintainable unless you have great documentation about the dependencies which is shared with all of the developers. It also makes unit testing of the tags harder.
I think part of my problem is that perhaps the page wrapper is (in my mind) such a different tag than most other custom tags. Most other tags provide some black boxed functionality:
<page:navitem text="" href="" />
This completely separates the rendering of the navigation from it's data. This makes a lot of sense, and probably doesn't need to know about it environment.
A page wrapper on the other hand is really just a "cleaner" form of a header/footer include. It's not really black boxing anything. I think it's more just making it look prettier. So, maybe a page wrapper shouldn't be help to the same standards that you might hold other tags to.