Skip to content

LotusScript Classes Deep Dive Part Four

Before going onto that one more LotusScript function that is relevant to classes, there is another topic worth discussing with regard to classes. This is not functionality in LotusScript classes itself, but a design pattern which has been available ever since LotusScript began, but one which has become very commonly used in other languages as they have developed. It fits well after the discussion on using Static for creating builder classes, because the builder pattern in Java is where it's most widely used. The design pattern I'm referring to is a fluent interface.

A fluent interface is an object oriented API that relies extensively on method chaining. The benefits come when you're wanting to call multiple functions in a row, it is easily readable and improves brevity in code. As I mentioned, it has become very common in Java builder classes. It's a pattern I've used in LotusScript for a little while, first in Volt MX LotusScript Toolkit. The NotesJsonNavigatorFluent and NotesJsonArrayFluent provided fluent functions to speed up building JSON in a NotesJsonNavigator.

Creating the Fluent Function

The approach is very straightforward. Typically classes will have a Sub like NotesDatabase.SetOption(), which don't return anything. Or they have a Function like NotesJSONNavigator.appendElement(passedElem) as NotesJsonElement which return the object being passed as a parameter. To convert this to a fluent function is straightforward, and done with NotesJsonNavigatorFluent. The function signature is changed from Function NotesJsonNavigator.appendELement(passedElem) as NotesJsonElement to:

Function NotesJsonNavigatorFluent.appendElementFluent(passedELem) as NotesJsonNavigatorFluent
    Call m_NotesJsonNavigator.appendElement(passedElem) 'm_NotesJsonNavigator = internal NotesJsonNavigator
    Set appendElementFluent = Me
End Function

The function does whatever it would normally do, then returns the current object. This allows you to do NotesJsonNavigator.appendELement(passedElem).appendElement(passedElem2).

Improving The Code Further

That is good, but it's not as easy to read as its Java equivalent would be. And what happens if there's an error with one of the calls? Imagine the following code:

Class Foo
    Private elem List As String

    Function appendElem(key As String, value As String) As Demo
        Me.elem(key) = value
        Set appendElem = Me
    End Function

End Class

Class Bar

    Public myString As String

End Class

Sub Initialize()

    On Error GoTo errLog

    Dim myFoo as New Foo
    Dim myBar as Bar

    Call myFoo.appendElem("1", "One").appendElem("2", bar1.test)
getOut:
    Exit Sub

errLog:
    MsgBox "Error " & Error() & " on line " & Erl
    Resume getOut
End Sub

This will throw an "Object variable not set" error on the line with appendElem() calls. In this case, it's easy to see it's the second appendElem() call produces the error. But it won't always be so obvious. Fortunately, just as Java allows you to use separate lines for each method call in the chain, so does LotusScript. We just need to change the code like so:

Call myFoo.appendElem("1", "One")._
    appendElem("2", bar1.test)

This throws an error where the error line is specifically the line with the second appendElem() call. So we can immediately tell which part of the chain it failed on. And it also makes it more readable.

Caveat

One caveat is that you need to understand what is happening when in the chain, and to avoid manipulating parameter values. Debugging would highlight that mistake. On order of processing, imagine is we had a Function setTest(string) as String in the Bar class and had this code.

Dim bar1 as New Bar()
Call demo.appendElem("1", bar1.setTest("One"))._
    appendElem("2", bar1.setTest("Two"))

This code will call:

  • bar1.setTest("One")
  • demo.appendElement("1", "One")
  • bar1.setTest("Two")
  • demo.appendELement("2", "Two")

This may not be a surprise, but knowledge is always better than assumptions.

Although fluent coding is not the norm in LotusScript, it starts to become very attractive after some years coding in Java, particularly more modern Java. It makes code feel more modern and look cleaner, even if it's not.