Hello,
What code do you like the most, left or right? See screenshot in link below:[View:https://drive.google.com/file/d/0B1P8s6ZKpj7wSnVTLVNONW1laVU:320:50]
https://drive.google.com/a/tvh.com/file/d/0B1P8s6ZKpj7wSnVTLVNONW1laVU/view?usp=drivesdk
Please elaborate why? I'm very interested in the answers.
Apart from the fact that the right hand one won't work (not all references to Company have been updated), I think the left is better. It's good practise to do your updates on a buffer with a strongly scoped transaction block, but using buffers elsewhere isn't necessary.
My opinion of course.
Your opinion is wrong ;)
Because this is an internal procedure you very much want to use a buffer scoped to the IP. If you just allow "free references" willy nilly you will be elevating the scope of the default buffer to the procedure block and causing unintended side-effects. Even if all you do is NO-LOCK reads this is a bad thing.
My preferred approach is to include buffer definitions such as:
define buffer customer for customer.
for all of the tables referenced in an internal procedure. This ensures that no accidental side effects occur due to unintended references to the default buffer. Of course you should also define a distinct "update" buffer and use strong scope for any updates -- that's a second buffer.
BTW -- the "buf" prefix and other junk (like "l") is hideous. Cluttering up your names with noise about the datatype makes your code unreadable gibberish.
FIND FIRST to find a unique record is also an abomination. Suppose there are two or more companies meeting your criteria? Why aren't you dealing with the rest of them? Or at least throwing an error that there should only be one? Why is the one that you just found magic?
Hi Tom,
FIND FIRST to find a unique record is also an abomination. Suppose there are two or more companies meeting your criteria? Why aren't you dealing with the rest of them? Or at least throwing an error that there should only be one? Why is the one that you just found magic?
I disagree with this. If you know that the records are unique and a FIND will never return more than one record then FIND FIRST will actually save you a wee bit of time because the ABL doesn't have to do its check for duplicates (i.e. the AMBIGUOUS function). Outside of that corner case you are correct.
Brian
huh? you only know records are unique if there is a unique index defined (and the damn fields that make it are mandatory and not null)… but then if the developer ‘knows’ that so should the ABL and don’t waste any time to check for anything :)
Nope. This is how it works and the info came straight from Mary Szekeley's mouth. By default we do what we need to do to determine if AMBIGUOUS should return true/false and by using the FIRST phrase you are telling us that you don't care about ambiguity so we don't do the work.
By the way, we are talking about nanoseconds here so for most people it won't really matter but for those who need to remove every unneeded nanosecond this will matter.
With all due respect I think you are perpetuating a myth. There is no check for ambiguity on a unique find -- I have never found an iota of evidence to support that contention. If the FIND is using a unique index there is no need to check anything -- the very nature of the index ensures that. If it is *not* a unique index then you should be using a statement that deals with multiple records such as FOR EACH.
Even if I am wrong (I'll happily buy you lunch if you can show that I am) -- the statement is still misleading the next programmer to come along and, in my mind, the downside of misleading code far outweighs any hypothetical minuscule saving of execution time. FIND FIRST is waving a flag saying that there could be multiple records -- but then doing nothing about the possibility.
BTW, I've talked to Mary about this too -- and I didn't hear what you heard. Maybe we asked slightly different questions?
Tom,
It came directly from the person who wrote the code. I stood in her office while she explained it to me many, many years ago.
Brian
Tom,
I am sure there are optimizations in the code related to the ambiguity check to make it as efficient as possible so it is likely it can detect the 'perfect scenario' and just flag ambiguity as false but I do know that it is possible that a second read has to be done to satisty the ambiguity check.
Brian
Well Brian,
Marian,
It's my understanding that this behavior has never changed (i.e. horse left the barn long ago).
Brian
I update the screenshot, I think all references are ok now. Thanks for noticing my quick copy paste mistake.
Like I said, I've asked Mary about it too. I didn't video the conversation so I have to rely on my pitiful wetware capabilities but my recollection is that she said that a UNIQUE FIND with a UNIQUE index does NOT check for ambiguity. What would it even check? Maybe we can invite her to drop in sometime and we can have a spirited discussion :) Or maybe we can get some of the current engineering people to weigh in on what the current code does.
Tom,
Is this a better code snip?
[View:https://drive.google.com/a/tvh.com/file/d/0B1P8s6ZKpj7wNGlRbUhtZ1RxeDg/view?usp=drivesdk:550:50]
The code snip for illustrating "our" preferred coding practices. I'm aware that the data type prefixes are not done according "clean code" (the book :-) ). And we also made CompanyCode a unique index.
Tom,
my goal is to define good naming conventions. What names will you use for your buffers in this case?
Yes, a unique find will try to avoid an ambiguous check. If an unique index is used and it can guarantee uniqueness, there is no check unless unknown values and/or BEGINS is involved. Otherwise, a check is performed.
Code that does not have the perfect scenario is an even worse problem... Because there really can be more than one record in that case using FIRST is almost certainly a bug waiting to happen.
If I spot "find first" in code without "find next" I always wonder what's wrong with the second, third, ... record.
Why didn't they use find last ?
If the index is unique, and find first is used, I assume the developer does not know the database schema (s)he is coding against.
Just my 0,02€
Even if there was an infinitesimal performance gain, I would argue against this practice as it confuses the next programmer to work on the code. The appearance is of non-unique records of which one is getting the first one. It that were actually done, it would be a violation of normal form. If the find is actually unique, one is confusing the programmer, who may not have advance knowledge of the related schema.
But, I also oppose define buffer customer for customer. By using unique names you make it immediately clear where the scope of that buffer is.
In my code I like to use a buffer named the same as the table for all no-lock read access. I create a buffer prefixed with "upd" for buffers that I intend to update (which includes CREATE statements).
Maybe we should also discuss the correct way to indent IF statements? ;)
Now that that's been sorted...
I assume that it is also common knowledge that you have a small performance gain if you do not indent. That is because spaces end up in the object file and then the ABL engine has to skip them before it reaches an executable statement. Although small, it /is/ a performance gain. The same is true for short versus long variable names. Short names execute faster.
We stopped indenting and use one-letter variable names only and our code is blazingly fast!
[mention:dc2ff39fa15940708b78017f1194db6a:e9ed411860ed4f2ba0265705b8793d05] about the correct way of indenting, I'm really interested.
These kind of best practice style rules, is this documented somewhere? My friend Google couldn't help me.
Patrick, you forget the cost of CRLF's .... ONE line for all code runs at ludicrous speed.
I would always use a FOR FIRST instead of a FIND or FIND FIRST (no need to use NO-ERROR). At least for MSSQL connected databases through the dataserver FOR FIRST include the SELECT ... TOP 1 phrase compared to a simple FOR, which result in a performance benefit.
community.progress.com/.../sql-statement_generated_from_for_buffer_should_contain_top_1