• Browse Blogs
  • My Blog
  • My Updates

+Tags Get help with tags?

  • View as cloud  | list

+ Similar Blogs

photo

Yellow is the...

72 Entries |  Tim Tripcony
Updated 
RatingsRatings 2     CommentsComments 34
photo

Lotus Nut

111 Entries |  Chris Whisonant
Updated 
RatingsRatings 23     CommentsComments 157
photo

Patrick Picar...

62 Entries |  Patrick Picard
Updated 
RatingsRatings 2     CommentsComments 112
photo

Urs Meli

42 Entries |  Urs Meli
Updated 
No RatingsRatings 0     CommentsComments 48
photo

TexasSwede

109 Entries |  Karl-Henry Martinsso...
Updated 
No RatingsRatings 0     CommentsComments 94

+ Bookmarks

+ Blog Authors  

All entries tagged with oop

1 - 13 of 13
  • Previous
  • Next
  • Page   1

OO-SSJS: Object Oriented Server-Sided JavaScript

Peter Presnell |   | Tags:  oop ssjs | Comments (0)  |  Visits (568)
 In XPages kindergarten we started writing our code with crayons.  We were all just starting to learn a complex subject and so our teacher would let us find any place within an XPage  to scrawl out code.  It wasn't pretty, but as long as it worked nobody seemed to mind....

Now in XPage first grade the rules are changing.  The crayons have been taken away and we are being asked to write code that can be easily read (and shared) by others.  This means our teacher is starting to pay more attention to the form of the code and not just what it does.  Having learnt to write LotusScript using OOP I am naturally looking to do the same with SSJS (and even JavaScript).  The following are some of the lessons I have learnt so far.
...
Notes:
  1. I am still a long way from university and writing a thesis on the subject but this is a first graders effort at OO-SSJS.  2nd graders please point out my mistakes.
  2. OOP is almost identical for JavaScript and SSJS so I will simply refer to SSJS but the following also applies when developing client sided Xpage code using traditional JavaScript (aka ECMAscript).
Classes:
As a LotusScript/C#/VB.Net developer I always associated OOP with classes.  It turns out that classes are not the only way to implement OOP.  Classes are a structured way of defining objects.  In contrast, the prototypeing model supported by SSJS provides a lot more flexibility.  This is not unlike Notes development itself right!!!  When I first started writing SJS it bothered me that the language was not strongly typed and that it did not have classes.  Now I am beginning to think this could be really cool.  In relational databases we have a regimented structure where every row (document) must have a set number of columns (fields) and each column must contain data of the same datatype.  In the Notes world almost anything goes and it is up to the skill of the Notes developer to exploit this dynamic capability (eg. showing multiple document types in a single view using common field names).  So what if LotusScript & SSJS don't support abstract classes, sealed classes and interfaces like java/c#?  Are those things really needed when the majority of Notes/Domino projects have a single Notes developer?  If a useful way can be found to instantiate a base class or the need to extend a sealed class becomes necessary then why not let this happen.  I don't need a "code-lawyer" creating artificial boundaries for me.  By the time I have finished the debate with the lawyer I could have the entire app written!

In SSJS we represent objects by creating a function and then instantiating the object using the new statement.  The function is referred to as the constructor for the object as it is executed whenever the object is first invoked just like sub new in the LS class.
Example 1: Object with variables defined via the constructor:-

function
employee ()
{
var privatevariable;
this.publicvariable;
}
var emp = new employee()
Properties:
Strictly speaking SJS does not have properties.  Rather, what SSJS supports is both private and public variables.  These can be defined in one of two ways:-
  1. Constructor: The easiest way is to create private/global variables inside the constructor as demonstrated above.  This has the advantage that the definition of the property cannot be over-ridden.  Variables are made public using this.variablename whereas private variables are defined using a var statement.
  2. Prototype: The format of OOP implemented by SSJS is known as protype-based programming and uses the prototype statement.  This technique provides better support when it comes to extending a base class (inheretance is a  key principal in OOP).  It also allows properties/methods to be added dynamically, a really powerful capability not available in java or C#.
Example 2: Object with variable defined via prototype

functionemployee()
{
this.Document=source;
}
employee.prototype.publicvariable;
The difference between a variable and a property is that a property allows additional logic to be executed each time a property's value is accessed.  In the case of SSJS we are most likely to create objects to represent the content of Notes documents.  The properties corresponds to fields, so when we attempt to get a property value we need to extract the value from the Notes document.  And when we set a property value we need to ensure that value is store back in the Notes document.   Not all properties behave this need, but a great many will.  Variables do not allow us to do this...

The solution I have developed for this is to pass the XSPDocument as a parameter to the object's constructor.  This is saved in a public variable (Document).  For each property I then add a public variable to the object (using prototype).  This can be made private if you have a compelling reason, but why bother?  Who are you really protecting by doing this?   I then add two public functions to the object for the get and set (using prototype).  If you only need a get (or set) then just one function will suffice.  The get function contain the logic for extracting the data from the XSPDocument along with any other preprocessing that may be required before it is used.  The set function contains the logic needed to process the value before it is saved back in the XSPDocument.  This may include validation logic to prevent invalid values being stored.  This is the concept of encapsulation (another key principal in OOP).  I can then use the get function much like I would use the LS get property and the set function the same as a LS set property.  I also have the option of using the public variable directly.  This would be done for the purposes of efficiency where I need to refer to a property many times and I do not wish to pull the data from the XSPDocument each and every time.
Example 3: Notes Field Represented as a Property

Employee.EmployeeID;
Employee.prototype.getEmployeeID=function()
{
if ( this.Document.hasItem("Emp_No")) {this.EmployeeID = this.Document.getItemValueString("Emp_No")}
return this.EmployeeID;
}
Employee.prototype.setEmployeeID= function(value)
{
this.EmployeeID = value;
this.Document.replaceItemValue("Emp_No",value);
}

Note: At  this time SSJS is only supported within Xpages.  Back-end processing would be supported via Agents or Web Services which must be written using either LotusScript or Java.  It therefore seems to make more sense to develop SSJS classes to interact with the XSPDocument class than it does the NotesDocument class.  If at a later time IBM provides a clearer strategy for SSJS this decision may need to be revisited.

To simplify the task of creating these property statements I have added a tool to the .Domino Framework as outlined in my previous blog.
No RatingsRatings 0

Property Generator for SSJS

Peter Presnell |   | Tags:  properties ssjs oop | Comments (0)  |  Visits (474)
 Release 1.1 of the .Domino Framework will contain an enhanced version of the Property Generator tool that will allow Object Oriented Programmers to generate SSJS property statements.  A sample of the SSJS code generated is as follows:-

Employee.prototype.EmployeeID;
Employee.prototype.getEmployeeID= function()
{
if ( this.Document.hasItem("Emp_No")) {this.EmployeeID = this.Document.getItemValueString("Emp_No")}

return this.EmployeeID;
}
Employee.prototype.setEmployeeID= function(value)
{
this.EmployeeID = value;
this.Document.replaceItemValue("Emp_No",value);
}

No RatingsRatings 0

XPages - The Good, The Bad and the UGLY - III

Peter Presnell |   | Tags:  oop xpages javascript | Comments (2)  |  Visits (893)
Progress is slowly being made and my perceptions of Xpages are constantly changing (not always in the same direction)....

First I wish to revise my statements from yesterday's blog about Server-Sided Javascript.  Tim Tripcony wrote an excellent article in which he pointed out some of the inaccuracies in my characterizations of server-sided Javascript.  It seems that server-sided JavaScript should largely be considered a distinctly different language from client-sided (traditional) JavaScript.  They both just follow the same general language syntax (just as LotusScript and VB.Net do).  It's a shame IBM chose to use the same name rather than coming up with a new name like LJScript of LotusJScript for this new language to make that distinction.  So I was wrong: Server sided JavaScript is (or can be) strongly typed.  Tim has also suggested how the JavaScript characteristic of closure can be used as a way to implement a level of OOP.  There are in fact a lot of discussion in the wider development community about Javascript and OOP.  Much of this exploits JavaScript's ability to define objects and then extend them using the proptotype statement.  Combined with closure this provides various techniques in which classes etc can potentially be implemented/simulated.  I would still rather see native support for OOL built into the programming language.  And perhaps given the way IBM have implemented server sided JavaScrript it may be that in time IBM will add these concepts directly to the language.  If they don't, you can expct to see a .Domino Framework 2.0 that does!

But every time I look at the issue of programming language support I still keep coming back to the one question.  What is it that IBM is planning to do?  I may not agree 100% with their plans but at least if I know where they are heading it might force to me jump off the fence.  e.g. If IBM's focus in the short-medium term will be to extend the capabilities of XPages and do very little with the other design elements then Notes developers would be smart to do the heavy lift of learning how to build applications with XPages.  If IBM's plans for programming language support is to extend server-sided JavaScript and leave LotusScript as it is (including leaving it out of XPages).then it would be better for LS developers like me to focus on learning/using this new language and largely forgetting about LS.  If this isn't clarified clearly I suspect a lot of developers will be tempted to sit on the fence.  LotusScript, Forms, Views, Outlines, and Framesets are all within most Notes developer's comfort zone.  XPages and server-sided Javascript involves a lot of "pain".

So on to today's observations.....

The Good: Drag/Drop - This is not new stuff for non-Notes development.  Products such as Visual Studio, Eclipse, and even VISIO have long supported the ability to drag/drop elements from a toolbox onto visual design elements.  It is such an intuitive way to work and way more productive to create an Xpage this way.  DDE 8.5.0 is still a little clunky when you try to drag/drop the controls around the Xpage after they have been created.  But this is largely a 1.0 release so it is perhaps not surprising.  I would hope that IBM add this same capability to forms and pages at a later stage as it is already hard to go back to the old way.

The Bad: Documentation - One of the biggest limitations I am finding at the moment is the difficulty in getting a detailed understanding about how Xpages and server-sided JavaScript works (LotusJScript ;) ).  With Xpages I am finding that I am drawing more on my previous, short, experience as a C# ASP.Net developer than my many years as a Notes developer.  Many Notes developers are not as lucky and must be struggling even more than I to understand important new concepts such as application, session, page lifecycle events clinet sided v server sided etc.  It would be great if there were a few redbooks, technical books etc that we could consult like a bible while enduring those first few days/week/smonths (years?) as an XPage developer.  I remember when I first learnt LotusScript how much I consulted my LotusScript book to figure out how to write my code.
No RatingsRatings 0

XPages - The Good, The Bad and the UGLY - II

Peter Presnell |   | Tags:  javascript oop lotuscript xpages | Comments (3)  |  Visits (980)
More observations on Xpages from my first few days in XPages kindergarten.

The Good: Source View.  This is up there as one of my favorite additions to Domino Designer.  It is also something I can easily relate to having used a similar feature in MS Visual Studio for ASP.Net development.  I am a developer and so I like to look at code.  Being an OOP developer I am used to seeing all my LS code in one place (LS library).  So being able to see visual elements such as XPages represented as a single block of XML code is really cool.  It provides options for me to do things I haven't been able to do with other visual design elements.  I can now see what I have done with my Xpage without the need to click on an endless number of controls and review all the tabs with various radio buttoms, check boxes and keywords.  I can use the source view to edit visual elements too small to see.  I can copy/paste the xml and do search/replace much as I can with LotusScript code.  I havent tried this yet, but I can probably now use TeamStudio code snippets as a way of creating a library of common xPage components (over an above custom controls).  I am hoping IBM plan to extend this capability to all other Visual design elements, especially forms and views.  If I do I might then be able to copy/paste codes between these design elements (see legacy code yesterday).

The Bad: Programming Language Support I was tempted to classify this as just plain UGLY, but that might be a little unfair.  I am sure a few people out there such as Nathan T Freeman and Andrew Pollack will disagree with me.  That's OK, I respect their opinions, even when they are wrong :)... Without doubt my single biggest disappointnment with xPages so far is the decision to support server sided scripting for XPages with a new variation of JavaScript.  Sorry, but I just don't accept that JavaScript is a programming language.  Most other development platforms employ JavaScript for client events only. If they could get Java or C# to run in a browser I am sure they wouldn't even be using JavaScript.  Most server sided programming outside of the Notes world is now done using OOP languages like Java or one of the .Net languages - C# or VB.Net.   Outside the yellowverse it is also pretty much accepted that OOP is the programming style of choice.  Within Notes Java is OOP and LotusScript can be (sort of, kind of).  JavaScript does not support classes (outside of hacks such as prototype), it doesn't even support strong typing, everything is a variant.  There are some cool things with this version of JavaScript such as implementations of @functions, but it is still a procedural scripting language.  It seems with this current version of XPages OOP is sadly not an option (agent hacks aside).

I have seen suggestions that JavaScript was chosen as a way of getting Xpages implemented and out there quickly using JFaces.  I am not sure if that is true.  If it is, I am not sure if that then means in the future support will be added for both Java and LotusScript for Server events and LotusScript for client events.  I hope that is the case as it creates a real dilema for me as to whether or not I would want to rewrite my applications from being OOP to procedural.  For me that is a giant step backwards from a software engineering perspective.  Xpages need engineering as they can be very complicated.  I am not sure if IBM have ever publicly commented on its choice of JavaScript for XPages and where this is leading....  It is is still my hope that one day soon IBM will publish a road map for Notes Development programming languages that clarifies the future for both LotusScript and Java.  In every Notes shop I have worked for in the past 10 years LotusScript has been the dominant programming language (95%+) .  Convincing people to move away from LotusScript may prove to be just as hard as convincing these same people to move away from Notes to Workplace.
No RatingsRatings 0

Polymorphism with LotusScript

Peter Presnell |   | Tags:  oop .dominoframework polymorphism | Comments (5)  |  Visits (899)
Of all the terms in programming I think polymorphism is one of the coolest.  While I cannnot include eclipse plug-in developer on my resume, I think being able to feature a cool term like polymorphism on my resume must be worth an extra $10 for my hourly rate!!!

Polymorphism is a common feature available in most object oriented programming languages such as java, c#, and VB.Net.  Search the Domino designer help and you will not find any mentions of this term.  In the limited coverage given to classes there are no hints as to polymorphism being available.  And yet, it does seem that LotusScript can perform a limited amount of polymorphism.

If you are a LotusScript developer you may not have had the need to ever understand polymorphism (even if it did add $10 to your hourly rate).   Consider a simple HR database such as the following:-
Class Person
' ...
End Class

Class Associate As Person
' ...
End Class

Class Contractor As Person
' ...
End Class

Class Manager As Associate
' ...
End Class
I could read a document from a Notes HR-related  database and then assign it to a variable that is any one of the above classes.  But what if I then wanted to start treating that variable like it belonged to one of the related classes?  In C# this can be achieved using casting.  It turns out that with LotusScript that the following code is possible:-
Dim Employee As Person
Set Employee = New Person(Doc)
Call Employee.Update()
Set Employee = New Manager(Doc)
Call Employee.Update()
In the above... The first time the Update method is invoked it will call the method defined in the Person class.  The second time the update method is called it invokes the method defined in the Manager class (assuming it exists).  There are some limitations with this approach.  In particular, the properties/methods must all be defined in the base class.

The .Domino Framework provides 100+ custom classes defined so the need for polymorphism does arise periodically and will now be implemented using the above technique (for no other reason than to add polymorphism to my resume).

No RatingsRatings 0

Building "Composite" Applications In Notes 6

Peter Presnell |   | Tags:  .dominoframework compositeapplications oop events | Comments (3)  |  Visits (823)

I am presently working on a project that requires coordination between separate components contained within a frameset.  In Notes 8 this would be considered a composite application but I need to implement this solution in Notes 6.0.  Fortuantely there has been some excellent articles recently posted by Tim TripconyJan Shulz , and Nathan T Freeman on the subject of remote event binding - an important part for creating composite applications.

I have now extended the .Domino Framework by adding a new DominoListener class.  This class is designed to listen for events that occur in a nominated Notes UI class.

Class DominoListener As DominoBaseClass Private iParent As Variant ' The object requesting a listener Private iTarget As Variant ' The UI object being monitored for one or more events Sub New(Parent As Variant,Target As Variant), DominoBaseClass(ENUM_CLASS__ABSTRACT + "DOMINOLISTENER") End Sub Property Get Parent As Variant Set Parent = iParent End Property Property Set Parent As Variant Set iParent = Parent End Property Property Get Target As Variant Set Target = iTarget End Property Property Set Target As Variant Set iTarget = Target End Property End Class

The DominoLIstener class is extended by DominoDocumentListener and DominoViewListener  classes designed to specifically listen for events in NotesUIDocument and NotuesUIView classes.  ( a DominoDatabaseListener may be added later).

Class DominoViewListener As DominoListener Sub New(Parent As Variant,Target As Variant) Call DominoBaseClass..ValidateClass(ENUM_CLASS__ABSTRACT,"DOMINOVIEWLISTENER") If (Not Typename(Target) = "NOTESUIVIEW") Then End Set iTarget = Target End Sub End Class Class DominoDocumentListener As DominoListener Sub New(Parent As Variant,Target As Variant) If (Not Typename(Target) = "NOTESUIDOCUMENT") Then End Set iTarget = Target End Sub End Class

The above classes are all abstract classes and demonstrate the use of a DominoBaseClass covered in a previous blog to implement/enforce class abstraction.

To wire two objects together I need to create a Listener class that defines the events to be monitored and the action to take when the event occurs.  The following demonstrates a single event, but I could just as easily monitor multiple events by adding additional delegates/methods to the code.

Class OpenFeatureListener As DominoDocumentListener Sub New(Parent As Variant,Target As Variant) If Not Parent Isa "DominoFeature" Then End Set iParent = Parent On Event PostOpen From Target Call DelegatePostOpen End Sub Sub DelegatePostOpen(Source As NotesUIDocument) Dim DesignListUIDoc As NotesUIDocument Dim DesignListDoc As NotesDocument Dim DesignList As DominoDesignList Set DesignListDoc = New NotesDocument(Source.Document.ParentDatabase) Call UIW.SetTargetFrame(ENUM_FRAME_DESIGN_LIST) Set DesignListUIDoc = UIW.ComposeDocument("","",ENUM_FORM_DESIGN_LIST) Set DesignList = New DominoDesignList(DesignListUIDoc) DesignList.Title$ = iParent.Title$ Call DesignListUIDoc.Refresh() End Sub End Class

The listener is invoked in the parent object with a simple statement

Set Handler = New OpenFeatureListener(Me,Source)

Within a composite application an object may have the need to observe multiple objects.  I have therefore created a DominoBroker class as a container for Listeners.

Class DominoBroker Private iListeners As Variant Sub Register(Listener As Variant) If Not Listener Isa "DominoListener" Then End If Not Isarray(iListeners) Then Redim iListeners(0) Else Redim Preserve iListeners(Ubound(iListeners)+1) Set iListeners(Ubound(iListeners)) = Listener End Sub End Class

This is not unlike Nathan's totally cool concept of a unicache Ideally I would like to have a single Broker for an entire Notes session, but presently I seem to be constrained by LotusScript to only being able to get a handle on UI objects that are currently active (one NotesUIDocument, one NotesUIView) or when LotusScript code launches a UI object (e.g. UIW.EditDocument).  So far I have only been able to share the love (broker) around between UI objects that have been loaded by a common UI object (class). Documents opened in preview mode from a view, embedded views etc. are a Remote event black hole.

Combining the above with framesets (to contruct the presentation layer) allows me to implement design patterns in Notes 6 very similar to Notes 8 composite applications.  The down side(?) is that I am restricted to only wiring Notes components and only for some very specific scenarios.  On the plus side this is all Notes code with no Eclipse required.

Note: The above is designed for Notes 6/7 only.  Notes 8 provides additional classes to support composite applications as well as a composite application editor.

No RatingsRatings 0

Adding Abstract Classes To A Framework

Peter Presnell |   | Tags:  .dominoframework oop classes | Comments (2)  |  Visits (1,694)

After writing my blog about implementing abstract (and other) classes in LotusScript I started to think about ways to reduce the code that would be required to implement this into each and every abstract/sealed class in a framework.  I have now gone back to my own .Domino Framework and added a new base class that implements much of the logic for abstract/sealed classes (and interfaces). 

Class DominoClass
Sub New(Source As Variant)
Dim Params As Variant ' Parameters passed to this class
Select Case Typename(Source)
Case "STRING"
Params = Fulltrim(Split(Source))
If (Ubound(Params) = 1) Then Call ValidateClass(Params(0),Params(1))
End Select
End Sub
'/**
' * Validate a class to ensure it conforms to rules for special class types
' */
Sub ValidateClass(ClassType As String,ClassName As String)
Select Case ClassType$
Case ENUM_CLASS__ABSTRACT: ' Abstract classes cannot be implemented directly
If (Typename(Me) = ClassName$ )Then
Error ERROR_USER_FATAL,ClassName$ + " is abstract and cannot be implemented directly"
End ERROR_USER_FATAL
End If
Case ENUM_CLASS__INTERFACE: ' Interfaces cannot be implemented directly
If (Typename(Me) = ClassName$) Then
Error ERROR_USER_FATAL,ClassName$ + " is an interface and cannot be implemented directly"
End ERROR_USER_FATAL
End If
Case ENUM_CLASS__SEALED: ' Sealed classes cannot be extended
If (Typename(Me) <> ClassName$) Then
Error ERROR_USER_FATAL,ClassName$ + " is sealed and cannot be extended by " + Typename(Me)
End ERROR_USER_FATAL
End If
End Select

End Sub
End Class

Now any class that extends this class (directly or indirectly) can assert itself as being an abstract class, sealed class, or interface on one of two ways:

Constructor: The following  scenario can be used when the constructor shares the same footrpint as the base class (single parameter of type variant) and there is no need to pass the original parameter to any intermediate base/super class.  It work by directing the constructor of the base class to take an alternative value than the one passed to the extended class.

Class AbstractClass As DominoClass
Sub New(Source As Variant), DominoClass(ENUM_CLASS__ABSTRACT + " ABSTRACTCLASS" )
...
End Sub
End Class

Method: The alternative is to invoke the ValidateClass method directly

Class SealedClass As AbstractClass
Sub New(Source As Variant)
Call ValidateClass(ENUM_CLASS__SEALED,"SEALEDCLASS" )
End Sub
End Class
No RatingsRatings 0

Reducing Programming Language Differences

Peter Presnell |   | Tags:  vb.net lotusscript oop java c | Comments (2)  |  Visits (741)
One of the things that struck me when I attended my first C# programming class was the fact that the instructor was often switching between code examples written in either c# or VB.Net.  These two languages had evolved in such a way that in many ways they had become the same.  This means programmers in one language can more easily adapt to develop/maintain code in the other.  This started me thinking about the opportunity to write Notes applications in such a way that non-Notes developers could better make the transition to develop/maintain LotusScript code.  The same concept also holds true for java, which is not all that different to C#.  The following are some of the coding practices that can be applied to LotusScript to give them a look/feel more like these other programming languages.
Note: The goal here is coding consistency between programming languages.  These suggestions do absolutely nothing to improve the functional nature of the LotusScript code and actually increases the length of the resulting code. 

Object Oriented Programming:
Java, C#, and VB.Net are all examples of object oriented programming languges.  With LotusScript the use of OOP (e.g. classes) is optional.  If you get into the habbit of using OOP when developing Notes applications via LotusScript the chances are the code will be WAY more understandable to a java or .Net developer.  Note: Without a proper class editor for LotusScript it can be a little more painful to maintain code in classes but the pain does subside after a while and a new eclipse editor for LotusScript is not far away...

Error Handling:
LotusScript does not support the try/catch construct found in many modern programming languages, but it is possible to simulate this by adding a non-functional try label at the start of the code and always using catch as the error handling label.  This results in code block similar to the following:-
Try:
On Error Goto Catch
.... (normal code)
Exit Sub
Catch:
.... (error handling)
Exit Sub

This concept can be extended to include the optional finally block used for code to be executed after both normal completion or an error.
Try:
On Error Goto Catch
.... (normal code)
Goto Finally
Catch:
.... (error handling)
Resume Finally
Finally:
.... (final code)
Exit Sub

If... Then... Else
Both java and c# require conditional expressions be enclosed in parenthesese - with LotusScript this is optional.  For consistency make it habbit to use this optional capability of LotusScript.
If (iDocument Is Nothing) Then ... Else ... End If
Method Calls
When invoking a methods (sub or function) with zero parameters in c# or java it is a requirement to place empty parentheses at the end of the method name - with LotusScript this is optional.  Again, for consistency, make it a habbit to use this optional capability of LotusScript.  The use of parentheses helps to make methods distinct from properties.  Note: LotusScript also requires the somewhat redundant Call statement to be used with methods - but thats another story...
Call UIW.ReloadWindow()

Inheritence
Both java and C# support the this statement as a way of referring to methods/properties of the current class.  With VB.Net and LotusScript the equivalent statement is the me statement.  To refer to a property/method in a base/super class that has been overriden in the current class .. notation is used. While it is only ever necessary to use either statement when the same variable/method/property exists in different scopes, it is often a good idea to use either statement to make it clear wherever a method/property defined elsewhere in the class is being invoked.  This also provides a way to minimize the use of variable names like EmployeeName1 to avoid clashes with property names.
If (Me.EmployeeName$ <> EmployeeName$) Then Me.EmployeeName$ = EmployeeName$

If (baseclass..EmployeeName$ <> EmployeeName$) Then baseclass..EmployeeName$ = EmployeeName$


No RatingsRatings 0

Implementing abstract classes, sealed classes, and interfaces in LotusScript

Peter Presnell |   | Tags:  lotusscript oop .dominoframework classes | Comments (0)  |  Visits (981)
This post was prompted after following all the fun Tim Tripcomy was having building a mini-framework to demonstrate remote event binding....

Rather than just getting frustrated with the lack of progress by IBM in developing the LotusScript language - in line with Microsoft's version of BASIC (VB.Net) - I started building the .Domino Framework.  This was my way of getting more out of LotusScript so that I could be even more productive.  And it works. I find that by using a framework I can build new Notes applications around 50% faster than before.  And we ALL know that Notes development is already signficantly faster than most (All?) other development platforms - right!!?  LotusScript currently falls short in providing a number of important OOP concepts, including abstract classes, sealed classes, and interfaces. Within the .Domino Framework I have chosen to implement these constructs as described below.  Note: One of the key difference with LotusScript is that errors for violating "the rules" are thrown at run-time and not at compile time.  Other OOP languages such as C#, VB.Net, and Java implement these OOP constructs with class modifiers such as "abstract", "sealed", and "interface" (can you guess which is which?).  These languages stop you making mistakes when you first try to write the errant code.

Abstract Classes
An abstract class is defined as a way of providing attributes (properties, methods, and events) that can be shared by subclasses.  e.g. An Employee class defines attributes common to FullTimeEmployee, PartTimeEmployee, and Contractor classes.  The employee class is deemed "abstract" if you cannot implement an employee class directly but must implement one of the available subclasses.  An abstract class can be simulated in LotusScript by using the constructor.  When an instance of a class is defined the constructor of ALL base classes are also invoked.  We can therefore do a check to ensure the class being implemented is not the abstract class itself:-
Class AbstractClass
    Sub New(Source As Variant)
        If Typename(Me) = "ABSTRACTCLASS" Then
            Error ERROR_USER_FATAL,"AbstractClass is abstract and cannot be implemented directly"       
            Exit Sub
        End If
    End Sub
End Class


Sealed Classes

Sealed classes are used when you wish to prevent a class being extended by another class.  Again the constructor can be used to validate sealed classes.
Class SealedClass As AbstractClass
    Sub New(Source As Variant)
        If Typename(Me) <> "SEALEDCLASS"     Then
            Error ERROR_USER_FATAL,"SealedClass is sealed and cannot be extended by " + Typename(Me)
            Exit Sub
        End If
    End Sub
End Class


Interfaces

Like abstract classes, Interfaces are not designed to be implemented directly.  They differ from abstract classes in that they provide no code for properties, methods, events but define the properties, classes, and events that must be present for a class to meet the requirements of the interface. e.g. in Tim's example he has certain methods that must be implemented to make a specifc class "bindable remotely" This could be achieved by implementing an IsBindable Interface.  Another common example would be an "IsSortable" interface that is used to define classes that can be sorted.  Classes implementing such an interface may require GetFirst, GetNext, and Compare methods for a sort function to work.  Interfaces are more challenging to implement in LotusScript.  Because we are restricted to extending classes in a single chain we can only implement multiple interfaces by definining them in the underlying base class(es).  In C# we could implement multiple interfaces by listing each required interface as part of the class definition.  e.g. if I have interface A, B, and C I cannot easily implement classes in LotusScript with interface requirements A, B ,C, AB, AC, BC, and ABC without repeating a LOT of code (YUK).  We also have no way of checking if all of the required properties, methods, events have been implemented correctly, rather we can merely thow an error when we attempt to invoke one of those attributes.  The code for an interface could look something like this....
Class Interface
    Sub New(Source As Variant)
        If Typename(Me) = "INTERFACE" Then
            Error ERROR_USER_FATAL,"Interface is defined as an interface and cannot be implemented directly"
            Exit Sub
        End If       
    End Sub   
    Sub Method1
        Error ERROR_USER_FATAL,Typename(Me) + " has not implemented method Method1"
    End Sub
    Sub Method2
        Error ERROR_USER_FATAL,Typename(Me) + " has not implemented method Method2"
    End Sub
End Class


The next release of the .Domino Framework will provide an example agent that demonstrates the above.
No RatingsRatings 0

History Of LotusScript - Part 3

Peter Presnell |   | Tags:  lotusscript .dominoframework vb oop | Comments (1)  |  Visits (946)

LotusScript is a dialect of the BASIC programming language.  Version 1.0  of LotusScript was released in 1993 as part of a new spreadsheet product called Lotus Improv.  LotusScript 2.0 added the ability to work with Notes applications and formed part of Lotus Visual Programmer (ViP).  ViP was designed as a competitor for Visual Basic, which had been released by Microsoft in 1991.   ViP was eventually discontinued as a stand-alone product and we saw LotusScript 3.0 added to Notes 4.0 in January 1996.  At this time LotusScript required the use of the "C API" to access Notes data.  In October 1996 Microsoft launched VB4,adding the ability to define custom classes, effectively making BASIC an Object Oriented Programming language.  In December 1996 Notes 4.5 was released adding the ability to create LotusScript libraries and providing 26 product classes that allowed direct access to Notes data.  At this time both Visual Basic and LotusScript were comparable products.  As discussed  last week in Part 1 Lotus/IBM continued to provide significant enhancements to the LotusScript language as part of Notes R5 (1999) and Notes 6.0  (2002).

In April 2003 the landscape of BASIC programming changed when Microsoft introduced VB.Net as part of its .Net Framework.  A new programming language (C#) was also developed as part of the .Net framework, but Microsoft also updated its VB language to allow devoted BASIC programmers an easy way to migrate to its new development platform.  This stragey seemed to work.  In Part 2 I contrasted the approach being taken by IBM who seemed to focus its effort post 6.0 on building a competing product for Lotus Notes called IBM Workplace.  Notes 8.0 provided some extensions but Notes 8.5 now looks like being the first release of Notes in which no extensions of the LotusScript language are provided and the promised Eclipse LotusScript Editor is also missing.  This is all comes despite the fact that LotusScript remains the core programming language for most Notes development.  Java has now been added as an alternative but it is still not implemented fully and does not have the same following as LotusScript.

I blogged last month about some of the things I would like to see added to the LotusScript language.  Many of these have been posted by me and others on IdeaJam But whilst there is little that can be done to extend the LotusScript language, the good news is that we as Notes developers can use the LotusScript language that we already have to fill in many of the gaps that exist in the product classes such as NotesDatabase and NotesDocument.  This uses the Object Oreinted Programming capabilities of Lotuscript to extend the existing product classes allowing us to add new properties/methods and even create new classes.  The following techniques will work for Notes 4.5+.

1) LotusScript Library
Create one (or more) LotusScript Libraries to hold your code.  Options include having one LotusScript library for all the new classes, or having a separate LotusScript library for each class.  The new classes can then be introduced to your Notes application via the Use statement.
Examples:
Use "BleedYellow" or Use "BleedYellow.BleedYellowDocumentCollection"

2) Create New Classes
Create one or more new classes.  It is suggested you chose names for your new classes that are derived from the product class being "extended" (e.g. DominoDocument, NotesDocument2, SuperNotesDocument).  Because LotusScript presently does not allow us to extend product classes directly we need to create new classes from scratch that include rather than extend the base class.

Example:
The NotesDocumentCollection class could be extended as follows:-

Class BleedYellowDocument Collection

  Public Documents As NotesDocumentCollection

  Sub New(Source As NotesDocumentCollection)
    Set Documents = Source
  End Sub

End Class


Note: If LotusScript supported direct extensions of product classes the above code could effectively be replaced with:-
Class BleedYellowDocumentCollection As NotesDocumentCollection
End Class

3) Make Base Object A Property
While the example above works, OOP principals require that Properties be used instead of exposing public variables directly.  This allows you the ability to wrap additional logic around the object at any time, such as validation, without exposing any changes in the interface to consumers of the class.

Class BleedYellowDocument Collection
  Private iDocuments As NotesDocumentCollection
  Sub New(Source As NotesDocumentCollection)
    Set iDocuments = Source
  End Sub
  Property Get Documents As NotesDocumentCollection
    Set Documents = iDOcuments
  End Property
 
Property Get Documents As NotesDocumentCollection
    Set iDocuments = Documents
  End Property
End Class

4) Extend The Constructor
One of the first extensions that can be applied to a class is the options for the constructor.  By always making the single parameter to a the constructor a Variant it becomes possible to pass a wide range of objects to the constructor, including arrays and lists.  In a way this overcomes one of the weaknesses of LotusScript, the inability to overload a method.  The TypeName statement can be used identify the type of object being passed.

  Sub New(Source As Variant)

    Dim Doc As NotesDocument
    Select Case TypeName(Source)
      Case "NOTESDOCUMENTCOLLECTION"
        Set iDocuments = Source
      Case "NOTESDATABASE"

        Set iDocuments = Source.GetProfileDocCollection("passingkeythatdoesnotalreadyexist" )
      Case "NOTESVIEW"

        Set iDocuments = Source.Parent.GetProfileDocCollection("passingkeythatdoesnotalreadyexist" )

        Set Doc =  Source.GetFirstDocument
        While Not Doc Is Nothing
         Call iDocumentCollection.AddDocument(Doc)
         Set Doc = Source.GetNextDocument(Doc)
       Wend
      Case "NOTESDOCUMENT"

        Set iDocuments = Source.GetProfileDocCollection("passingkeythatdoesnotalreadyexist" )
        Call iDocuments.Add(Source)
      Case "OBJECT"

        Set iDocuments = Session.CurrentDatabase.GetProfileDocCollection("passingkeythatdoesnotalreadyexist" )
    End Select
  End Sub

 

Applying the above code....

Set Collection = New BleedyellowDocumentCollection(Nothing)            ' Create empty document collection in current database

Set Collection = New BleedyellowDocumentCollection(DB                    ' Create empty document collection in DB

Set Collection = New BleedyellowDocumentCollection(Doc)                    ' Create document collection with single document Doc

Set Collection = New BleedyellowDocumentCollection(DB.Document) ' Create document collection with all documents in database DB

Set Collection = New BleedyellowDocumentCollection(View)                  ' Create document collection with all documents in view View

 

5) Add New Properties/Methods
Build out your new class by adding additional properties/methods (Note: The OOP term Method = Sub/Function in LotusScript).  You can also rewrite the logic of the product class by adding code to the new extended class.

Example: A new Add method could be developed that provides a much wider range of options for what is added to the collection.  Passing a NotesView could add all document in that view to the collection.

Sub Add(Source As Variant)
  Select Case TypeName(Source)
    Case "NOTESVIEW"
.. code to add documents in view
  End Select
End Sub


6) Using The New Class
The properties/methods of the base class can be accessedd via the base object.  The new properties/ethods are accessed via the new class.

e.g.

Dim UIW As New NotesUIWorkspace
Dim Collection As BleedYellowDocumentCollection
Dim Favorites As NotesView

Set Collection = New BleedYellowDocumentCollection(UIW.CurrentView) ' Create collection with document selected in view
Call Collection.Document.Add(Doc) ' Adds document to collection using existing NotesDocumentCollection method
Call Collection.Add(Favourites) ' Adds all the document in the Favourites folder the the collection using the new enhanced Add method


.Domino Framework
The .Domino Framework provides a large number of examples of the above in practice.  A lot of the code is found in a LotusScript library base.Domino.Application.  This library provides 100s of new properties/methods for classes such as DominoDatabase, DominoView, DominoDocumentCollection, and DominoDocument.  You can use these classes directly or take parts of the code to build your own custom classes.  So don't just wait for IBM to take the lead, If you are not already doing so, start building your own custom classes to fill in the gaps needed by your applications.

No RatingsRatings 0

Domino.Reflection Namespace Extended

Peter Presnell |   | Tags:  oop inspector reflection .dominoframework | Comments (0)  |  Visits (478)

I have just finished expanding the Domino.Reflection namespace to allow the new Inspector tool to browse the contents of LotusScript libraries. 

Inspector will be able to display information about data documents, profile documents, design documents, and deletion stubs found in ANY database. Inspector will be able to provide a list of all (or selected) design documents found in a database (Domino Designer is not required).

As part of the display information for Design documents I have decided to provide information about any classes found in a selected LotusScript library.  Using the extended DominoScriptLibrary class (part of the Domino.Reflection namespace), I can now return a list of properties and methods for a nominated class.  I can also get the code used  for any one of the properties/methods.  Combining these features together Inspector becomes (amongst other things) a basic class browser for LotusScript libraries.

Both the extended Domino.Reflection namespace and the new Inspector tool will be released as part of the 0.5 beta of the .Domino Framework planned for the end of this week.

No RatingsRatings 0

Building flexiblility into class constructors

Peter Presnell |   | Tags:  lotusscript oop | Comments (6)  |  Visits (526)

One of the limitations in LotusScript for OOP is the lack of support for method overloading i.e. the ability to invoke a method passing a different number of parameters and/or a different combination of parameter types.....

This limitation can be negated in part by making parameters of type Variant.  parameters not needed can have a value of Nothing passed.  I have found this particularly useful in creating the class constructor.  Most applications have core objects that are stored in a NotesDocument and invariably accessed via a Form.  So many classes I create are extensions of the NotesDocument class.  The .Domino Framework provides a DominoDocument class that extends both the NotesDocument and NotesuIDocument classes for each core object.  The constructor for this class takes a single parameter (Source) of type variant.  This allows me to instantiate the class by passing a reference to (a) a background NotesDocument object, (b) a foreground NotesUIDocument object, (c) a string which could represent the DocumentUNID of the document or some other single key, or (d) an array which contains partial keys for the document.  The single constructor evaluates the type of parameter passed and processes each type differently achieving a similar result to other programming labhuages that allow multiple constructors.

Update: The example has been updated to include some of the great ideas posted as comments.  I still have just one parameter but that variable could contain an array or a list....

e.g.

Sub New(Source As Variant)

Select Case Typename(Source)
Case "NOTESDOCUMENT"
Set iDocument = Source
Case "NOTESUIDOCUMENT"
Set iUIDocument = Source
If Source.Document Is Nothing Then On Event PostOpen From Source Call OnPostOpen Else Set iDocument = Source.Document
Case "STRING"
Call GetByKey(Cstr(Source))

Case "STRING()"
Call GetByPartialKeys(Cstr(Source(0),Cstr(Source(1))

Case "VARIANT LIST"
Forall parameter in Source
Select Case Listtag(parameter)
Case "document"
Set iDocument = parameter
End Select

End Select

End Sub
No RatingsRatings 0

Customizing Templates

Peter Presnell |   | Tags:  .dominoframework lotusscript customization template oop | Comments (0)  |  Visits (516)
So this week I spent a lot of time trying to think of cool ways to make the .Domino Framework more easily customizable.  This following is the solution I have come up with and can apply to any template that uses OOP and want to make the code easily customized....

The .Domino Framework contains a LOT of classes.    Using one example, the Domino.Applications namespace contains classes for DomioSession, DominoDatabase, DominoDocument .... that extend the NotesSession, NotesDatabase, and NotesDocument ... classes.  I have added a lot of methods and properties that I have found to be useful, including a lot of ideas that came from other Notes developers.  But this is certainly not a complete list and other people may even want to change the definitions of some of the properties, methods, and events to improve or adapt the code for specific needs.
  1. I have copied all "My" code in a new LotusScript library called Base.Domino.Applications
  2. I have renamed all the classes to start with base.  e.g. baseDominoSession, baseDominoDatabase, baseDominoDocument
  3. Returning to the original Domino.Applications library, I have included Use "Base.Domino.Applications"
  4. I have then rewritten the class definitions to extend the base classes.  e.g. Class DominoSession as baseDominoSession
  5. And finally I have removed all the code from these class definitions except for an empty constructor.
  6. All the code in the .Dominio Framework continues to use the DominoSession, Dominodatabase, DominoDocument... classes as before so any customization added to the "Domino" classes will always become available.
Anyone adopting the .Domino Framework is now able to customize the classes with their own code without the need to modify any of the base code.  Customization can include adding new properties/methods/events as well as rewriting/overloading the existing properties/methods/events. 

The one thing a customizer needs to do is make sure that the Prohibit design refresh flag is set for the Domino.Applications library (I can probably set this as the default).  That way when a new version of the .Domino Framework is released it will update the Base.Domino.Applications library (and hence the base classes) without making any changes to the existing customization.

This technique could be applied to any template/code library.  Imagine if IBM were to apply this technique to their own templates such as the mail template.  We could customize the various classes developed by IBM without having to worry about how to merge the code again when a new release becomes available.  I could modify one of their methods in my ownh library and then their code would run my code...
No RatingsRatings 0

  • Previous
  • Next
Jump to page of 1
Skip to main content link. Accesskey S
IBM Lotus Connections Help Tools About