Welcome!

Java IoT Authors: Elizabeth White, Pat Romanski, Charlotte Spencer-Smith, David Sprott, Liz McMillan

Related Topics: Java IoT

Java IoT: Article

Evolving Functionality

Evolving Functionality

C++ brought into vogue the concept of interfaces, abstractness, and implementations. Java went a step further and formalized them with proper keywords for each of the concepts. There are a substantial number of patterns in which interfaces, abstract classes, and classes can be combined for various purposes. You only have to look at the book Design Patterns, by Erich Gamma et al (Addison-Wesley), to realize the importance of recognizing these constructs.

Constructing a software program that you expect to have a long life is an attempt to evolve its functionality over time, without abandoning older behavior for backward compatibility. This is a lot more essential when you're designing libraries and frameworks. The newer libraries should work with older systems that were designed for the older releases of a library. Here are some concrete examples of why this is important and how to accomplish this in situations where every programmer is encouraged to adapt the scheme owing to its simplicity.

What Is Evolving Functionality?
To understand what evolving functionality is, let's walk through the design of a very simple class in Java. Here's the class:

class LogFacility
{
public log(final String message)
{
// implementation
}
}
LogFacility provides a mechanism to log messages. Everyone on the team would use this functionality as follows:
LogFacility lf = new LogFacility()
lf.log("log this message for me");

As it's simple and useful, it's hard to argue against it. Now I take this utility and ship it to two different teams. One team wants to log to a file and the other to stdout. I improvised and came up with StdoutLogFacility and FileLogFacility, and suggested that the programmer use the appropriate logging facility as follows:

StdoutLogFacility lf = new
StdoutLogFacility();
lf.log("log this message for me");

FileLogFacility lf = new
FileLogFacility();
lf.log("log this message for me");
You'd quickly realize that irrespective of what log facility is constructed, it gets used the same way. This is a cue to design an interface for the usage of the log facility as follows:
public interface ILogFacility { public
log(final String message); }
StdoutLogFacility and FileLogFacility would implement this interface. In this scenario the programmer would do the following:
ILogFacility lf = new
StdoutLogFacility();
lf.log("log this message for me");
ILogFacility lf = new FileLogFacility();
lf.log("log this message for me");
As you can see, irrespective of the nature of the construction, an object of type ILogFacility is used the same way.

This brings us to an important observation in OO programming - construction is different from usage. In other words, the construction interface of an object is different from its usage contract/interface. We can delegate the construction of the ILogFacility to any number of mechanisms, but the usage remains the same. Using this property let's investigate a method where the programmer doesn't have to do the following:

ILogFacility lf = new FileLogFacility();
This line of code is hard-coding the construction of an implementation. In doing so we create a compile-time dependency with the implementation. And we can't substitute StdoutLogFacility for FileLogFacility because that dependency is necessitated by the compiling.

So, in a general sense, you can't really vary the implementation of a given interface at runtime if we use the "new" option for construction. Also you'll have to know the name of the implementation class, which may not even exist at compile time. What to do? The solution lies in understanding the factory pattern. Here's an example:

class ObjectFactory
{
public static Object create(final String
objectName, Object args )
throws CreationException;
}

You can attempt the following:

ILogFacility lf = ObjectFactory.create
(ILogFacility.NAME, null);
if.log("log my message"):
As a programmer you've delegated the construction of an interface named ILogFacility.NAME to a factory. This factory could look up a system-wide properties file for a class that's responsible for this interface and load it at runtime. Let's look at one such properties-file entry:
Objects.loggingObject.className=com.your_
company.StdoutLogFacility;

Assuming ILogFacility.NAME is "Objects.loggingObject", it is not difficult for the factory to do the following:

public static Object create(final String
objectName, Object args )
{
Properties systemWidePropertiesFile;
String className = systemWide
PropertiesFile.getValue
(objectName);
Object o = Class.forName(className);
return o;
}

Using this mechanism you can improvise StdoutLogFacility gradually without impacting its users. For example, you've improved logging but don't want to replace the older implementation until it's been field tested. You can cut and paste the source code of StdoutLogFacility to another class called StdoutLogFacility1 and replace your properties file as follows:

Objects.loggingObject.className=com.your_company.Stdout
LogFacility1
This way the older clients can continue to use the older implementation while you migrate to the new one. You can continue to evolve this functionality while incrementing the numbers. The same facility can provide a radically different implementation if necessary. For example:
Objects.loggingObject.className=com.your_company.Socket
LogFacility

logs all your messages to a socket.

This discussion isn't limited to logging; any of your core modules can follow the same pattern, which allows them a path for evolution while maintaining backward compatibility.

To summarize the points so far, we've learned the following:

  1. Construction is different from usage
  2. Use interfaces, not implementations for, key areas of functionality
  3. Use factories to construct implementations, at runtime
  4. You can use properties files to associate implementations with their interface names
  5. Having an interface.NAME as a standard allows a programmer a simple reference to instantiate an interface

Usage Pattern for an Evolving Implementation
Let's reexamine how we can utilize an interface. The emphasis here is that you get your implementations via a global factory instead of "new"ing them explicitly. This allows for runtime variations of the implementation. For example:

MyInterface i = (MyInterface)ObjectFactory.create
(MyInterface.NAME,null);
i.useMethod();
Let's examine the MyInterface.NAME:
interface MyInterface
{
public static final String NAME =
"MyInterface";
                                                                                                                        . .. other public method signatures
}
Using a synonym like "interface.NAME" instead of a literal string, we reduce the risk of getting the name wrong. If every interface has the same public synonym, it's just that much easier for the programmer to instantiate an implementation for it.

Interface Definition for an Application-Wide Factory Service
Now we'll discuss the factory object in more detail and define some desirable characteristics. The idea is we'll use this factory object to create all our implementations for the desired interfaces. By that I mean to choose interfaces that are going to be instantiated by factories. Once decided, these interfaces can be instantiated by the same global object factory. The aim of this section is to define a simple interface for such an application-wide factory service.

Static vs Nonstatic Method
The method "create" of the ObjectFactory is declared static and public. It's public for obvious reasons and static so the programmer can invoke it without an object reference. For example:

ObjectFactory.create(..)
instead of
ObjectFactory of = new ObjectFactory();
of.create(..)
There are some exceptions to this rule for example, if you want to evolve the functionality of the factory itself. The method also throws a suitable exception indicating any failures in the construction process. There are some interesting consequences to the nature of this exception, which I'll cover at the end of this article.

getObject vs createObject
At this point I'd like to change the name of the "create" method of the ObjectFactory to "getObject". create() implies that an object is being created every time the method is called. This may not be true for a number of reasons. Certain objects you may want to create only once, others with each request, and some as part of a pool. Because of this, getObject() suits the semantics of this intention more accurately.

Passing Arguments
Certain objects require construction arguments. How do you pass them? The arguments are passed via the second parameter to the function call. This could be any object, including a collection of objects that get passed to the constructor of the target object. This can get sophisticated with EJBs when the constructors are invoked through reflection and the correct constructor called. But for simplicity the classes can have default constructors, with a well-known "init()" method that accepts the passed parameter as an argument.

The implication is that programmers not only need to know the interface name of the object that they want to instantiate, but also the nature of its arguments. This I call the construction interface of the object. This needs to be published and adhered to by all the implementations. And it's the responsibility of the programmer to pass the correct set of arguments. Otherwise an exception is thrown by the generic factory.

Caching Strategy
Once you start using this facility, it won't be long before you start asking, "How can I limit the number of object occurrences of a specific class?" For example, singleton. To facilitate this a factory can use multiple strategies to cache object instances. The factory can save the instantiated objects in a hashtable keyed by their interface names. So, when a repeated request comes in for an interface, the factory can return the previously constructed object. But how does the factory know to cache an object? You can specify in the properties file that a certain interface needs to be cached, which is how it's done in EJBs at deployment time. Specifying the number of object instances at deployment time is more generic. But for systems of medium complexity, you may want to define an ISingleThreaded interface and implement that interface to force multiple instances of the object. This avoids the errors that might occur due to lack of knowledge at deployment time, or you could provide both facilities.

Name-Based Caching May Not Be Sufficient
Interface name-based caching sounds good until you consider the fact that a given implementation can support multiple interfaces. In this case you'll have two such objects cached when one would have been sufficient and even wrong at times. I believe the right approach is to use caching based on class names instead.

Pooling Support
I think a factory shouldn't provide pooling; it should be implemented on top of factory. Otherwise the simple factory interface also needs to deal with synchronization and return to pool semantics.

Support for Object Filters
When a factory instantiates an object, it can also pass the object to an object filter and return the output of the filter instead. This allows for the chaining of objects, which is similar to the servlet chaining popular in Web-based systems. It's fairly trivial to do, but adds a great value to the overall functionality. For example, using such a functionality you can convert an incoming result set to a comma-separated string or sum the values into a single entity. All this can be done without recompiling the target code. This properties file demonstrates how this can be accomplished:

Objects.employee.className=com.comp.Employee
Objects.employee.filterName=SumSalary
Objects.SumSalary.className=com.comp.Sum-
EmployeeSal
The Default Object
When you're specifying target implementation objects via a properties file, it's possible that anything might go wrong in the construction process, resulting in an exception. In this case you'd like a default implementation to be available. For example:
MyInterface myObj = null;
try
{
myObj = ObjectFactory.getObject
(MyInterface.NAME,null)
}
catch( FactoryException x)
{
x.printStackTrace():
myObj = new MyDefaultObject;
}
Doing this everywhere discourages the programmer from using the facility. The following code alleviates the problem:
MyInterface myObj = ObjectFactory.get
Object (MyInterface.NAME, args, new
MyDefaultObject();
This method doesn't throw any exceptions, instead it returns the MyDefaultObject on any kind of internal exception, ensuring the default functionality of the application.

A Well-Defined Factory Interface to
Fulfill the Factory Service

With that discussion we're able to define an interface for our factory object:

interface IFactory
{
Object getObject(final String
interfaceName, Object args) throws
FactoryException;
Object getObject(final String
interfaceName, Object args, Object
defaultObject);
}
An interface definition tells you only the contract of the factory and doesn't specify its intended behavior. For that reason I'm summarizing here the desired characteristics of a typical factory implementation:
  1. Provides a static façade for easier calling semantics
  2. Uses getObject, not createObject, semantics
  3. Requires a default constructor for the objects to be constructed
  4. Arguments are passed to the init method for initialization
  5. Caching is based on the class name of the object
  6. Caching is also based on the IsingleThreaded tagging interface
  7. Supports object filters
  8. Supports default objects
  9. Uses an application-wide configuration interface for class definitions
ObjectFactory Implementation
Although we've defined an interface for a factory, we need a convenient set of static methods that would make use of the above interface internally. Such a facility provides the best of both worlds. On one side it obviates the need to instantiate a factory interface and on the other it adheres to a nonstatic factory interface definition. Here's one such implementation. Obviously many variations are possible, but the idea is to give the programmer the simplest way to accomplish the characteristics stated above (see Listing 1).

Role of an Application-Wide Configuration Service
So far all the object definitions are stored in a properties file. It's not that difficult for the factory implementation to instantiate a properties object and read in the properties file. What if in the future you'd like to move the entries from a properties file to a database, an LDAP, or an XML configuration file?

For this reason the factory implementation accesses the object definitions through a common configuration interface.

Interface Iconfig
{
public String getValue(final String key)
throws ConfigException;
public String getValue(final String key,
String defaultValue );
}
Again, for programmer simplicity, this interface is exposed through a static Config class as follows:
Class Config
{
static public String getValue(final String
key) throws ConfigException;
static public String getValue(final String
key, String defaultValue );
}
With this you'd be able to do:
String value = Config.getValue("key","default value");
Why go to such lengths when properties is such a simple interface; why not use it? Frequently you would want the IConfig implementation to exhibit the following characteristics:
  1. Case-insensitive keys so you don't have to constantly remember capitalizations
  2. Ability to include multiple-properties file inside the main configuration file
  3. Ability to provide substitutions based on keys that were defined at the beginning of the properties file
All these can be provided gradually by the evolving implementations of IConfig. In this case, one of the facilities of the framework evolves using the same principles.

Evolving an Interface
So far I've discussed where the implementations are changing. What if the interface itself has migrated to the next level? Although less common, this will happen eventually, even in the best of designed interfaces. For instance, with the logging interface defined above, I'd like to extend the interface by providing a logging mechanism for exceptions. One approach is to extend the base interface instead of modifying it:

interface ILogFacility_1 extends
ILogFacility
{
public void log(Throwable t);
}
If there's an implementation that supports the ILogFacility_1 interface, it automatically supports the ILogInterface and hence can be used in a backward-compatible manner. On the other hand, if an older implementation that supports only ILogInterface is used in a newer environment that's expecting ILogFacility_1, there are two alternatives:
  1. Let the system throw a class-cast exception and correct the mistake
  2. Write the client code in such a way that this can be handled gracefully:
Object logFacility =
ObjectFactory.getObject
(ILogFacility.NAME,null,new MyLogFacility);
if (logFacility instanceof ILogFacility_1)
{
(ILogFacility_1)logFacility.log(x);
}
else (logFacility instanceof ILogFacility)
{
(ILogFacility)logFacility.log(x.getMessage());
}
Request-Based Factories
As I've mentioned, factory plays a central role in adapting this evolution-based approach to programming. The factory I've discussed so far is primarily creation-based because it instantiates the necessary class and calls the well-known method to initialize it. A more sophisticated approach would be a request-based factory in which the input symbolic name refers to a request rather than a class name. You can simulate the creation-based factory from a request-based factory. For example:
Object o = RequestBasedFactory.getObject
("GET_OBJECT", null):
The request-based factory locates a class name identified by "GET_OBJECT" in a properties file. Instead of calling the init method to initialize the object, the request factory calls the "executeRequest" method with the parameters. Whatever the executeRequest method returns is then returned to the caller as the return object.

When the executeRequest method returns the self-reference, we basically have the RequestFactory behaving like a creation factory. RequestFactory has broader applications than a simple CreationFactory. For example:

RequestBasedFactory.getObject("GET_EMPLOYEE_
ROWS","employee_name=John Doe")
invokes a database request executor identified by "GET_EMPLOYEE_ROWS" and returns the result set back to the caller.

Interfaces and Exceptions
I'd like to cover one more detail since we're dealing extensively with interfaces, particularly such generic interfaces as the factory interface I've shown here. When a factory tries to load a class at runtime and fails, all the client sees is the factory exception. If you're not careful, the root cause of the exception is never known. To deal with this scenario, interfaces should define exceptions that can carry with them a child exception, and the child exception can carry another child exception. This way the root exceptions are propagated all the way to the top. When the final exception is printed, you'll see a complete hierarchy of exceptions, which is extremely good for debugging purposes. I call this the principle of Kangaroo exceptions, and it's necessary for interface-based programming. This is because interfaces are like firewalls and compile-time exceptions can't propagate through them without help. This concept of Kangaroo exceptions hides the root exception in terms of the interface-specific exception.

Conclusion
Using a simple application-level factory service, it's possible to effectively employ interfaces and implementations to write code that provides backward compatibility. Even when you don't need this compatibility, it enables you to try new bug fixes without affecting the old behavior. This provides developers with some assurance that they won't undo everything they've done before.

More Stories By Satya Komatenini

Satya Komatineni is Chief Technology Officer of INDENT, Inc and the author of a Java based RAD framework for developing J2EE based HTML applications. The product has the distinction of supporting multiple html transformations (XSL,JSP, proprietary templates) while utilizing the same data abstraction to interact with EJBs, relational databases and ERP systems. After earning an M.S. in Electrical Engineering from Indian Institute of Technology, New Delhi, worked with LAN based collaboration technologies, C++ patterns and frameworks, Java and Web based frameworks in a distributed environment.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


@ThingsExpo Stories
SYS-CON Events announced today that Interoute, owner-operator of one of Europe's largest networks and a global cloud services platform, has been named “Bronze Sponsor” of SYS-CON's 18th Cloud Expo, which will take place on June 7-9, 2015 at the Javits Center in New York, New York. Interoute is the owner-operator of one of Europe's largest networks and a global cloud services platform which encompasses 12 data centers, 14 virtual data centers and 31 colocation centers, with connections to 195 ad...
SYS-CON Events announced today that Alert Logic, Inc., the leading provider of Security-as-a-Service solutions for the cloud, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. Alert Logic, Inc., provides Security-as-a-Service for on-premises, cloud, and hybrid infrastructures, delivering deep security insight and continuous protection for customers at a lower cost than traditional security solutions. Ful...
The Quantified Economy represents the total global addressable market (TAM) for IoT that, according to a recent IDC report, will grow to an unprecedented $1.3 trillion by 2019. With this the third wave of the Internet-global proliferation of connected devices, appliances and sensors is poised to take off in 2016. In his session at @ThingsExpo, David McLauchlan, CEO and co-founder of Buddy Platform, will discuss how the ability to access and analyze the massive volume of streaming data from mil...
Join us at Cloud Expo | @ThingsExpo 2016 – June 7-9 at the Javits Center in New York City and November 1-3 at the Santa Clara Convention Center in Santa Clara, CA – and deliver your unique message in a way that is striking and unforgettable by taking advantage of SYS-CON's unmatched high-impact, result-driven event / media packages.
SYS-CON Events announced today that Commvault, a global leader in enterprise data protection and information management, has been named “Bronze Sponsor” of SYS-CON's 18th International Cloud Expo, which will take place on June 7–9, 2016, at the Javits Center in New York City, NY, and the 19th International Cloud Expo, which will take place on November 1–3, 2016, at the Santa Clara Convention Center in Santa Clara, CA. Commvault is a leading provider of data protection and information management...
With an estimated 50 billion devices connected to the Internet by 2020, several industries will begin to expand their capabilities for retaining end point data at the edge to better utilize the range of data types and sheer volume of M2M data generated by the Internet of Things. In his session at @ThingsExpo, Don DeLoach, CEO and President of Infobright, will discuss the infrastructures businesses will need to implement to handle this explosion of data by providing specific use cases for filte...
WebSocket is effectively a persistent and fat pipe that is compatible with a standard web infrastructure; a "TCP for the Web." If you think of WebSocket in this light, there are other more hugely interesting applications of WebSocket than just simply sending data to a browser. In his session at 18th Cloud Expo, Frank Greco, Director of Technology for Kaazing Corporation, will compare other modern web connectivity methods such as HTTP/2, HTTP Streaming, Server-Sent Events and new W3C event APIs ...
SYS-CON Events announced today that Pythian, a global IT services company specializing in helping companies adopt disruptive technologies to optimize revenue-generating systems, has been named “Bronze Sponsor” of SYS-CON's 18th Cloud Expo, which will take place on June 7-9, 2015 at the Javits Center in New York, New York. Founded in 1997, Pythian is a global IT services company that helps companies compete by adopting disruptive technologies such as cloud, Big Data, advanced analytics, and DevO...
SYS-CON Events announced today that Avere Systems, a leading provider of enterprise storage for the hybrid cloud, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. Avere delivers a more modern architectural approach to storage that doesn’t require the overprovisioning of storage capacity to achieve performance, overspending on expensive storage media for inactive data or the overbuilding of data centers ...
Fortunately, meaningful and tangible business cases for IoT are plentiful in a broad array of industries and vertical markets. These range from simple warranty cost reduction for capital intensive assets, to minimizing downtime for vital business tools, to creating feedback loops improving product design, to improving and enhancing enterprise customer experiences. All of these business cases, which will be briefly explored in this session, hinge on cost effectively extracting relevant data from ...
Companies can harness IoT and predictive analytics to sustain business continuity; predict and manage site performance during emergencies; minimize expensive reactive maintenance; and forecast equipment and maintenance budgets and expenditures. Providing cost-effective, uninterrupted service is challenging, particularly for organizations with geographically dispersed operations.
With the Apple Watch making its way onto wrists all over the world, it’s only a matter of time before it becomes a staple in the workplace. In fact, Forrester reported that 68 percent of technology and business decision-makers characterize wearables as a top priority for 2015. Recognizing their business value early on, FinancialForce.com was the first to bring ERP to wearables, helping streamline communication across front and back office functions. In his session at @ThingsExpo, Kevin Roberts...
As enterprises work to take advantage of Big Data technologies, they frequently become distracted by product-level decisions. In most new Big Data builds this approach is completely counter-productive: it presupposes tools that may not be a fit for development teams, forces IT to take on the burden of evaluating and maintaining unfamiliar technology, and represents a major up-front expense. In his session at @BigDataExpo at @ThingsExpo, Andrew Warfield, CTO and Co-Founder of Coho Data, will dis...
SYS-CON Events announced today that iDevices®, the preeminent brand in the connected home industry, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. iDevices, the preeminent brand in the connected home industry, has a growing line of HomeKit-enabled products available at the largest retailers worldwide. Through the “Designed with iDevices” co-development program and its custom-built IoT Cloud Infrastruc...
Eighty percent of a data scientist’s time is spent gathering and cleaning up data, and 80% of all data is unstructured and almost never analyzed. Cognitive computing, in combination with Big Data, is changing the equation by creating data reservoirs and using natural language processing to enable analysis of unstructured data sources. This is impacting every aspect of the analytics profession from how data is mined (and by whom) to how it is delivered. This is not some futuristic vision: it's ha...
Silver Spring Networks, Inc. (NYSE: SSNI) extended its Internet of Things technology platform with performance enhancements to Gen5 – its fifth generation critical infrastructure networking platform. Already delivering nearly 23 million devices on five continents as one of the leading networking providers in the market, Silver Spring announced it is doubling the maximum speed of its Gen5 network to up to 2.4 Mbps, increasing computational performance by 10x, supporting simultaneous mesh communic...
The cloud promises new levels of agility and cost-savings for Big Data, data warehousing and analytics. But it’s challenging to understand all the options – from IaaS and PaaS to newer services like HaaS (Hadoop as a Service) and BDaaS (Big Data as a Service). In her session at @BigDataExpo at @ThingsExpo, Hannah Smalltree, a director at Cazena, will provide an educational overview of emerging “as-a-service” options for Big Data in the cloud. This is critical background for IT and data profes...
SYS-CON Events announced today that Men & Mice, the leading global provider of DNS, DHCP and IP address management overlay solutions, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. The Men & Mice Suite overlay solution is already known for its powerful application in heterogeneous operating environments, enabling enterprises to scale without fuss. Building on a solid range of diverse platform support,...
One of the bewildering things about DevOps is integrating the massive toolchain including the dozens of new tools that seem to crop up every year. Part of DevOps is Continuous Delivery and having a complex toolchain can add additional integration and setup to your developer environment. In his session at @DevOpsSummit at 18th Cloud Expo, Miko Matsumura, Chief Marketing Officer of Gradle Inc., will discuss which tools to use in a developer stack, how to provision the toolchain to minimize onboa...
SYS-CON Events announced today that VAI, a leading ERP software provider, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. VAI (Vormittag Associates, Inc.) is a leading independent mid-market ERP software developer renowned for its flexible solutions and ability to automate critical business functions for the distribution, manufacturing, specialty retail and service sectors. An IBM Premier Business Part...