I am getting rubocop error 'Class definition is too long. [236/100]'.
My class looks like below:
class SomeClassName
include HelperModule
attr_accessor :aaa, :bbb, :ccc
.... methods .....
end
What might go wrong?
The rubocop docs ClassLength says "length of a class exceeds some maximum value".
What does it mean?
This likely means that your class definition takes more than 100 lines of code.
Yes, this is because the overall lines are considered to be too many by rubucop. I agree classes shouldn't get too long but think that should ultimately be determined by: does the class have a single responsibility, are the methods concise enough, are there methods that could be shared via module, etc... The number/alert is a great warning though. If things in the class look OK, you can add # rubocop:disable ClassLength
immediately above the class definition.
(There's lots of good info here already, but I came to this answer looking for the syntax for specifying the max lines per class in Rubocop, and I figure others might come here for that as well.)
In .rubocop.yml
# Allow classes longer than 100 lines of code
ClassLength:
Max: 250 # or whatever ends up being appropriate
General answer
Do I need to disable this cop if I want my class to be longer than 100 here or need to configure the maximum length. What would you suggest?
I use rubocop with this workflow, assuming I encounter a pre-existing code base with loads of warnings:
Run rubocop --auto-gen-config
to create a "TODO" file. Include that file in your primary rubocop configuration file. See their documentation for details. In your example, it would generate a configuration that allows long classes (at least 236 lines, or more if you have larger classes).
Now, if you run rubocop
, it will ignore all offences that you put in your TODO file - i.e., everything will looke fine now. Only if you introduce more errors/warnings (like a class with 237 lines) will it fire up again. So, at this point, rubocop
will not do anything for you except prevent you to make it worse.
Once in a while, when I got some time to kill, I pick a rule from the TODO file and work on it. There are three possibilities:
- Remove the rule from the TODO file. This will restore the original behaviour of
rubocop
.
- Relax the number associated with it. Say, the class length is limited to 250 right now; I would like to set it to (say) 100 lines, but I know that I do not have time to refactor many classes right now. So I set it to 240. This will trigger all classes that are between 240 and 250 lines; likely only a few that I can handle easily. I fix them and move on. Another day, I maybe return to it and go from 240 to 230 etc.
- Sometimes I decide that I do not bother about a particular warning. Then I move the configuration from the TODO file to the proper .rubocop file, allowing it permanently.
So, there are no hard and fast rules about all of this. You are supposed to find your own values. Some things that rubocop objects to are totally fine with me since they are more down to coding style than correctness or whatever.
Specific answer
Do I need to disable this cop if I want my class to be longer than 100 here or need to configure the maximum length. What would you suggest?
I most certainly do have a maximum amount of lines configured for my class files (as well as for methods). The length of a unit of code (be it a class or a method) is a very simple yet effective "code smell" that points to grown code and candidates for refactoring/splitting.
I have picked some numbers for me, and I stick with them. I.e., I don't constantly move them up or down to suit the particular code around, but if a piece of code grows "1 line too large", I take action. Most times my target is to split it roughly in half, which will, in the long run, lead to the minimum required effort.
If a class is very long, it usually breaks the "one responsibility per class" rule. It is usually beneficial to break it down into parts. Not just random subclasses, but actully OO-justifiable, patterned, constructs.
If a method is very long, it can sometimes point to OO measures to be taken (i.e., classes introduced or the method being split over existing classes; especially if the method consists of large if/else
constructs or especially case
statements), but more often it calls for simple old-fashioned refactoring into smaller (likely private) methods.
Have fun finding your favourite settings in rubocop, it's awesome.