RSS

Author Archives: znerd

About znerd

Christian, husband, father, IT specialist.

PhoneGap US Day 2013: Moving Forward

The first day of the PhoneGap Conference 2013 (Portland, OR) was really good. In this article I will briefly touch upon what was presented (follow the links to the presenters sites for more info on that) and then elaborate on how I see the technology can be taken to the next level, with a focus on enterprise contexts.

I am not going to say anything about the technology side of things, like OS support. There is a lot of discussion and interest in that area already.

PhoneGap Conference Day One

The first day (July 18, 2013) I attended presentations by:

  • Andy Trice, on basics, deployment to devices, debugging, etc.
  • Christophe Coenraets, on designing your PhoneGap application properly (with 10 11 architecture principles)
  • Holly Schinsky, on integration of your PhoneGap with native code for the device.

The day was both inspirational and informative, and it was good to meet a lot of people that are on the edge of technology.

Infancy Challenges

It seems Adobe PhoneGap (or it’s open source mother project Apache Cordova) is very much in it’s infancy. Integrating these technologies in enterprise projects without any on-site support is going to provide some challenges:

  1. Documentation: At first sight there is quite a lot of documentation. But for someone getting started, it is difficult to get a consistent answer on some initial questions, like:
    • What is the difference between Corova and PhoneGap? And what about Icenium?
    • How do I install this stuff on my machine? Should I download a ZIP, do ‘git clone’ or use ‘npm install’?
    • What kind of directory structure am I supposed to use?
    • How do I set myself up for debugging and profiling?
    • How do i add a plugin to my project, in a way that I support local compilation, PhoneGap Build and perhaps even Icenium?
  2. Inconsistencies in approaches: Even if you manage to get the information you need to get started, you will find there are different approaches for critical things like the directory structure:
    • If you use the (OS-specific) ‘create’ command, then you will get an OS-specific project. However, if you use the (improved, but less known) ‘cordova create’ command, then you get a completely different structure, with a project that supports multiple OSes from one directory hierarchy. Potentially there is also a ‘phonegap create’ command which might work in a similar way.
    • The ‘cordova emulate’ command runs your application in an emulator, but the ‘phonegap’ command does not have an explicit command for that, but you can run ‘phonegap run’, which will start the emulator only if there is no connected device available.
  3. Separation of concerns: In enterprise projects, it is common practice is to store the team’s files in a version control system such as Subversion or Git, and to store only the files in there that the team has authored, not the generated files.
    However, with Cordova/PhoneGap you get a whole hierarchy of generated files. And it seems that you cannot avoid editing files in that hierarchy or adding new ones, for things like registering custom plugins, adding custom splash screens and icons, etc.
  4. Integration with enterprise tools: As it currently stands, integration with common enterprise tools like e.g. Maven and Jenkins seems possible, but appears to require quite a lot of manual labor. There seem to be no Maven plugins available on the Central Repository and there might be some manual steps involved in building iOS apps.

Potential for Efficiency Improvements

On top of these challenges, I see a lot of potential for making people more efficient in creating PhoneGap applications.

A good first step was that all three presenters shared some example projects with useful (working!) code, all on GitHub:

Again, that is a good start, that can be improved upon by:

  • having official examples with a consistent approach,
  • make these examples more prominent,
  • tackle a number of things that most people will want to address in their projects anyway, like single page applications, page animations, addressing the click delay on touch devices, theming, etc.

Moving It Forward

Combining all the above, here is a non-exhaustive list of things that could be done to move Cordova/PhoneGap forward:

  1. Have a single and prominent set of interconnected tutorials on the site that answers FAQs, and guides people all the way from installing PhoneGap on their specific platform to running an example application on their emulator or device.
  2. Have a deprecation warning banner on documentation pages that pertain to older versions of PhoneGap, with a link to the latest version.
  3. Have a consistent CLI across PhoneGap and Cordova, with the PhoneGap variant only adding additional commands and features.
  4. Explicitly document and deprecate old directory structures and the old OS-specific ‘create’ command in favor of a new ‘cordova create’ or ‘phonegap create’.
  5. Standardize on a directory structure that separates authored from generated files. To comply with the Maven Standard Directory Layout, it could be set up as follows:
    • src/ – contains all authored (source) files
      • src/main/www/ – the shared PhoneGap ‘www’ directory
      • src/main/platform/ios/ – the files to merge into the iOS project, including icons, splash screens, plugin definitions, etc.
    • target/ – contains all generated files
  6. Design and implement a strategy for upgrading Cordova/PhoneGap versions, allowing people to keep their projects untouched.
  7. Make sure people do not have to touch any generated files, allowing them to run something like ‘cordova platform remove ios && cordova platform add ios’ without losing any information.
  8. Implement a Maven plugin that supports creating assets and integrates with PhoneGap Build.
  9. Implement a Jenkins plugin for integration with PhoneGap Build.

If you have any feedback, do let me know in the comments or on Twitter: @ernstdehaan.

 
1 Comment

Posted by on 19 July 2013 in Geen categorie

 

Tags: ,

Released: uasniffer 1.1

The uasniffer library just got upgraded to 1.1. Highlights of the new release:

  1. Now detecting Kindle Fire, PlayStation Portable and Opera Tablets.
  2. Improved detection of Nook e-readers.

With uasniffer you get a Java-based library that detects a wide range of devices, OSes, browsers and browser engines:

  • common browsers: MSIE, Firefox, Safari, Chrome, Opera, etc.
  • e-readers, e.g. including the Nook, Kindle, Kindle Fire, etc.
  • all iOS devices (iPod Touch, iPhone, iPad)
  • Microsoft Windows (3.1, 95, 98, ME, 2000, XP, 7, 8, etc.)
  • MacOS (up until Mountain Lion)
  • Linux, including Android variants
  • less common OSes: AIX, FreeBSD, HPUX, IRIX, BeOS, etc.
  • Firefox (from early Phoenix prototypes up until 15+)
  • Blackberry devices
  • Symbian devices (e.g. Nokia and Samsung phones)
  • Sony PlayStation (PSP) devices, including the Vita
  • less common browsers: Epiphany, Maxthon, Flock, Camino, Konqueror, OmniWeb, Dolphin, etc.
  • old browsers: NCSA Mosaic, Netscape 1+, MSIE 2+, etc.
  • mobile and mini variants, e.g. Opera Mini, Fennec, IE Mobile, etc.
  • bots, such as Pingdom and the Google Bot

To use uasniffer in your Maven-based project, declare the following dependency:

<dependency>
<groupId>org.znerd</groupId>
<artifactId>uasniffer</artifactId>
<version>1.1</version>
</dependency>

Then in your Java code analyze a specific agent string as follows:

UserAgent ua = Sniffer.analyze(agentString);

To output the detected names for inclusion in an HTML class attribute, use the getNamesAsString() method:

String allNames = ua.getNamesAsString();

E.g. for an Amazon Kindle 3 the output will be something like this:

Device-NoPhone
Device-Mobile
Device-Ereader
Device-AmazonKindle
Device-AmazonKindle-3
Device-AmazonKindle-3-0
Browser-Kindle
Browser-Kindle-4
Browser-Kindle-4-0
BrowserEngine-WebKit
BrowserEngine-WebKit-528
BrowserEngine-WebKit-528-5
BrowserEngine-WebKit-528-5-0
BrowserEngine-WebKit-528-5-0-0
BrowserOS-NIX
BrowserOS-Linux
 
Leave a comment

Posted by on 25 August 2012 in Geen categorie

 

Judging XINS: The Good, the Bad and the Ugly

Looking Back

Back in 2002 or 2003, while working at an internet service provider (Wanadoo Netherlands, now called Online), we were constantly integrating frontend applications created by one team with backend applications created by another. To improve integration, our development team created a technology that would evolve into the contract-first development tool now known as XINS. It worked like a charm for the people involved (architects, developers, IT opeations, management and testers), getting nothing but praise.

But that is a while ago, and the landscape has changed; so how does XINS fare after about 8 years? Looking back, what is arguably good, bad and ugly about it?

The Good

  • The contract first approach really pays off in terms of quality and productivity. Once the contract is agreed upon by the involved developers and/or development teams, there’s suddenly a lot less room for discussion. And it’s fail fast; the contract is validated at both sides (client and server). This approach makes XINS unique and a real productivity monster. Developers are able to focus on the actual implementation code and hardly have to deal with after-the-implementation-discussions on integration issues;
  • Strong operational excellence (like failover, load balancing, error handling, logging, etc.) increases productivity and improves overall quality of these aspects. Part of the functionality is built into the framework, the rest is generated from the specifications.
  • From specifications, test forms can be generated. This is not only great for developers testing their own stuff, but also for other development teams, for testers and operations. It’s easy to peek at XINS-based applications.
  • Performance has always been very good, with automated performance tests in place to detect regressions. The overhead of the XINS runtime is typically less than a millisecond.
  • As long as it goes over HTTP, XINS supports various transport protocols, like JSON, XML-RPC, SOAP and the default: a simple browser-friendly protocol (HTTP GET/POST in, XML out).

The Bad

  • XINS still uses DTDs for validation of the specification files, instead of using the much more powerful XML Schema standard (or even RelaxNG).
  • The XML-based specification files use custom file name extensions, like .fnc, for function definitions, .typ for types, etc. This typically confuses editors and disables syntax highlighting.
  • Unit testing of function implementation classes is hard, they they require generated code (their superclasses). Nowadays, such classes would normally be POJOs.
  • The default protocol has some quirks: e.g. it requires XML support in the browser (which Safari does not offer), it is impossible to send empty strings (because these are interpreted as nulls) and errors are returned using the 200 OK status, which is not in accordance with the HTML spec, etc.
  • XINS 2.3 still uses various non-standard data type classes; this will be fixed in XINS 3.0. Examples of such data types include the PropertyReader (will become Map<String,String> in XINS 3) and the Element class (XINS 3 will use the W3C DOM API instead).

The Ugly

  • XINS tries to be too much at once; it not only generates stuff (code, documentation and test forms), but it also compiles compiles Java code, generates Javadoc, produces a WAR file, enforces an approach to application configurations, etc.
  • As a tool, XINS does not fit in well in the current ecosystem of (Java) build tools and IDEs. It has its own source directory structure, it has its own build system, it does not integrate directly with Maven, etc.
  • All transport protocols are supported, as long as it is HTTP. Local calls are supported, but then everything needs to be wrapped in HttpServletRequest and HttpServletResponse objects. Especially for binary data, this introduces a lot of overhead: binary data is converted to an inefficient format (Base64 or hex), transported in the inefficient format (overhead!) and then converted back to the binary format. Note that this involves storing the data in memory (more than) twice on the server side!
  • XINS hardly evolves: the community is minimal and development is slow.

Crowning the Successor

Overall, XINS is a productivity monster that addresses a topic no other tool appears to cover as good. But it has its share of issues; and integration with other processes and tools makes it less developer-friendly.

There is definitely room for an improved contract-first technology, especially if it would offer the following properties and features:

  1. Strong generation of code, documentation and browser-accessible test forms, similar to XINS.
  2. A runtime environment (client- and server-side) that provides strong operational excellence, similar to XINS.
  3. No attempt to be a one-size-fits-all; instead, make it easy to integrate this technology in existing contexts (tools, processes and technologies).
  4. Easy to pick up for current Java developers; this requires easy integration with modern build tools and IDEs.
  5. Transport-independence, supporting local calls, HTTP (including browser compatibility and efficient binary data handling), as well as other transports, with solid data type conversion.
  6. Strong integration with an existing component technology, such as Jigsaw or OSGi.
  7. Reusing an existing specification technology, such as WebIDL.

Conclusion

There is plenty of room for improving XINS, especially when it comes to adaptation to the current Java ecosystem. Still, in its current form, XINS is a mature technology that really shines when it comes to productivity and operational excellence.

 

Clean CSS with Server-Side Browser Detection (2/2)

In the first article of this duo I explained the use case for server-side browser detection. In this second post I will give a practical example, including some sample Java, HTML and CSS code.

Practical Use Case

Let’s create a simple download page with three variants:

  • an EXE file for Windows users;
  • a DMG file for Mac OS X users;
  • and a TAR GZ file for Linux users.

When the operating system of the visitor is either of these three, then the appropriate download should be highlighted.

Here’s what the result HTML5 should resemble:

<!doctype html>
<html lang="en" class="BrowserOS-Windows">
<head>
  <meta charset="utf-8">
  <title>Downloads</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Downloads</h1>
    <ul class="DownloadLinks">
      <li><a class="Windows" href="/install.exe">Windows installer (EXE)</a></li>
      <li><a class="Mac"     href="/install.dmg">Mac OS X installer (DMG)</a></li>
      <li><a class="Linux"   href="/install.tgz">Linux installer (TAR GZ)</a></li>
    </ul>
</body>
</html>

Then this is the CSS:

body {background:white;}
h1 {color:green;}

.DownloadLinks a {border:1px solid white;}

.BrowserOS-Windows .DownloadLinks a.Windows,
.BrowserOS-MacOS   .DownloadLinks a.Mac,
.BrowserOS-Linux   .DownloadLinks a.Linux {border-color: green; font-weight:bold;}

The Java Library ‘uasniffer’

When using Java, you can use the uasniffer library I wrote. It takes an agent string and transforms it to what can be used as CSS class names. For example, the following agent string:

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)

is transformed to the following names:

Device-Desktop
Device-NoPhone
Browser-MSIE
Browser-DesktopMSIE
Browser-DesktopMSIE-7
Browser-DesktopMSIE-7-0
Browser-DesktopMSIE-7-0-0
BrowserEngine-Trident
BrowserOS-Windows
BrowserOS-Windows-NT
BrowserOS-Windows-NT-6
BrowserOS-Windows-NT-6-0
BrowserOS-Windows-Vista

Compiling the Library

To use this library, you need to get it from the Git version control system first:

git clone https://github.com/znerd/uasniffer.git

This will create a uasniffer directory. Then go to that directory and compile it using Maven. E.g., from the command line:

mvn package

Implementation With a JSP

A JSP that would use this library could be written as follows:

<%@ page import="org.znerd.uasniffer.*" %><%
String agentString = request.getHeader("user-agent");
String uaClasses = AgentSniffer.analyze(agentString).getNamesAsString();
%><!doctype html>
<html lang="en" class="<%=uaClasses%>">
<head>
  <meta charset="utf-8">
  <title>Downloads</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Downloads</h1>
    <ul class="DownloadLinks">
      <li><a class="Windows" href="/install.exe">Windows installer (EXE)</a></li>
      <li><a class="Mac"     href="/install.dmg">Mac OS X installer (DMG)</a></li>
      <li><a class="Linux"   href="/install.tgz">Linux installer (TAR GZ)</a></li>
    </ul>
</body>
</html>

Conclusion

In general, avoid browser sniffing. When you do need it, the uasniffer library makes server-side browser sniffing extremely easy.

If this was helpful on your project, let me know.

 
Leave a comment

Posted by on 13 May 2011 in Geen categorie

 

Clean CSS with Server-Side Browser Detection (1/2)

Why?!

We all know that browser detection is bad, but let us look at some situations in which it may actually make sense; consider the following use cases:

  1. A specific (old?) browser needs special CSS styles to make things look/work acceptably.
    For example, Firefox 3.0 needs a negative margin on an INPUT field, to correct a bug.
  2. Certain content should be highlighted to give a visual clue that this content appears most appropriate for the visitor’s context, like browser and OS.
    For example, on a download page, you want to highlight a download for Mac OS X 10.6, because that is what the visitor appears to use.

Alternative Solutions

Typical solutions for these problems are:

  1. Use CSS hacks.
    Downsides: Unreliable, cumbersome and very hard to maintain.
  2. Use conditional comments.
    Downside: IE-only.
  3. Use feature detection. Various client-side frameworks support this, e.g., Modernizr or jQuery’s $.support.
    Downsides: Only works when JavaScript is enabled, only on more recent, capable browsers and may impact performance negatively on less capable devices.
  4. Use client-side browser detection. This has the advantage of being able to use more than only agent string; using navigator.vendor gives more reliable results.
    Downside: Works only when JavaScript is enabled and impacts client-side performance.

The Case for a Different Path

Excluding the first one, the mentioned solutions have their applications in modern web development. However, they certainly do not cover all ground. An alternative solution for the specified use cases would be welcome if it would comply with all or most of the following requirements:

  1. Reliable, e.g. should automatically pick up new browser versions.
  2. Easy to apply.
  3. Easy to maintain, i.e., no hacks like html>/**/body {}.
  4. Generally applicable, i.e., not specific to IE.
  5. Supports Progressive Enhancement, i.e., does not require JavaScript.
  6. Supports older and less capable browsers as well as more recent and capable ones.
  7. High performance, no time lost detecting features client-side on a limited CPU.

Server-Side Detection

An alternative solution is to have a server-side algorithm add some CSS classes to an element on the HTML document. For example, an iPad agent string could result in the following BODY tag being generated:

<BODY class="Device-Tablet Browser-Safari BrowserEngine-WebKit BrowserOS-iOS">

Let’s look at what such an approach has to bring to the table in terms of requirements coverage:

  1. Reliability: Fair, but not very good, since it relies on the agent string which is easy to spoof. On the other hand, newer browser versions are typically picked up either automatically or with a small update of the detection algorithm.
  2. Easy to apply: Yes, definitely: BODY.BrowserOS-MacOS .MacDownload {border: 1px solid green;}
  3. Easy to maintain: Yes, you only deal with (readable!) CSS.
  4. Generally applicable: Yes, only limited by what user agents offer (of course) and what the algorithm detects; but the algorithm can be extended.
  5. Supports Progressive Enhancement: Yes, perfectly. Works without a single line of JavaScript.
  6. Supports older and less capable browsers: Yes, the detection is done server-side, independent of the browser.
  7. High performance: Yes, server-side algorithm should take (way) less than 10 ms.

What’s Next?

Does it sound like there is a valid use case for server-side browser detection? Let me know in the comments! In a followup article, I will give some code samples.

 
Leave a comment

Posted by on 12 May 2011 in Web Development

 

TDD Versus DDT

Test-driven development (TDD) is commonly accepted as a practical approach for producing high quality production code and high quality unit tests at virtually the same time.

This short article is about an alternative approach, called Documentation-driven testing (DDT). While it does not apply in all situation (which approach does?) I have used it effectively, although until now I’ve never taken the effort to describe how we did it.

This is how TDD works:

  1. Write a minimal test for the currently non-existent production code; no more than is needed to make the test fail; and not compiling is a form of failing.
  2. Make sure the test fails.
  3. Write the production code; program only what is needed to make the test succeed. And yes, take this literally, even if it appears stupid (e.g. returning a constant from a computation method).
  4. Make sure the test succeeds.
  5. Either go to step 1 or refactor the code and go to step 3.

Now, here is how DDT works:

  1. Write Javadoc API documentation for the production code, with a just an no-op implementation. The code should compile and the Javadoc API documentation should be generated.
  2. Write unit tests using only that documentation. This should be done by somebody other than the one that wrote the documentation.
  3. Make sure the test fails.
  4. Implement the production code.
  5. Make sure the test succeeds and, if not, find the source of the error (documentation, production code or test code).
  6. Go back to step 1 or refactor the code and go to step 5.

Now, what is the advantage of this approach? The main driver is the quality of the documentation, including the consistency with the production code. Note that you should already get a good review of the quality of that documentation in step 2, since a lack of understanding on the side of the unit test author should ring some bells.

It is clear this approach is not applicable everywhere, all the time. As is suggested in Uncle Bob‘s great book Clean Code, avoid comments except for public APIs. There it may be an approach that works for your team; if it works for you (or not) do let me know!

 
1 Comment

Posted by on 27 December 2010 in docs, javadoc, tdd

 

Bizarre: Site Redirecting to About:Blank

The site http://www.vbtelecom.nl is redirecting to about:blank. How bizarre! And it works in both Firefox 3.6.10 and Safari 5.0.2:

$ telnet http://www.vbtelecom.nl 80
Trying 77.95.248.16...
Connected to redirect.server.eu.
Escape character is '^]'.
GET / HTTP/1.1
Host: http://www.vbtelecom.nl
 
HTTP/1.1 302 Found
Date: Tue, 19 Oct 2010 19:49:19 GMT
Server: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny6 with Suhosin-Patch
X-Powered-By: PHP/5.2.6-1+lenny6
Location: about:blank
Vary: Accept-Encoding
Content-Length: 0
Content-Type: text/html
 
Connection closed by foreign host.

 
Leave a comment

Posted by on 19 October 2010 in bizarre, http, redirect, vbtelecom

 

XINS Lacking IPv6 Support

If you get the following error while running a XINS-based application:

org.xins.common.text.ParseException: The string "0:0:0:0:0:0:0:1%0" is not a valid IP address.

then you found out the hard way that XINS lacks IPv6 support. This applies to all current versions of XINS: 2.2, 2.3-beta1 and 3.0-beta1.

To work around this, set the system property java.net.preferIPv4Stack to true.

 
Leave a comment

Posted by on 30 April 2010 in ip6, ipv6, xins

 

XINS 3.0 Beta1 Released

Just now I tagged 3.0-beta1 of my experimental XINS fork (which is not so experimental from the perspective that it has been running in production-sites since 2007).

Source and related stuff available from GitHub:

For a complete download, get this ZIP package:

Recent changes include:

  • Ant 1.8.0 is now properly supported
  • Logdoc definitions are now validated using XSDs (Logdoc 0.3 included)
  • Default runtime config file reload interval is now 5 instead of 60 seconds.
  • Not initializing logging subsystem (Log4J) if system property org.xins.server.logging.init is set to false.
  • Not setting context IDs (in Log4J terminology: NDC.push() calls) if property org.xins.server.contextID.push is set to false (system, bootstrap or runtime property).
 
Leave a comment

Posted by on 28 April 2010 in ant, apache ant, github, logdoc, xins, xins3

 

The Importance of Contract-First Development

In enterprise IT projects, software services are typically consumed by other teams or even organisations than those who programmed those services. For example, a Billing system can be instructed by a User Profile system to allocate billing details for a new user profile. Or a Web Frontend system can ask a Session Management system for the data pertaining to a certain session ID.

This is typical service-orientation.

Expectation management
A challenge in such a service-oriented approach is making sure that all involved parties – and that can be or become a lot more than just 2 – have the same expectations from the service. In my experience this is the number one source of frustrations and issues.

Before a service is built or extended, the parties involved at that point in time typically reach agreement what the new functionality should do and how it should be accessed. It is then quite common to have those teams work in parallel, because time-to-market is key.

But even if the teams do not work in parallel, when the service provider delivers functionality for testing and integration, expectations from the other parties can be very hard to meet. For example, service consumers may have expected different formats or may have expected necessary transformations would be done by the service provider, while the service provider is pushing the requirement to the callers.

When this happens, project deadlines and stress levels are at stake.

And the more consumers and the more time it takes for the service provider to deliver a first version, the higher the risk.

Working with contracts
The common solution to this is to work with a contract that defines the agreements between the provider(s) and the consumer(s). Such contracts vary from informal (e.g. Word-documents lacking strict interface definitions) to formal (WSDL with very strict constraints).

Such contracts can be written at the start or they can be generated from existing code.

Generating a contract from existing code is generally a bad idea. The contract is then focused on the implementation, which is subject to change. Then if the implementation changes, what happens to the interface? If it should also change, this violates the common principle of Separation of Concerns. And it is clearly the wrong way around, the contract is the agreement, not the implementation chosen by the provider.

Another issue with contract generation is that the contract can be very much focused on the implementation, including specific data types tailored towards an implementation within a certain platform or programming language. This has an impact on the callers and, in the long term, also on the consumer, since the latter may be forced to stick with legacy implementation choices.

An implementation-independent contract
A first step towards a complete solution to this challenge is to author a contract that is implementation-independent. Such a contract can be agreed upon from the start by all involved parties. Real separation of concerns: the contract is the common agreement, while providers and consumers are free to make their own choices within the bounds of the contract.

This may appear a complete solution.

However, in practice, contracts change, possibly even during the initial implementation project. So what should be done in such a case? Is the contract still leading or will the contract by bypassed by reality?

Based on my experience in professional environments I dare say that if the contract can be violated, it will be. With impact on stability/reliability and on stress levels. In the battle between contract-orientation and project deadlines, the former is easily sacrificed.

Contract-first development
The only way to really guarantee that you can keep the promise of an independent contract is to integrate your contract-orientation in your development process, making the implementation(s) dependant on the contract, preferrably on both sides of the contract (providers as well as consumers).

One way to achiebe this is to make your code link to the contract somehow, for example by having a URL to your WSDL files in all implementations, making sure that failures to adhere to the contract result in errors.

Validation at runtime
To avoid the contract being bypassed, implementations should check all service invocations to make sure the contract is respected.

This can be achieved by generating server- and client-side code from the contract. Having access to the contract (in some form) the implementation then checks all aspects of the invocation. Not only the  preconditions (consumer requests), but also postconditions (provider responses). If either a consumer or a provider violates to the contract, that must be treated as a fatal violation. Only then your contract will actually be leading.

Validation on the server versus on the client
So if you want to validate your contract, where should you do it: on the client (consumer) or on the server (provider)?

The best approach to this is to do it in both locations, for good reasons:

  1. Separation of concerns: both ends should assume their responsibility, which is to adhere to the contract and consider violations fatal. Neither end can be sure the other end will validate the contract, so they should not assume that.
  2. The provider and the consumer may have access to different versions of the contract. Validation on both ends will likely catch any incompatible differences in the contract versions.

Your contract is your treasure!
Now when you have accomplished a true contract-oriented development process, you will find the contract is your gold mine. The contract is typically orders of magnitude simpler than implementations, making it easy to read and change. But since it describes an extremely important integration point so well (concise) and so correctly, it is easy to reuse it for all sorts of of purposes. For example:

  • generation of documentation, e.g. Word-documents or web pages, etc.
  • generation of forms or programs for manual use (including human testing)
  • generation of unit-, performance- and load-tests
  • generation of IDE projects, such as Visual Studio, Eclipse, NetBeans, XCode, etc.

To enable certain possibilities, the formal part of the contract needs an additional informal part. The informal part can include examples and human-readable descriptions. They can also help humans understand the contract and its purpose faster and more easily.

Examples of contract-orientation
While WSDL is an example of a contract definition language for web services, it does not provides a full contract-orientation process, requiring the contract to be held.

The only fully contract-oriented projects I am aware of are those I initiated: XINS and Logdoc. The first (XINS) is an open-source web services framework (that generates server- and client-side Java code), while the latter (Logdoc) implements contracts for logging, again including a Java-implementation.

Do you have experience with contract-orientation? Do you know of other projects that put contract-orientation in the heart of their approach? Please let me know in the comments!

 
3 Comments

Posted by on 17 April 2010 in contract first, contract-orientation