Domino anti-patterns 14 Jan, 2004
OK, so here’s something a little controversial. We all like to read articles about best practice, doing things the “correct” way, and so on. How about some stuff on the bad ideas, the so-called anti-patterns that exist? Or is that an overly-negative endeavour do you think? I dunno. But I’m going to kick this off anyway, with some gems from the Notes world… Feel free to chip in!
First off, a view, with an action bar button in it. This button is labelled “Create blah blah document…”, and naturally enough one would expect that it performs some kind of @Command([Compose])
call. Not so! Check this out:
@Prompt([OK]; "New Document";
"Please use the button on the main navigator to create a new blah blah document");
@PostedCommand([FileCloseWindow])
Urgh. Almost as bad as the Querysave
form traps that prevent the use of CTRL-S or similar, in favour of pressing an action bar button.
OK, next. Querypaste
events in every single view of a database, denying document pastes. Plus, just for good measure, an agent that removes any documents pasted-in. Now, there may be a good reason for this in the odd application, but in every single database you ever created? Sorry, no.
Next! This guy was just kidding himself:
TheEnd:
Msgbox "Process completed. Error count was 0"
OK. So what’s this next bit for then?
lblErrs:
intErrCount = intErrCount + 1
Resume TheEnd
Gah. On to the last one for today (these are all real examples, and better still, all feature in the same application).
An agent designed to export a 60+ column view. This is done by concatenating a load of strings to make up the “header” of the export text file. These strings all correspond to the view column titles, and are delimited by a tilde. Cue one entirely senseless bit of code already — NotesView.Columns()
anyone?
Then, the code walks the view, and for each NotesDocument
, extracts a value from the ColumnValues
property and appends it to this gigantic string. Meh. Here’s an extract:
data1$ = Doc.Columnvalues(2) + "~"
data2$ = data1$ + Doc.Columnvalues(3) + "~"
data3$ = data2$ + Doc.Columnvalues(4) + "~"
…
data68$ = data67$ + Doc.Columnvalues(69) + "~"
What do you reckon on that? The export takes over an hour in this database (there are around 15,000 documents in the view), and the end-result still has to be manually imported into one’s reporting package of choice (MS Excel). How would you go about addressing this? For a start, why not use COM? Go straight to Excel. The Lotusscript agent isn’t readily portable, and does not lend itself to tweaks. It skims NotesDocument
objects instead of using the far more efficient NotesViewEntry
class. The string concatenation is an abomination, the resulting export file is horrible, and the code itself, when printed, takes up four sheets of A4. It also crashes my Notes client spectacularly nine times out of ten. First time I’ve seen a RBOD in Notes 6.5! Oh yes, the database contains at least three implementations of this anti-pattern, each fundamentally the same, just tailored for their respective views. Code re-use anyone?!?
Bring on your tales…
I think you've hit on an important one, though: messing with standard Domino UI features like save shortcuts, action buttons or copy/paste. Applications that force their own UI conventions without huge gains in usability or safety are a real pain.Nik Shenoy#
(Cunning pseudonym BTW badger!)Ben Poole#
My usual reponse to this kind of code is a quick re-write and loud grumblings about people learning about functional programming. Some day someone will listen and I'll be out of a job.
;)John Marshall#
boy, some people are just mean!
;-)jonvon#
Admittedly the chap wasn't really a Notes developer and knew very little about the object model and properties. I'fact, I thought it was rather an ingenious solution. I can only imagine him thinking 'Notes is so crap. I wish there was a way to just tell the document not to save itself.'Colin Pretorius#
Thats nothing Ben. I once had to rationalise another "developers" lotusscript which was 60 pages of A4. The script was intended to do something involving appointments and calendars but instead of writing functions and subs the developer had copied and pasted their orginal code and changed just changed a couple of variables each time, such as the day. It was so big that they had had to take all the comments out because it would no longer save.
Just one long big if statement….urghhhh!Ed#
With my example, I picked on this code being that long because what it does is so … simple. There’s just no need for that kind of nonsense.
As for your example Colin, oh that was beautiful :-D Ben Poole#
Sounds like Notes to me :)
With regards to the topic, i'd be interested to see the shonky code I wrote when I was first learning Notes compared to the shonky code i'm writing now. Unfortunately that was at another company and i've since misplaced my "backups".Marcin#
Put's into perspective how bad the orginal was.
Volker, I think the manager must have been impressed with that mammoth piece of scripting because the 'developer' went one rung up the career ladder and became a senior developer. Maybe there's non technical benifts to be had from writing bad apps.
Ed#
My Principle: Some don't stop there…
Colin Pretorius#
My advise would be to test it try it and optimise your codedesign so that when the bug reveals itself again in R6 you can easily re-engineer it to support the handling with the viewobject, YEH for Notes :-)
Edwin Lucke#
(Says he, the expert ;-).
Kinda makes one wish something like Notes were *koff* open-source *koff*, don't it?Colin Pretorius#
I once wrote a LotusScript agent that was four or six pages long, and didn't use functions at all. Code re-use? Bah! Nope, this thing just turndled through a MASSIVE loop, applying all sorts of criteria to the documents it was handling.
In my defence, I was going to tidy it up and export all the re-usable bits into functions once it actually worked. The app was a grou-calendar affair - it aggregated everyone's calendar by trawling them all and copying the documents into a database. It didn't copy anything that already existed, but would copy updated (edited) documents since its last trawl. It also had to remove any old documents (appointments 7 days in the past or older) - unless they were repeating documents. This was in the R4.6 days, and if you remember how it handled repeating documents you can guess where most of the kludges were^W^Wwork was happening in this app!
As say I was going to tidy it up. I demoed it to a salesman in the company. He kept a copy of the demo, and showed it to a customer. Well, actually, he sold it to the customer. So, after a mere five days of existence this app had been sold.
I kludged it working, then went to install it. To be honest, that was the day on which I decided development wasn't for me - my perfectionist tendancies would stop me from ever shipping anything!
(I'd developed intranet-style apps there before, and done other development work at a previous company. Some were even sold. But none were sold so quickly, or in such a shocking state when sold.)
I'm now happily stuck on the Admin track, with occasional dabbles in development. Just for fun, you understand… ;)
To be fair, we used this app internally at our company as well. It trundled on reasonably reliably until R5 came out. R5 had a group calendar function - not one as easy to use as mine, because it was some wierd embedded Java app - but one that worked well enough. And R5 also changed the repeating events handling, so it broke my app anyway. That combination sounded the death knell for my app, and I was a very happy man! ;)
Philip Storry#