New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
disallow multi-lines endless methods #577
Conversation
disallow endless methods for a few reasons - changes the history of the method declaration on every update to the logic - needs to be converted to a regular method once more code gets added - easier to introduce bugs (for example if the def is missing it just becomes a variable assignment) - inconsistent method declaration
This automated commit dumps the contents of the full RuboCop config. [dependabot skip]
Hmm... I'm personally a fan of endless method definitions, and find them to be a good fit for simple methods, especially in projects not using Sorbet. # contrived example
class Service
end
class MySQL < Service
def initialize(db_name, user, pass)
@db_name = db_name
@user = user
@pass = pass
end
def name = "MySQL"
def port = 3306
def url = "mysql://localhost:#{port}"
def connection_string = "#{url}/#{@db_name}?user=#{@user}&password=#{@pass}"
end
class Redis < Service
def initialize(db_name, pass)
@db_name = db_name
@pass = pass
end
def name = "Redis"
def port = 6379
def url = "redis://localhost:#{port}"
def connection_string = "#{url}/#{@db_name}?password=#{@pass}"
end Are we seeing many people make mistakes with them? |
Specifically with regards to
|
I think the default of I'd like to challenge your motives:
If the method body is being changed often, could it be that there is some abstraction missing? Maybe the method should not be defined there in the first place? Maybe the single line of code is trying to be "too smart" instead of preferring multiple simple statements (like using guard clauses to return early), etc etc.
Sure but same can be said for
Unit testing would surely catch this if the endless method is public, and if it's private I agree with @sambostock that there is a better linter to detect that.
Agree with this. It feels weird to me, but I know I need time for my eyes to get used to it. |
@sambostock I notice you're preferring single line methods to constants. Wouldn't we rather folks leveraging constants where they can? class MySQL < Service
DB_NAME = "MySQL"
DB_PORT = 3306
DB_URL = "mysql://localhost:#{DB_PORT}"
def initialize(db_name, user, pass)
@db_name = db_name
@user = user
@pass = pass
end
def connection_string
"#{DB_URL}/#{@db_name}?user=#{@user}&password=#{@pass}"
end
end
A lot can be done in a single line in ruby... There's a risk we'll start seeing more and more business logic wrapped in a single line example1, example2
Not mistakes per say, but more using them in a non-organized mixed in with other methods way. def foo
...
end
def bar = foo
def foobar= value
...
end |
I agree it's a good place to start. We can set some tripwires and get more strict later as needed. |
ee5fd03
to
dc43308
Compare
This PR is ready for another look. Leaving the default |
While our team uses endless methods sparingly, and avoid multiple lines of logic, we often use this syntax: def foo = {
faz: "baz",
hello: "world",
} |
I think we should disallow endless methods for a few reasons
cop for this https://github.com/rubocop/rubocop/blob/master/lib/rubocop/cop/style/endless_method.rb