Live data from Hacker News

Programmers should never trust anyone, not even themselves

carbon-steel.github.io

91–100 of 163 posts

Re: Programmers should never trust anyone, not even themselves

#91

> Failing tests indicate the presence of bugs, but passing tests do not promise their absence. As somebody who primarily lives on the testing side of the house, I've definitely run into cases where the developer promises that their unit tests will make a new feature less buggy, then about 5 minutes later I either find a mistake in the test or I find a bug in something that the developer didn't think to test at all. I…

> ... instances where tests are written too early ... omg yes. However, reading this makes me wonder how the TDD people handle this.

By using TDD, which promotes isolating the changeable surface area to a small area during discovery. That way you don't have to introduce the complexities of API changes across the rest of the application surface area, avoiding the churn spoken of earlier.

Re: Programmers should never trust anyone, not even themselves

#92
post #4

>> Random access of a character in a text buffer could take constant time (for ASCII) or linear time (for UTF-8) depending on the character encoding This is true, but incomplete. All unicode encodings take linear time, not just utf-8. That's because a character can contain multiple code points. Utf-32 allows for random access of code points in constant time, but not characters. Utf-16 has variable length code points…

Really, it's not even random access per se that takes linear time, but random access indexed by code points. You can access the middle of a UTF-8 string just fine if you index by byte position. (Or more generally, by code units for UTF-16.)

Re: Programmers should never trust anyone, not even themselves

#93

> Failing tests indicate the presence of bugs, but passing tests do not promise their absence. As somebody who primarily lives on the testing side of the house, I've definitely run into cases where the developer promises that their unit tests will make a new feature less buggy, then about 5 minutes later I either find a mistake in the test or I find a bug in something that the developer didn't think to test at all. I…

My gift to any team I work with is an integration test harness that usually has some kind of DSL for setting up state. This looks wildly different depending on the project. But my theory is that if tests are easy to write then it is easy to make more of them. So it is worth it to write some ugly code one time under the hood to make this happen.

If every test requires copy pasting a bunch of sql statements and creating a new user and data, my experience is the team will have 3-4 of these kinds of tests. But if the test set-up code looks like `newUser().withFriends(3).withTextPost(“foo”).withMediaPost().sharingDisabled().with…` then the team is enabled to make a new integration test any time they think of an edge case.

Re: Programmers should never trust anyone, not even themselves

#94

> Failing tests indicate the presence of bugs, but passing tests do not promise their absence. As somebody who primarily lives on the testing side of the house, I've definitely run into cases where the developer promises that their unit tests will make a new feature less buggy, then about 5 minutes later I either find a mistake in the test or I find a bug in something that the developer didn't think to test at all. I…

> I've also seen instances where tests are written too early, using a data structure that gets changed in development

That's as clear a signal that they are testing the wrong interface as you can get.

Unfortunately, developers think of tests as testing code, not interfaces. As a natural consequence, they migrate towards testing the most complex break-down of their code as they can; it increases the ratio of code coverage / number of tests... at the cost of functionality coverage.

Re: Programmers should never trust anyone, not even themselves

#95

I think "trust, but verify" (as mentioned in the article) is a much more useful motto than "never trust anyone". The latter isn't an useful attitude, if you took it seriously you would have carefully check or rewrite everything from the ground up. And then you'd either have to trust the hardware anyway or enlist in a course on VLSI design. "Trust, but verify" is much more practicable, at least if you don't feel the n…

> "Trust, but verify"

Even though my entire career has been software, I was an Electrical Engineering major, so I have taken VLSI design (and even designed an 8-bit ALU). My first job was writing embedded software, and would frequently "trust, but verify" the hardware through the use of a logic analyzer.

When I pulled out printouts from the analyzer to show the hardware team that the hardware had a bug, the surprised and incredulous look on their faces was priceless. The blow was somewhat softened by the fact that I'd also found a software bug.

The constant blame shifting between SW and HW teams is one reason I left that job after less than a year.

Re: Programmers should never trust anyone, not even themselves

#96

> Failing tests indicate the presence of bugs, but passing tests do not promise their absence. As somebody who primarily lives on the testing side of the house, I've definitely run into cases where the developer promises that their unit tests will make a new feature less buggy, then about 5 minutes later I either find a mistake in the test or I find a bug in something that the developer didn't think to test at all. I…

> I've generally come to think that unit tests should be used to baseline something after it ships In theory, but I've never seen anyone successfully write tests after something ships. By that time much of the context that should be documented in tests is forgotten.

I've done a handful of tests over the years. Once in a while the original didn't have any tests and I had no confidence I could change it without writing tests. Once in a while the original was buggy and after getting tired of going back top fix bugs I wrote a few tests. Once I had a case where the fix for bug A introduced by B, which the obvious fix was revert this code that made no sense thus bringing back bug A - when someone realized this was happening every year we write a few tests just to stop that pattern.

The above those is a very rare exception. The general rule is once code is shipped management doesn't allow you time to make it better.

Re: Programmers should never trust anyone, not even themselves

#97
> Programmers Should Never Trust Anyone, Not Even Themselves

Yep. Can confirm, the best programmers are often paranoid. I guess over time your brain becomes more logical and you start to notice inconsistencies everywhere around you... Then before you know it, it feels like you're living on planet of the apes.

Re: Programmers should never trust anyone, not even themselves

#98

Earlier quoted context omitted.

I inherited an ancient project that had literally tens of thousands of test. I reviewed hundreds of them, tried rewriting dozens of them. Eventually, realize that essentially all of the tests were just testing that mock data being manually manipulated by the test gave the result of test expected. Absolutely nothing useful was actually being tested. Some team spent a couple of years writing an unholy number of tests a…

The first box on the testing checklist states that the test should first fail. I wonder how they managed to not test anything while seeing the tests transition from failure to success.

From the GP: mock data being manually manipulated by the test gave the result of test expected.

These tests are easy to write - your mock returns something, and then you verify that the API does nothing (thus the test fails), then returns whatever the mock does and the test passes. These tests are easy to write and they do fail until code is written. However they are of negative value - you cannot refactor anything as the code only calls a mock, and returns some data from the mock.

Re: Programmers should never trust anyone, not even themselves

#99
post #20
post #4

>> Random access of a character in a text buffer could take constant time (for ASCII) or linear time (for UTF-8) depending on the character encoding This is true, but incomplete. All unicode encodings take linear time, not just utf-8. That's because a character can contain multiple code points. Utf-32 allows for random access of code points in constant time, but not characters. Utf-16 has variable length code points…

IMO within a small range iterating isn't too painful. It's probably safe, maybe even close enough to optimal for typical use, to have an array or list of bytestrings for each line. Or maybe more complex Line (of text) objects that record the byte-length, 'codepoint'-length, and '(display)character'-length. There might even be special cases built in for typical and massive documents (number of lines) and overly long l…

In most real world cases N is small and so a linear search for data beats a binary search - the binary search is going to stall the pipeline with cache misses all the time, while the linear search will prefetch everything into the cache before you need it thus resulting in not pipeline stalls.

Of course different computers (CPU, memory configuration... they all matter) have different characteristics so where N is large enough is different for each. However in general linear search is fast enough these days. Where it isn't you can look at a profile to verify you hotspot.

Re: Programmers should never trust anyone, not even themselves

#100

> Failing tests indicate the presence of bugs, but passing tests do not promise their absence. As somebody who primarily lives on the testing side of the house, I've definitely run into cases where the developer promises that their unit tests will make a new feature less buggy, then about 5 minutes later I either find a mistake in the test or I find a bug in something that the developer didn't think to test at all. I…

> ... instances where tests are written too early ... omg yes. However, reading this makes me wonder how the TDD people handle this.

Why would anybody doing TDD have tests highly coupled with the implementation? They shouldn't have this problem at all.

The GP diagnostic isn't good here. Those are bad tests, not tests written too early. What doesn't mean you shouldn't wait for your functionality to be accepted before testing it; some times you should; but this happens for completely different reasons.

Post reply on HN