Defining Responsibilities: Dividing a 1,276-Line Java Class into Targeted Classes
Photo by Markus Spiske

Defining Responsibilities: Dividing a 1,276-Line Java Class into Targeted Classes

The 1,276-line monolith that tries to perform everything in a single class still looms enormous even after you have broken up the large methods of BtnGeraSerrada.java. We extracted methods like validateStatus and createRequisitionHeader in my previous article, which cleaned the code but did not yet make it modular. The next step is to apply the Single Responsibility Principle (SRP) and separate this God Class into more manageable, targeted classes. We can turn this chaotic beast into a system that is simpler to test, maintain, and expand if we assign each class a single task. Are you prepared to reorganize roles and restore order to the chaos?

From One to Many

 In Article 2, we reduced and elucidated the purpose of lengthy methods in BtnGeraSerrada.java. However, the Single Responsibility Principle (SRP), a fundamental component of SOLID principles, is still broken by the class. According to Clean Code author Robert C. Martin, "A class should have only one reason to change." BtnGeraSerrada currently manages transaction management, note creation, status checking, and more — all in one location. By moving tasks to new classes, we can address that.

Why Split into Classes?

 A God Class like BtnGeraSerrada is a maintenance nightmare. Because of its overlapping responsibilities it is harder to test, scales poorly, and confuses developers. To make sure that every class has only one purpose, SRP tells us to separate responsibilities. We can identify at least three different roles for BtnGeraSerrada:

  1. Serrada Management: Orchestrating the overall process (e.g., validating status, coordinating actions).
  2. Note Generation: Creating requisitions and production notes (e.g., createRequisitionHeader, criaProducao).
  3. Note Locking: Blocking notes after creation (e.g., bloquearNota).

Let’s extract these into separate classes.

Example 1: Extracting SerradaManager

The serrada process is currently orchestrated via the go method. This logic should be transferred to a SerradaManager class:

Article content
SerradaManager.java

Now, BtnGeraSerrada becomes a thin wrapper:

Article content
BtnGeraSerrada.java

By doing this, the orchestration logic is isolated, and SerradaManager is in charge of controlling the Serrada process.

Example 2: Extracting NoteGenerator

Note generation is handled by the createRequisitionHeader and criaProducao methods. Let's move them to a class called NoteGenerator:

Article content
NoteGenerator.java

SerradaManager can now delegate to NoteGenerator, maintaining a clear separation of duties.

 Example 3: Extracting NoteLocker

 The bloquearNota method locks notes to prevent edits. This is a distinct responsibility:

Article content
NoteLocker.java

Note-locking logic is isolated in this way, allowing for testing and reuse.

A Personal Perspective

Class splitting avoided the failure of one project. A single class grew to thousands of lines, and e very change broke something. We were now able to reason about the code without fear after using SRP. These new classes serve as the foundation of a modular structure for BtnGeraSerrada.

What’s Next?

Although our roles have been divided, these classes are still tightly coupled to frameworks such as EntityFacadeFactory. We'll address dependency injection and interfaces in the next article.

Takeaways

  1. SRP is a game-changer: Each class should have one reason to change.
  2. Modularity improves clarity: Splitting responsibilities makes code easier to understand and test.
  3. Small steps, big impact: Class extraction sets the stage for deeper refactoring.

How do you deal with excessively ambitious classes? Have you split a monolith using SRP, or are you unsure where to begin? As we continue this refactoring adventure, I would love to hear about your wins, challenges, or concerns. Please share your experiences in the comments section below!

Full disclosure: this article was written with the aid of Grok, an AI built by xAI, who helped me organize my ideas and polish the content. The concepts and insights, however, are based on my own daily experiences as a coder.
Wellington Terroni

Senior Android Engineer | Mobile Developer | Kotlin | Java | Jetpack Compose

2h

Interesting

Like
Reply
Paulo Guedes

AI Engineer | Computer Vision | MLOps | RAG | LLM | M.Sc. in Computer Science

4h

We underestimated the value of clean method naming. After splitting up a huge function, descriptive names alone made the code 10x easier to follow—especially during code reviews.

Like
Reply
Paulo Cavalcante

Data Scientist | AI · Machine Learning · Statistics · Data Analytics | Python · R · SQL · Databricks · Git · Big Data

4h

Helpful insight, Cassio

Like
Reply
Ashley Marques

Full‑Stack Engineer | Angular  | C# | .NET  Framework

5h

Very useful!!

Like
Reply
Aleson França

PHP | Laravel | React | FullStack Backend-focused Engineer | Developer | Engineer | Docker | Kubernetes | GCP

5h

Thanks for sharing, Cassio

Like
Reply

To view or add a comment, sign in

More articles by Cassio Menezes

Insights from the community

Others also viewed

Explore topics