Objects and actors are communicating state machines, offering and consuming different services at different points in their lifecycle. Two complementary challenges arise when programming such systems. When objects interact, their state machines must be "compatible", so that services are requested only when they are available. Dually, when objects refine other objects, their state machines must be "compliant", so that services are honoured whenever they are promised.In this paper we show how the idea of multiparty compatibility from the session types literature can be applied to both of these problems. We present an untyped language in which concurrent objects are checked automatically for compatibility and compliance. For simple objects, checking can be exhaustive and has the feel of a type system. More complex objects can be partially validated via test cases, leading to a methodology closer to continuous testing. Our proof-of-concept implementation is limited in some important respects, but demonstrates the potential value of the approach and the relationship to existing software development practices.
Objects as communicating automataTwo significant state-related challenges arise when programming object-oriented systems. We describe how these both relate to the idea of an object as an automaton, and then present a tool which speaks to both challenges and aligns well with test-driven development practices.Compatible usage. To use an object safely, one must understand its inner automaton: its states, the services available in each state, and the state transitions that result from service requests. We call this the compatibility problem. In standard OO languages the automaton is hidden away behind a flat collection of methods comprising the object's interface. The compatibility problem is compounded by the fact that interacting with one object may indirectly cause a state change in another object.Compliant refinement. The second challenge is complementary. To safely specialise the behaviour of an object, one must take care to respect its automaton: each state of the overriding object must be contravariant with respect to services offered, and covariant with respect to services consumed. We call this the compliance problem. Compliance is the key to robust compositionality: compliant implementations can be safely substituted for abstractions, as embodied by the slogan "require no more, promise no less" [20], allowing the abstractions to serve as boundaries between components. Yet in traditional OO languages compliance is captured at the level of method signatures, not at the level of the object's underlying automaton.Test-oriented methodologies. The modern context for both of these problems is an increasingly incremental and test-driven development process. In test-driven development [2], programmers deliver features by first defining test cases which characterise them, and then writing enough code to make the tests pass.