Blogs

  • Browse Blogs
  • My Blog
  • My Updates

Tags Help

  • View as cloud  | list

Similar Blogs

photo

Patrick Picar...

62 Entries |  Patrick Picard
Updated 
RatingsRatings 2     CommentsComments 112
photo

Lotus Nut

111 Entries |  Chris Whisonant
Updated 
RatingsRatings 23     CommentsComments 157
photo

Uh Clem's Adm...

54 Entries |  Chris Mobley
Updated 
RatingsRatings 8     CommentsComments 55
photo

Life is too s...

33 Entries |  Barbara Skedel
Updated 
RatingsRatings 3     CommentsComments 56
photo

Yellow is the...

72 Entries |  Tim Tripcony
Updated 
RatingsRatings 2     CommentsComments 34

Jan Schulz

Blog Authors:  Jan Schulz  

All entries tagged with oop

The Adapter Pattern or working around that LS has ...

Jan Schulz  |     |  Tags:  oop lotusscript  |  Comments (0)
Peter Pressnel wrote a post about class casting and polymorphism in LotusScript. Unfortunatelly, in LS you can only extend one class, not implement Interfaces (like in every other OO language). Interfaces lets you add functionality to a given class by implementing the Interface: a Person will also by "Compareable" by implementing that interface. Now every method which needs a "Compareable" argument can work with Persons.

This missing feature in LS basicly means that you have to build this functionality anew every time you need it: you need a person.compareToAnotherPerson(aPerson as Person) and also your sorted list (or whatever needs something compared) needs to know about that method. This means a lot of unnecessary programming and also it binds your code together and you will very soon get either a very big LS file or the famous "Illegal circular use" error. Not nice!

But we have help from the Adapter Pattern. Instead of adding the functionality by implementing an interface we ask for an adapter of the object which implements this interface [1].

The adapater pattern is usually also implemented via an interface: IAdaptable.getAdapter(classname) which either returns an object of that classname or nothing. As there is no Interfaces in LS this method is implemented in a basic class from which every other of my custume classes is derived: BasicObject. This class also implements "toString() (usefull as a message to logError()...) and such basic things.

The API contract for that method is very easy: either return an object of the specified class, which represents the original object or nothing. Classcasting an object now becomes:
dim managerĀ  as Manager
set manager = person.getAdapter("MANAGER")
if manager is nothing then Error 1000, "Person is not a Manager!"
[...]
instead of
dim manager as Manager
if not (person isa ucase("Manager")) then error 1000, "Person is a not a manager!"
set manager = person
[...]

So the insert method of a sorted list, which expects a "Compareable" object (or nothing), would be something like this: list.insert(me.getAdapter("COMPAREABLE")).

This is the BaseObject.getAdapter implementation.
Class BaseObject
' [ public function toString() as String ... ]

'/**

' * Returns an Adapter of the current Object of the aked-for type or nothing
' * The basic implementation returns this object if the caller asked for the class
' * or a subclass of the class of the current object
' * Should be overwritten to do something more usefull!
' * @autor Jan Schulz
' */

Public Function getAdapter(nameOfObject As String) As BaseObject
If Ucase(nameOfObject) = Typename(Me) Then
Set getAdapter = Me
End If
If Me Isa Ucase(nameOfObject) Then
Set getAdapter = Me
End If
End Function


End Class
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.

An addition would be the implementation of an AdapterManager (see the article on eclipse.org): This would even solve the problem that you need to know the adapter class in the "adaptable" object (-> problems with "Illegal circular use"...). This would need a small AdapterFactory with one methods: getAdapter(object as BaseObject, classname as String). This factory would be implemented for each used combination and then an instance of such an object added to the AdapaterManager. Now you can query the AdapaterManager for an Adapater of your object: getAdapterManager().getAdapter(object, "SomeClassName"). In this method you would ask each adapterFactory for this combination and return if you get an object back (or nothing if no factory can return such an object). Now the object wouldn't need to know that it is adaptable to a "SomeClassName".

[1] This pattern is usually used in other OO languages to keep the API of an class small and clean: if you need your person compareable, the methods of the "Compareable" Interface would be part of the API contract for the "Person" class. This is usually not desireably, especially if you add serveral interfaces.

Fun with ... garbage collection

Jan Schulz  |     |  Tags:  oop  |  Comments (0)
Todays fun: my logger (basicly an AgentLog, but with an underlying NotesDocument) opened a second doc where it shouldn't and worse didn't save the first document with the proper logging output. Turned out, that the last logAction call in the logger.delete sub (called by the garbage collector) found that the underlying logdoc was nothing (and so not saved until I turned on flushAlways) and so created a new one with only the "new log opend" and "log closed" message in it. Fun if you expect half a page of debugging output for an webagent (which you need because the agent is not working :-/ ) and only get "Log opened and closed"...

The fix was to cache the parent Database of the Logdocument in the Logger object.

This Database was actually cached (Dim logDB...) in the OpenLogFunction Declaration section (the Logger is an extention), but it seems that this script lib was garbage collected before calling delete on my object and as the DB got collected, so gets every object which came from that DB. By-by logdoc...

It seems that something changed between last years domino (7.0.x or 8.0.1, not sure which I tested on) and 8.0.2 in the garbage collection routine, as the same logger setup worked some month ago without this problems. Or I garabage collection is influenced how many classes/ScriptLibs you use in the your agent...

So, todays lesson learned: Do not cache objects in other scriptlibs Declaration section if you use that object in delete... Fortunately this is my only class with a deconstructor :-)

testable code = better code?

Jan Schulz  |     |  Tags:  design unittest pattern oop  |  Comments (0)
After my entry about event delegation, I went out and refreshed my memory about Design Pattern (The GOF book was the first - and up to now my only - book about programming. Hey, It's just a hobby for me :-). I also found the Google Testing Blog. Especially one of the entries was very interesting: writing testable code. Here are my Top7 from that entry:
  1. Don't mix object graph construction with application logic
  2. Ask for things, Don't look for things (aka Dependency Injection / Law of Demeter)
  3. Don't do work in constructor
  4. Favor composition over inheritance
  5. Favor polymorphism over conditionals
  6. Don't mix Service Objects with Value Objects
  7. Mixing of Concerns
So even if I don't plan on writing unittests (lsUnit and lsMock anyone?) I found the recomendations quite usefull and will try to follow them in my programming.

Skip to main content link. Accesskey S
IBM Lotus Connections Help Tools About

Tags

A tag is a keyword that is used to categorize an entry. To view the entries with a particular tag, click a tag name or enter a tag in the box.
The tag cloud indicates the frequency of tag use. Popular tags appear darkest. The slider control adjusts how many tags are displayed in the tag cloud.