Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

As part of a research I'm working on, I'm looking for public APIs that only work correctly when you apply a certain sequence of actions on them.

For example, the java.nio.channels.SocketChannel class, from the Java standard library, only works correctly with sequences such as open() -> connect() -> read() -> read() -> close(). A more complete demonstration if how it may be used may be represented in the following graph:

valid usage of SocketChannel

Additional examples of Java standard library APIs that require certain sequences are java.io.PrintStream (very similar to the one above) and java.util.Iterator (which requires a next() call between every two remove() calls, thus enforcing a certain sequence).

So, does you favorite API for doing X also behave that way? I would very much like to know about additional APIs that require a certain method sequence for correct usage; especially classes that are not part of the Java standard library. The more complex the sequence(s) required, the better.


Some APIs require a sequence that spans across multiple classes, for example:

X x = new X();
x.setup();
Y y = x.createNewY();
Z z = new Z(y);
z.doSomething();

These examples are also interesting, but I'm mostly looking for sequences that all appear in the same class.


EDIT added bounty for greater visibility. I'm sure many of you have encountered many APIs that will match this description - I would really appreciate some good examples.

share|improve this question
2  
If you're interested in this topic, The Pragmatic Programmer has a chapter on temporal coupling. –  rmx Nov 25 '10 at 16:31
    
Your graph doesn't display in the latest version of Chrome –  Martijn Verburg Nov 25 '10 at 16:39
    
@Martijn odd, it's just a png hosted on imgur... it should work on all browsers. –  Oak Nov 25 '10 at 16:40
    
@Oak Hmm, I'm not seeing it or a link to it. –  Martijn Verburg Nov 25 '10 at 16:41
    
@Martijn: Eh? Works fine on my end –  TheLQ Nov 25 '10 at 16:53

8 Answers 8

From the Spring framework

The Lifecycle interface forces the following action sequence:

start (isRunning)* stop

which is used in just about all the principal components that make up the framework. Fortunately, this lifecycle is managed by the container.

From the Hibernate framework

The Lifecycle interface supports the following action sequence:

(onDelete, onSave, onUpdate)* onLoad

From the Servlet API

My all-time favourite - the lifecycle of a servlet:

init service destroy

with service delegating to the doGet, doPost operations etc.

share|improve this answer

Maybe I'm misunderstanding, but would the following fit?

  • java.lang.Thread

    must call thread.start() before thread.stop()

  • InputStream and OutputStream

    should not call other methods after calling close()

share|improve this answer
    
You are not misunderstanding, that's the sort of thing I'm looking for - only, as I've said in the question, I would very much prefer classes outside the Java standard library. Also, the more complex the better! –  Oak Nov 28 '10 at 23:47

java.sql.ResultSet

contains operations which require a certain order:

move commands (absolute(int row) or next()),

read/write commands (getInt(int columnIndex) or updateInt(int columnIndex, int x)),

write-back-to-datasource commands (updateRow()),

release commands (close()).

share|improve this answer
    
As an added bonus to get at a ResultSet you need to go over several classes, beginning with: DataSource ds; Connection cn = ds.getConnection(); Statement st = cn.createStatement(); ResultSet rs = st.executeQuery(String query); –  Ray Nov 29 '10 at 11:35

An upcoming "best practice" to handle this problem in the initialization phase of objects in Java, is to use a Builder pattern which has a so-called builder on which the steps are taken, and then an object is requested built. If the steps are invalid, the builder fails.

From http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html:

Widget z = new Widget.Builder("3", 4.0).
                     manufacturer("333").
                     serialNumber("54321").build();

The Builder is a nested class to Widget, which then has methods called (returning the same builder object again) until the build() method is called, which creates and returns the Widget needed.

Can reduce complexity quite a bit.

share|improve this answer
    
What problem? I haven't mentioned any problems, I'm just looking for examples of complex, existing, sequence-requiring APIs. –  Oak Nov 28 '10 at 23:30
    
I'm not saying you have problems, but for complex classes this can get the "oh, we need another constructor with nine arguments" situation under control. Having many constructors each taking many arguments is a problem. –  user1249 Dec 1 '10 at 6:22

What about the java.util.Calendar? It doesn't require a complcated action sequence, but it's a real PITA for the number of times you need to use it:

//1. get a new instance
Calendar cal=Calendar.getInstance();
//2. set the different fields
cal.set(Calendar.DATE, 12);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.YEAR, 1982);
//3. use it, for whatever
Date d=cal.getTime();

And, not to talk about the Java Transaction API, when Bean managed:

@Stateless
@TransactionManagement(BEAN)
public class ExampleBean {

    @Resource
    private SessionContext ctx;

    public void foo() {
        UserTransaction utx = ctx.getUserTransaction();

        // start a transaction
        utx.begin();

        // Do work

        // Commit it
        utx.commit();
    }
}

The JAXB marshalling

//1. get context
JAXBContext jc = JAXBContext.newInstance( Foo.class );
//2. create Marshaller instance
Marshaller m = jc.createMarshaller();
//3. set properties
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
  Boolean.TRUE);
//at last, marshall
m.marshal( foo, System.out );

and unmarshalling:

//1. get context
JAXBContext jc = JAXBContext.newInstance( Foo.class );
//2. create Unmarshaller instance
Unmarshaller u = jc.createUnmarshaller();
//3. optional: set properties, format validation, schema validation, etc
u.setValidating( true );
//4. unmarshall
Foo foo = (PurchaseOrder)u.unmarshal(
       new FileInputStream( "po.xml" ) );
share|improve this answer

The academic paper "ESP: path-sensitive program verification in polynomial time" includes examples for opening and closing files, in addition to verifying calls to fprintf. And the concept works with general FSMs, and this may be closer to what you are looking for.

The bonus is that the ESP system verifies that you actually obey these rules. Also related to this line of research is BLAST.

If you want requirements that are more explicit in the programming language, look into Foster's Flow-Sensitive Type Qualifiers. Which can be useful, for example, to check that a "tainted" string has been cleansed before being used in a SQL query.

Depending on the nature of your project, you should look into the classic push before a peek or a pop on a stack. I'm not sure how well the above approaches could handle that case, because counting the number of calls made is important.

share|improve this answer
    
Thank you; but I'm looking for actual, existing APIs, not papers that discuss how to analyze and/or verify them. –  Oak Nov 28 '10 at 23:31
    
@Oak: Please look deeper, I specify three APIs in my answer. Also, the papers could give you ideas. Perhaps you could explain your research project? –  Macneil Nov 28 '10 at 23:38

The C++ STL has a variety of rules about when iterators are invalidated. For example, adding an element to a vector may cause all the iterators into that vector to be invalidated.

Any container library must have special cases for empty containers.

I've dealt with a database api, IBPP, it required a ->Start() call to the transaction object, before creating any statements associated with the transaction. Eventually you would call ->Commit(); (or ->Rollback() if things didn't go well) Other APIs are similar, but probably a bit more complex because of issues such as autocommit.

I've certainly dealt with internal code that acted that way. However, I considered that a bug.

The pygame module in python requires that call .init() and then .display.set_mode() to setup a graphics mode.

Everything I can think of has relatively trivial versions of this. I can't think of any cases that has a really complex version like you really want.

share|improve this answer
    
Yes, I guess it's not easy to find - that's why I asked it here with a large audience. Also, I'm specifically looking for Java APIs, but looking for database APIs does look like a good idea. –  Oak Nov 29 '10 at 9:09

Like parsing an XML document?

DocumentBuilderFactory dbf = DocumentBuilderFactory.getInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File("file.xml"));
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.