A piece of functionality should do one thing (preferably with its name describing that functionality).
In the case of include, it should… include.
If you need to add an and into the name of the functionality to describe what it does… it’s doing too much.
If you need to include/abort a lot (*), can I suggest you set up a macro in your IDE/test editor to do so. There’s no need to clutter the language to accommodate seemingly edge-cases like this.
I also think “needing to abort after an operation is performed” can be extended out to pretty much any operation, so it doesn’t make much sense to me to add it specifically to include.
–
Adam
(*) I don’t recall ever needing to do this. I’m sure I have, but with no sort of frequency. Certainly not enough to think it might be a good thing to roll into the language.
Hmm… interesting. Never knew you could do <cfdump abort="true"> (since CF9 to boot).
<cfdump
var = "#variable#"
output = "browser|console|file"
format = "text|html"
abort = "true|false"
label = "text"
metainfo = "yes|no"
top = "number of rows|number of levels"
show = "columns|keys"
hide = "columns|keys"
keys = "number of keys to display for structures"
expand = "yes|no"
showUDFs = "yes|no">
I can see that it would be useful in code bases where a lot of code is broken out with includes.
In a practical sense it seems easier to “cut and paste” or “hot key” in a cfabort beneath a cfinclude than to change the abort attribute. And I can’t think of a scenario where I’d be populating the abort attribute with a variable.
While I’d argue that its appropriate in cfdump as its a tool for debugging, I’m not convinced its appropriate in cfinclude.
Fully agree with @adam_cameron - this should NOT be implemented at all.
Edit: I’d actually even argue that cfdump shouldn’t have an abort attribute, but I can see why that’s useful given the lack of proper debugging tooling in CFML.
there are many use cases for this, e.g. a template that requires a user login can check if the user is logged in, and if not include the login form and abort, or a wizard controller template that would include different “step” template and stop execution once the correct step is included.
sure, there are many ways to do those things. this will just make it a tad easier, and it makes a lot of sense IMO.
makes since because it is a quick use debugging tool. It is not meant to be left in the code past development. is not a debugging tool and should not have an abort attribute. I would say you should review your coding practices if you need to abort after a cfinclude.
Personally I think cfinclude is a bad practice in most cases, in that variables should never appear out of no where. The bad code I have seen over the last 15 years is mainly due to poor uses of cfinclude. Use a component and functions.
You were going for pragmatic for a use case that promotes bad practice in the majority of cases.
There are a lot of “pragmatic” things a language could do, but the sum of those will inevitably lead to the mess CFML is right now.
Surely could do with an email attribute to email yourself dumps for debugging. Even though I have to do that sometimes because no CFML servers currently offer proper and working well way of breakpoint debugging, I’d say adding this to the language would be one of the worst things to do.
In those cases: use the appropriate separate tags/functions and if one doesn’t want to type them: IDE snippet/template.
First of all, this falls into the category of something along the lines of:
function getUltimateAnswer(isCalculated) {
if (!isCalculated) return "come back in 7 million years";
return 42;
}
// vs
function getUltimateAnswer(isCalculated) {
var result = "";
if (!isCalculated)
result = "come back in 7 million years";
else
result = 42;
return result;
}
I had a professor that would fail an assignment if there was a function with two return statements as in the first example. Now, I write code that does this on occasion, as it is quicker to implement. However, on a whole, I do strive to stick with the conditional logic with a single exit point.
Thats what I see is going on here. You may be doing maintenance on a some rather large and otherwise complicated templates, to where adding a else block around the remaining body of the template is not feasible. While sometimes necessary, using aborts as a normal way to end a request is, IMO, bad practice. It should be treated more like exit(1) for C programs. You should really only do it if there is a problem that you need to quit immediately before circuits get fried (well, maybe not that dramatic ;)).
However, that does lead me to an interesting thought that I shall bring up as a new thread…
if I had lived in the theoretical world like your professor then I may have done it the second way as well.
but for all intents and purposes, the first way is much more performant than the second one, and I always opt for the side of performance with all other factors being equal.
I think you’re spot on in your response to @modius. What Geoff is referring to here IS different because it exits a template and it doesn’t stop execution of everything.
Also: There is a conceptual difference.
@21Solutions problem CAN be solved with the existing language and using two separate tags for their respective purpose. Or if he’s too lazy to type it, use a Snippet. Under the premise that I (and others) think this coding style is not a good practice, I don’t think it should be made “acceptable” by a language shortcut.
From looking at the other discussion @modius linked, it looks like to me that the problem raised there can be efficiently solved with <cfexit>. SURELY the include tag could get an exit-attribute instead of @21Solutions suggest abort-attribute, but it kind of is the same situation from my point of view: meddling to things that should be separated into one tag just because we can.
And LuceeLang should not be about creating a new mess of “shortcuts” for a doubtful purpose - that’s a bad approach to language design.
If both of these are the same, but you can already do the first one without changing any of the engine code, then I’d be in favour of sticking with what we already have
sure Kai, I’m too lazy. that’s why I spent time posting this here instead of creating a simple custom tag that overrides the default behavior of the engine which would have taken a fraction of the time I spent on this here.
I think there’s a fundamental philosophical decision that LAS need to make about Lucee:
Is Lucee meant to be a language that enshrines best practices to appeal to a broader range of developers (i.e., outside the CFML pool), or is it meant to be “just CFML.Next” and carry over the sort of “quick’n’dirty” solutions that have given CFML such a bad reputation amongst so many non-CFML developers?
Many language design decisions cannot be made in a vacuum of just syntax and semantics. They need to be informed by the vision and mindset of the language philosophy. I think this is exactly one of those issues.
The “best practices” answer says: each tag should do one thing and do it well – don’t mix in unrelated functionality.
The “quick’n’dirty” answer says: sure, add exit="true" – but add it to every tag that could conceivably need to be the last executed one in a file.
Calm down, Igal. No one said you’re lazy. I said that if you’re too lazy to type it (=the additional abort tag as it was clear from the context) then use a snippet.