Friday, November 30, 2007

Rant about Notes 8, Lotus/IBM

Nathan writes "Where is the love".

More and more, I think, "Where is the hate?" :)

I was on the point of starting a rant in the comment section on the post, but after half an hour of writing/rewriting my frustrations with (my perceived) impression of IBM/Lotus directions, I decided to keep the rant on my blog.

Every week 5+ blogposts enter my RSS-reader about how great Notes 8 is. Almost nothing about the bugs/bad integration between the new client and Domino Designer (maybe I am the only one having problems), or how, once again, the majority (the non-java) of developers were screwed over in a release.

What mostly irritates me is that the scripting tools in Domino Designer has less functionality your average notepad-clone. You (Lotus/IBM) want me to learn Java? Then give the Designer team the resources to make tools that doesn't stink of the 1990s.

It doesn't make me happy when I think about how much resources they probably put into making 100+ different-looking icons look more or less like one (orange-ish) icon.

From my point of view, it looks like the marketing-department in Lotus/IBM has a LOT more power/resources than the developers of Notes/Domino.

Most of what's great in Notes/Domino has been there since pre version 7. Of all of the things the developer-community has asked for (in partner-/public forums), what has been implemented?

Domino Designer in Eclipse? Great!! When did you say it's going to be released?

If you want to rant about how wrong I am, please do.. I don't deny that I could be. :)

Thursday, November 29, 2007

Notes/Web JS to get text from aliased combobox/dialog list

Something I needed today. Thought i could share it with you. Easy to make, but sometimes one forgets that Notes supports JS.

I forgot to refresh, so the alias doesn't show :)

The reason I didn't use "Refresh field on keyword change" is that it's awful on web (reloads the page).

The alias of the combobox/dialog list was the corresponding number to the text (One|1, etc).


In Notes, the code also works with hidden/computed fields. For computed fields, set value = @ThisValue.

For the web, you should probably set the text-field to editable, "HTML Attributes" -> "type=\"hidden\"".

In Notes, onChange fires when the field looses focus/value has changed. On the web, the event fires when you select another value.

JS-header - Common Javascript:

function textFromMultivalue( multival, valuefield ){
var f = document.forms[0];
/*if valuefield is the name of the value-field,
get field from form */
var valuefield = ( typeof valuefield == 'string' ) ?
f[valuefield] :
/*if multival is the name of the multival-field,
get field from form */
var multival = ( typeof multival == 'string' ) ?
f[multival] :

valuefield.value = multival.options[
multival.selectedIndex ].text;

onChange in multi-value field (also Common Javascript):
textFromMultivalue( this, 'name_of_textfield' );

Tuesday, November 27, 2007

Maintaining Strong Typing in LotusScript

Update 28.11.07: Tim Tripcony wrote a somewhat related article about using ByVal for input parameters. Recommended read!


Upon reading "Code Complete", I discovered that a way of using Subs I've previously thought of as bad practice, actually is quite normal.

The author writes (I apologize if I interpreted this wrong) that some developers think that functions should be used for mathematical calculations/simple operations and procedures used for more advanced stuff. In LotusScript, from his description, a Sub is a procedure and a Function is a function (duh..).

He also suggest that when you make procedures, you put input parameters (read) first , and output-parameters (modify) second, to make it easier to read the code.

One of the advantages with using subs this way is that you can always maintain strong typing. This enables you to capture coding-errors at compile-time, instead of at runtime.

In the code below:
createToyotas is a sub that has an outputparameter, List As Toyota
toyotas is a function that returns a variant containing List As Toyota

The compiler recognizes that a "Toyota" doesn't have a method "destroyWorld", whereas the variant, also a Toyota, passes through compiling.

Error caught at compile-time with strong typing, whereas the variant doesn't cause an error until runtime.

In most cases you could probably pinpoint the runtime-error quite fast, but catching it at compile-time is preferrable for me at least.

Also, the most common error would probably be a spelling-mistake, not trying to run a random thought-up method.

Performance-wise, there may also be advantages, especially if you're using inheritance/creating many objects/etc.

When debugging there doesn't seem to be much advantage using strong typing over variants.

>> Extremely simple db with some (messy)test-code (test-agent, StrongTypingAdvantage)

If you can think of other advantages, or disadvantages for that matter, please post a comment!

Tuesday, November 20, 2007

Input Validation - On Invalid, open URL

This only works on the web.

If you put something like this in Input Validation on a field:
@If( @ThisValue = "dontpanic" ;
@Failure( "[]" ) ;
@Success )

When the user writes "dontpanic" in a field with this input validation, and try to save the document, they will be redirected to my blog.

The only use-case I can think of at the top of my head is lookup-based login-forms.

..code to check username/password..
@If( authenticated ;
@Success ;
@Failure( "[/" + @WebDbName + "/login?OpenForm&error=wrong_username]" )

Another use case is maybe to limit too wide searches. A customer recently searched for *ia*, in a several CMS' and thought that the search didn't work (when I tested, the search took 3-4 minutes to complete).

If you can think of/have other ways to make use of this, please post it in the comments..

Monday, November 19, 2007

Timesaver - Converting several values to text

I've so far only found use for it in lookup-columns, but different people, different needs.

If want to make a pipe-separated lookup-column of values like these: subject(string), ranking(number), previous_ranking(number), posted(date), modified(date)

You can combine values of the same data-type under one @Text like this:
@Implode( subject :
@Text( ranking : previous_ranking ) :
@Text( posted : modified ) ; "|" )

Apart from a timesaver, I also find it easier on the eye, than:
@Implode( subject :
@Text( ranking ) : @Text( previous_ranking ) :
@Text( posted ) : @Text( modified ) ; "|" )

Or, even worse:
subject + "|" +
@Text( ranking ) + "|" + @Text( previous_ranking ) + "|" +
@Text( posted ) + "|" + @Text( modified )

Friday, November 16, 2007

Templating: Lookups -> HTML

Update, 08.12.07: An improved, more readable technique

Inspiration, ExtJs, through Rich Waters.

I've more or less come to the conclusion that HTML in lookup-views is evil.

On one of the apps I work with, there were two access levels, reader, and editor. I used to have a column for each access, and pull HTML from the view.

col := @If( @UserRoles = "[Editor]" ; 4 ; 5 );
@Implode( @DbLookup( "" ; "" ; "(lupView)" ; key ; col ; [FailSilent] ) ; "" )

This became a headache sometimes. I'd change something in one of the columns to go with new design-desicions. Maybe it was lunch, the end of the day, or talking to a co-worker, not exactly sure, but sometimes only one column remained altered. I'd program javascript/make css for the new HTML, and think everyting is ok. Release the update. Users got JS-errors/corrupted designs/etc.

The errors wouldn't come as far as to applications in production now, as we test thouroughly before release, but it could still be a maintenance headache.

Step one to get rid of headaches:

Moving the presentation out of the view

Get rid of HTML-views, use simple lookup-views (value1|value2|value3) instead. Example of transformation to HTML.

(missing </table>)

Step two to get rid of headaches:

Using template-strings

You're probably not going to save any time writing the transformation to HTML using templates the first time, but you'll save time in the long run. Having the template in one string instead of concatenating bits of the html-per-item on several lines also increases readability of the code.

Example of simple evolution:


>> Simple demoapp

For my access-level-problem, I either write a separate template for each access (e.g. add edit link for [Editor]),
or put @If(@UserRoles = "[Editor]" ; "" ; @Return("") ) at the top (don't do anything if not editor).

Document generator - Discworld "characters"

I've mostly used Jakes fakenames-app for demos, but I've got tired of cleaning out design-elements to make it lean bytewise.

Run java-agent generateDiscworldCharaters to make documents. Currently set to 500 documents. No uniqueness check.

I use four arrays, first-name/title, last-name/"the Something", guild/company, address/country. Math.random() and a loop to create documents.

>> Discworld name generator

Saturday, November 10, 2007

Book recommendation, Code Complete

Just started reading this book:

Book description

Take a strategic approach to software construction and produce superior products with this fully updated edition of Steve McConnells critically praised and award-winning guide to software development best practices.

It deals with software development/project-management issues that I've seen at my place of work. A very interesting read.

Code Complete at Amazon
Code Complete at O'Reilly Safari (where I'm reading it)

Saturday, November 3, 2007

Templating using a NotesForm

Coding templates in an agent leads to very verbose agents/a maintenance nightmare (in my opinion). Coding them in a NotesDocument makes it hard to use them in a Design-template context.

This technique has little verbosity beyond the actual code to generate HTML, and works great in a Design Template-context. It supports modularity, as each field is a potential module. Since the templates are forms, the dynamic "modules" also work in stored documents.

You can combine Java (through LS2J), formula (through Evaluate) and LS , just like you can when you're using agents for templating web-pages. If you're a Java-guy, then you probably would need a little more code (testing field names with Regular Expression) to achieve the same.

Combine this technique with @UrlQueryString in Form Formula if you want the ability to present data in several content-types.

The technique relies on Execute, a WQO-agent and field-names following a pattern. I chose Execute because it's faster than making a testing-routine for patterns. If you're planning on putting this technique to use in real applications, I suggest you use Regular Expressions, Instr, etc. to look for valid field-names, as Execute is horrible to debug.

The demo

I have one pattern that I look for in a field-name, "wqo_actonfield_". The third token (separator = "_") is the method to be executed. The rest of the tokens are ignored to allow several fields executing the same function.

You could also have the rest of the tokens being parameters for the method being executed.

For instance field named "wqo_search_google_dontpanic" -> run a function that inserts HTML with search-results into the field.

>> Demo Application.


WQO-agent for demo:

Form, one demoBody-field:

Result, web

Form, six demoBody-fields:

Result, web (click for full size)

As always, comments are appreciated :)