
“People who implement new and improved interfaces always seem to get that wrong” - vfc1
https://lkml.org/lkml/2015/9/9/602
======
lighthawk
“People who implement new and improved interfaces always seem to get that
wrong.”

Linus is completely right on this. I have seen this over and over again where
developers, creative and problem solving as they are, attack things with their
limited experience and knowledge and fail to understand things fully before
heading in like a bull.

There is a time and place for that sort of behavior, though. Linus wrote Linux
with that same mentality. Sure, he was exponentially smarter and more able. :)
But, that was the time for starting fresh with a cavalier attitude. However,
if you try to contribute something like this to Linux today, as mature and
stable as it is, and majorly screw it up, yes, you are wrong and expect your
ass to get chewed.

I just worry for Linux's sake who, if anyone, will be able to replace Linus if
he were to choose to retire or were whisked away by aliens (I won't say die).
Some related discussions about that:

[http://ubuntuforums.org/archive/index.php/t-424721.html](http://ubuntuforums.org/archive/index.php/t-424721.html)

[https://www.reddit.com/r/linux/comments/2fnnva/what_would_ha...](https://www.reddit.com/r/linux/comments/2fnnva/what_would_happen_to_linux_kernel_if_linus/)

~~~
jordanlev
> attack things with their limited experience and knowledge and fail to
> understand things fully before heading in

Over the years I gradually came to this core truth of programming: solving
problems is easy, it's _understanding what the problem is_ that's hard.

Kinda sorta similar to "it's not about coding, it's about modelling":
[http://www.chris-granger.com/2015/01/26/coding-is-not-the-
ne...](http://www.chris-granger.com/2015/01/26/coding-is-not-the-new-
literacy/)

~~~
npizzolato
I found a quote recently by G.K. Chesterton about this that I really like.

"In the matter of reforming things, as distinct from deforming them, there is
one plain and simple principle; a principle which will probably be called a
paradox. There exists in such a case a certain institution or law; let us say,
for the sake of simplicity, a fence or gate erected across a road. The more
modern type of reformer goes gaily up to it and says, “I don’t see the use of
this; let us clear it away.” To which the more intelligent type of reformer
will do well to answer: “If you don’t see the use of it, I certainly won’t let
you clear it away. Go away and think. Then, when you can come back and tell me
that you do see the use of it, I may allow you to destroy it."[1]

[1] [http://www.chesterton.org/taking-a-fence-
down/](http://www.chesterton.org/taking-a-fence-down/)

~~~
GrinningFool
That used a lot of words to say very little.

~~~
simoncion
It _appears_ to be less true now than in days past, but humans are -first and
foremost- storytellers. we like to tell stories, we like to listen to stories,
and we -often- better remember lessons imparted in the form of a story.

Moreover, if you're trying to alter someone's opinion about the truth of a
matter, you almost _always_ need bolster your core argument with supplemental
material. You often don't know much about your listener's background, you
probably don't know what motivates him, and he may very well be opposed to
your core argument for entirely unreasonable reasons. It's often best to
surround your core argument with a large, somewhat varied structure, so that
many folks will find _some_ way to latch on to it.

------
thomasahle

              if (isdigit(*str)) {
      -               io_tlb_nslabs = simple_strtoul(str, &str, 0);
      +               str += parse_integer(str, 0, &io_tlb_nslabs);
    
      and obviously nobody spent even a *second* asking themselves
      "what if parse_integer returns an error".
    

Can anybody explain why parse_integer would return an error, when
isdigit(*str)?

Also, why is the result (presumably integer) added back to the string?

EDIT: Regarding to "adding to the string" I realize that's just C pointer
arithmetic.

~~~
detaro
EDIT: I'm wrong, victorNicollet spotted my mistake. I thought that:

    
    
        str == "09"
    

fails. Leading zero indicates base 8 -> 9 is an invalid digit.

But that is parsed as "0" and the 9 is left in the string.

~~~
jandrese
IMHO, "leading zero indicates octal" is as old as it is wrong. There are a
handful of cases where this is helpful, and an ocean of cases where it breaks
things unexpectedly because someone tried inputting prettyprinted data.

At least with Hex you can't mistake the 0x prefix for anything else.

One of the best features of inet_pton over inet_addr is that the former
doesn't do automatic conversions and instead assumes every field is a decimal
number. The latter has a hidden trap where 192.168.0.11 is different than
192.168.000.011.

~~~
acveilleux
Yeah, so it's a wrong thing in 2015 where the only significant use of octal is
in unix permissions which themselves are only octal because of PDP-7/8.

The 9/18/36-bits architectures have lost but octal conventions of C was made
on the PDP-7 (18 bits) and until the early 1980s, 36-bit machines were
commercially available (PDP-10.)

~~~
SixSigma
I use octal with tr

------
unfamiliar
String processing in C is a nightmare. It looks like you basically have to be
omniscient to avoid every corner case and potential error.

~~~
AndyKelley
String processing in computers is difficult. You have to be careful to avoid
every corner case and potential error.

~~~
ExpiredLink
> _String processing in computers is difficult._

Not in e.g. Java and many scripting languages.

~~~
ori_b
Write a function that takes three Unicode strings, concatenates the first two,
and returns whether they are equivalent to the third.

If your answer is "use a library", that holds for C too.

------
shmerl
_> We had similar issues with the completely moronic and misdesigned crap
called "strlcpy()", which was introduced for similar reasons, and also caused
nasty bugs where the old code was actually correct, and the "converted to
better and safer interfaces" code was actually buggy._

What's wrong with strlcpy? When I need one, I take the code from OpenBSD:
[http://cvsweb.openbsd.org/cgi-
bin/cvsweb/~checkout~/src/lib/...](http://cvsweb.openbsd.org/cgi-
bin/cvsweb/~checkout~/src/lib/libc/string/strlcpy.c?rev=1.13&content-
type=text/plain)

Reasons for having it are surely not moronic because it provides security
benefits.

~~~
teacup50
It's not strlcpy he had an issue with.

His issue was converting a whole lot of code over to strlcpy() while
introducing bugs that didn't previously exist.

For another example of this kind of irrational thinking, look at NeoVim's
massive churning changes to the Vim codebase for the purposes of
"modernization".

~~~
justinmk
What changes to Neovim are you referring to?

We are generally very careful about "cleanup" patches in Neovim. Some
examples:

[https://github.com/neovim/neovim/pull/2418](https://github.com/neovim/neovim/pull/2418)

[https://github.com/neovim/neovim/pull/1788](https://github.com/neovim/neovim/pull/1788)

[https://github.com/neovim/neovim/pull/1340](https://github.com/neovim/neovim/pull/1340)

At least one tangible benefit to some of these changes is that it allows us to
enable -Wconversion.

We've also rejected dozens of cleanup patches for quality reasons.

------
jandrese
I'm curious what Linux has against the strl* functions. He says that they can
be implemented wrong too, but it seems like they are harder to screw up than
the strn* versions that required you to manually terminate the string when it
hits maximum length.

~~~
mzs

      $ ./a.out kjv.txt
    

Hmm... Why is this taking so long?

    
    
      ^\
      $ db core
      ...
      a.c:28:strlcpy(dst, src, 8);
      ...
      > d src
      0040000: 496e 2074 6865 2062 6567 696e 6e69 6e67  In the beginning
      0040010: 2047 6f64 2063 7265 6174 6564 2074 6865   God created the
      0040020: 2068 6561 7665 6e73 2061 6e64 2074 6865   heavens and the
      0040030: 2065 6172 7468 2e20 4e6f 7720 7468 6520   earth. Now the 
      ...
    

Oh, that's why.

~~~
jandrese
That doesn't explain anything. The manpage explains the problem though:

RETURN VALUES The strlcpy() and strlcat() functions return the total length of
the string they tried to create. For strlcpy() that means the length of src.
For strlcat() that means the initial length of dst plus the length of src.
While this may seem somewhat confusing, it was done to make trunca- tion
detection simple.

So strlcpy/strlcat parse all of src regardless of what you pass on that third
parameter. And they'll happily run off the end of the buffer if your string
isn't null terminated. I see what Linus was so mad about now. All because they
want to return the length of the original string instead of the length of the
copied string.

The underlying problem is that C is too limited in return types from
functions. There should really be a fourth (optional) flag to strncpy that is
set if the string was truncated to fit in the new buffer, and the function
would return the number of characters copied, not the number of characters in
the source string.

~~~
mzs
True, but another problem for kernel is when something takes too long, which
is what I was highlighting in a light hearted manner.

The different return is more like what MS does with the _s routines, though it
uses a special length return and flag option.

------
TallGuyShort
>> People who implement new and improved interfaces always seem to get that
wrong.

How many lessons we seem to have to learn the hard way in our careers that
others before us have learned:
[https://en.wikipedia.org/wiki/The_Mythical_Man-
Month#The_sec...](https://en.wikipedia.org/wiki/The_Mythical_Man-
Month#The_second-system_effect)

------
jeremysmyth
Much as I like git, its inconsistencies wind me up sometimes.

Anything that's not very commonly used or immediately obvious tends to be
buried in some arcane option, and not always an option to a command you'd
expect.

This is not a non-sequitur: Linus might have thought good things while first
implementing git, but it's one example of a tool that I use on the command
line but has many, many alternative UIs that all claim to be better (not just
graphical, even CLI) interfaces.

~~~
seiji
Git isn't the best system—it just became the most popular system. [http://git-
man-page-generator.lokaltog.net](http://git-man-page-generator.lokaltog.net)

~~~
0xdeadbeefbabe
Seems to me that it became popular because it was better than other popular
options at the time like CVS and SVN. I use it today because of a choice I
made in the past, and I can use it more effectively today than hg.

~~~
seiji
Git is popular because when GitHub was in full startup mode (and not the
current $350 million in cash, sit-on-their-hands mode), they ran bar meetups
and gave every ruby novice in the world free alcohol to join their platform.

Turns out free booze times tens of thousands of initial users beats the better
interface of hg being advertised on impersonal mailing lists.

At this point, (experienced) people have just gotten used to all the weird
edge cases and overly complex ways of doing things with git, so changing back
to a simpler way is now more complicated.

~~~
herge
The linux project was using git before github even existed, and would probably
still use it even if the rest of the world had chosen, say, bazaar instead.

~~~
0xdeadbeefbabe
hahah I almost forgot bazaar.

~~~
kelvin0
Hey, I still use bazaar and aside from some minor quirks it has been quite
robust over the years.

------
vfc1
this one made me think on improvement refactorings that always break
something, even though the old code needed improvement. Specially just before
releases.

~~~
mreiland
The best time to push to production is Friday afternoon, everyone knows that!

~~~
AnimalMuppet
"I don't always test my code. But when I do, I test it in production."

Credit where due: I stole that from a co-worker named Kalen Braley. (He
doesn't actually do that, as far as I know.)

~~~
deathanatos
[https://www.thinkgeek.com/product/f141/](https://www.thinkgeek.com/product/f141/)
— if you want it on a shirt :-)

~~~
AnimalMuppet
Ah. So my coworker stole the saying, just like I stole it from him.

------
rqebmm
A corollary of "if it ain't broke don't fix it" is "if you can't read it don't
refactor it."

[http://www.joelonsoftware.com/articles/fog0000000069.html](http://www.joelonsoftware.com/articles/fog0000000069.html)

~~~
munificent
It really bugs me that "refactoring" has been taken to mean _any_ code change
(hopefully) without end-user visible effect. We didn't need a new word for
that. Refactoring is about doing that in a _rigously reliable way_.

My rule is, if you don't have _good tests_ , you aren't "refactoring" you're
"moving shit around and praying you don't break something".

~~~
jeremiep
My rule is: tests only check the presence of bugs, not their absence. And is
usually little more than wishful thinking to delude people into believing
their code to be bug-free.

Understanding the code is worth WAY more than having good tests. Most of the
great programmers who inspire me don't write tests but have the deepest
understanding of whats going on.

~~~
npizzolato
I've seen far more problems from people who think they understand the code so
they don't need tests than from people who write tests to check their code.
The best of the best might be able to get by without tests, but us common-folk
stand to benefit a lot from writing tests and listening to the design feedback
they provide.

~~~
jeremiep
While I agree with the general idea in theory, I haven't seen it happen that
often in practice.

More often than not tests will constrain the architecture of the actual system
and result in code that is much more complex than what is required to solve
the problem at hand. People then start having blind faith in their tests while
being completely oblivious to what they don't test. At that point the codebase
is such a mess that you do need tests to maintain it.

People who focus on understanding their code work very, very hard to keep
their codebase simple enough to quickly wrap their heads around it. I know I
modify my codebase way too much for it to have tests - I'd spend more time
refactoring the tests than progressing and I wouldn't be able to simplify the
architecture as much because my attention is now on how testable the code is
rather than how simple it is.

I see projects shipped with unittests that still required maintenance and
debugging 6 months down the road, and others without tests that worked
flawlessly out the door.

Of course, there's a difference between understanding and thinking you
understand, but that's another matter entirely as we're walking into Dunning-
Kruger territory!

I'm not saying tests are bad! Far from it, I do write tests for functions
where the logic isn't obvious, but my point is that there's too much focus on
testing and not enough on actual quality and simplicity.

~~~
munificent
Sounds like a lot of projects you worked on had tests at the wrong
granularity.

Fine grained unit tests are good for helping you find out _where_ a bug is in
the code, at the expense of calcifying your architecture. "Functional",
"integration", "end-to-end" or other higher level tests don't pinpoint a bug
as easily but in return they give you greater freedom to reorganize your
implementation.

For example, I work on a code formatter:

[https://github.com/dart-lang/dart_style](https://github.com/dart-
lang/dart_style)

It has a metric ton of tests, which is absolutely critical for ensuring a
change to one corner of the formatting doesn't regress other things.
Formatting is solving a bunch of global constraints, so almost every change
interacts with other things.

I've rewritten almost the whole thing twice at this point, and the tests never
slowed me down. That's because they're functional tests: they just run the
formatter and validate the expected output.

It does mean I spent a hell of a lot more time figuring out _why_ some test
was failing, but it made refactoring a joy.

------
hanlec
This got me thinking how much test coverage exist for the kernel. It sounds
like most of those issues could've been caught by tests (and I'm not referring
to API compatibility, but purely to the behavior of the implementation)

------
slxh
Many times, it might be because most people don't like changes when what they
have works, and not because the new interfaces are worst.

------
rancur
can unit tests be written for every use case that's known to work with the old
method, and then used on every new replacement? People wouldn't even get to
submit design changes like this unless it passes all known use cases.

