Infer Type helps you to decouple your programs, particularly in the context of pluggable and service-oriented architectures.
For a quick introduction, refer to this hands-on example set up in the context of Martin Fowler's Dependency Injection Pattern.
Infer Type is a new Eclipse refactoring that redeclares a reference with its smallest possible interface. It is a kind of "Extract Interface meets Use Supertype Where Possible", but more intelligent than the former and less global in its effect than the latter.
Infer Type computes for a given reference ("declaration element") the transitive closure of all members accessed on the reference and all other references it might get assigned to. For this, it uses a static program analysis of the assignments, parameter passes, and returns in a program. From the closure, it creates a new type (interface or abstract class), inserts it into the type hierarchy, and redeclares the reference with it. Infer Type regards particulars of Javas type system such as subtyping (of course), overloading (to some extent), access to protected and private members, and even type casts; the program resulting from the refactoring will always (except for bugs in the refactoring) be type correct, even if this requires introduction of more than one new type along an assignment chain.
A first brief example of how Infer Type might ease your life as a coder is given here. Admittedly, this example is simplistic, so perhaps it needs more to convince you.
this
as a
parameter) so that the server can call back the client
for whatever it needs to know. The method signature of
the service as implemented by the server will then look
something like void
service(Client c)
.service
's formal
parameter c
(on which the callback is to be
issued) does exactly this.Stack
as
subtype of Vector
,
allowing its users to pass a stack where a vector is
required. This risks a stack being used by library code
(to which it is passed as an actual parameter) in such a
way that the specification of a stack is broken, for
instance by inserting or removing elements at arbitrary
positions. By inferring the type on the formal parameter
(with declared type Vector
)
of the library method in question one can check
without working through the code whether dangerous
methods are being accessed. Because the computation of
the inferred type is based on a static program analysis,
the result is conservative, i.e., it may include elements
that are never called in any possible invocation of the
method.copy
function
that depends on read
and write
functions to become independent of concrete on read
and write
implementations (which might be members of different
classes representing a specific source and sink), these
functions should be factored out into specific
interfaces, representing abstract read and write
functions. Such can also be done with Infer Type.This article describes much of how Infer Type works.
Once you have installed Infer Type, you have also installed a refactoring named Multiple IT Refactorer. This refactoring repeatedly visits all declaration elements of the project, package or class on which you called it and applies Infer Type on each one of them until no more changes to your program are possible. Multiple IT Refactorer is non-interactive: it introduces new types without prompting the user. As a result, you get a program in which all elements are declared with minimal (ie, containing only the members needed) or maximally general (ie, no more general supertype could be introduced which could be used instead) types. While this refactoring itself has only theoretical merit (it can be used to compute the cost of maximally decoupling your code), it tests Infer Type systematically: after each change to the program, the program must compile cleanly. The refactoring checks this continuously.
We have tested Infer Type by applying the Multiple IT Refactorer on various projects, the most prominent being JUnit and JHotDraw. These projects were somewhat special in that only moderate use of arrays and inner types, as well as the ?: operator was made. We expect most remaining bugs to relate to these language constructs.
Our testing strategy cannot check whether the introduced types are truly minimal, ie, whether or not they contain members that are not needed in any context. For this, one could try to remove members from types at random and see whether the program still compiles. Also, it does not check whether the refactoring affects the semantics of the program; since only types in declarations are changed and since all introduced new types are abstract, such errors would likely be associated with static and/or dynamic binding. A theoretical proof that such problems cannot occur might be possible; we have however not attempted such.
see here
see here
© The IntoJ Team, 2005, 2006, 2007.