All posts
Jul 10, 2023 in Tooling3 min
Identifying responsibilities in a large class
Posted by
Ragunath Jawahar
Ragunath Jawahar
@ragunathjawahar

Large classes are a result of the "one more thing" problem. You have a perfect class that does one thing, and your users like it. However, they want it to do one other thing and another and then another. Before we realise it, the class becomes responsible for many different things.

All hope is not lost. If you can identify these different responsibilities, you can extract the properties and functions to a new class or move them to an existing class where they belong.

Eureka can give you a helping hand when it comes to solving this problem.

Where to start?

Every class has a vocabulary unique to the problem statement it is catering to. To surface this information, Eureka has the vocabulary panel. Once you have the tool up and running on the class you are interested in, click on the "Words" tab on the vocabulary panel.

Selected "Words" tab in the vocabulary panel
Selected "Words" tab in the vocabulary panel

From the list of words, see the ones with a smaller frequency count than those on the top. The count is a relative measure, so finding words with a "mid-range" frequency count could work best. I am interested in duration, volume, and chrome for this example.

Identifying a cluster

A cluster is a group of properties and functions that fulfil a responsibility. These members can either be transferred to a new class or moved to an existing one. For example, if the members contribute to the feature envy code smell, we move them to an existing class. We might create a new class if it is a missing abstraction problem. But before we address either one of these code smell, we need to identify the cluster. Eureka provides you with a tool that can help.

The cluster identification feature specifies a start node and one or more hub nodes. Using this information, Eureka can traverse the graph and identify subgraphs that fulfil a responsibility within the class.

Start node

The start node can be any node that matches terminology or search criteria. It does not have to be the "first" node in the graph.

Hub node

When you traverse the nodes in the graph, there could be nodes with unusual incoming or outgoing dependencies. If your start node is connected to one of these hub nodes, it could traverse the majority or almost the entire graph. To prevent this from happening, we need to specify these nodes to the tool so that we can stop traversing beyond these hub nodes.

Some candidates for hub nodes are,

  • Entry points to the framework classes (e.g.) onCreate(Bundle) and onViewCreated(View, Bundle) for Activity and Fragment classes in Android. It could be controller functions for web frameworks. A class can have one or more entry-point functions.
  • Constructors, <init>()
  • Class initializer, <clinit>()
  • Shared dependencies (e.g.) several functions may use view model properties in an Android application.

In general, look for members with many incoming/outgoing dependencies.

Image showing a method hub node (left) and a field hub (right)
Image showing a method hub node (left) and a field hub (right)

Using the tool

Press "Cmd + K" or "Ctrl + K" to bring up the dialog to specify the start and hub nodes. As you add more and more hub nodes, you'll notice the network shrink smaller and smaller. Here are a few examples with their corresponding start and hub nodes.

Example 1: Duration

"duration" cluster
"duration" cluster

Example 2: Volume

"volume" cluster
"volume" cluster

Example 3: Chrome

"chrome" cluster
"chrome" cluster

Next steps

After identifying a network, figure out the kind of code smell and refactor away. Possible code smell can be,

If you don't have Eureka, install it using Homebrew.

brew install legacycodehq/tap/eureka

You can check out the project page, and if you like the tool, consider starring the project on GitHub! 🌟

Overall, how helpful was this article?
😭🙁🙂😍

Stay ahead of the curve! 🚀

Subscribe now and never miss our cutting-edge, innovative content.
Address
Legacy Code Headquarters (OPC) Private Limited,
L-148, 5th Main Road,
Sector 6, HSR Layout,
Bengaluru, Karnataka-560102,
India.
© 2023–2024 Legacy Code HQ. All rights reserved.