<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lotushints &#187; performance</title>
	<atom:link href="http://www.lotushints.com/tag/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lotushints.com</link>
	<description>Lotus Notes tips &#38; tricks you always hoped you will not need</description>
	<lastBuildDate>Thu, 29 Dec 2011 09:47:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Design patterns &#8211; Part 11: Bridge pattern</title>
		<link>http://www.lotushints.com/2009/06/design-patterns-part-11-bridge-pattern/</link>
		<comments>http://www.lotushints.com/2009/06/design-patterns-part-11-bridge-pattern/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 07:00:38 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Best practices]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[bridge]]></category>
		<category><![CDATA[custom classes]]></category>
		<category><![CDATA[Lotus Notes]]></category>
		<category><![CDATA[object-oriented]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=361</guid>
		<description><![CDATA[In part 11 of Design pattern series we will go into creating and using the Bridge design pattern. It is moderately used and uses encapsulation, inheritance and aggregation to separate responsibilities into other classes. The Bridge pattern decouples an abstraction from its implementation so that the two can vary independently. Usage The pattern is most [...]]]></description>
			<content:encoded><![CDATA[<p>In part 11 of <a href="../category/design-patterns/">Design pattern series</a> we will go into creating and using the Bridge design pattern. It is moderately used and uses encapsulation, inheritance and aggregation to separate responsibilities into other classes.</p>
<blockquote><p><strong>The Bridge pattern</strong> decouples an abstraction from its implementation so that the two can vary independently.</p></blockquote>
<p><span id="more-361"></span></p>
<p><strong>Usage</strong></p>
<p>The pattern is most useful, when both classes (implementation and abstraction) are assigned to different task handling. In our example, we will look at how to separate data and actions to build a list of products and navigate it.</p>
<p><strong>Data representation class</strong></p>
<p>This is an abstract class with only navigational methods specified. Data representation class must implement navigational logic in its methods and thus assures that no other class will change or handle any properties without data representation class knowledge.</p>
<p>Also, for needs of our example, we will also define a type that will contain product id, name and price.</p>
<pre>Type TBridgeData
   strId As String
   strName As String
   dPrice As Double
End Type

Class CBridgeDataObject
   Sub NextRecord ()
   End Sub

   Sub PrevRecord ()
   End Sub

   Sub AddRecord (strId As String, strName As String,_
   dPrice As Double)
   End Sub

   Sub RemoveRecord (strId As String )
   End Sub

   Sub ShowRecord ()
   End Sub

   Function ShowAllRecords () As String
   End Function
End Class</pre>
<p><strong>Product data class</strong></p>
<p>Class itself inherits from Data representation abstract class. Also, it contains all navigational logic as well as data handling.</p>
<p>Beware that for this example, I did not actually load the data from the database. Instead I created five (5) products in the class construct. In real life, you should have read the data from your database!</p>
<pre>Class CBridgeProductData As CBridgeDataObject
   Private m_nCurrent As Integer
   Private m_AProducts () As TBridgeData

   Sub New ()
      m_ncurrent = 0

      Redim m_AProducts(4)

      m_AProducts(0).strId = "PR-0001"
      m_AProducts(0).strName = "Product 1"
      m_AProducts(0).dPrice = 100.00

      m_AProducts(1).strId = "PR-0002"
      m_AProducts(1).strName = "Product 2"
      m_AProducts(1).dPrice = 1000.00

      m_AProducts(2).strId = "PR-0003"
      m_AProducts(2).strName = "Product 3"
      m_AProducts(2).dPrice = 150.00

      m_AProducts(3).strId = "PR-0004"
      m_AProducts(3).strName = "Product 4"
      m_AProducts(3).dPrice = 400.00

      m_AProducts(4).strId = "PR-0005"
      m_AProducts(4).strName = "Product 5"
      m_AProducts(4).dPrice = 330.00
   End Sub

   Sub NextRecord ()
      If (m_nCurrent < Ubound (m_AProducts)) Then
         m_nCurrent = m_nCurrent + 1
      End If
   End Sub

   Sub PrevRecord ()
      If (m_nCurrent > 0) Then
         m_nCurrent = m_nCurrent - 1
      End If
   End Sub

   Sub AddRecord (strId As String, strName As String,_
   dPrice As Double)
      Dim n As Integer

      n = Ubound (m_AProducts) + 1
      Redim Preserve m_AProducts (n)

      m_AProducts(n).strId = strId
      m_AProducts(n).strName = strName
      m_AProducts(n).dPrice = dPrice
   End Sub

   Sub RemoveRecord (strId As String)
      Dim n As Integer
      Dim m As Integer
      Dim nCount As Integer
      Dim nIndex As Integer

      m = 0
      nIndex = -1
      nCount = Ubound (m_AProducts)
      For n = 0 To nCount
         If (m_AProducts (n).strId <> strId) Then
            m_AProducts (m).strId = m_AProducts (n).strId
            m_AProducts (m).strName = m_AProducts (n).strName
            m_AProducts (m).dPrice = m_AProducts (n).dPrice
            m = m + 1
         Else
            nIndex = n
         End If
      Next

      Redim Preserve m_AProducts (nCount - 1)
      If (m_nCurrent > n) Then Call Me.PrevRecord ()
   End Sub

   Sub ShowRecord ()
      Dim strDisplay As String

      strDisplay = m_AProducts (m_nCurrent).strId &#038; { } &#038;_
      m_AProducts (m_nCurrent).strName &#038; { €} &#038;_
      m_AProducts (m_nCurrent).dPrice

      Messagebox strDisplay
   End Sub

   Function ShowAllRecords() As String
      Dim n As Integer
      Dim strDisplay As String

      strDisplay = ""
      For n = 0 To Ubound (m_AProducts)
         strDisplay = strDisplay &#038; Chr(13) &#038;_
         m_AProducts (n).strId &#038; { } &#038;_
         m_AProducts (n).strName &#038; { €} &#038;_
         m_AProducts (n).dPrice
      Next

      ShowAllRecords = strDisplay
   End Function
End Class</pre>
<p><strong>Product base class</strong></p>
<p>Now, that we have our data classes created, we need to build an abstraction class that will call actual navigation and display the list contents or item if necessary. As we might have multiple classes that should have same functionality, it is a must to create a base class first. This class will encapsulate Data representation abstract class.</p>
<pre>Class CBridgeProductBase
   Private m_DataObj As CBridgeDataObject
   Private m_strGroup As String

   Public Property Get Data
      Set Data = m_DataObj
   End Property

   Public Property Set Data
      Set m_DataObj = Data
   End Property

   Sub New (strGroup As String)
      m_strGroup = strGroup
   End Sub

   Sub Next ()
      Call m_DataObj.NextRecord ()
   End Sub

   Sub Prev ()
      Call m_DataObj.PrevRecord ()
   End Sub

   Sub Add (strId As String, strName As String, dPrice As Double)
      Call m_DataObj.AddRecord (strId, strName, dPrice)
   End Sub

   Sub Remove (strId As String)
      Call m_DataObj.RemoveRecord (strId)
   End Sub

   Sub Show ()
      Call m_DataObj.ShowRecord()
   End Sub

   Sub ShowAll ()
      Messagebox "Product group: " &#038; m_strGroup &#038; Chr (13) &#038;_
      m_DataObj.ShowAllRecords()
   End Sub
End Class</pre>
<p><strong>Concrete product class</strong></p>
<p>Concrete product class in our case, will only be used to alter presentation when ShowAll method is called. This is not a must.</p>
<pre>Class CBridgeProducts As CBridgeProductBase
   Sub New (strGroup As String)
   End Sub

   Sub ShowAll ()
      Messagebox "Displaying all products"
      Call CBridgeProductBase..ShowAll ()
   End Sub
End Class</pre>
<p><strong>Implementation</strong></p>
<p>For test purposes, I have created an agent that will:</p>
<ul>
<li>create product list</li>
<li>navigate forward and backward</li>
<li>add an item to the list</li>
<li>remove an item from the list</li>
<li>display single product or all products at any time,</li>
</ul>
<pre>Sub Initialize
   Dim products As CBridgeProducts
   Dim data As CBridgeProductData

   Set products = New CBridgeProducts ("product group 1")
   Set products.Data = New CBridgeProductData ()

   Call products.Show ()
   Call products.Next ()
   Call products.Show ()
   Call products.Prev ()
   Call products.Show ()
   Call products.ShowAll ()

   Call products.Add ("PR-0010", "New product", 1475.00)
   Call products.ShowAll ()
   Call products.Remove ("PR-0004")
   Call products.ShowAll ()
End Sub</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/06/design-patterns-part-11-bridge-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom user sidebars in web applications</title>
		<link>http://www.lotushints.com/2009/03/custom-user-sidebars-in-web-applications/</link>
		<comments>http://www.lotushints.com/2009/03/custom-user-sidebars-in-web-applications/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 07:00:20 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Best practices]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Lotus Notes]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[sidebars]]></category>
		<category><![CDATA[widgets]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=217</guid>
		<description><![CDATA[When I was assigned to rebuild company&#8217;s web site for the second time in 7 or 8 years, I have decided that it is probably the time to implement some modularity to the database. First in line were sidebars. Why? Well, despite &#8220;awesome&#8221; notes rich text to HTML rendering, web content was always contained in [...]]]></description>
			<content:encoded><![CDATA[<p>When I was assigned to rebuild <a href="http://www.nil.com">company&#8217;s web site</a> for the second time in 7 or 8 years, I have decided that it is probably the time to implement some modularity to the database. First in line were sidebars. Why? Well, despite &#8220;awesome&#8221; notes rich text to HTML rendering, web content was always contained in rich text field on a document, making it very customizable. On the other hand, sidebars were always subforms that were then connected to the document via a field (user specified subforms name). This was customizable, but regular content editors did not have designer access to the database. Thus, all modifications were relayed to us, developers. And there were quite a bit of modifications. I will pitch you my idea of solution to this problem.</p>
<p><span id="more-217"></span></p>
<p><strong>First step</strong></p>
<p>In order to ensure that content editors could alter sidebars by itself, they had to be moved from design elements to documents. All fine and well. However, if you look at typical sidebar, it is assembled from multiple parts called widgets. This widgets can be e.g. adverts, link boxes, etc. Now, I wanted to achieve as much modularity as I could and there used to be quite a lot of sidebars, containing same widgets (not all, but some). So why force a user to create same thing multiple times? Thus, widgets came to be.</p>
<p><strong>Widgets</strong></p>
<p>Widget (in this case) is the smallest single component that can be displayed in a sidebar. This can be a simple image, or a complex linkbox. Widget in Notes database is a simple document containing descriptive name, short web name and a rich text field. This rich text field contains content for the widget. It can be pure notes content or it can be HTML, that CSS will change into something &#8220;edible&#8221;.</p>
<p>Simple, and easy. However, what you now don&#8217;t want, is for users to link multiple widgets into web content documents. For one, content of sidebars is usually content related, meaning that web pages on same topic will probably have same widgets. And it has to be user friendly if you want users to use it. So, you can&#8217;t expect users to be comfortable with a feature that gives them more work if they decide to change something. And here is where Sidebar documents come in handy.</p>
<p><strong>Sidebar documents</strong></p>
<p>Sidebar document is nothing else but a container of widgets. What I did was enabled user to choose widgets he wants in this sidebar and he/she can sort them however he/she sees it fit. Sidebar document also contains a rich text field that will contain content of specified widgets rich text fields.</p>
<p><strong>Subform</strong></p>
<p>Now, that I had sidebar documents created, there is one thing I could not avoid. I had to create a subform, which I can include on each web form there is. This subform includes a rich text item and some HTML. On the plus side, you now only need one subform for all sidebars.</p>
<p><strong>What does this bring me?</strong></p>
<p>Well, besides the fact that users will now be able to do their own sidebars and have an easy way to change it&#8217;s contents (which means less work for you), this organization also gives you one powerful feature. All computed values and hide formulas that you will specify in widgets will be recalculated once they are displayed as part of the document and displayed on web. Thus, you can i.e. add a computed value that computes from a field on web page form and will compute correctly when displayed on web page.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/03/custom-user-sidebars-in-web-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problems with names.nsf refresh</title>
		<link>http://www.lotushints.com/2009/02/problems-with-namesnsf-refresh/</link>
		<comments>http://www.lotushints.com/2009/02/problems-with-namesnsf-refresh/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 08:00:49 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Lotus Domino]]></category>
		<category><![CDATA[database cache]]></category>
		<category><![CDATA[maintenance]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[user registration]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=174</guid>
		<description><![CDATA[At work, we experienced an interesting problem. We use public servers names.nsf to register new web users. However, a couple of months back, that suddenly stopped working. A person document was created, user was added to all required groups, but upon login, a user would obtain an error that he is not authorized to perform [...]]]></description>
			<content:encoded><![CDATA[<p>At work, we experienced an interesting problem. We use public servers names.nsf to register new web users. However, a couple of months back, that suddenly stopped working. A person document was created, user was added to all required groups, but upon login, a user would obtain an error that he is not authorized to perform that operation. The only thing that did the trick was to restart domino server.</p>
<p><span id="more-174"></span></p>
<p>We opened PMR and had a huge testing with IBM support team. However, it was not until LotusSphere, when one of our developers got a hint we never expected. In servers .ini file, there was a following line: <strong>NLCACHE_VERSION=4</strong>. Now, apparently setting NLCACHE_VERSION to value 4 causes some sort of a bug that stops cache from refreshing. However, if you delete parameter from .ini file, default value of 2 will be set for this parameter and everything will work just fine.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/02/problems-with-namesnsf-refresh/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Multilingual applications</title>
		<link>http://www.lotushints.com/2008/10/multilingual-applications/</link>
		<comments>http://www.lotushints.com/2008/10/multilingual-applications/#comments</comments>
		<pubDate>Mon, 06 Oct 2008 08:00:01 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Basic]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Lotus Notes]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[maintenance]]></category>
		<category><![CDATA[Multilingual]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[string repository]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=35</guid>
		<description><![CDATA[The other day, at work, there was a discussion about possible ways to create an application that could easily be ported into different languages. At the end, we got stuck on two possibilities. One was to simply make a new copy of the database and translate all design elements. The second one was to have [...]]]></description>
			<content:encoded><![CDATA[<p>The other day, at work, there was a discussion about possible ways to create an application that could easily be ported into different languages. At the end, we got stuck on two possibilities. One was to simply make a new copy of the database and translate all design elements. The second one was to have a string repository (either in the same database or in central place) and then load strings from there.<span id="more-35"></span></p>
<p><strong>Which to pick? </strong></p>
<p>With first possibility, we can say goodbye to design templates and every database in different language has to be maintained separately which can have major influence on maintenance costs. Also re-translating every prompt could end up in code corruption. On the other hand, as all strings are in design elements, there are no ill effects on application performance. Second possibility allows each and every database design to be updated from the same template, thus minimizing code corruption risks and maintenance costs. However, loading all those strings into design elements can present a significant performance issue.</p>
<p><strong>Test preparations</strong></p>
<p>I decided to create a test database that would shed some light upon performance issues with using string repository. I managed to randomly create 300 string resources via agent. Then, I created 3 forms containing 200 computed values each. Computed values would first obtain a random number from 1 to 300 and then load specific string. Why 3 forms? Two of them were using a bad programming habit I came across, using NoCache and ReCache parameters in all @DbLookups. The last one was the one with first @DbLookup re-caching data and all others reading from that cache.</p>
<p>I created another 3 forms, similar to these, but with a little twist. Those forms would read strings from different database.</p>
<p>Now all that I lacked was a sufficient timing system. That was a piece of cake. I created a timer class, which basically reads tick count using GetThreadInfo function on QueryOpen and PostOpen events on the form. Then it recalculates tick count difference into seconds and prints a result in the status bar of Notes client.</p>
<p><strong>The test</strong></p>
<p>I decided to perform a test on a working development server. Each form was used to create 10 documents twice. Once on a regular database and once on full text indexed one. Results of testing (in seconds; comma delimits decimal places) are displayed in images below.</p>
<div id="attachment_39" class="wp-caption alignnone" style="width: 501px"><a href="http://www.lotushints.com/wp-content/uploads/2008/10/ma_graph1.gif"><img class="size-full wp-image-39" title="ma_graph1" src="http://www.lotushints.com/wp-content/uploads/2008/10/ma_graph1.gif" alt="Results when string repository is in same database" width="491" height="302" /></a><p class="wp-caption-text">Results when string repository is in the same database</p></div>
<div id="attachment_40" class="wp-caption alignnone" style="width: 502px"><a href="http://www.lotushints.com/wp-content/uploads/2008/10/ma_graph2.gif"><img class="size-full wp-image-40" title="ma_graph2" src="http://www.lotushints.com/wp-content/uploads/2008/10/ma_graph2.gif" alt="Results when string repository is in same full-text indexed database" width="492" height="302" /></a><p class="wp-caption-text">Results when string repository is in same full-text indexed database</p></div>
<div id="attachment_41" class="wp-caption alignnone" style="width: 503px"><a href="http://www.lotushints.com/wp-content/uploads/2008/10/ma_graph3.gif"><img class="size-full wp-image-41" title="ma_graph3" src="http://www.lotushints.com/wp-content/uploads/2008/10/ma_graph3.gif" alt="Results when string repository is in different database" width="493" height="304" /></a><p class="wp-caption-text">Results when string repository is in different database</p></div>
<div id="attachment_38" class="wp-caption alignnone" style="width: 504px"><a href="http://www.lotushints.com/wp-content/uploads/2008/10/ma_graph4.gif"><img class="size-full wp-image-38" title="ma_graph4" src="http://www.lotushints.com/wp-content/uploads/2008/10/ma_graph4.gif" alt="Results when string repository is in different full-text indexed database" width="494" height="305" /></a><p class="wp-caption-text">Results when string repository is in different full-text indexed database</p></div>
<p><strong>The conclusion</strong></p>
<p>Results were a surprise. With forms opening with delays from 0.9 seconds up, there is no way of using string resources to load each and every string used in an application. Even if string repository is in the very same database and the database is full text indexed.</p>
<p>Obviously separate databases are no big solution as well, due to above mentioned reasons. Perhaps one could get away with having separate forms/sub-forms and only use string repository for prompts and in scripts and thus avoid possibility to corrupt application code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2008/10/multilingual-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

