> Things like indendetation, formatting, naming – god forbid you did it differently than I would have.
I agree with chilling out about this when it's a human making the changes...except now that we have autoformatters we can actually be more pedantic about this than ever before :) If the autoformatter doesn't agree with what you wrote, bam, red CI.
> Everyone writes tests
A big thing I've learned over the years is that making your code testable often takes more foresight and experience than actually writing the tests. "What's the right way to test this?" becomes an important question when starting something new. And "Can we make it easier to test this?" becomes an important question when inheriting something.
This is why a lot of people don't test or claim that testing takes more time since "we spend half our time fixing the tests" - a lack the experience to design code that's testable.
I think it's also worth pointing out that up to a point, code that's testable tends to be more maintainable. This largely has to do with coupling and cohesion. Code that's hard to test in indicative of too much coupling and/or not enough cohesion.
This pendulum can swing too far the other way though. I hate when relatively straightforward code is made more complicated in the name of testing (often comes up when dealing with non deterministic sources of data, such as the current time). But this, in my opinion, is a comparatively small problem.
100% you should test private functions if it makes sense. Whether something is public or not has no bearing on the value you'll derive from testing. If anything, sometimes you can avoid real headache by focusing specifically on the private function (by definition, the private function has to be more focused than the public function calling it).
>I think it's also worth pointing out that up to a point, code that's testable tends to be more maintainable. This largely has to do with coupling and cohesion. Code that's hard to test in indicative of too much coupling and/or not enough cohesion.
I feel like whenever someone complains that the code is hard to test, there's always someone who's quick to claim that it's just indicative of problems with the code itself, rather than an issue with writing tests. This rings false to me.
Making code testable is simply one aspect that you need to take into consideration when writing code, along with readability, extensibility, modifiability etc. If you remove one of those constraints, it often becomes easier to focus on optimizing for the other constraints. I don't believe that adding testability as a constraint somehow makes the code better - more often, it just forces you to write the code in a certain way which feels 'logical' when considering the constraint of testability, but makes it harder to optimize the other constraints. The feeling of 'revelation' when you end up needing to modify code to make it more testable is mostly just the constraints imposed onto the code.
In my experience people who learn about “testing” learn an inflexible TDD based version where everything has to be covered in unit tests, meaning everything has to become overly complicated so dependency injection will work instead of merely creating the only thing you’d ever want it to use.
If you’ll allow other things like integration tests as the first level of testing, things get simpler. Unit tests aren’t the only kind of test and in fact they’re the least good kind.
Much of the time, once my code is the way I want, there's almost nothing to test. Any tests I write would just be an echo of the implementation itself. I think if you're using your static type system to its fullest and writing clean, "obviously correct" code, 80% of your tests are simply not necessary at all. It goes:
The type system does help a lot, but I find the tests matter more for the next engineer(s) who need to touch your code. Modifying code you didn't write and don't 100% understand while being sure you didn't break existing features is priceless.
You definitely have to write fewer tests in well typed languages like Rust, but you still need some tests! Maybe 1/3 as many as in something like Python, rough guess.
Testing is to ensure your code functions the way external users expect it to. There's a reason SQLite has an extremely robust test suite even if their code is great.
Testing that the internal interfaces / abstractions in your system is less important - which I believe is what you're getting at. Those tests are definitely echoes of the implementations. Often they're for other developers.
I don’t get what you mean about autoformatters. For me they run on save so it’s pretty hard to get errors from them. And I found the big advantage was not caring about formatting at all. I could write a long line and have everything rearranged and indented with a keystroke, and I didn’t need to worry about eg maintaining vertical alignment in the code or whatever.
The idea is that you run them on save, but you also run them again in CI in a "fail if you would've made changes" mode, so that if someone has their editor misconfigured or edits text with cat or whatever you still force them to run the formatter somehow before they can land their PR.
I agree with chilling out about this when it's a human making the changes...except now that we have autoformatters we can actually be more pedantic about this than ever before :) If the autoformatter doesn't agree with what you wrote, bam, red CI.
> Everyone writes tests
A big thing I've learned over the years is that making your code testable often takes more foresight and experience than actually writing the tests. "What's the right way to test this?" becomes an important question when starting something new. And "Can we make it easier to test this?" becomes an important question when inheriting something.