<?xml version="1.0"?>
<rss version="2.0">
<channel>
  <title>The Kitchen in the Zoo - gui tag</title>
  <link>http://blog.maxant.co.uk:80/pebble/tags/gui/</link>
  <description>&lt;small&gt;A blog where Ant writes about anything he finds interesting! &lt;a href=&#039;http://www.linkedin.com/in/maxant&#039;&gt;&lt;font color=&#039;white&#039;&gt;Who is Ant?&lt;/font&gt;&lt;/a&gt;      &lt;a href=&#039;/pebble/pages/copyright.html&#039;&gt;&lt;font color=&#039;white&#039;&gt;Copyright 2005-2012 Ant Kutschera&lt;/font&gt;&lt;/a&gt;&lt;/small&gt;</description>
  <language>en</language>
  <copyright>Ant Kutschera</copyright>
  <lastBuildDate>Thu, 10 May 2012 20:07:00 GMT</lastBuildDate>
  <generator>Pebble (http://pebble.sourceforge.net)</generator>
  <docs>http://backend.userland.com/rss</docs>
  
  
  <item>
    <title>Auto-update of Midlets</title>
    <link>http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html</link>
    
      
        <description>
          &lt;p&gt;Any professional application should be capable of updating itself over the internet. Even Midlets! The idea is fairly easy in that the Midlet needs to make a call to the server to check what version the latest software has, and compare that to the installed version. If there is a newer version available, then it needs to start the (mobile) device&#039;s browser and point it at the URL of the new JAD file. The device will take care of the download and installation after that. So, the following article shows you exactly how this can be implemented.&lt;br /&gt;
&lt;br /&gt;
First off, refer to the &lt;a href=&#034;/pebble/2010/02/21/1266791340000.html&#034;&gt;previous article&lt;/a&gt;, which described a framework for making server calls.&lt;br /&gt;
&lt;br /&gt;
The sequence diagram looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;img src=&#034;/pebble/images/autoUploadMidletsSequenceDiagram.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
&lt;br /&gt;
Based on the framework, the following JSP can be installed serverside, which reads the version number out of the JAD file:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
&amp;lt;%@page import=&amp;quot;java.io.FileInputStream&amp;quot;%&amp;gt;
&amp;lt;%@page import=&amp;quot;java.io.RandomAccessFile&amp;quot;%&amp;gt;
&amp;lt;%@page import=&amp;quot;java.io.File&amp;quot;%&amp;gt;
&amp;lt;%@page import=&amp;quot;java.util.List&amp;quot;%&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;%
RandomAccessFile raf = null;
try{
	String version = null;
	String path = request.getSession().getServletContext().getRealPath(&amp;quot;index.jsp&amp;quot;);
	File f = new File(path);
	f = f.getParentFile();
	f = new File(f, &amp;quot;jads/nameOfJad.jad&amp;quot;);
	raf = new RandomAccessFile(f, &amp;quot;r&amp;quot;);
	String curr = null;
	while((curr = raf.readLine()) != null){
		if(curr.startsWith(&amp;quot;MIDlet-Version:&amp;quot;)){
			version = curr.substring(16);
			break;
		}
	}
	%&amp;gt;OK
	&amp;lt;%=version%&amp;gt;|

	add other master data like the users details, their roles, etc. here...

	&amp;lt;%
}catch(Exception e){
	log.warn(&amp;quot;failed to read master data&amp;quot;, e);
	%&amp;gt;ERROR
	&amp;lt;%=e.getMessage() %&amp;gt;
	&amp;lt;%
}finally{
	if(raf != null) raf.close();
}
%&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;p&gt;This JSP is called when the Midlet starts, and effectively delivers &amp;quot;master data&amp;quot; to the device, such as the users roles, account details and importantly, the version number of the latest available JAD file on the server. Based on this version number, which is read as the MIDlet-Version property out of the JAD on the server, the client can decide if the currently installed version is up to date. The Midlet does this by calling the &lt;code&gt;getAppProperty(String)&lt;/code&gt; method, passing it the String &amp;quot;MIDlet-Version&amp;quot;, which reads the version of the local JAD, that was used to install the current version.&lt;br /&gt;
&lt;br /&gt;
Once the client has decided that there is a newer version available, it can ask the user if they wish to update by making an Alert the current screen. If the user chooses to install the update now, then all that is left is to open the devices browser to point at the new JAD which is online, and then close the application. Putting it together in a convenient method gives the following:&lt;/p&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
private void checkForUpdate(){
	final String currentVersion = getAppProperty(&amp;quot;MIDlet-Version&amp;quot;); //eg 1.0.62
	new MasterDataGetter(currentVersion, model, this) {
		public void onSuccess(Object md) {
			MasterData masterData = (MasterData) md;
			model.setMasterData(masterData);

			if(currentVersion != null &amp;amp;&amp;amp; masterData.getLastestVersion() != null){
				if(isUpdateAvailable(masterData.getLastestVersion(), currentVersion)){
					//does the user want to?
					
					Alert a = new Alert(
								&amp;quot;An update is available (version &amp;quot; + masterData.getLastestVersion() + &amp;quot;.\r\n&amp;quot; +
								&amp;quot;Would you like to download and install it now?&amp;quot;);
					a.setType(AlertType.CONFIRMATION);
					a.removeCommand(Alert.DISMISS_COMMAND);
					final Command no = new Command(&amp;quot;No&amp;quot;, Command.ITEM, 1);
					final Command yes = new Command(&amp;quot;Yes&amp;quot;, Command.ITEM, 2);
					a.addCommand(yes);
					a.addCommand(no);
					a.setCommandListener(new CommandListener() {
						public void commandAction(Command c, Displayable d) {
							if(c == yes){
								try {
									platformRequest(Constants.getBaseUrl() + &amp;quot;jads/nameOfJad.jad&amp;quot;);
									destroyApp(true); //coz we are performing an update!
								} catch (ConnectionNotFoundException e) {
									//tough titties :-( ie platformRequest couldnt be called
									e.printStackTrace();
									handleException(&amp;quot;Failed to open browser to get installation files.&amp;quot;, e, AlertType.ERROR);
								} catch (MIDletStateChangeException e) {
									handleException(&amp;quot;Failed to destroy midlet&amp;quot;, e, AlertType.ERROR);
								} finally {
									notifyDestroyed();
								}
							}else if(c == no){
								showCurrentView();
							}
						}
					});
					Display.getDisplay(Main.this).setCurrent(a, currentView);

				} //endif is update available?
			} //endif neither version is null

			//now we have already called maxant, and the user has confirmed that they are
			//happy to go online (eg BlackBerry shows them the URL of the first connection
			//attempt), we can continue to GA. we are trying to hide this fact from the user
			//as it may put of some users.
			gaUploader.track(&amp;quot;start&amp;quot;);

		}//end #onSuccess

		public void onError(int code, String result) {
			if(model.isShowDebugInfo()) sendDebugLog.callServer(&amp;quot;error with update check &amp;quot; + code + &amp;quot;: &amp;quot; + result);
			//tough titties, dont offer to upgrade
		}

	}.callServer();
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010 Dr Ant Kutschera &lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;title=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;title=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;title=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;title=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;title=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;title=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;t=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;title=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html&amp;amp;t=Auto-update+of+Midlets&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2010/03/18/1268939460000.html</guid>
    <pubDate>Thu, 18 Mar 2010 19:11:00 GMT</pubDate>
  </item>
  
  <item>
    <title>Choosing a Model/Event Pattern</title>
    <link>http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html</link>
    
      
        <description>
          &lt;p&gt;The following diagrams show different implementation patterns of models and corresponding events, as typically used in the UI. Depending upon your needs, you can use the following tables to decide which pattern to implement. &lt;br /&gt;
&lt;br /&gt;
The patterns are split into model patterns and event patterns. Not all combinations of the patterns make sense, but patterns can be combined to fulfill your unique requirements. At the end I make some recommendations.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Model Pattern 1 - Automatic Event Firing&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#034;/pebble/images/modelEventStrategies/modelEventStrategies_modelPattern1.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
With the above pattern every change to the model results in an event being fired. Typically if the focus of a text field is lost, the model gets set (in Eclipse RCP perhaps using databinding). Any views that show this model attribute get notified and update themselves. Works well for cases where multiple views of the same model need to be continuously up to date. A big disadvantage is the number of events which get fired. You also need to watch out for cyclic dependencies whereby an event updates a second view, and that update fires another event which updates the first. UI performance can suffer with this pattern, because its granularity is simply too fine.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Model Pattern 2 - Manual Event Firing&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#034;/pebble/images/modelEventStrategies/modelEventStrategies_modelPattern2.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
This pattern lets the caller (typically the controller) fire an event after it has finished updating all parts of the model. Typically the controller performs any validation of multiple fields, may call the server and when everything is good, updates the UI&#039;s model. An example might be when an input dialog is closed and the data from that dialog&#039;s model needs to be incorporated in one single sweep into the main model. Advantages of this pattern are that events are only fired when all data has been validated together and you can be sure all data is coherent. The disadvantage with this pattern is that you rely on the caller to fire the event (the developer must remember to write that code!). What typically happens is that the same fire method gets called frequently. When implementing this pattern, you can choose if you supply one &amp;quot;fire&amp;quot; method which takes an enumerator, or whether you supply many methods, one for each relevant level of granularity.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Model Pattern 3 - Coarse Grained Model Methods&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#034;/pebble/images/modelEventStrategies/modelEventStrategies_modelPattern3.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
In order to reduce the number of events which are fired by Model Pattern 1, and reduce the problems of the caller having to fire events in Model Pattern 2, the above pattern provides coarse grained methods for updating multiple model parts together, in one &amp;quot;transaction&amp;quot;. The model implementation sets all the relevant parts based on the given parameters, and only at the end fires a relevant or several relevant events (in the above example, perhaps an event that some elephants were added and an event that some hippos were added).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Model Pattern 4 - Model with Suspendable Event Firing&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#034;/pebble/images/modelEventStrategies/modelEventStrategies_modelPattern4.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
A different solution to the disadvantages of Model Patterns 1 &amp;amp; 2, is to allow the caller to suspend event firing temporarily. While this approach is interesting, its comes with dangers like losing events from concurrent model updates. For example, a user event causes a call to update a large amount of attributes. In the mean time, another user event causes a single attribute to be updated, but because event firing has been suspended as part of the first update, its event is never fired. The solution is that when resuming event firing, a generic event is fired, to tell all listeners that the entire model may have changed. While this pattern builds upon Model Patterns 1 &amp;amp; 2, it still suffers like Model Pattern 2, by relying on the caller to make a call to resume event firing at the end. Again, a controller can encapsulate these extra calls for resuming, so that they are at least all located in a logical place.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Event Pattern 1 - Listener is told about granularity of event&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#034;/pebble/images/modelEventStrategies/modelEventStrategies_eventPattern1.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
In the above pattern, the listener is given a hint about what has changed. The listener can then base its decision on what to refresh upon this context. Better implementations don&#039;t use Strings, rather use an object hierarchy, firstly so that the pattern becomes strongly typed, and secondly so that tests of &amp;quot;implements&amp;quot; can be carried out, so that the listeners implementation does not get filled full of &amp;quot;if&amp;quot; or &amp;quot;switch&amp;quot; statements. For example, a specific listener may be interested when any animal in the zoo is modified, whereby a different listener may be interested in specific events like elephants and hippos changing. With this pattern, the listener must have a reference to the model in order to get the refreshed data and as such may not know that only one item in a list has been changed, causing it to refresh more of the view than necessary, as might be the case with tables where only one row has changed.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Event Pattern 2 - Listener provides context specific methods&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#034;/pebble/images/modelEventStrategies/modelEventStrategies_eventPattern2.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
In this pattern, the listener is informed about fine or coarse grained events, but does not get told about say individual rows in a table which have changed, forcing the whole table to be updated. This pattern is also less flexible than Event Pattern 1, because the implementation cannot test for an events superclass. Effectively this pattern is like Event Pattern 1 when using Strings, only it is strongly typed. As such, Event Pattern 1 is more flexible.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Event Pattern 3 - Listener receives model parts - fine grained&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#034;/pebble/images/modelEventStrategies/modelEventStrategies_eventPattern3.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
With this pattern the listener is told exactly what has changed, which has the advantage that the listener only needs to update exactly what has changed, for example a single row in a table. This pattern implicitly relies on Model Pattern 1, and is hence fine grained.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Event Pattern 4 - Listener receives multiple model parts - coarse grained&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#034;/pebble/images/modelEventStrategies/modelEventStrategies_eventPattern4.jpg&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
This pattern extends Event Pattern 3 by becoming capable of handling multiple updates because the listener is given a number of changed items at the same time. It might be associated with Model Pattern 2, 3 or 4, where multiple updates are performed before the event is fired, however as shown, it is constrained because all changes need to be of the same type.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;In my experience Model Pattern 3 and Event Pattern 1 are the best combination because they are the most flexible and reduce the number of events being fired which improves performance and usability. In cases where it is important for the view to only update certain rows of a table, the listener methods can be changed to also pass the changed objects to the listener, however this is only required in cases where UI&amp;nbsp;performance would otherwise be really poor.&lt;/p&gt;
&lt;p&gt;I would like the thank Mike Moor and Vera Fischer of the SBB for their inputs. &lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010 Dr Ant Kutschera&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;title=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;title=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;title=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;title=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;title=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;title=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;t=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;title=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html&amp;amp;t=Choosing+a+Model%2FEvent+Pattern&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2010/03/17/1268863200000.html</guid>
    <pubDate>Wed, 17 Mar 2010 22:00:00 GMT</pubDate>
  </item>
  
  <item>
    <title>GUI Performance Enhancement Strategies</title>
    <link>http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html</link>
    
      
        <description>
          &lt;p&gt;Graphical User Interfaces (GUIs) tend to be event driven. A user performs an action and the GUI sends that event to any interested components through a &lt;a href=&#034;2008/01/02/1199309880000.html&#034;&gt;Model-View-Controller&lt;/a&gt; mechanism. When the events being sent represent fine grained actions (for example a single field on a form changed, as opposed to coarse grained events like the form being submitted), the performance of the GUI can become an issue. Other examples of when performance of the GUI might become an issue are:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;when the model in the GUI is large,&lt;/li&gt;
    &lt;li&gt;when the GUI needs to process the data a lot in preparation for displaying it (either client or server side),&lt;/li&gt;
    &lt;li&gt;when the GUI is poorly implemented and duplicate listeners exist meaning that components are refreshed multiple times, unnecessarily.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;
The following strategy has been used to help improve GUI performance. This list is ordered with the easiest / most important tasks (least effort, best improvement) at the top:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;ensure a clean MVC implementation, without duplicate listeners,&lt;/li&gt;
    &lt;li&gt;add data caches,&lt;/li&gt;
    &lt;li&gt;optimise caches (e.g. they hold more than one object graph),&lt;/li&gt;
    &lt;li&gt;optimise refreshing of non-active elements.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;br /&gt;
&lt;strong&gt;&lt;u&gt;1) Clean MVC Implementation&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;
First of all, read the &lt;a href=&#034;2008/01/02/1199309880000.html&#034;&gt;MVC article&lt;/a&gt; on this blog. Then, using a profiler or debugger follow your controller as it fires model change events. Are any model listeners fired more than once for any reason? If they are, it is less than optimal and you need to first look for mistakes in the programming logic. If there really is a good reason that the event is fired for a component multiple times, look at getting the component to cache events and process them all on the last event. This can get messy however, and you need to ask yourself if the event model is coarse grained enough. Why does a component get multiple events in the first place?&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;u&gt;2) Add Data Caches&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;
In a good implementation you should be using design patterns such as the Business Delegate. This pattern hides the details of where data is retrieved from. It might come from a service or maybe directly from a database. Its client doesn&#039;t actually care. So this is the ideal place to start caching your model data, if not directly within the model (if you have one central model for your entire GUI). Either way, the aim of a cache is to only retrieve data from a slow method call if it&#039;s really required. For example, the user saves a sales order. In order to get updated stock levels, you probably need to call a service which will take some time. In this case, as soon as the sales order is saved, the stock cache becomes dirty, meaning that it needs to be updated before it can be used safely. On the other hand, if a user adds a customer to the system, this has no effect on the stock levels, so there is no need to reload the stock cache. It is not marked as dirty.&lt;br /&gt;
&lt;br /&gt;
Since this cache is reliant on listening to the model to determine if it is dirty or not, it needs to be client side. Whether it is stored in the business delegate or seperately is the designers choice.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;u&gt;3) Cache Optimisation&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;
Taking the above example of stock and sales, consider the following example. A user wants to add an item to a sales order. To do so, they need a list of products to choose from. That list of products comes from a products cache, however it might be dependent on the stock list, if they can only sell things which are in stock. As soon as they add the item to the sales order, the stock cache becomes dirty, since stock has been removed.&lt;br /&gt;
&lt;br /&gt;
A cache of the stock in a warehouse might hold a lot of details about the stock. For example, each stock item might have a reference to its supplier which might be a fully loaded supplier object containing all the details of that supplier. It would probably be better to look up the supplier in a supplier cache, but that in turn is poor for performance. So reloading this stock cache and all its deep object graph (all the supplier info) might take a long time.&lt;br /&gt;
&lt;br /&gt;
As soon as the user wants to sell something else from stock, the system needs that stock cache to be reloaded, because it is now dirty from the previous sale. But above it was just stated that that will take a long time. So let&#039;s think about the data that is actually required. Do you need supplier information for selling stuff? Unlikely. So why load it all? A better option is to hold two caches. The first is the original with references to supplier information. The second is a light weight cache with a shallow object graph, meaning you simply have a list of stock items with as few details as required during sales. To load the list of products that are in stock is now much quicker. The trade off is that you hold the list of stock twice, but at least the second list is light weight.  &lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;u&gt;4) Optimise Refreshing of Non-active Elements&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;
Have a look at the GUI below:&lt;br /&gt;
&lt;br /&gt;
&lt;img alt=&#034;&#034; src=&#034;images/gui_performance.jpg&#034; /&gt;&lt;br /&gt;
&lt;br /&gt;
Each tab is a different view of the overall model. Generally speaking, they all have a table which shows data in rows and a form which drills down to show the details of the selected row. But only the current tab needs to be refreshed if the relevant model change event comes along. Since all tabs inherit from a common class, that common class was changed to decide for itself if it would refresh straight away, or store the event and refresh later, when the view becomes active.&lt;br /&gt;
&lt;br /&gt;
In fact, as well as remembering what to refresh and deferring until later, it also optimises what needs refreshing. First of all, it wouldn&#039;t refresh the table twice! Second, there are several levels of refreshing. First, the table can be refreshed without reloading data from the cache (if for example the objects in its model contain the changes that need showing, which is what happens when the user updates data in the form). Second, the table can be refreshed after reloading its model from the cache. Finally, as well as reloading the table, it can change the selected row and update the form. If an event for this final refresh level comes in, while the view is inactive, there is no need to complete refreshes for the other two levels, since this final level already incorporates the other two. Same goes for the second level, in that it already includes the first level. So the code works out what really needs refreshing and defers until the point where you really need that refresh, namely when the view is activated. The trade off is that activating a view (by selecting its tab) is slower, but overall far fewer cache reloads and table/form refreshes take place.&lt;br /&gt;
&lt;br /&gt;
This optimisation strategy was used on &lt;a href=&#034;http://bookstore.maxant.co.uk&#034;&gt;maxant BookStore&lt;/a&gt;. The results were a fully usable GUI that stores many thousand rows of data in memory. The GUI is quick and satisfying to use. Before the optimisations, the GUI was very painful to use indeed, and would easily have put off potential customers from buying the product.&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;title=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;title=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;title=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;title=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;title=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;title=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;t=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;title=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html&amp;amp;t=GUI+Performance+Enhancement+Strategies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2008/04/20/1208683320000.html</guid>
    <pubDate>Sun, 20 Apr 2008 09:22:00 GMT</pubDate>
  </item>
  
  <item>
    <title>Object Orientation (OO) in GUIs</title>
    <link>http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html</link>
    
      
        <description>
          &lt;p&gt;I was taught (hopefully rightly) that a class contains data relevant to it and methods which act on that data. For example, a class representing a Monkey might have attributes like date of birth, male/female, number of children, and a reference to the zoo where it lives. Methods might be getYearsOld() to work out how many days old it is, haveSex(List&amp;lt;Monkey&amp;gt; partners) [aren&#039;t chimps well known for group sex?], addChild(Monkey kid), setZoo(Zoo newHome).&lt;br /&gt;
&lt;br /&gt;
Equally a complex graphical user interface component like a tree or a table might contain a matrix or hierarchy of cells and methods for setting the cells attributes (data, size, borders, rendering information, etc). It would typically have renderers for painting the cells as well as perhaps editors for editing the data in the cells. In fact, Swing has a rather nice implementation of Tables, Trees and even Tree-Tables. Eclipse JFace is fast catching up.&lt;br /&gt;
&lt;br /&gt;
So if you do find yourself building something like this, say in Java Script, look at the nearest thing you can find that already exists, analyse how object oriented it is, then implement something similar (even sub-class it).&lt;br /&gt;
&lt;br /&gt;
What you want to avoid is creating a load of helper methods which just build the GUI in a totally pre-object-oriented manner - Builder Classes as I call them. &lt;br /&gt;
&lt;br /&gt;
I have seen this done several times by programmers that learned to program in the object oriented age. It might be expected from an older programmer who learned to program pre-object orientation, or one that has never used an object oriented language. But its odd when its done by programmers selling themselves as knowing object orientation. Very odd indeed.&lt;br /&gt;
&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;title=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;title=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;title=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;title=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;title=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;title=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;t=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;title=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html&amp;amp;t=Object+Orientation+%28OO%29+in+GUIs&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2008/01/08/1199828640000.html</guid>
    <pubDate>Tue, 08 Jan 2008 21:44:00 GMT</pubDate>
  </item>
  
  <item>
    <title>SAP, SOA and a GUI</title>
    <link>http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html</link>
    
      
        <description>
          &lt;p&gt;When I first learned about SAP, I was led to believe it was insular. Sharing its data or uploading data to it was possible, but expensive and discouraged. If you have SAP, stick with it.&lt;br /&gt;
&lt;br /&gt;
Then came XI, the SAP eXchange Infrastructure which is the SAP offering for Enterprise Application Integration (EAI), or now rather Enterprise Service Bus (ESB). With it, you can build marvellous Service Oriented Architectures (SOA).&lt;br /&gt;
&lt;br /&gt;
So what?&lt;br /&gt;
&lt;br /&gt;
Well, my experience of XI is that its used as a replacement for IDOCs, BAPI, EDI and the like. Instead of those hard to use protocols, simply subscribe to a published web service.&lt;br /&gt;
&lt;br /&gt;
But hang on... If SOA is in use, couldn&#039;t we go a step further? SAP isn&#039;t very good at really rich clients (GUIs), and chances are, to develop one would cost a huge amount.&lt;br /&gt;
&lt;br /&gt;
So what about the idea of building your business logic on top of existing SAP functionality, so that you extend it to suit your business processes, and then build that rich client on top of the SOA that SAP can offer from your business logic?&lt;br /&gt;
&lt;br /&gt;
An example would be the project I&#039;m working on at the moment. We need to build a planning tool for use in Service Stations for trains. Service stations consist of a large number of platforms where trains can be serviced. Some types of service can only be done on some platforms (axle change for example). As well as planning which trains go where and when and for how long, teams need to be allocated to each service, and only some teams can perform some types of service. &lt;br /&gt;
&lt;br /&gt;
Now service management (that is what work needs to be carried out on what trains) is already in SAP. It provides a report for each incoming train, and the teams can update the reports with new found problems and the work that they completed.&lt;br /&gt;
&lt;br /&gt;
Personnel management (who works in which team, and which team works on what platforms, etc) is not currently in SAP at this client, but I am sure with its HR functionality, it wouldn&#039;t be hard to get that working.&lt;br /&gt;
&lt;br /&gt;
The physical planning of locations and time slots could be hard to implement in SAP if it doesn&#039;t already exist, but that could be where you develop your business logic.&lt;br /&gt;
&lt;br /&gt;
Finally we need the GUI. Think along the lines of Microsoft Project, and Gantt charts showing task planning as well as resource allocation. Optimisation of resources as well as track space is one goal here.&lt;br /&gt;
&lt;br /&gt;
That type of GUI with drag and drop functionality, slick GUIs, realtime updating of the plans, etc. is apparently not really possible with SAP, and if it is, is very expensive because you need to find someone who can do it.&lt;br /&gt;
&lt;br /&gt;
But with Java technologies like Swing or Eclipse Rich Client Platform (RCP), building a GUI like that is easy and fairly cheap (Java developer rates are currently around 30% less than SAP developers). So instead of building the back end in Java EE and calling an application server, just call SAP XI instead...&lt;br /&gt;
&lt;br /&gt;
Although its technically very feasible, suggesting this type of integration still brings strange looks. While XI is still relatively new, people have not got used to thinking about integrating like this. Integrating two stand alone systems is fine. Using XI to provide an ESB or to connect to one is fine. But Building a single system out of an SAP backend and a Web Service capable front end is somewhere the people I work with don&#039;t want to go.&lt;br /&gt;
&lt;br /&gt;
If you have other experiences, please mail me at &lt;a href=&#034;mailto:sap_soa_gui@maxant.co.uk&#034;&gt;sap_soa_gui@maxant.co.uk&lt;/a&gt;.&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;title=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;title=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;title=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;title=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;title=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;title=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;t=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;title=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html&amp;amp;t=SAP%2C+SOA+and+a+GUI&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2006/10/17/1161079200000.html</guid>
    <pubDate>Tue, 17 Oct 2006 10:00:00 GMT</pubDate>
  </item>
  
  </channel>
</rss>

