Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Java Tip 84: Customize scoping with object keys - JavaWorld

Java Tip 84: Customize scoping with object keys - JavaWorld

Tutorial Details:

Java Tip 84: Customize scoping with object keys
Java Tip 84: Customize scoping with object keys
By: By Mark Roulo
Java's standard scopes may be insufficient for some projects
orrect scoping is one of the keys to success when developing large-scale programs. Paying too little attention to scoping often leads to spaghetti code that is difficult to understand, extend, or maintain. Java provides four standard scopes to restrict access to the data and methods in a class. However, custom-tailored scoping is occasionally desired on large projects, usually to avoid a choice between speed and safety. I'll show you how you can create custom scoping to avoid this tradeoff. Following the techniques described here, you should be able to do so without a significant increase in complexity.
Why scoping?
Scoping controls the depth of access to data and methods, and is one of the tools used to control large software projects. In a program with hundreds of thousands of lines of code, allowing one piece of code to modify any piece of data it wants rapidly leads to chaos. More restrictive scoping of data and methods -- private versus public, for example -- makes programs easier to understand, extend, and maintain, because you don't need to examine as much code when making changes. For small projects, scoping is often not critical -- if a program is only 10,000 lines long, it's easier to keep track of everything. For large projects with many programmers, however, scoping can be the difference between long-term success and failure. Keep in mind, then, that the techniques I present to you work for programs of all sizes, but are most appropriate for large applications.
Some scenarios
When is standard scoping insufficient -- and when is it not? I know of three cases when tailoring a scope to do exactly what you want is more practical than using a standard Java scope. Custom scoping can help you out when you want to:
Disallow certain scripting capabilities
Control mutability across packages
Boost performance
We will consider each use in turn.
Disallowing certain scripting capabilities
A scripting language can add value to applications by allowing users to extend and tailor applications themselves. Occasionally, your application will have functionality that must be used cautiously, such as the ability to reset remote systems. You can restrict access to the GUI by adding a password and warnings to prevent accidents. However, you may wish to prevent scripting from making use of this capability entirely. In such a case, you would place the GUI and the forbidden functionality in the same package, and then create a reset function-package scope.
Sometimes, however, this isn't acceptable. In such cases, you need an approach that doesn't require packaging the GUI and the functionality together. Custom scoping allows the two to be separate, and still protects the functionality from scripting.
Controlling mutability
Creating objects in Java is slower than creating stack objects in C++. Because the cost of object creation in Java is higher than in C++, well-designed Java programs pay close attention to object creation than well-designed C++ programs. One way to safely create fewer objects in Java is to make them immutable -- to not provide a way for the object's state to be changed, in other words. An example of this in the standard libraries is the String class. If an object's state cannot change, references can be safely passed to the object throughout the application.
However, this doesn't always work. A data-processing program might start with an object containing raw data and slowly add information to the object as it passes through the application. A good example of this would be a stock-screening application that starts with objects containing raw stock data, and then adds more information -- the performance of a single stock relative to the industry, say -- as the objects are processed.
In a small application, you can provide the add methods with a javadoc saying, in effect, "Don't call this unless you are the relative performance comparator." As the application gets larger, and more engineers work on it, this approach becomes riskier. Hardcoding restrictions into the program, instead of using comments and hoping that everyone reads them, allows the application to detect access bugs automatically.
Boosting performance
You occasionally need raw access to the internals of an object for speed. As an example, you might have an object containing a large array. The large array is private, and contains getters but no setters because the object is immutable:
public class ImmutableIntArray
{
private int[] data;
public ImmutableIntArray (int[] data)
{
this.data = data;
}
int getElementAt (int index)
{
return data[index];
}
}
There is no method that returns the raw data element, because this would defeat the purpose of making the object immutable. Occasionally, however, client code may need to process the contents of data quickly. Although it may take too long to return a copy of the data, working on the raw data element might be fast enough. It would be a reasonable design decision to grant access to data only to those clients who need it, and not to the entire application.
The custom approach
There are two aspects to the idea of creating custom scoping. First, class names, which are always strings, are visible throughout an application. And second, objects of various classes can only be created by a restricted set of clients.
You can create objects whose class names are visible to the entire program, but which can only be constructed by very restricted clients. The objects of these classes can then be used as key objects. Callers are required to pass in these key objects to method calls, and the method being called can check them against a list of legal keys.
Here's a working example of this:
public class Main
{
static public void main (String[] args)
{
try
{
System.out.print ("This should work ...");
ValidExampleCaller.sampleMethod();
System.out.println (" and it did.");
}
catch (InvalidKeyException e1)
{
e1.printStackTrace();
}
try
{
System.out.println ("This should fail ...");
InValidExampleCaller.sampleMethod1();
}
catch (InvalidKeyException e2)
{
e2.printStackTrace();
}
}
}
/**
*
*/
class InvalidKeyException extends java.lang.Exception
{
public InvalidKeyException (String message)
{
super (message);
}
}
class ExampleCallee
{
/**
* This method prints 'Hi!' to standard out, but can only
* be called by the ExampleCaller class.
*
* @param key 'key' is an object restricting access to this
* method. If 'key' is not an instance of
* class ValidExampleCaller.Key, an InvalidKeyException
* is thrown.
*/
public static void sampleMethod (Object key) throws InvalidKeyException
{
if (key.getClass().getName().equals ("ValidExampleCaller$Key") == false)
throw new InvalidKeyException("Can't call sampleMethod() with key " + key);
System.out.println ("Hi!");
}
}
class ValidExampleCaller
{
static private final class Key
{
}
static public void sampleMethod () throws InvalidKeyException
{
ExampleCallee.sampleMethod (new Key());
}
}
class InValidExampleCaller
{
static private final class Key
{
}
static public void sampleMethod1 () throws InvalidKeyException
{
ExampleCallee.sampleMethod (new Key());
}
}
The ExampleCaller class can call the sampleMethod in ExampleCallee successfully, but no other class can.
Before using this approach, you should consider a number of its details and implications:
ExampleCallee depends on ValidCaller 's cooperation: The ExampleCallee class depends on ValidCaller cooperation in enforcing the scoping restrictions. ValidCaller can cheat by making the Key class public, or by handing out references to Key objects. However, even with standard scoping, legal callers can cheat. Our approach assumes cooperation between the valid caller classes and the callee, just as standard Java scoping does.
The Key object is a static inner class: This means that both static and nonstatic member functions in the ValidCaller class have access to sampleMethod . To prevent static methods from calling sampleMethod , make the Key object nonstatic.
The Key object is a private inner class: Making Key private means that subclasses of ValidCaller cannot construct Key objects. Making Key a protected inner class grants access to child classes as well.
Key need not be an inner class: Key could be a package-scope class if your intent is to grant any class in a package access to sampleMethod() .
Key must not be anonymous: The Java language does not specify a naming convention for anonymous inner classes, and different compilers generate different names for anonymous inner classes. Because of this, you should name the Key class.
The compiler can't help you: The compiler detects violations of standard scoping, but not custom scoping. If you use the approach illustrated here, you will not detect an illegal access until runtime. Detecting mistakes at compile time is preferable, of course, so you should use standard scoping if possible.
Conclusion
Standard Java scoping is sufficient for most projects. For large projects, however, you occasionally need to construct very specific scoping relationships. The approach to doing so presented in this article uses only the standard JDK 1.1 language constructs, and does not require any extensions to the Java language. This approach does add some complexity, though, so you should use it with caution. If you find yourself using this technique often, you need to reconsider your design.
BIO: Mark Roulo is JavaWorld 's Java Tip technical coordinator. He has been programming professionally since 1989 and has been using Java since the alpha-3 release. He works full time at KLA-Tencor, where he is part of a team building a large, distributed, parallel, multicomputer application for image processing (among other things) writte


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Java Tip 84: Customize scoping with object keys - JavaWorld

View Tutorial:
Java Tip 84: Customize scoping with object keys - JavaWorld

Related Tutorials:

Container support for objects
Container support for objects
 
Reloading Applets
Reloading Applets
 
Applet to Applet Communication
Applet to Applet Communication
 
Design networked applications in RMI using the Adapter design pattern
Design networked applications in RMI using the Adapter design pattern
 
Java Tip 72: Press Escape to close your Swing dialog windows
Java Tip 72: Press Escape to close your Swing dialog windows
 
Java memory management
Java memory management
 
Trace your steps in Java 1.4
Trace your steps in Java 1.4
 
Quickly access files and directories you use repeatedly
Quickly access files and directories you use repeatedly
 
Check out three collections libraries
Check out three collections libraries
 
Java Tip 132: The taming of the thread
Java Tip 132: The taming of the thread
 
roots of constants classes
roots of constants classes
 
Use select for high-speed networking
Use select for high-speed networking
 
Filtering and Transforming Digital Images
Filtering and Transforming Digital Images In this Issue Welcome to the Core Java Technologies Tech Tips for April 7, 2004. Here you\'ll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
 
libbraille
Libbraille is a computer shared library which makes it possible to easily develop for Braille displays. It provides a simple API to write text on the terminal, directly draw dots, or get the value of keys pressed on the Braille display.
 
OpenSign
OpenSign OpenSign is a java applet for signing text in a webbrowser using a PKCS-12 key-files or keys located in MS Crypto API CSP's in a Win32 environment. The applet is based on code kindly provided by IT-Practice and everyone is encouraged to subm
 
Simple classes for JDBC
Simple classes for JDBC
 
Trustin Lee\'s String/Object Converter - Changes
TL-convert Trustin Lee's String/Object Converter provides a simple API to convert Java objects into strings and vice versa. It is developed to replace Jakarta Commons BeanUtils and Jakarta Commons Convert and to provide only String/Object converters.
 
The power of table-oriented programming
The power of table-oriented programming When object-oriented programming languages began to be used in enterprise applications, designers had problems fitting the object-oriented model with the relational model. In the object-oriented model, data is enca
 
Tech Tip: Using the Varargs Language Feature
Have you ever needed to pass in many instances of the same object type to a method, but you don't know at compile time how many instances there will be? Find out how the new varargs language feature makes it easy to handle situations like this.
 
J2SE Platform Migration Guide (pdf)
This guide helps developers migrate Java applets, standalone applications, Java Web Start applications and development tools from version 1.3 and 1.4 of the Java platform to version 5.0.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.