Some cases to consider

Bob Jacobsen

A couple people have written and called me privately with questions. Based on the questions received, I’ve pulled some points together to share with the group. I haven’t been following jmri-developers for a while, pending whatever consensus arises. So the following might not be quite on-point for the discussion. Use these as you wish.

First, lets consider some cases where people might or might not have common views about how to deal with contributed code:

1) Somebody contributes a self-contained new feature which seems to work, doesn’t change or break anything existing, has lots of test coverage, passes the CI screens, and the code looks nice and clean. - This ones an easy no-brainer to start with, and I expect people think it clearly should be merged.

2) Same as (1), except it doesn’t have any tests at all. Should it be merged to get that feature in people’s hands? Should the author have to write tests before that happens? Just 1 (to pass CI), or lots (to improve various metrics)? Or should somebody else step up and add tests? Who? One of the advocates of complete testing? Somebody who agrees it’s a cool feature?

3) Same as (1), except that it doesn’t pass a bunch of the code-style CI tests, i.e. maybe unused variables or javadoc warnings or unchecked casts or …. Should the author have to cleanly fix all these & get CI passing? Or will somebody who really cares about those step up and fix them? Or would it be OK to just put @Suppress statements in the files, suppress them all, and move on?

4) Same as (1), except that even though it has tests and passes CI, the code doesn’t look so good: Massive cut and paste, lots of casting, uses every number from 0 to 158 as a bare constant, sometimes in decimal and sometimes in hexadecimal, throws exceptions for normal returns across levels, Yet it’s a really cool feature much loved by users. Now what? Who does what?

Now a similar range on tooling/infrastructure changes:

A) A developer wants to include a new developer tool that requires _no_ change at all by others - it just works, has documentation, does not change any existing process, etc. I.e. a new Javadoc doclet that produces prettier output and can be distributed from JMRI GitHub. What needs to be considered before merging this?

B) As (A), but there’s no documentation about how to use it. Is that needed before merge? Does the author need to write it, or should somebody else step up? How good does it have to be?

C) As (A), but it requires installation and/or setup of some utilities to use it. E.g. another IDE that somebody wants to support or a tool for (optional) testing. Does that need documentation? Anything else?

D) As (A), except it’s a mandatory step. E.g. another preprocessor that has to be run to convert some new-format text for compilation, needed on every clean build. If this requires every developer to install something, is there some cost-benefit balance done? By who? What counts as cost? What counts as benefit?

E) As (A), but it’s a new “primary build tool”, which has the side effect of making existing build tools no longer equivalent. i.e. the change to IDE X means that command-line Maven builds are not longer building the same thing, or Ant builds are, or whatever. Is there some cost-benefit balance done here? By who? What counts as cost? What counts as benefit?

(I was discussing A-E with a developer yesterday, and he said “And what if I get burned by somebody breaking Eclipse build setup again, because I was away long enough to miss the discussion?”)

Sometimes there’s an overlap of the cases, when somebody wants to make a cross-cutting change that touches 50% or 80% or 100% of the files, either now or eventually. How is that evaluated?

i) A light syntactic migration, such as `new AList<Foo>` changed to `new AList<>`. Is it OK to make a migration like this in big chunks of files, even all at once? Just a few files? If somebody starts with just a few, do they have an obligation to complete it so that the code “has a consistent form”? Or does somebody else?

ii) A heavier syntactic migration, where tastes may differ. For example, changing anonymous inner classes to lambdas, or changing loops to functional stream operations. Should people just make these conversions as they write new code? Is it ok to migrate old code? Code that other people are known to be continuously working on, even if they don’t agree the new form is clearer? Can people still write the old forms if that makes them more productive? When is the new coolness a mandatory good, when is it a matter of taste and choice, and when is it a pretentious pain that we should kill with fire?

iii) We’ve had a convention for handing functional migration through deprecation cycles. But when do we have to wait the cycle and when can we just get on with making the changes? Should we mark the code someway to separate those? If so, who’s going to do that work for all that code? Is it the people advocating for this, or will some other people be encouraged / imposed on to do it as they work on the code? Do we need a new release system, and if so, will the proponents of that do the work of setting it set up, tested, documented, etc or should somebody else be expected to do that, including being criticized afterwards?

iv) If there’s a functional migration that’s universal, like a change to logging or an interface in the jmri package or the version of some run-time or test library, how does that get done? Should the proponents be given the very large burden of making the change all at once? That’s a lot of work. It’s even more work to do it slowly, one bit at a time, because of coordination and communication burdens. But that spreads it out in time, or across people. But _how_ do you equitably spread this work across people who don’t necessarily value the change over the things they actually want to work on? When can something be imposed, and when is it not worth it?

That’s a lot of items, probably too many to think through. Maybe you can tell what I think about them, maybe not, but I encourage you all to consider each one. They’re not hypothetical. Every single one of those has a concrete example in JMRI’s history. Some were routine, a few more were easy, but some of these were very very hard. People want to make changes, and other people don’t want to get stuck with the work and/or side-effects. And that happens in lots and lots of ways. It would be good to consider them now so as to have come context when the next time one comes up.

Underlying the differences of opinion seems to be a larger question:

What it the relative importance of each of the following in the future direction of JMRI:
- cool new CS features, structures and tools in use
- clean library structure that’s usable externally
- more tested and certified code as a part to the future
- cool new app features for model railroaders

100% of any of one those four is not OK. But is 25%/25%/25%/25% the goal? If at least half should be on features and future is important, are we talking 10%/10%/20%/50%? If some developers are interested in using JMRI to learn about new techniques and cool tools, does that mean 25%/25%/10%/40% is the goal?

And once you have an idea of which is important, are there any more things that can be added to the list? What fraction of the future direction should be assigned to each of your new ones?


Bob Jacobsen