Visualizing Your Code Using Tree Charts 🌳
Visualizing complex code structures often helps me create a mental model of my code. One powerful tool for achieving this clarity that I use is the tree chart.
Tree charts provide a hierarchical view of code, making it easier to trace relationships, identify dependencies, and gain insights into the overall architecture. In this post, I'll dive into how I leverage ZingChart to create these charts efficiently and effectively.
Tree Chart Basics in ZingChart
The first step in creating a tree chart is to set your chart type
to 'tree'
in your chart configuration settings object.
let chartConfig = {
type: 'tree'
/* ... */
}
Next we need to create some nodes for the tree. Tree nodes have many properties available, but there's only a couple that they actually need: type
, id
, name
, and in this case parent
.
Strictly speaking you can link nodes together a few different ways, one of which is by using type: 'link'
objects, but using the parent
property for nodes will better suit our use case here.
let chartData = [
{
type: 'node',
id: 'unique-id',
text: 'Displayed on Chart',
// Leave parent as empty string if root node
parent: 'id-of-parent-node'
},
/* ... */
];
let chartConfig = {
type: 'tree',
series: chartData,
/* ... */
}
Finally there are two more options we need to add. aspect: 'tree-down'
will orient the tree top-down ⬇ instead of left-right ➡, and orgChart: true
will style the chart with right angles instead of curves and add boxes around the nodes.
let chartData = [
{
type: 'node',
id: 'unique-id',
text: 'Displayed on Chart',
// Leave parent as empty string if root node
parent: 'id-of-parent-node'
},
/* ... */
];
let chartConfig = {
type: 'tree',
series: chartData,
options: {
aspect: 'tree-down',
orgChart: true,
/* ... */
},
/* ... */
}
Putting this all together (with a few extra stylistic options added and some demo nodes created), the below demo shows a basic tree.
Dynamically Generating Chart Data from Code
Now that we have a basic tree setup, know the shape of the tree node objects, and know how to relate them with each other we have all of the components to display the relationship between classes that inherit from one another in our code.
Let's start with some basic code that demonstrates inheritance
// Level 1
class User {
constructor(username, email) {
this.username = username;
this.email = email;
}
}
// Level 2
class Admin extends User {
constructor(username, email) {
super(username, email);
}
}
class Member extends User {
constructor(username, email) {
super(username, email);
}
}
Then we'll add them to a set so we have a list of every Class
let classList = new Set();
classList.add(User);
classList.add(Admin);
classList.add(Member);
Now we can map these classes to tree nodes using the set we just created. Using Object.getPrototypeOf(className)
we can get a reference to the parent class of any Class, and using .name
we can get the name of that class as a string
.
const chartData = [...classList].map((className) => {
return {
type: 'node',
// Class names are unique so we can use them as an ID
id: className.name,
name: className.name,
// Grab the name of the parent class
parent: Object.getPrototypeOf(className).name
};
});
Complete Demo
To flesh out the demo a bit we've added a few more classes. To see how they inherit from each other in the code, check out the JavaScript tab.