Edmund Kirwan

About Edmund Kirwan

Edmund is a programmer with a telecoms company in Stockholm where he is currently working on a large-scale network simulator. In his spare time he thinks far too much about program-structure.

How deep is your code?

Dependency tuples.

Picture your code. Picture all those functions on which there are no source-code dependencies. That might sound odd: if there are no source-code dependencies on a function then what is its purpose? Well, we must distinguish between compile-time dependencies and run-time dependencies. True, all entities at run-time must be called by other run-time entities: it’s turtles all the way down (or at least all the way to freshly powered-up hardware and its firmware-initialized instruction pointer).

In the hyper-modern weirdness of compile-time, however, the source-code dependency is king and two types of function indignantly shun all source-code dependencies. The
 
first type includes those functions called from outside your source-code. The main() function offers a good example: you write nothing that explicitly calls your main() function, rather the environment smashes into your source-code to find it. The second type includes those functions which implement a signature declared in an interface somewhere else. Clients of such functions seldom if ever call them directly, opting instead to call them via their interface declarations. Yes, the system puts two and two together at run-time to establish what to execute, but at compile-time your system’s flexibility depends on these functions’ being called only via associated interfaces. The source-code dependencies fall on the interface signature, the implementing functions escaping the downpour. (This second type also includes functions inherited from a superclass and called via that superclass but we shall mainly concern ourselves with interfaces here.)

So, back to our visualization. Consider a toy system composed of a single class, Wonder. This class has three functions: Java’s static main() function which instantiates the Wonder object by calling the constructor; the constructor itself, Wonder(); and function a() which is called by the constructor, see figure 1.

A simple system

Figure 1: The simple Wonder system.

How many source-code dependency tuples are there in figure 1? There is one: {main(), Wonder(), a()}. A tuple is an just ordered set of elements. A source-code dependency tuple, on function-level, is just an ordered set of source-code function dependencies. If these look like plain-old call-paths that is because the two concepts share DNA. Call paths, however, burst to life only at run-time, magical manifestations of conditional execution sequences that leap from implementation to implementation, oblivious to interface. Source-code tuples hibernate in the file-system permafrost, frozen – sometimes for years – between updates. They terminate syntactically on any function that in turn has no source-code dependencies, be it implementation or interface declaration.

Given that the structure of a program on function-level is simply the enumeration of its functions and their inter-relationships, we can say that the function-level structure of a program is in some sense the union of all its function-level dependency tuples. Some further examples may be helpful.

A second system

Figure 2: Expanded Wonder.

Figure 2 shows a slightly expanded Wonder class, now with the constructor calling three other functions. There are now three dependency tuples: {main(), Wonder(), a()}, {main(), Wonder(), b()} and {main(), Wonder(), c()}.

A third system

Figure 3: Even more Wonder.

Figure 3 has four dependency tuples. All cosmically interesting, of course, but what has this to do with how, “Deep,” code is?

Code depth.

The depth of a dependency tuple is simply its cardinality, that is, the number of elements it contains. So in figure 3, the tuple {main(), Wonder(), c(), d()} has a depth of four. The depth of a program, then, is the average depth of all its dependency tuples. Thus figure 3 shows a system with a depth of 3.5. Given that a change to a function has a greater probability of rippling back to dependent functions than rippling forward to independent ones, depth interests programmers because the deeper a dependency tuple, the more functions are potentially impacted by changes to that tuple. In figure 3, function e() has three transitively-dependent functions: c(), Wonder() and main(), whereas a() in the shorter tuple has just two.

Code depth, of course, hardly claims to be the only or even the most-important driver of a program’s structure, it merely elbows its way into the rabble of competing influences; but programmers should not ignore it. Let us take a glimpse at the best and worst configurations of our Wonder system, from depth’s perspective.

A sunburst system

Figure 4: The Wonder sunburst.

Figure 4 shows the depth-wise ideal configuration of our Wonder functions, that is, the shallowest-possible configuration: the sunburst. (It would be shallower still if we were prepared to tolerate main() function’s calling all others statically.) No function here has more than two functions transitively-dependent on it.

A terrible system

Figure 5: A lack of wonder.

Figure 5, on the other hand, shows the worst configuration for our Wonder system: a single tuple, maximally deep. Five functions here have more than two functions transitively dependent on them. Again, depth remains one of many influencing factors and programmers certainly do not enjoy the freedom to configure their functions any way they wish; at the very least, semantic constraints demand a logical decomposition. So how deep is code? Do programmers keep to the shallows?

Analysis revisited.

Those who have sampled so pitifully small a set as that comprising Junit and Ant should neither draw firm conclusion nor withhold speculation. Figure 6 shows the function-dependency tuple depth of each release of JUnit from version 3.6 to version 4.9.

JUnit depth

Figure 6: JUnit depth.

This graphs shows that JUnit maintained an average tuple depth of around 5.5, that is, most functions could expect to reside within a tuple of 5.5 functions (the standard deviation was around three). This hardly seems excessive. Few programmers would find the complexity of such tuples overwhelming. Compare this, however, with Ant’s historical trajectory.

Ant depth

Figure 7: Ant depth.

Figure 7 shows Ant’s depth which in version 1.6 has soared to almost twenty (with a standard deviation of around eight). Many programmers might find this suspicious. They might question why most of the functions should find themselves in such long and potentially-ripply tuples. Perhaps more projects should employ depth-guages.

Summary.

Into the pachinko machine of our program we pour the metal balls of our analytical thoughts, watch them bobble and bounce as they fall through webs of intricate dependency tuples and see them collect in the tray with feelings of either satisfaction (“Those functions are structured precisely as they ought to be”) or bewilderment (“That function is connected to what now?”).
 

Reference: How deep is your code? from our JCG partner Edmund Kirwan at the A blog about software. blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


8 − four =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close