Converter::Base#build_mutation has boolean parameter 'is_copy' Open
def build_mutation(name, data, update = false, return_keys = "id", is_copy = false)
- Read upRead up
- Exclude checks
Boolean Parameter
is a special case of Control Couple
, where a method parameter is defaulted to true or false. A Boolean Parameter effectively permits a method's caller to decide which execution path to take. This is a case of bad cohesion. You're creating a dependency between methods that is not really necessary, thus increasing coupling.
Example
Given
class Dummy
def hit_the_switch(switch = true)
if switch
puts 'Hitting the switch'
# do other things...
else
puts 'Not hitting the switch'
# do other things...
end
end
end
Reek would emit the following warning:
test.rb -- 3 warnings:
[1]:Dummy#hit_the_switch has boolean parameter 'switch' (BooleanParameter)
[2]:Dummy#hit_the_switch is controlled by argument switch (ControlParameter)
Note that both smells are reported, Boolean Parameter
and Control Parameter
.
Getting rid of the smell
This is highly dependent on your exact architecture, but looking at the example above what you could do is:
- Move everything in the
if
branch into a separate method - Move everything in the
else
branch into a separate method - Get rid of the
hit_the_switch
method alltogether - Make the decision what method to call in the initial caller of
hit_the_switch
Converter::Base#build_mutation has approx 8 statements Open
def build_mutation(name, data, update = false, return_keys = "id", is_copy = false)
- Read upRead up
- Exclude checks
A method with Too Many Statements
is any method that has a large number of lines.
Too Many Statements
warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements
counts +1 for every simple statement in a method and +1 for every statement within a control structure (if
, else
, case
, when
, for
, while
, until
, begin
, rescue
) but it doesn't count the control structure itself.
So the following method would score +6 in Reek's statement-counting algorithm:
def parse(arg, argv, &error)
if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
return nil, block, nil # +1
end
opt = (val = parse_arg(val, &error))[1] # +2
val = conv_arg(*val) # +3
if opt and !arg
argv.shift # +4
else
val[0] = nil # +5
end
val # +6
end
(You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)
Converter::Base#build_mutation is controlled by argument 'update' Open
data = cleanup(data) unless name.downcase.include?("update") || update
- Read upRead up
- Exclude checks
Control Parameter
is a special case of Control Couple
Example
A simple example would be the "quoted" parameter in the following method:
def write(quoted)
if quoted
write_quoted @value
else
write_unquoted @value
end
end
Fixing those problems is out of the scope of this document but an easy solution could be to remove the "write" method alltogether and to move the calls to "writequoted" / "writeunquoted" in the initial caller of "write".
Converter::Base#build_mutation is controlled by argument 'is_copy' Open
data = copy(data) if is_copy
- Read upRead up
- Exclude checks
Control Parameter
is a special case of Control Couple
Example
A simple example would be the "quoted" parameter in the following method:
def write(quoted)
if quoted
write_quoted @value
else
write_unquoted @value
end
end
Fixing those problems is out of the scope of this document but an easy solution could be to remove the "write" method alltogether and to move the calls to "writequoted" / "writeunquoted" in the initial caller of "write".
Converter::Base#build_mutation has boolean parameter 'update' Open
def build_mutation(name, data, update = false, return_keys = "id", is_copy = false)
- Read upRead up
- Exclude checks
Boolean Parameter
is a special case of Control Couple
, where a method parameter is defaulted to true or false. A Boolean Parameter effectively permits a method's caller to decide which execution path to take. This is a case of bad cohesion. You're creating a dependency between methods that is not really necessary, thus increasing coupling.
Example
Given
class Dummy
def hit_the_switch(switch = true)
if switch
puts 'Hitting the switch'
# do other things...
else
puts 'Not hitting the switch'
# do other things...
end
end
end
Reek would emit the following warning:
test.rb -- 3 warnings:
[1]:Dummy#hit_the_switch has boolean parameter 'switch' (BooleanParameter)
[2]:Dummy#hit_the_switch is controlled by argument switch (ControlParameter)
Note that both smells are reported, Boolean Parameter
and Control Parameter
.
Getting rid of the smell
This is highly dependent on your exact architecture, but looking at the example above what you could do is:
- Move everything in the
if
branch into a separate method - Move everything in the
else
branch into a separate method - Get rid of the
hit_the_switch
method alltogether - Make the decision what method to call in the initial caller of
hit_the_switch
Converter::Base#build_mutation has 5 parameters Open
def build_mutation(name, data, update = false, return_keys = "id", is_copy = false)
- Read upRead up
- Exclude checks
A Long Parameter List
occurs when a method has a lot of parameters.
Example
Given
class Dummy
def long_list(foo,bar,baz,fling,flung)
puts foo,bar,baz,fling,flung
end
end
Reek would report the following warning:
test.rb -- 1 warning:
[2]:Dummy#long_list has 5 parameters (LongParameterList)
A common solution to this problem would be the introduction of parameter objects.
Method build_mutation
has 5 arguments (exceeds 4 allowed). Consider refactoring. Open
def build_mutation(name, data, update = false, return_keys = "id", is_copy = false)
Converter::Base has no descriptive comment Open
class Base
- Read upRead up
- Exclude checks
Classes and modules are the units of reuse and release. It is therefore considered good practice to annotate every class and module with a brief comment outlining its responsibilities.
Example
Given
class Dummy
# Do things...
end
Reek would emit the following warning:
test.rb -- 1 warning:
[1]:Dummy has no descriptive comment (IrresponsibleModule)
Fixing this is simple - just an explaining comment:
# The Dummy class is responsible for ...
class Dummy
# Do things...
end
Converter::Base#cleanup doesn't depend on instance state (maybe move it to another class?) Open
def cleanup(data)
- Read upRead up
- Exclude checks
A Utility Function is any instance method that has no dependency on the state of the instance.
Converter::Base#safe_parse doesn't depend on instance state (maybe move it to another class?) Wontfix
def safe_parse(str)
- Read upRead up
- Exclude checks
A Utility Function is any instance method that has no dependency on the state of the instance.
Converter::Base#convert_keys_to_camelcase doesn't depend on instance state (maybe move it to another class?) Open
def convert_keys_to_camelcase(data)
- Read upRead up
- Exclude checks
A Utility Function is any instance method that has no dependency on the state of the instance.
Converter::Base#copy doesn't depend on instance state (maybe move it to another class?) Open
def copy(data)
- Read upRead up
- Exclude checks
A Utility Function is any instance method that has no dependency on the state of the instance.
Converter::Base#remove_quotes_from_keys doesn't depend on instance state (maybe move it to another class?) Open
def remove_quotes_from_keys(data)
- Read upRead up
- Exclude checks
A Utility Function is any instance method that has no dependency on the state of the instance.
Converter::Base#remove_quotes_from_boolean_values doesn't depend on instance state (maybe move it to another class?) Open
def remove_quotes_from_boolean_values(data)
- Read upRead up
- Exclude checks
A Utility Function is any instance method that has no dependency on the state of the instance.
Converter::Base#convert_to_json doesn't depend on instance state (maybe move it to another class?) Open
def convert_to_json(data)
- Read upRead up
- Exclude checks
A Utility Function is any instance method that has no dependency on the state of the instance.
Missing top-level class documentation comment. Open
class Base
- Read upRead up
- Exclude checks
This cop checks for missing top-level documentation of classes and modules. Classes with no body are exempt from the check and so are namespace modules - modules that have nothing in their bodies except classes, other modules, or constant definitions.
The documentation requirement is annulled if the class or module has a "#:nodoc:" comment next to it. Likewise, "#:nodoc: all" does the same for all its children.
Example:
# bad
class Person
# ...
end
# good
# Description/Explanation of Person class
class Person
# ...
end
Missing magic comment # frozen_string_literal: true
. Open
module Converter
- Read upRead up
- Exclude checks
This cop is designed to help upgrade to after Ruby 3.0. It will add the
comment # frozen_string_literal: true
to the top of files to
enable frozen string literals. Frozen string literals may be default
after Ruby 3.0. The comment will be added below a shebang and encoding
comment. The frozen string literal comment is only valid in Ruby 2.3+.
Example: EnforcedStyle: always (default)
# The `always` style will always add the frozen string literal comment
# to a file, regardless of the Ruby version or if `freeze` or `<<` are
# called on a string literal.
# bad
module Bar
# ...
end
# good
# frozen_string_literal: true
module Bar
# ...
end
Example: EnforcedStyle: never
# The `never` will enforce that the frozen string literal comment does
# not exist in a file.
# bad
# frozen_string_literal: true
module Baz
# ...
end
# good
module Baz
# ...
end
Use compact module/class definition instead of nested style. Open
module Converter
- Read upRead up
- Exclude checks
This cop checks the style of children definitions at classes and modules. Basically there are two different styles:
Example: EnforcedStyle: nested (default)
# good
# have each child on its own line
class Foo
class Bar
end
end
Example: EnforcedStyle: compact
# good
# combine definitions as much as possible
class Foo::Bar
end
The compact style is only forced for classes/modules with one child.