Hidden Dependencies in Open Source Systems

This section contains several examples of hidden dependencies we found in 3 open source systems:  Drawlets 2.0, Apache FtpServer 1.0.3, and JUnit 4.4. The examples are taken from our ICSM 2010 paper.  

If you have encountered a problem due to a hidden dependency while programming, we will appreciate if you could share it with us.

Hidden Dependency in Drawlets 2.0

The HD exists between the method initialize() of the class SimplePanel and the method paint(Graphics c) of the class JDrawingCanvasComponent. The method initialize encodes the style of the canvas on which the figures will be drawn. The style determines the contour color of the figures, the background color, and so forth.

The style values are encoded in the class variable style of another class SimpleDrawingCanvas that also contains method paint(Graphics c). This method passes the data from the variable style into the parameter c. The method paint(Graphics c) of the class JDrawingCanvasComponent uses the values encoded in the formal parameter c to paint the background of the canvas and the contours of all the figures. Consequently, both methods share the concept “contour color”.

An IECA relation exists between these two methods. The full implication that establishes PHD between methods initialize and paint(Graphics c) is (toolPalette ≠ NULL) AND (toolbar ≠ NULL) AND (canvas ≠ NULL) IMPLIES (canvas ≠ NULL).

Consider the following change request: “Do not draw the contour for ellipse, but keep the contours for all other figures”. The change starts in the class SimplePanel in the method initialize, setting the contour color to be the same as the background color of the canvas that makes the contour of the ellipses invisible. However, the change implemented in this way impacts all the figures, making their contours also invisible. The change propagates to the method paint(Graphics c) where the contour color of the figures different from ellipse is changed back to a visible color. Therefore, the relation between the two methods is a HD.

Hidden Dependency in Apache FtpServer 1.0.3

In Apache FtpServer, the tool revealed a PHD between the constructor of the IODataConnectionFactory class and the method execute of the class AUTH (Fig. 2). IODataConnectionFactory creates a connection that allows the data to be transferred on the FTP server. The user can opt for a secure data transfer using a secure protocol, which by default is SSL (Secure Socket Layer). Once the connection is established, the user can be authenticated on the server. During authentication, the execute method is called. The method expects one of the following connection types: not secure, SSL or TLS (Transport Layer Security).

Consider that a new secure protocol (NSP) is developed and the following change request is formulated: “Allow the user to use NSP instead of SSL as a default protocol”. The change starts in IODataConnectionFactory where the default secure protocol is changed to NSP. Next, the change propagates to execute where a new condition is added for the NSP protocol. Both methods have to be changed since they are both implementing the protocol concept; therefore, a HD exists between them.

Hidden Dependency in JUnit 4.4

In JUnit the methods getDescription() of the class CompositeRunner, and the method getTestHeader() of the class Failure belong to the PHD set, as depicted in Fig. 3. The method getDescription() creates an object of type Description and encodes the name of the test case in it. A Description object represents a test case or a test suite. The test case is then executed, and if it fails, its name is printed to the standard output. The name is decoded by the method getTestHeader() of the class Failure.

The methods share the “test case” concept. The class variable fChildren is an array with elements of type Description that represents a tree that stores the information about test cases of the test suite. The Description class contains additional class variables. For example, the name of a test case is stored in the string fDisplayName, while the class variable EMPTY of type Description represents a test suite with no test cases. We describe the postcondition and precondition of the two methods in Table III, where we used boldface to indicate the significant precondition conjunct.

Consider the following change request: “When a test fails, display the names of the test suites that the test belongs to”. The change starts in the method getTestHeader of the class Failure. The information about the parent of the test case is already displayed, but the names of the other test suites in the hierarchy are not available in the fDrescription object. Consequently, we change the method getDescription so that the complete name in the suite hierarchy is preserved in a new class variable of the class Description. We change the method getTestHeader to read the information in this variable and include the complete name in the returned string. The change propagates between the two methods; therefore, we can conclude that the pair (getDescription, getTestHeader) is a HD.

©Radu Vanciu & Vąclav Rajlich