Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling large classes

I've recently begun coding in Java in the past few months. I have a Matrix class that's becoming much too bloated with a lot of methods. I also have a SquareMatrix class that extends Matrix, and reduces some of the bloat.

What I've found is that alot of the methods in the Matrix class are relevant to matrices in general. It has all the basics, like addMatrix(Matrix), multiplyMatrix(Matrix), multiplyMatrix(float), then more complex methods like getGaussian(Matrix) or getLUDecomposition(Matrix).

What are my options in reducing the number of lines in my class Matrix? Is it normal for a class to become extremely large? I don't think so... Is this something I should have considered early on and refactoring is difficult? Or are there simple solutions?

Thank you!


Edit: After reading a couple of responses, I'm considering doing the following:

Utility class Matrix contains all common/basic methods for a matrix

Delegation classes (Helper/sub):

*Helper Class* getGaussian(..), getLUFactorization(..), ...

Subclasses (extends Matrix) SquareMatrix, LowerTriMatrix, UpperTriMatrix, ...

Delegation seems similar to defining multiple .cpp files with headers in C++. More tips are still welcome.


Edit2: Also, I'd prefer to refactor by properly designing it, not quickfixes. I hope it helps down the road for future projects, not just this one.

like image 487
BLaZuRE Avatar asked Apr 18 '12 08:04

BLaZuRE


2 Answers

Interfaces should be both complete and minimal, meaning that a type interface should contain all methods necessary to achieve the needed and meaningful tasks on that type, and only these.

So analyse the API methods of Matrix and determine which of them belong to the core API (which must have access to the internals of the class to accomplish their task), and which are providing "extended" functionality. Then reduce the class API to the core functionality, migrating the rest of the methods to separate helper / utility / subclasses which can accomplish their goals using the public core API.

For refactoring / unit testing help, consider getting Working Effectively with Legacy Code by Michael Feathers.

like image 182
Péter Török Avatar answered Sep 28 '22 14:09

Péter Török


Refactoring is definitely a good thing, but it's difficult to refactor reliably unless you have good unit tests. Test-driven development offers a way to achieve a codebase that is usually easy to refactor.

For existing code without unit tests, this means that before you need to first isolate the area to be refactored, write unit tests first, and then refactor. If this is for just a personal project though, you can probably get away by writing tests for just the minimal set of features you want to survive the refactor intact.

Regarding how to go about the refactoring you have at hand, there are several principles and methods like some other answers have noted. What's worked for me in most cases is:

Strictly enforce the following style rules:

  1. Methods cannot be longer than 40 lines
  2. Class fan-out cannot be more than 20

There are others, but I personally found these to be most helpful in steering myself away from bad design. Limiting method length forces you to really think about method signatures and write concise, focused methods. This usually makes duplication easier to spot and remove. Limiting class fan-out has a similar effect at the class level, it forces you to think hard and about the class's role and make it concise.

Tools such as checkstyle can enforce both of these, along with a bunch of other style rules.

Both Eclipse and IDEA IntelliJ provide an "extract method" refactor, which makes it as simple as highlighting the code you want to extract and hitting a shortcut key. IntelliJ even checks for occurrences of the exact same code in the class and replaces them with a call to the new method as well. In fact I'd recommend using such refactoring tools all the time over doing a manual copy-paste and edit.

like image 28
oksayt Avatar answered Sep 28 '22 14:09

oksayt