--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CALsUZFHmU%2B8aAHLNV3nu5HK98d4%2BEw0Ez-GBJZHpTD7gddSSJA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CAMJiBK4ZzCG_5Noa-3ctfcmgHCArXri6wqXUnbypeQ%3DK%3Dnxz_A%40mail.gmail.com.
HI all,We'd like to start using static analysis against the puppet code base both to catch certain classes of coding errors and to enforce best coding practices. Those are laudable goals of course, but there is plenty of room for opinions on what qualifies. This email is a request to solicit some opinions :)To kick the discussion off: at this point, we're leaning toward using rubocop for static analysis, identifying a set of checkers ('cops' in rubocop lingo) and then setting up some CI integration, either in travis-ci or houndci, to enforce those cops against PRs.
Rahul Gopinath has put together a PR with an initial proposal of 'cops' we might use:There's some initial discussion in that PR but the tldr of the proposal is to enable these cops:Lint/UnreachableCodeLint/ConditionPositionLint/UselessComparisonLint/LiteralInterpolationLint/ElseLayout
and then there's been some discussion on the PR around these two cops:Style/AndOrLint/AssignmentInConditionEach of those two checks catch coding patterns which both are a source of some bugs and, at the same time are idiomatic in certain cases. So there's room for discussion on those two.
And then there are a *bunch* more cops for a variety of style/lint checks which we could consider enabling in addition to the above. There's some documentation of the various cops in the rubocop yaml files at:
So, thoughts?Kylo--
--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CALsUZFHmU%2B8aAHLNV3nu5HK98d4%2BEw0Ez-GBJZHpTD7gddSSJA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
Keep in mind that we can always take a layered approach. Could hire a small number of cops, then add more as our crime rate decreases.
Have we done an initial run to see how much crime we have? Is it a daunting amount?
On Mon, Jul 14, 2014 at 10:56 AM, Kylo Ginsberg <ky...@puppetlabs.com> wrote:
For the build and test pipeline integration, I think it would be great to have it as part of the PR process. However, since every once in a while we have things enter that don't go through a PR (normally quick little fixes and such), then we should also have this running in Jenkins.
I don't think that it should be executed as part of "rake spec", since that would slow it down for us whenever we run them, and it is really one of those things that once we get into the habit of abiding by the rules, we very rarely actually break them. What I've done before is have a separate job in Jenkins for running static checks. It gets kicked off after the spec tests passed and in parallel with the next stage after specs (in our case, that is packaging).
and then there's been some discussion on the PR around these two cops:Style/AndOrLint/AssignmentInConditionEach of those two checks catch coding patterns which both are a source of some bugs and, at the same time are idiomatic in certain cases. So there's room for discussion on those two.
The only idiomatic part of the and/or one that we'd get rid of is failure statements: do_something() or raise "Noooo!!!". I'm willing to drop that for the slightly more wordy:if !do_something()raise "Nooooo!!!!"endIn fact, I often like that construction better because it is more future proof. If it turns out that you need to add extra actions in the error case, then there isn't any need to perform refactor first.
And then there are a *bunch* more cops for a variety of style/lint checks which we could consider enabling in addition to the above. There's some documentation of the various cops in the rubocop yaml files at:I think we should avoid any purely formatting cops. Instead we should figure out a common formatting utility to use and just take code formatting out the path of a developer's whims.
So now putting on my opinionated hat ;)On Mon, Jul 14, 2014 at 12:04 PM, Andy Parker <an...@puppetlabs.com> wrote:
On Mon, Jul 14, 2014 at 10:56 AM, Kylo Ginsberg <ky...@puppetlabs.com> wrote:
For the build and test pipeline integration, I think it would be great to have it as part of the PR process. However, since every once in a while we have things enter that don't go through a PR (normally quick little fixes and such), then we should also have this running in Jenkins.
Yep, +1 on it being in Jenkins also.I don't think that it should be executed as part of "rake spec", since that would slow it down for us whenever we run them, and it is really one of those things that once we get into the habit of abiding by the rules, we very rarely actually break them. What I've done before is have a separate job in Jenkins for running static checks. It gets kicked off after the spec tests passed and in parallel with the next stage after specs (in our case, that is packaging).
In Rahul's PR it's a separate rake task. It's faster than than a full Jenkins spec matrix, and platform-independent, so we could possibly run it in parallel with specs.
and then there's been some discussion on the PR around these two cops:Style/AndOrLint/AssignmentInConditionEach of those two checks catch coding patterns which both are a source of some bugs and, at the same time are idiomatic in certain cases. So there's room for discussion on those two.
The only idiomatic part of the and/or one that we'd get rid of is failure statements: do_something() or raise "Noooo!!!". I'm willing to drop that for the slightly more wordy:if !do_something()raise "Nooooo!!!!"endIn fact, I often like that construction better because it is more future proof. If it turns out that you need to add extra actions in the error case, then there isn't any need to perform refactor first.I agree. I'm +1 with jettisoning and/or entirely.I'm also +1 on adding Lint/AssignmentInCondition, both because I've seen the occasional bug that would be caught by this, and more often I've seen some confusion for code readers that would be caught by this ("did they really mean an assignment here?"). I believe it can be addressed simply by parenthesizing the expression.
That said, I recognize that assignment-in-conditions is widely used and thus this one may be controversial, so I'm curious to hear others' thoughts.And then there are a *bunch* more cops for a variety of style/lint checks which we could consider enabling in addition to the above. There's some documentation of the various cops in the rubocop yaml files at:I think we should avoid any purely formatting cops. Instead we should figure out a common formatting utility to use and just take code formatting out the path of a developer's whims.Why have a separate tool? I'd rather have fewer tools if it gets the job done, but I may be missing your point. That said, I'd be inclined to go light on pure formatting cops unless they catch bugs or really help with readability. Are the following uncontroversial?
Whitespace cleanup:Style/TrailingBlankLineStyle/TrailingWhitespaceStyle/IndentationConsistencyStyle/IndentationWidthThose four are primarily of interest to me b/c lots of editors do these things automagically (good thing) so some PRs end up with unrelated edits to fix the above. Might as well nuke them once and for all and get cleaner PRs.Similarly, alignment checkers catch readability issues:Lint/BlockAlignmentLint/DefEndALignmentLint/EndAlignmentOkay, there are more I find tempting but that's enough for now ....Kylo--
--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CALsUZFE45L%3D0ECAzPY%2BW2UmP_nGYSmC6ktxb%2Bwpk2r%2B4%2BcNNvg%40mail.gmail.com.
Yep, I noticed that. Does houndci just work from the rubocop configs? If it does, then I'd be a little worried that we are limiting ourselves to only using rubocop for checking PRs. My concern might not be valid and it is all going to be ok :)
--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CANhgQXvi-FXfVcNDH75wsX2DZZtN0c58P8enUHOP-nt8GpE5%3Dw%40mail.gmail.com.
and then there's been some discussion on the PR around these two cops:Style/AndOrLint/AssignmentInConditionEach of those two checks catch coding patterns which both are a source of some bugs and, at the same time are idiomatic in certain cases. So there's room for discussion on those two.
The only idiomatic part of the and/or one that we'd get rid of is failure statements: do_something() or raise "Noooo!!!". I'm willing to drop that for the slightly more wordy:if !do_something()raise "Nooooo!!!!"endIn fact, I often like that construction better because it is more future proof. If it turns out that you need to add extra actions in the error case, then there isn't any need to perform refactor first.
[..snip..]and then there's been some discussion on the PR around these two cops:Style/AndOrLint/AssignmentInConditionEach of those two checks catch coding patterns which both are a source of some bugs and, at the same time are idiomatic in certain cases. So there's room for discussion on those two.
The only idiomatic part of the and/or one that we'd get rid of is failure statements: do_something() or raise "Noooo!!!". I'm willing to drop that for the slightly more wordy:if !do_something()raise "Nooooo!!!!"endIn fact, I often like that construction better because it is more future proof. If it turns out that you need to add extra actions in the error case, then there isn't any need to perform refactor first.It is possible to get back most idiomatic constructions by slightly tweaking the cops. In fact it is rather easy to do so, and here[1] is a custom cop that checks for And/Or only in conditionals.- I feel that the boolean control flow idiom is actually useful.A pattern that I have seen often in code is of the typeunless x = mymethod()x.do_somethingend
Which falls foul of Lint/AssignmentInConditionI think that it would be better written as`x = mymethod() and x.do_something`rather than`(x = mymethod()) && x.do_something`which is recommended in the ruby style guide from rubocop if we restrict and/or to purely control flow operators.
--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/d3442dc7-2193-44aa-a000-18ecc2327082%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/77907278-9756-4ec4-a7fe-4d165a3cf9db%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CA%2BemFfzOtUwAp7otOUZ-oo0PcSbKSf8BRLFkGhGgu6eBUubj6A%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CALsUZFG5Uf3PUKnrVCH33RzaXEA2UZX0YtPzhyiWnxZKih3uwA%40mail.gmail.com.
For the ease of management, I would like to split that into two PR,
one dealing with the original Lint/* and a second one dealing with
Style/AndOr since the number of violations of Style/AndOr is really
large, and it may be better to tackle it separately.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CA%2BemFfyOH0XPsBfU6%2BHgFOOqJ-bV1VASzKYJ8iJYyOaVUnKLFg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
I'm concerned about the complete removal of and
and or
as flow control operators. My understanding is that we're removing these to make the code more consistent and readable but I think that doing a wholesale replacement of flow control operators with boolean operators may set us about as far back as removing the flow control operators will move us forward.
Take the following example:
- execute_prerun_command or return nil + execute_prerun_command || (return nil)
I think that the latter is less clear than the former. Moreover, removing the parentheses is an illegal expression:
[1] pry(main)> def logical_comp
[1] pry(main)* false or return :x
[1] pry(main)* end
=> nil
[2] pry(main)> logical_comp
=> :x
[3] pry(main)> def boolean_comp
[3] pry(main)* false || return :x
[3] pry(main)* end
SyntaxError: unexpected tSYMBEG, expecting keyword_end
false || return :x
^
[3] pry(main)> def boolean_comp
[3] pry(main)* false || (return :x)
[3] pry(main)* end
=> nil
The flow control operators have a lower precedence for a specific reason - when explicitly used for flow control they behave correctly. Their very low precedence makes them suitable for this specific use case. As we've seen using flow control operators in conditional expressions can do surprising things, which is why we certainly should strip them from conditionals. However removing the flow control operators and replacing them with boolean operators will flip around the problem - instead of precedence in conditionals screwing us up, we'll have precedence in flow control doing unexpected things. This will remove one class of errors but introduce another.
We can continue forward with removing flow control operators for the sake of consistency and unambiguity, but doing this means that we should remove the use of flow control style operations entirely. Instead of using and
/or
/&&
/||
we should use if
instead. This will clearly indicate that we're doing flow control in the code and will completely sidestep the entire problem of operator precedence. However, if we're not going to replace flow control operators with true conditionals, then I don't think we should replace flow control operators at all.
- - -
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CALsUZFG_gtNQk5qAFES4Ku09nd70iTCLZ9LDgsT_ZFQLh5h%3DeQ%40mail.gmail.com.
When reviewing pull request 2900 to add Rubocop and remove instances And/Or, I came across some rather interesting behavior with how the boolean operators interact with some keywords and methods. For the sake of clarity I'm copying my comment from the pull request to here for discussion:I'm concerned about the complete removal of
and
andor
as flow control operators. My understanding is that we're removing these to make the code more consistent and readable but I think that doing a wholesale replacement of flow control operators with boolean operators may set us about as far back as removing the flow control operators will move us forward.
Take the following example:
- execute_prerun_command or return nil + execute_prerun_command || (return nil)I think that the latter is less clear than the former. Moreover, removing the parentheses is an illegal expression:
So the boolean operators don't have equivalent behavior to the flow control operators in a number of circumstances - how do we want to proceed with this?
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CALVJ9SK8UbNmu30aqwG50iLg50Pk%2BTVDezGZFKd%3DKmwFcrLCSQ%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CA%2BemFfzVKzhQv%2Bx1gZRZt-FX9jP1gx5HMUXdtRJcbGjoWgHe3w%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
-Jeff
--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CAOXx1vHSHOQN5kdU%2Bq0u8NV9PPT8z74%3DeM3M0vJ%2B172G07u2Xg%40mail.gmail.com.
Right now the PRs are doing a mechanical transformation to remove a keyword that we don't want to use. What is missing is that it isn't transforming the code into what later changes to that code should preserve. Or put another way, if we got a PR that contained new code that looked like that we would reject it, I think. It passes the test of not using disallowed operators, but it doesn't pass the test of being written in a form that a reader would expect.
So to summarize, this is our plan for Rubocop:- We propose to enable AndOr cop in small chunks, giving preference to those files/directories that are heavily in development.- For AndOr, the conclusion seems to be to avoid keywords completely, and ensure that the instances where they are used are changed do not hurt readability.- As a prototype, we have turned on AndOr on lib/pops directory PR 2892
On Tuesday, July 29, 2014 11:00:46 PM UTC-7, Kylo Ginsberg wrote:On Tue, Jul 29, 2014 at 4:42 PM, Andy Parker <an...@puppetlabs.com> wrote:
Right now the PRs are doing a mechanical transformation to remove a keyword that we don't want to use. What is missing is that it isn't transforming the code into what later changes to that code should preserve. Or put another way, if we got a PR that contained new code that looked like that we would reject it, I think. It passes the test of not using disallowed operators, but it doesn't pass the test of being written in a form that a reader would expect.I agree that the purely mechanical transformation applied to the genuinely flow control cases introduces constructs that would slow me down as a code reader (and that I'd be very unlikely to write).So are there objections to converting such cases to use 'if', etc? Personally I'd find that clearer and easier to read. And it would still allow us to eliminate the and/or keywords which we've identified as the source of some bugs/confusion.Kylo
--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/ab872dad-c258-4e09-81b3-8c13f17bc968%40googlegroups.com.
On Tue, Aug 5, 2014 at 3:50 PM, rahul <ra...@puppetlabs.com> wrote:
So to summarize, this is our plan for Rubocop:- We propose to enable AndOr cop in small chunks, giving preference to those files/directories that are heavily in development.- For AndOr, the conclusion seems to be to avoid keywords completely, and ensure that the instances where they are used are changed do not hurt readability.- As a prototype, we have turned on AndOr on lib/pops directory PR 2892Also a heads-up that for pull requests:1) a week or so ago, we added a travis job that fails if any of the .rubocop.yml enabled cops report anything (these are just the cops that were uncontroversial at the beginning of this thread)2) just now, I turned on houndci.com which will comment on pull requests based on the same configurationNote that hound *can* be configured with a separate config file of its own, but we don't have one, so it falls back to the .rubocop.yml. If we wanted to have a set of cops which triggered comments on the PRs, but didn't figure travis fails, we could get that by having a separate houndci.yml. Not sure what I think of that, but just putting the idea out there.
Kylo--
On Tuesday, July 29, 2014 11:00:46 PM UTC-7, Kylo Ginsberg wrote:On Tue, Jul 29, 2014 at 4:42 PM, Andy Parker <an...@puppetlabs.com> wrote:
Right now the PRs are doing a mechanical transformation to remove a keyword that we don't want to use. What is missing is that it isn't transforming the code into what later changes to that code should preserve. Or put another way, if we got a PR that contained new code that looked like that we would reject it, I think. It passes the test of not using disallowed operators, but it doesn't pass the test of being written in a form that a reader would expect.I agree that the purely mechanical transformation applied to the genuinely flow control cases introduces constructs that would slow me down as a code reader (and that I'd be very unlikely to write).So are there objections to converting such cases to use 'if', etc? Personally I'd find that clearer and easier to read. And it would still allow us to eliminate the and/or keywords which we've identified as the source of some bugs/confusion.KyloYou received this message because you are subscribed to the Google Groups "Puppet Developers" group.To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/ab872dad-c258-4e09-81b3-8c13f17bc968%40googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.--
While hacking rubocop, I found that I can get it to autocorrect even
more `Style/AndOr` violations if I replace the use of the `not`
keyword with `!` first. The Rubocop is able to do the necessary
changes automatically. So I think we should turn on the `Style/Not`
cop also for our code for three reasons
1. It is essentially free, with rubocop able to supply the entire set
of corrections in its autocorrect mode
2. It is consistent without goal of avoiding keywords with confusing precedence.
3. Rubocop autocorrect is the best we can hope for, since it ensures
that the AST resulting from the changes are same, and hence the
semantics of the new and old fragments are same. Hence we avoid bugs
that cold go undetected otherwise.
I also propose to turn on the `Style/SpaceAfterNot` which disallows
space after the operator `!` so that usage such as `! mymethod` is
flagged in favor or `!mymethod`
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CA%2BemFfz56%3DNTedoRVbM32FVCZpnKov7BoSwewTpJR9rc%2BR2QRA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
While correcting AndOr, I come across methods calls such as `if
value.is_a? FixNum or value.is_a? Integer`
How should we parenthesize it? is it `(value.is_a? FixNum) ||
(value.is_a? Integer)` or should it be `value.is_a?(FixNum) ||
value.is_a?(Integer)` ?
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CA%2BemFfwFLqgiNaK_mSXvxWepXmJeD%2BLx2mVcKmOV_fu%3DJRqx5g%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
On 2014-09-08 24:13, Andy Parker wrote:
On Fri, Aug 8, 2014 at 3:11 PM, Rahul Gopinath <ra...@puppetlabs.com<mailto:ra...@puppetlabs.com>> wrote:
While correcting AndOr, I come across methods calls such as `if
value.is_a? FixNum or value.is_a? Integer`
How should we parenthesize it? is it `(value.is_a? FixNum) ||
(value.is_a? Integer)` or should it be `value.is_a?(FixNum) ||
value.is_a?(Integer)` ?
value.is_a?(FixNum)
Parens around the method arguments are the clearest fix and we should
put them in everywhere IMO :)
+1, except in internal DSL like logic where it reduces readability
>> So I think we should turn on the `Style/Not` cop
>
> Either way, I'm a +1 for adding in this rule too.
>
> No space after ! is my preferred style. And I'll just stop any
style wars
> and say it is the preferred style of the codebase (I am
channelling the
> puppet code gods).
>
+1
On Sunday, August 10, 2014, Rahul Gopinath <ra...@puppetlabs.com> wrote:
> Here is a related issue,
>
> I notice that there are different conventions for spacing followed
> when using method calls with parenthesis,
> including `method(a,b)`, `method( a, b )` and `method( a,b )`. Does
> the list have a preference for one of the styles when I add
> parenthesis (to those methods that are not DSL like)?
>
> I think our choices are
> `mymethod(a,b)` -- currently supported by rubocop
> `mymethod( a, b )` -- another common style
>
> or any other...
I guess I'm in the any other camp.
mymethod(a, b)
I guess I'm in the any other camp.
On Sunday, August 10, 2014, Rahul Gopinath <ra...@puppetlabs.com> wrote:
> Here is a related issue,
>
> I notice that there are different conventions for spacing followed
> when using method calls with parenthesis,
> including `method(a,b)`, `method( a, b )` and `method( a,b )`. Does
> the list have a preference for one of the styles when I add
> parenthesis (to those methods that are not DSL like)?
>
> I think our choices are
> `mymethod(a,b)` -- currently supported by rubocop
> `mymethod( a, b )` -- another common style
>
> or any other...
mymethod(a, b)
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CA%2BemFfzcMrOytP9zEy%3DS-rSET_12g0NDZwHmVULcZsK6S5n9-A%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
On 2014-11-08 19:06, Trevor Vaughan wrote:It depends very much how the methods are phrased and what they do.
I prefer:
cmd x or return nil
as opposed to, if x then return nil, just because it flows better.
Technically, though, a standard should be standard even if it's a bit
irritating at times and I think that this one might qualify.
Trevor
And there are several ways to to do that...
return nil unless it_is_ok?
return nil if bad_things_happened?
Personally I avoid designing with use of "and"/"or" and would not mind a bit if they were not allowed anywhere. But I recognize it could be very irritating for someone that is used to phrasing/organizing code a different way.