Controversial Programming Opinions (2012)
programmers.blogoverflow.com
programmers.blogoverflow.com
I think this opinion is much misunderstood.
It should read: people who are not interested in what they are doing are unlikely to ever become very good at it.
People who are interested in a topic will have their brains work overtime at different times of day, will be picking up information even if they are not specifically looking for it, will be trying to understand stuff they are not specifically required to, and so on.
As pointed by some people (like David Allen) our brains have something called Reticular Activation System which, if programmed, brings to our conscious attention when something interesting happens. And then we will also have easier time keeping focus.
People who like coding will probably not see it as only work but also choose to do it in their own time and that usually results in private projects.
I do electronics at home and this usually includes some kind of microcontroller and coding, just because I like it. But I don't have public repositories and I don't do open source projects because I do my own fun projects at work and get directly rewarded for it.
The truth is that (good) interviewers don't care when/where/how you acquired your skills and knowledge. They just care that you have the knowledge and ability, and also that your learning is on a consistent upward trajectory.
We ask if people do side projects not because side projects are mandatory, but because the goal of an interview is to surface any and every reason to believe the candidate is qualified. In practice, most engineers don't put side projects or hobby projects on their resume or even their GitHub profiles, and they won't spontaneously bring it up during the interview. Asking if they've worked on any fun hobby projects usually strikes up good conversation, loosens up the candidate, and maybe unearths some skills and interests that don't show up on the resume.
If a candidate says they don't program outside of work, it's not a negative. It's neutral. We just move on.
I look for signs that the person is interested in what they are doing. Private projects with public repositories are a sign but nowadays I see people started showing up who force themselves to do these projects just to improve their interview prospects.
I even had one person admit it when it was obvious they can't tell me anything about their own project.
Obviously, this is a result of a very know effect where judging performance based on some measurements causes people to pervert this measurement.
Other signs that people overlook and misunderstand is deep knowledge on any topic related to software development. If somebody could acquire good, deep understanding of at least one topic it shows they were likely at least at some point interested in it.
People are sometimes put off that I seem to be asking large number of hard questions and then grilling to death, but that's what I am doing, looking for signs of being interested in something.
I even have one question where I ask: What is the question you would like me to ask you? That's just another occasion to have a discussion on something where the candidate can demonstrate their deep knowledge.
As an interviewer, it's fascinating to read forums like /r/cscareerquestions where people are working hard to game the interview system. Coding Bootcamps have also become bad at training students to pass interviews by practicing coding questions and putting cookie-cutter "side projects" in their GitHub profile.
One of our local coding bootcamps had students post their class projects to GitHub as "side projects" to show to interviewers. The catch was that every graduate from the boot camp had the exact same "side projects" that followed the same formula.
As an interviewer, it's amazing to see people arrive at interviews with an idea that we're just robots trying to check items off of a checklist. The internet pop-culture view of coding interviews is that they're just arbitrary gatekeeping that can be bypassed if you simply know which magic words to say to your robot interviewers.
Tip for interviewers: Speak to your interviewers as if they were your future peers or managers.
Interviewers and interviewees have different incentives.
My job as an interviewer is to see through bullshit as efficiently as possible and decide on some realistic compromise when selecting candidates.
I also sometimes look for job myself. Technically, I could go with the flow and do whatever other candidates are doing. But I don't want to and I don't need to. I have over two decades of both development and interviewing experience and I know that just being myself and not trying to impress anybody is already going to impress interviewers a lot.
I gladly offer information about which parts of the requirement I am lacking and also I will immediately say that I don't know something when I don't -- without trying to impress on the interviewer that I know more than in reality. This alone lets me stand out from other candidates.
There is one more reason not to try to game the process. It is the most important one. I want to be building trust with my manager from day one. Misleading about my knowledge and experience is best way to immediately taint that cooperation.
That exposes a real problem. WIth people gaming the interview process that is good advice.
But it surely it is part of the process that leads to mono cultures? Workplaces with 25-35 year old white men? (Or what ever)
How can you get a diverse good group? Does diversity matter? I think it does, am I right?
When you get that one job, you want good relationship with your manager. Trying to game the system means your manager will have higher expectations that will not be met, causing possibly dissapointment or trust issues.
By trying to game the system you have almost 100% chance of damaging your future relationship. You need to ask yourself whether that's something you want.
The crazy part is that some of these interviewees even have work experience and ought to know better!
This depends on the person and company doing the interview, I think. I work as a consultant implementing a specific software package and recently interviewed with a Unicorn trying to switch to mroe general purpose coding. The difference in the process is night and day. When I do interviews with consulting firms it's almost always someone with significantly more experience than me. And they are usually pretty free flowing and in depth discussions.
The Unicorn interview was 100% checking boxes. I had 4 leetcode style coding challenges and the only thing that really mattered was solving the problem. The discussion ones were pretty obviously interviewers asking questions from a piece of paper. The only goal there was to give them something good enough to write in the box so that it would pass later review.
I had one where we solved the problem half way through the session and went on a big tangent about how to engineer a solution to a related fuzzy problem.
I do agree though that interview standardization can lead to mediocre interviewer practices if the interviewer isn't truly committed to improving their recruiting skills (which is sometimes the case if a team is on a crunch, for example).
The programming in your free time comes up all the time because people, like the OP, see it as a signal. If you do it, you're good. If you don't, you're bad.
And specific to your point - "do you code in your free time" as an interview question - if it didn't provide you with signal that you thought was useful in determining the quality of a candidate, you wouldn't ask it. So, why are you (interviewers in general) asking it?
I don't think it is going to be very controversial when I say that people who are enthusiastic about programming, have experience completing projects, can solve difficult problems, can show they have knowledge of concepts, are intelligent and know how to work with other people tend to do just that -- perform better at their jobs.
Also, I don't ask "do you code in your free time". I ask for any projects private or professional they have been working on recently that they think are fun and interesting.
I've noticed this in my software work. When I'm on a project that I'm personally excited by, I feel like I'm firing on all cylinders and am vastly more productive. Driven by COVID fear, I switched jobs over the summer to a company that would allow me to work from home. I'm not at all interested in the project I'm working on. And I feel like it shows...I don't retain things that coworkers have already explained, I don't feel a drive to learn more than necessary about the domain, etc. Maybe some of it is just COVID-brain, but my goodness being interested in your work makes a world of difference.
Not everybody has to be uber excited about everything they do. I surely can empathize with every person that wants to have a well paying job but just don't feel anything towards anything that is well paying.
Just set your expectations realistically. If you are of slightly above average intelligence and you are not uber excited about programming (ie. typical developer), chances are you are never going to be rock star developer. Plan your career realistically taking that into account. Maybe work in area that doesn't require changing entire stack every 2 years?
My friend decided consciously (we had a discussion) he is not ambitious but still wants to earn. He is now Cobol developer working with people that are on average twice his age. He has been and will be well paid for many years. He works 8h day, has time for his kids and other interests. He says he couldn't be happier.
More specifically, I wouldn't call solving Project Euler problems "software development". It's a game, a puzzle, that requires programming. And I wouldn't call requirements analysis, UI design, testing, etc., "programming", But they are fundamental aspects of software development.
It's possible to treat programming as a calling and software development an occupation.
* 1-based indexing is superior to 0-based indexing.
* If you use spaces to indent code, or in any way rely on a fixed width font to "line things up", you have a fundamental misunderstanding.
* Relatedly, the 80 column "rule" is as stupid in code as it would be in prose. Use your aesthetic sense.
* Vim and Emacs both have terrible user interfaces, and are an inferior experience to even a normal text editor let alone a decent IDE. Users have Stockholm Syndrome.
* For beginners, BASIC is great and Python is terrible.
* There are many languages with a 'mystique', like Lisp and APL. The correlation between 'mystique' and practical utility is inverse.
* Source code should liberally use Unicode symbols.
* Sigils to indicate variable type are actually pretty great, especially if enforced by the compiler. (See above regarding BASIC)
Let the flames begin!
We are not typesetting; formatting resources should be kept to a minimum to make the code easy to handle in plaintext. Fortunately, code is restricted enough that we can do pretty well without those.
You don't write spaces to align text in Word: it's a nightmare to maintain and the software provides better tools for that purpose. Why do we still write code as if we were using a typewriter?
You may think you are improving readability by aligning columns of text, but then, the impossibility of standardizing such baroque formatting rules goes against that. Furthermore, you are preventing people from using a variable-width font, which is actually better for readability.
I find tabs better for indentation but in practice end up using spaces.
Horizontal scrolling is almost always a bad experience for the user. But 80 is way too restrictive. I'd say no more than half a standard monitor wide is the character limit. What's a standard monitor depends on what's used by the devs writing the code of course.
> Source code should liberally use Unicode symbols.
Give it a few years. But make sure there's a good normalization (there are several ways to print the same glyph on the screen that are different bytes in memory)
Also 80 columns is near impossible to adhere to for more verbose language.
E=m*c^2 or
objectEnergyInJoule = massOfObjectInKilograms * speedOfLightInVacuum^2 ? a = b/c
or numApples = numBananas/apple BananaConversionRateI would rather give a function the descriptive name in such a way that the parameters can then be given trivial, mnemonic names.
Strawmannish example:
incrementAccountBalance(a, n)
{
...
}
The descriptive function name gives away what a and n are, so it is unhelpful to make this: incrementAccountBalance(account, amountToIncrementBy)
Reasonable middle ground: incrementAccountBalance(acct, delta)Further, non-descriptive naming often assumes that the programmer reading and modifying the code has domain-specific knowledge. That might be true of mid level or senior engineers have have been with a particular company for years, but the new grad coming into a financial services company (a field he has no training or familiarity with) will have no idea what "a" or "b" means. I was in that position, and the descriptive naming absolutely would have helped me to learn and become productive with the codebase faster.
I'd say that your reasonable middle ground would be the best practice.
Not if you use Unicode (and Chinese language).
I thought the rule was ridiculous - until I realised one of my colleagues had set his computer up with 3 tmux sessions side by side, each perfectly fitting a 120 column code window. He never had to scroll sideways, and he was very productive with his setup. The fact he knew exactly how wide to make his terminals made his workflow much better.
I don’t follow that rule on my own projects, beyond keeping line lengths “reasonable”. But that rule might be on to something.
120 characters/3 columns is great for more verbose languages, but I find it a bit too wide for a vertical split on a 15” laptop monitor.
Emacs on the other hand, has the problem you describe, and probably always will because of how hard xdisp.c is to modify and because the maintainers of Emacs probably do not consider the problem important enough to justify a big change to xdisp.c.
I was never a vim user, but my cursory investigation led me to conclude that vim, too, has the problem you describe.
So if "monitor wide" is 80 characters, like a DEC VT-100 terminal, or WYSE-50 or whatever, then we have a 40 column rule.
By the way, what's the misunderstand with lining things up?
Fixed width:.good
Flexible:....not good
.............so not good
const ONE = 1;
const MILLION = 1_000_000;
Even without non-whitespace it's a problem:def foo(arg1,
........arg2,
........arg3)
For the second one, I'd write it this way.
def foo(
....arg1,
....arg2,
....arg3)
I prefer that even in a fixed width font.
> If you use spaces to indent code, or in any way rely on a fixed width font to "line things up", you have a fundamental misunderstanding.
As long as the limitations of lining things up "exactly" are avoided, spaces shouldn't be any different than whatever way comes from true understanding.
If anything, the editor should "render" the text in a form that is pleasant to the eye, divorcing the meaning from the presentation.
Lining up things too much is a "works for me" way of baking presentation into the data, where the writer assumes that because it looks good o their setup, it will look well for the reader too.
Similarities can be seen to building web pages on tables, sending around Word documents, or hard-wrapping emails.
The real problem comes when people start aligning things on the middle of the line.
So instead of this:
def some_method(param1
param2):
statement1
you do this: def some_method(
param1,
param2):
statement1
Hanging indents work regardless of whether you use tabs or spaces for indentation.I will add:
* Tabs > spaces
* Proportional > monospaced
* White background > dark theme
But holy cow the white background made me angry hahah
I don't know if I use tabs or spaces anymore. I hit tab, but my IDE just sort of makes it up from there. Works well enough.
Pascal was the first language I was taught in.
I still have not (after 40 years) learnt Python... Hang on, when did Python start....That long
10 PRINT "Retardo_88"
20 GOTO 10
To fully grok this, the concepts you need are: the idea that you can instruct a computer to do things, the notion of source code as a list of such instructions which will normally be executed one at a time, in order, and - crucially - that the instructions can reference other instructions and that this is the fundamental leap that makes computers interesting. In other words, Turing Machines 101. It's a perfect demonstration.Now consider the simplest equivalent program in Python:
while(true):
print("Retardo_88")
In addition to all of the insights mentioned above, you need the concept of higher order control flow statements, the concept of nested execution, the concept of boolean literals, the concept of a function call... there are so many questions that are hard to answer. Why do I need parentheses? Why do I need the colon? What's the deal with the indent? What gives with the weird grammar of "while true"? Etc...It gets worse the moment you want to do anything nontrivial and have to wrestle with objects, methods, and dot-syntax. BASIC sends the message that computers are simple, easy to grok things that follow simple, logical rules; Python sends the message that they are a bottomless well of dizzying complexity.
A great intro CS curriculum could be some RISC assembly -> C -> Lua -> Haskell -> Agda, maybe also branching off into lisp and prolog.
If you wanted to get really extreme, you could even tack on “Discrete transistors -> logic ICs -> FPGA ->”
No thanks. Hard pass.
!@#$%^&*()_+}
On a related note, if I could get a keyboard with an extra 50-60 keys that would send the proper scan codes to type unicode characters in one keypress that would be awesome.
https://www.pckeyboard.com/page/product/UB40B5A
Then there are the point of sale keyboards, this one has 60 keys you insert your own paper labels.
https://www.officedepot.com/a/products/361528/CHERRY-SPOS-Sm...
In this instance the Unicomp keyboard is not reprogrammable, while the Cherry is fully programmable.
I don't care about the indentation method, I just want to press Tab, or Ctrl+S and have it do the right thing. Not waste any brainpower thinking about it.
Although given that I, random internet stranger, agree on 6 out of 8 of your points, it mean that they aren't too unpopular. :)
there is a common perception that programmers often don't get statistics. Not that I do either, but just saying.
What if I just like the aesthetics of consistently-indented code?
> 1-based indexing is superior to 0-based indexing.
this breaks the identity `arr[idx] == *(arr + idx)`. as a c++ (and sometimes c) dev, I tend to consider "index" and "offset" to be functionally equivalent. hard pass.
> If you use spaces to indent code, or in any way rely on a fixed width font to "line things up", you have a fundamental misunderstanding.
I find "lining things up" to be pretty helpful for spotting mistakes in tedious code (eg, matrix initialization) where you have a bunch of similar lines of code in a row. am I missing your point, or do you just not agree this is useful?
And I think that's the problem. Programmers have collectively conflated the concept of "offset from the address" and "position in the list" as the same concept, and they're not the same thing. Both concepts have their uses but they're separate distinct concepts. C and C++ don't index* a list, they simply offset it, and too many other languages that don't care about in-memory addresses or offsets have carried the concept from offset over to index erroneously.
I believe there is a few languages which can let you set it
Well, then, make the identity `arr[idx] == * (arr + idx-1)`.
Your identity perfectly illustrates why 1-based arrays are worse rather than better.
I'm hundreds of times more likely to have to write lastElement = array[array.length - 1] (there's the 1 again!) than I am to have to reason about the equivalent pointer arithmetic.
And for that matter all algorithms for which zero-based indexing makes more sense are simpler, such as working with polynomials and expansions where the zeroth power is included in the expansion.
Having said that, I too prefer 1-based indexing because the list of algorithms that are written more cleanly (i.e. without constantly causing bugs when you implement them) is far larger for me personally, including all of linear algebra and related numerical methods.
That is, are there any languages that are both one-based, and will let you do that trick?
Well yeah, the UI isn't great. The whole point is to make it your UI, no?
I agree that Python isn't great for beginners, but I don't think BASIC is great either beyond a simple introduction to how we make computers do our bidding.
Forces okayish formatting, error codes are pretty readable, good library support for doing everyday useful things (for people not in the cs community), you don't have to strictly worry about type for your tiny scripts...
Why do you think it's not great? (in all sincerity)
The indentation is nice, but the language is not much more high-level than C, teaches bad habits by not thinking in types and granular interfaces, and encourages a counterproductive style of defensive programming - i.e. C++ is an awful language, but at least I can encode basic information about my code in the type system. Python trades that away so I have to write tests for the entire surface area - inside and out - of my code.
If there is something fundamentally wrong with my code, tell me now, not when it's half way through a job or worse attached to spending money.
You can write bad code in any language, but bad languages influence the way you think about programming. For example, C++ encourages you to think about side-effects in the language like SFINAE, D encourages you to metaprogram everything, Rust encourages you to think like a compiler (lifetimes), Haskell teaches you how to manage stateful code in a controlled and measured manner, etc. etc.
In conclusion, Python is not a terrible place to start (JS takes that award to my eye), but the progression to writing genuinely reliable and fast code is too obfuscated. I'd rather we teach people C. C requires a helping hand, you can fumble around with Python.
“Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.” - Stan Kelly-Bootle
Previous Lisps were impractical largely due to lack of libraries, but Clojure comes with first class Java interop out of the box. But you still get macros.
You, though, you're getting there.
lol tell that to the banks and trading firms that pay Arthur Whitney millions for his APL interpreter that looks like something out of the IOCCC
1-based indexing is a special case of 0-based indexing.
* If you use spaces to indent code, or in any way rely on a fixed width font to "line things up", you have a fundamental misunderstanding.
Fundamental misunderstanding of what? Not having shit PRs on Github?
* Relatedly, the 80 column "rule" is as stupid in code as it would be in prose. Use your aesthetic sense.
Yeah okay true
* Vim and Emacs both have terrible user interfaces, and are an inferior experience to even a normal text editor let alone a decent IDE. Users have Stockholm Syndrome.
Also true
* For beginners, BASIC is great and Python is terrible.
The language for a beginner is irrelevant, the only metric that matters is: Are you enjoying your coding experience? Keeping students coding is all that matters the language is irrelevant.
* There are many languages with a 'mystique', like Lisp and APL. The correlation between 'mystique' and practical utility is inverse.
This is almost a tautology, of course mystique will lead to less practical utility because their is simply less interest, less tooling, and less understanding about how to use the tool.
* Source code should liberally use Unicode symbols.
Someone has never looked at Agda source code before and it shows.
* Sigils to indicate variable type are actually pretty great, especially if enforced by the compiler. (See above regarding BASIC)
Gross.
Yeah, it seems that your evil plan works. People just can't stand it despite your clearly stated intent.
Yes! But programmers are weird like that,I understand the rationale in case of C(Nothing that couldnt be solved then and there) but for high level or scientific computing? How many off by one bugs caused by this?
> If you use spaces to indent code, or in any way rely on a fixed width font to "line things up", you have a fundamental misunderstanding.
Agree, that's one of the things I hate about python, the indentation are probably the worst solution to the problem of scoping code.
> Relatedly, the 80 column "rule" is as stupid in code as it would be in prose. Use your aesthetic sense.
Agree
> Vim and Emacs both have terrible user interfaces, and are an inferior experience to even a normal text editor let alone a decent IDE. Users have Stockholm Syndrome.
Agree, both are very good pieces of software but I feel 99% of the new people swearing by them just do it to try to appear l33t
> For beginners, BASIC is great and Python is terrible.
In 1995? Perhaps. Now? Hell, no.
> Source code should liberally use Unicode symbols.
Hell no.
> There are many languages with a 'mystique', like Lisp and APL. The correlation between 'mystique' and practical utility is inverse.
More or less, great, but difficult, programming languages would never become mainstream, and like good old Joe Stalin used to say "quantity is a quality on its own"
> Let the flames begin!
As always with these type of comment OP is not as alone as they think they are.
The concept of x[k] meaning the object k spaces away from the beginning of x is very general, and still intuitively meaningful in languages without pointer arithmetic.
Because mathematics and physics use 1-based array index since ever? I first learned about matrices in math classes, then in numerical methods (All 1-based) and then we programmed in Fortran (1-based).
It is not that is more logical, it is just a convention. But I have seen wayyyy more people complaining about 1-based index languages than about 0-based languages.
I follow the 80-column rule in prose.
It's an immensely self-documenting and self-explanatory system, and vastly different in that regard than anything else.
(Though once you go down the rabbit hole you eventually start to realize that elisp is a crappy way to program and the whole thing has a big-ball-of-mud architecture... Oh well.)
Point is, your preconceptions, from the heights of your experience, of what "newbies" find intuitive are likely very wrong.
a[b]
is equivalent to
*(a + b)
with a being a pointer and b an integer. this can be seen as well in the fact that
a[b]
is equivalent to
b[a]
where in both cases a is a pointer and b is an integer.
Thus, the index into an array is fundamentally the same as an offset into that array. Usually, in languages that do use 1-based indexing (like in pascal strings), the 0th byte is used for something else.
The point being that thinking in terms of 1-based indices means that you have to use a system where addr+0 is invalid, and the first element of an array at address X is X+1.
Now you could just shift everything by 1 and just declare that +1 means +0, but then you lose all meaning to the offset vs index and ahhhhhh
There are many reasons to depart from this idea in languages far removed pointer arithmetic. For example, Julia has 1-based indexing and I appreciate it for that when doing computational mathematics. It is closer to familiar notation: A[1][1] is the element of matrix A in row 1 and column 1. In a language with zero-based indexing, it is sometimes easier for me to allocate an extra row and column, wasting memory, than to shift indices and risk an inevitable off-by-one somewhere.
By definition, the highest voted answers are also the least controversial. "Anti-establishment" and "populist" maybe. Unpopular? Certainly not.
My controversial opinion is that most software tests should be integration tests that use randomized inputs. I doubt I'll get very many upvotes for that idea.
*racist
If you said php is a pretty good language and I enjoy working with it you may get a lot of closet php developers upvoting you.
A real unpopular opinion is testing is not worth the effort.
Good for fuzzing, bad for determining whether the output is what you expected it to be, because finding out what the output should be is .. the reason you wrote the software.
I've seen this done with an automated spec translation tool that produced an unoptimised but correct H264 decoder and set of reference inputs to achieve coverage of the actual target decoder.
The solution for this is property based tests. Outputs almost never have maximum entropy. They have invariants, and they're related to the inputs in various ways.
Trivial example: authenticated encryption. The input is some random text, some random key, and some random nonce. The result is a message. One property to check is the fact that the message can successfully be decrypted with the same key, and the resulting plaintext will be the same as the random text from the beginning. Another property is that any message that is not the message you computed will fail to decrypt (assuming you pretend not to know the key when as you corrupt the message). Testing (crudely) that you can detect forgeries (or at least accidental corruptions).
I mean consider this example of a "controversial opinion":
> Print statements are a valid way to debug code.
I'd place this about as controversial as "functions with many arguments are an ok choice".
The fact that there is neither a statement about the proper indexing of arrays or which programming language to never use is clear evidence this list isn't about controversial topics.
Probably not, but largely because you used the word "randomized". One of the most annoying things to deal with in a CI workflow is flaky tests (where something unchanged will randomly fail, or re-running will result in a different outcome).
The most common way I've seen this happen is with an external dependency like using a database server or calling a 3rd party API. The failure is usually temporary (eg: timeout) and so it's a false negative. This trains developers to do a lazy workaround: re-run the build until it passes.
True "randomized" data has the possibility that you get all kinds of flaky tests, but that they cause false positives: the failures are legitimate, passing is not.
Pseudo-randomized [1] data is a different story (see: fuzzing [2]), because you still have predictable tests -- the difference is a human doesn't have to think up thousands of test cases. I'd say it's also important to add specific test cases when you do find a specific type of failure, just to be sure that always gets tested.
I think if you call it "pseudo-random" or "fuzz testing" you'll find it's much less controversial.
Just records the input whenever the test fails, and have an option to re-run a test, with those inputs. The tests are still flaky but it doesn't matter if we can reproduce the results.
You don't even have to record all inputs. You could just use a random seed, and record the seed at each run. Test become deterministic again simply by fixing the seed (typically to a value that caused the previous run to fail).
If you want to have the build (test) result feedback to save the input, that's an ok goal but I think it's hard to pull off: now you have your build making commits to source control (causing another build), or you have test data stored somewhere else not in source (when really, it should be part of source).
Here's a link that talks about the above in more detail - https://software.rajivprab.com/2019/04/28/rethinking-softwar...
I use a seeded random number generator. During development I seed it randomly. When crashes happen I output both the seed and iteration so I can hardcode that seed and reproduce the problem. And then in the CI I’ll often fix the seed so the test suite is stable.
But it’s also good practice to run fuzzers outside the context of a CI. You want your CI tests to be fast and stable. Fuzzer tests can also be slow and thorough. Foundationdb has dedicated hardware that runs their fuzzer 24/7 and spits out any errors it finds. If that fuzzer finds problems it doesn’t break the build. But someone will take a look, reproduce the problem, hopefully convert the bug into a unit test and fix the issue.
On a separate note, if the fuzzy tests find something wrong, the data should definitely be integrated in the stable test suite to ensure non regression.
I guess another controversial opinion: this is a problem with the idea of CI (or at least how we work with it and what we expect to get out of it), rather than the idea of randomized tests.
Flaky tests are an indicator of poor code: maybe it's your actual code, maybe it's a bug in the test code, or maybe it's external dependency + lack of error handling in the test code but there's a problem somewhere.
I did admit this was controversial! But it fits in with a more general view that there are a lot of tools which make good servants but poor masters. Auto-builders are a good thing, partly because (as you say) they can help to clarify what is required to make a build, and partly because (especially for dependency-heavy software, which seems to be the norm nowadays) they can help catch things quickly when the dependencies shift beneath you. Making them a hard gate on releases seems a little too close to making the tooling your master, though.
(Somewhat separately, I also worry about CI acts as a hiding place for complexity. Sometimes it reaches that point where nobody knows how to make a build without the CI tool any more. Then local testing and debugging becomes difficult.)
I do also agree that CI can hide complexity, but that's true of any tool as well as non-CI builds. Compared to a human running things, it's at least somewhat self-documenting due to being scripted.
That's not correct because it leaves out motivation to vote. Imagine a controversial question where, say, 1/3 of the population feels super strongly and is likeliest to vote on it. Their view will shoot to the top. Then the other 2/3 will go "wtf is wrong with this community".
But generally I’m with you. Unit testing is overused and often makes code harder to read maintain and build on. That’s aside from it not providing information most unit test advocates think it provides.
I live my life by the "4 good hours" rule, inspired by the book Deep Work by Cal Newport. If I can put in 4 good hours of deep work where I am iterating and learning on a skill, I consider the day a success.
This rule is specific to improving at a new skill in flow state. This does not mean I blow off the rest of the day or refuse to answer emails after those 4 hours. I still exercise, answer emails, write documentation, cook dinner, etc. It just means I choose to be kind to myself after I've achieved those 4 good hours.
After you work at a job for a while, things can tend to be come stale and you stop learning. I have a novel approach to this: I find a new job that will actually be challenging. This is actually harder than you think!
In Deep Work, Cal estimates that you have 4 good hours of learning in you a day. Hell: You probably have less. The four hour rule refers to virtuoso violin players[0] who I am willing to admit probably have more talent and dedication than my stoner self.
0: https://www.johndcook.com/blog/2013/02/04/four-hours-of-conc...
It would have to be actual work though. Do we all honestly think the average developer would genuinely be able to set aside all the internet distractions and put their 6 hours in (2 hours communication + 4 hours development)?
That said, I think it's a mistake to believe that there is an upper limit on productive hours in a day. I'm part of a mentoring group where I see this idea stated as fact by a lot of juniors. The catch is that they've all read different sources that put the upper limit at anywhere from 4 hours to less than 2 hours per day. This leads to a self-fulfilling prophecy where they stop trying to work after they've reached their pre-determined target, whatever that is.
When working alone or in isolation, I can often put in 10+ hours of measured, productive time in a day. The key for me is to do it in 2-hour chunks, with 1-hour breaks in between to recharge by playing with the kids, cooking and cleaning, exercising, and so on. I wouldn't recommend doing this consistently for an employer, but it's been a huge boost for hourly consulting and working on my own business.
Would you be open to giving feedback as an experienced deep worker?
My goal is convert people like you as opposed to people that have never even heard the term (at the beginning).
trywinston.com (you'll get a bounceback w/ my email for feedback if you sign up)
No worries if not!
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%"
Unfortunately everybody seems to forget about the last bit.
One or two micro-optimizations may not add up to much. But a habit of, say, avoiding unnecessary object churn, might add up to a very large efficiency gain, a few microseconds at a time.
Admittedly this may depend on the domain you're working in. And of course some people may take the advice to an extreme in the other direction but this is (IMHO) rarer and much easier to correct.
Performance is a design issue and it is hard to do as an afterthought. In fact often microptimizations are the only optimizations you can do without changing your design.
That said I would draw a distinction between implementation and design. The surface API needs to be well thought out before hand. But this should be done before writing any real code (exploratory code aside).
value out > value in
(from comments of https://softwareengineering.stackexchange.com/questions/8008...)
That's similar to my reaction to "Unit testing won’t help you write good code." Of course it won't... but you are just using it as an excuse to not test you code at all.
Managers are the last people I'd want to learn on the job this heavily - they can't start from not knowing coding if they want to manage engineers.
A general doesn't need to know how to fly a fighter jet. But it helps if they stay up to date on modern tactics.
One of the most frustrating things working with non-technical managers is their lack of understanding of the effort needed to accomplish a task. Oh you need to re-write an entire library from scratch, work with Joe and have it done by Wednesday (today is Monday).
Now good luck explaining and convincing them that two days is not enough.
A good manager with a good team that includes one or more senior technical people will be able to rely on their guidance and lead the team effectively.
But any non-technical manager with a junior team is a recipe for disaster.
And scaling back, a manager of a cross-functional team is at a similar disadvantage. I work in a field where we mix ME, EE, CS/Software Engineering, IT/Ops, and other fields. A team could consist of people from all disciplines. Hell, right now I am learning the basics of astrodynamics so I can write the software related to it, the lead is an AE and can't code to save their life. They're still an effective leader.
In a previous team, the lead could not manage a Linux server, but still had sysadmins in the team. Did that make them an inherently bad leader? No, they deferred to the expertise of those team members. Like a good leader.
Of course engineering managers should be able to write code.
The worst situations are with those in the middle. "I know what the computer is: a list of PowerPoint documents uploaded in SharePoint, so that's what we're going to do. Also, I don't really understand what you guys do, but here is a new Jira where you have to document it step by step. Then I will read your descriptions, and regularly schedule meetings based on my misunderstanding of what you wrote."
In fact, imagine a manager what wouldn't even go to work, and just let the engineers work alone. Ironically, that would be more Agile than what 90% of companies do.
I don't think that's true, I just think premature generalization is more common among people who have internalized the maxim about premature optimization.
Of course we know this. We can observe it in the huge uptake of static typing and functional/immutable approaches in areas they were uncommon not so long ago. We can see it in the huge rifts over whether/how much to use JS on the web or how to build cross platform UI. But it’s interesting to me to look back and see how dramatically some attitudes have changed on topics that seem almost banal now.
> Amazingly, more than half the candidates couldn’t write this function in any language
I don't think this is true. Or, they were interviewing candidates fresh out of college who never really paid attention in any classes. Or, the problem was presented to the candidate in an overly complicated fashion (which is weirdly common in technical interviews) and the interviewee was confused, although that seems unlikely.
I think it's easy to get wrapped up in this mindset of "oh we need super complex algorithm whiteboarding because candidates nowadays don't know how to code!" when you hear stories like this, and it's just not true -- at least in my experience of interviewing candidates. Maybe I've just been lucky.
"super complex algorithm whiteboarding" is obviously not the answer. You want something so simple no qualified person could fail even under stress, but hard enough that you know that the person is confident in writing if-statements. "Iterate a B-Tree in-order" filters too many people, "compute the area of a circle" is maybe a bit on the easy side.
I'm not sure I could do this without a B-Tree class to look at, people say "b-tree" and really mean one of like 20 possible designs.
Adding knowledge of a relatively obscure operator (can't remember the last time I needed it in real life) just makes it a trivia test.
I can't.
* Fizzbuzz with a loop that has a recursive call inside. * Fizzbuzz with a loop that has two additional, resetable counters
I don't even work as a developer and managed that in less than one minute of thought. Any experienced developer who cannot program Fizzbuzz isn't good.
Man, I used to work with a developer who, in basically all respects was a better developer than I am. But he was terrible for adding these type of pointless comments. When I'd point out in a review that his comment used the same 3 words as the code did in a different order he'd get all defensive.
A data field called "imageURL" that's a string -- is that a remote or local URL? Where did it come from/how much can I trust that it's well-formed? (And why isn't it already an actual `ParsedURL` type?) Another datatype has three fields "name", "username", and "id", all strings, with no explanation of their purpose or differences.
This means that I either have to track down the teammate that wrote the code and ask them every single time I run into something like this. Or I have to execute the whole program and reverse engineer the answer. Both are colossal wastes of time compared to a few "useless" or "repetitive" comments.
//Assign 5 to the val called a
val a = 5;
// Chosen by fair die roll. Completely random
const kEschatonThreshhold = 5;
val a = kEschatonThreshhold;Do you think that's possible for every field in all, or even most, applications and languages? I do not. And so I don't think we should be allergic to a few wasted sentences of prose.
Put that information in your types and (i) you don't need to write those comments and (ii) the compiler can help you check if you haven't made mistakes.
By that logic, the code is already written and doesn't include that information in its comments, either.
> if the person who wrote the code had written a doc comment, I would know [the invariants].
If you're going to ask that the person who wrote the code have written it differently, there's (in general, at least) no reason to ask for comments in preference to types.
To a point. Believe me, there are levels of repetition you would find less tolerable than a lack of documentation. Here's a real world example: we had a bunch of classes with lots of attributes. The getters and setters for those attributes were automatically generated (with a macro), because we had lots and lots of them. In the headers however, we wrote the prototypes in full, so the tools could find them more easily:
Foo getFoo();
Bar getBar();
Baz getBaz();
void setFoo(const Foo &foo);
void setBar(const Bar &bar);
void setBaz(const Baz &baz);
So far so good. Now documentation is an important thing. So important in fact that we had to document every single method in all classes. And since we were using Doxygen, we were a bit constrained. Foo getFoo(); ///< Get foo
Bar getBar(); ///< Get bar
Baz getBaz(); ///< Get baz
void setFoo(const Foo &foo); ///< Set foo
void setBar(const Bar &bar); ///< Set bar
void setBaz(const Baz &baz); ///< Set baz
OK that's redundant, not too bad, and QA is happy now. Well, no. First, we are supposed to be using Javadoc style documentation. Second, we need to document every arguments, and the return values. How are we supposed to understand a getter if we don't document its return value? /**
* Get foo
*
* @return foo
*/
Foo getFoo();
/**
* Get bar
*
* @return bar
*/
Bar getBar();
/**
* Get baz
*
* @return baz
*/
Baz getBaz();
/**
* Set foo
*
* @foo The new Foo
*/
void setFoo(const Foo &foo);
/**
* Set bar
*
* @bar The new Bar
*/
void setBar(const Bar &bar);
/**
* Set baz
*
* @baz The new Baz
*/
void setBaz(const Baz &baz);
And so on, often for 20 attributes instead of just 3. I am not even kidding. Now we could say it's just a matter of space, but it isn't: sometimes, there was an attribute that was a bit special, and the comment reflected that: /**
* Set wiz
*
* @baz The new Wiz. Must not be Merlin.
*/
void setWiz(const Wiz &wiz);
Except the additional comment could as well be absent, because it was totally lost in the noise. I've missed several cogent pieces of information that way.Worse, the tech lead, who acknowledged that this practice was useless at best, and had the clout to have this restriction relaxed, refused to do so. To this day I'm not sure why. I have a couple hypotheses (plain inertia, don't fix what's not blatantly broken, don't want to argue with QA, afraid of regulation…), but nothing solid.
If I had to chose between no comment at all and that, I'm not sure I would chose that. Sure, I would lose valuable comments, but if I already lost them because of sheer noise, I didn't lose much at all.
And the reason is that you're not always just reading the header. When I'm looking at a `setWiz` call site, my IDE can pop up just that one docstring and save me a bunch of aggravation.
You have to actually notice it for it to matter. A missed comment is no better than an unwritten comment.
> When I'm looking at a `setWiz` call site, my IDE can pop up just that one docstring and save me a bunch of aggravation.
Didn't know about that. My IDE never did that (I used Visual Studio at some point, and now QtCreator).
For me comments should concentrate on the why and maybe the how but mostly ignore the what. That should be obvious from the code.
string imageURL; // Url of an image
//Insert new customer into database
_db.Insert(newCustomer);
The number of times I've had to point out how incredibly pointless comments like this are in code reviews is far too high. As is the number of times I've had to point it out to the same developer. //Insert new customer into database
_db.Insert(oldCustomer);
As a reaction to this, I used to work somewhere that had a zero-comment policy. If you wanted to describe something you had to do it in the function and variable names. Overreaction in the other direction.Also, maybe that was a large block of code that was replaced later with a function call. Or maybe the code used to validate things about the customer used to be there before the function call and now that's all been wrapped into the called function.
I would guess that the reality is more nuanced. Programmers who don't code in their spare time will probably find their knowledge becoming out of date. But that's because our profession doesn't really have a concept equivalent to continuing (Medical | Legal | etc) requirements, so we aren't really given an opportunity to sharpen our saw outside of our free time.
But that's only if you're consciously doing it to learn new things. My guess is that spare time programming for the sake of spare time programming actually has a deleterious effect. Though I admit I base this on conjecture and over-inference into scanty evidence. There are some anecdotal observations that colleagues who spend their evenings and weekends grinding away on code have a tendency to also be the ones who have trouble concentrating or make burnt out fuzzy brain mistakes at work. And there's some empirical evidence from other domains such as language learners and musicians that, past a certain point, additional time spent practicing actually does more harm than good. Brains develop fatigue, too.
However I think programming "as a hobby" is a poor metric for judging who is going to be the best programmer, in terms of a hiring process, for two reasons:
1. It's already well-known that many companies will favor people who program outside of work during a hiring process, so many people will try to appear as if they are the kind of person who lives and breathes coding, and cultivating that image is much different than actually getting practice.
2. Raw programming skill is not always the best indicator of how good a contributor to a project someone will be. Sure you have to be competent at coding, but beyond a certain level, assuming the project is not particularly technically challenging like HPC or computer graphics or something, things like communication skills, being able to write good documentation, and being able to produce in a consistent and predictable way play as much a part in the team's success as being a wizard on the keyboard.
And I say that as someone who does spend a lot of my free time coding.
I can think of a lot of reasons why. The AoC problems have a bite-sized satisfaction that a messy real world app may lack, for one thing. But mostly I think it's yet another symptom of procrastination.
I've found that the rockstar coders I work with often produce a very high volume of output that is technically excellent but doesn't actually contribute much to the company's profits.
I suspect that that kind of work output is currently overvalued by the prevailing business climate. FAANG companies can afford a "throw a bunch of stuff at the wall and see what sticks" approach, and venture capitalism pulls that up to a meta level. My own bias is that I've never worked under either regime, so I'm used to seeing a different mix of strengths be more valuable.
In 30+ years of programming, vast majority of bugs I've fixed were diagnosed with a few strategically placed print statements.
"I just print values. When I’m developing a program I do tremendous amount of printing. And by the time I take out, or comment out the prints it really is pretty solid. I rarely have to go back." — Ken Thompson in the book Coders at Work by Peter Seibel
It works a lot of the time (but not always, not great for debugging locks on stdout, for example). If you only have time to learn one debugging technique, this is the one to learn.
- Good abstractions are hardware instructions on layers of steroids. Bad abstractions are tabula rasa models that don't acknowledge the nature of the operations that the hardware is doing.
- "var id: type" syntax is both ugly and impractical.
- "inconsequential syntax details" like my last opinion are actually important aspects of a programming language and not just bike-shedding.
- If a programming language includes a package manager that points to a repository by default, then it's a not a serious programming language.
- Drivers don't belong in the kernel. The kernel should just define an interface for you/manufacturers to write drivers for.
I'm not sure what you mean, having a default repository seems like a sane decision to me. Do you have a language in mind that doesn't do this?
Very few languages include a package manager as part of the LANGUAGE.
Premature Abstraction is the root of all evil.
Don’t panic! The code will be a mess. Let is be a mess. Don’t abstract too early, or the eventual mess that regenerates will be even worse than without an abstraction.
If a part of your application or assumptions in a piece of code haven’t changed for 12 months, then abstract that part of your application. However, only abstract the bare minimum.
I wrote a book called “Relevant Search” and created one of the most popular Elasticsearch plugins (Elasticsearch Learning to rank). I’ve worked in Solr, Lucene, and Elasticsearch for more than 8 years more or less constantly.
I have, at any given time, dozens of google tabs open dedicated to Solr, Lucene, Elasticsearch. Sometimes on basic things to jog my mind.
Knowing how to interpret information online, what exactly to search for, and having memory to be jogged by other context is just part of what it means to have a skill.
Memorizing documentation is rarely a good use of brain cells IMO, even pre google when instead you used a book index/ToC to do the same thing.
Personally I think they're plain dumb. Not saying I can't hide my ego and move on, just that I think they're a massive waste of time on a leaky abstraction rooted in organizations that value talking about things more than doing them.
UML sequence diagrams are pure gold.
I have no idea how you can accomplish anything remotely complex without extensively talking about it (and writing it down!) first. It works fine for 2-months projects, but not for 2-years projects.
Not surprised that this would be controversial.
> 17. Software development is just a job.
A bit disappointed that #17 is controversial in principle, though it is certainly a hobby for some and a religion/obsession for others. Maybe what I'm looking for is "Software development can be just a job and that's OK - it doesn't have to be an all-consuming passion that devours all of your waking hours, even if your employer or boss thinks it should be. People with varied interests can be better developers than people who have few interests outside of software development or computing technology. Most software applications depend on expertise outside of software development, often knowledge in a specific application domain (such as science, mathematics, engineering, game design, business, or communication) as well as expertise in computer-human interaction or sociotechnical design."
Hopefully that wouldn't be particularly controversial, but it probably would be. ;-p
So those are two different meanings of "just a job".
This is a potentially dangerous one, my opinion is (when misinterpreted) this notion will make your product as disposable as your employees.
While the examples given to achieve this are not themselves bad, in the wrong hands the notion of ensuring minimal effort is required to understand any code produced can be used to enforce mediocrity, to make difficult writing good code by reducing everything to the lowest common denominator out of fear of something being too difficult for everyone to understand... within reason, it's important to embrace and exploit qualities not shared by all employees - there is a risk in certain employees becoming difficult to replace, but it's better than the guarantee that nothing of value will be produced.
Heck, if you want a controversial opinion then arguably "disposable engineers" is an openly stated goal of programming languages like Go. [I'm not sure I'd entirely agree with this opinion but I wouldn't entirely disagree either].
Hard disagree. Unit tests themselves, yes, are really only great at regression testing.
Writing code that is unit-testable helps you write excellent code.
I actually think integration tests are vastly more useful than unit tests, and in general unit tests should be employed: a) if you are testing business logic which is not obvious, b) as a method of debugging or c) when it makes it faster to iterate on a particular piece of code during development.
I think excitement about unit-testing has become over-generalized to domains where it doesn't make sense. For instance, in a mobile application unit testing your networking layer does not add value 99% of the time, will be way less helpful than hands-on testing of the UX, and just adds busy work to modifying the code-base because you have to maintain the tests as well.
That's definitely a problem... in Java. I've had to deal with it before (in Java), and I think part of the problem is that people start using that abstraction pattern before there's actually multiple potential concrete implementations. In Ruby, I've applied something like this pattern, except all I'm doing is wrapping the service library to make my own DSL, and it's working tremendously well and allowing for excellent testing.
And yes. Anything can be overapplied / mis-applied, and sure, unit testing might be more susceptible / abused in these ways.
Essentially, I unit-test my functional code (libraries, etc) and I integration test my OO code (actual features, as the whole feature). It's not only a really easy way to test each kind of thing, but enforcing the functional library / OO features has led to (IMO) practically perfect code :D
But that's what I mean: the second concrete implementation is the mock which has been created for unit testing, and this is how unit testing introduces complexity and indirection.
So what I'm doing is that I have a wrapper object with a private member variable that's the client from the service's API library (for this example, it's DialogueFlow). My wrapper then has a function for each basic thing that my code actually wants to do with the library, translating from the plain data objects (or straight arguments) that're in use in the rest of my codebase into the nested object mess that DF talks in (and back again, when there's return values).
Then in tests, I just monkeypatch the private `client` method/variable to return/be the mock. The mock then replicates only the functionality that I actually use from the service's library, which is easy to do since there's only one file to look at for all usage.
I now have my own DSL for interacting with the service, and I understand the service well enough to fake it, which has been super helpful. So far I'm loving it, and it doesn't feel at all like the "where's the !#$%! bean" hell of Spring.
Scrum turns great developers in average developers.
The author points this out as controversial, possibly because it might make people feed bad. I think it’s just wrong. Measuring programmers by output means you’re ranking your team based on who’s doing the most in that context. That includes what opportunities they’ve been provided, their areas of expertise, the level of autonomy they’re given, etc. Getting people to reach their full potential is hard work. Sure, there are developers who require little to no effort to be high performers. Chances are it’s because of the opportunities they were given in the past to get there.
> 6. Not all programmers are created equal [...] In actual fact, the performance of one developer can be 10x or even 100x that of another.
is "wrong" given that
> There can definitely be a 10x difference in “full potential”.
> measuring two developers and saying one is 10x more productive than the other doesn't mean that the first is 10x better, just that they are 10x better at what you are measuring under the terms you are measuring.
If you’re interpreting the author’s statement as an assessment of full potential, then you may be right. I didn’t read it that way, and honestly I don’t think that assessment can be easily made.
None of that seems to imply that the opinion is "wrong" though, it seems more like an orthogonal concern.
If your in a team which helps you succeed you'll perform better.
I've been very good at leaving jobs where I don't feel like I'm a good fit. On my previous team I spent most of time helping junior developers. This was extremely rewarding on a personal level. While I wasn't writing 500 loc a day, this was impressive enough to net me a promotion and a 60k raise after about a year .
Thinking that your simply the greatest programer that ever was doesn't mean you'll work well on a team .
Maybe this is just a semantic argument, but there are definitely 1/100xers out there. Even worse, developers so bad that they are actually net negatives. They take up more of the senior's time through bug fixing and mentoring than it would have taken the senior to just write the code themselves.
Anyway here's mine: readability is subjective and readable code must allow for exceptions in styling rules.
We have automated tools to format our code. They work great. They end arguments and take some work off your plate. Personally, I have better things to do than fiddle around where my curly-braces are placed.
For manual code styling, I agree.
Because it’s the language used for the AP test. I hate it as well that students know it first.
When I went, our first classes used C++, but a couple years later they switched to beginning with Scheme. (IIRC it was PLT Scheme, which is now Racket.)
Totally agree
Here are my journey with programming languages with the learnings
1. Java - OOP, JVM, benefits of statically typed language
2. Python - Simplicity. Java's verbosity kills productivity. If used properly, dynamically-typed language boosts developer productivity
3. Java/TypeScript - Asynchronous programming with promises. It was mind blowing.
4. GoLang - Parallel programming with goroutines. Explicit errors as values reduces windows of having runtime errors.
One of my favorite tools in the JS world is Prettier, mostly because it reduces the opinion surface. I want more tools and practices like that.
> One of my favorite tools in the JS world is Prettier,
I have no idea how these two statements can exist in the same comment. They're basically polar opposites to me. Prettier is one of the most obnoxiously, over-bearingly, self-indulgent opinionated pieces of code I've ever tried to work with. And they even say it themselves, with pride: opinionated.
Exactly, so what made your team choose Prettier versus the other tools if not the fact Prettier is the trendier choice? If some of these other tools becomes the tool du jour, what's the guarantee that people won't start arguing that you should all move over to it? You only see it as nipping the argument in the bud while a single solution holds the majority mindshare on what to do with the argument.
I could go on and on and on. And on some teams I've been on, people have. I just roll my eyes at all of this. None of it matters. At all!
Prettier takes 10 seconds to set up and our prettierrc file typically has one or two settings at most, often we don't stray from the defaults at all. It's totally painless. It'd take a very compelling tool to compete with that. If one comes along, sure, whatever. The goal is to minimize bikeshedding. Truly eliminating it is a tall order.
This is factual and irrelevant. Writing good software is more than just writing "good code". Unit tests help reproducibility. They help orient contributors, too, as failing tests give clues and passing tests give comfort. Plus, if you have automation like Dependabot updating your libs, you want a basic sense of whether the fully automatic updates are sane from looking at the test results.
This is idiotic. First of all, yes, as mentioned in the quote, tests will make sure that the code doesn't break if some rando changes it. But also, code that can be correctly unit tested is usually good, well-organized code. The simple act of writing code that can be properly unit tested is a significant step towards writing good code.
I used to think this -- now I believe they have another almost as important purpose as a sort of "check your work" step. Not necessary for every "unit," but useful when a given class/method has high (irreducible) complexity.
> Use your brain
IE, here is your confidence in our code (0...100%) and here are tools to increase that confidence (unit testing, integration testing, monitoring, etc.). At that point it is straightforward to say, "does this unit test increase my confidence?" and then go onwards. The thing is you need to learn to accurately gauge your confidence which can be difficult at times, especially when you are dealing with unknown unknowns, but if you iterate on it you get to a place where problems pop up in the areas you are least comfortable with and that is a good signal you're at least approximating it correctly.
> It’s OK to write garbage code once in a while.
I feel like these two go together. I think something which is often forgotten in programming discourse is that the single most important thing which code can do is create real-world value. A lot of times we get caught up in coding the "right way" because we as programmers look at code all day, but the truth is nobody else is going to see the code once it's shipped, and it doesn't matter one bit to the user if it's beautifully designed code or a mountain of kludges as long as it performs the same.
Sure good coding practices are important, but I actually think that an expedient solution now is often better than a perfect solution a week from now, and how well-factored particular piece of code is should be a function of how many times it should be touched rather than an absolute standard.
> what’s your most controversial programming opinion?
- Unit tests are a poor man's compiler (or a decent type system will decimate the number of unit tests).- Python is a toy. If you're developing a product there's always a better option.
How do you test asymptotic behavior with unit tests?
It would seem that is the kind of thing which is analytically demonstrable from the input types knowledge of the same features of the underlying operations (and, thus, theoretically within reach of a type system, if you wanted to design a type system with that in mind), but only subject to loose approximation in anything like unit testing.
Yes, you might make a formal proof of asymptotic behaviour and the property that the iterator returns a set, given a certain approximate model of the system, of course. However, it doesn’t just become simple or practical given the existence of a suitable type system alone.
Also I am not sure of the usefulness of tests of the asymptotic behaviour of an implementation of a data structure over tests over the applicable data and system. Is there a demand for this? What I mean is separate from the proof that a theoretical hash set had X complexity in its operations. That is clearly interesting.
Unit testing might be for the poor man, but how much money will the man doing the formal proof have left at the end of it?
I can't think the same for Haskell, which in my controversial opinion makes Haskell more of a toy language than Python.
Sure, but reducing the requirement for unit tests by 10% still requires the vast majority of the tests that would otherwise be required.
Many of these still stand - but that's presumably because they aren't really controversial - as indicated by the popularity by vote.
I think it's odd that the submitters of most of the opinions considered them controversial tbh.
That one didn't age well; and it was only eight years ago! Unless you replace it with JSON, of course.
Every. single. Java. object. now has to have them. The average Java data class is a tiny stub at the top of the file that contains the class name and the data structure definition, followed by a parasitical mound of getters, setters and builders. This unsightly growth of boilerplate ends up being regenerated by the IDE tooling every time it changes anyway. I feel like I'm working with C, except that the code I'm editing has already been through the macroprocessor.
Any needles of "smart" logic are drowned out in the haystack of dumb accessors.
That same haystack, coupled with auto-regeneration, makes it very easy to clobber any "smart" accessors, so nobody dares to be clever. It's always logic on the outside of the class. There is a thing do'er that does something to the class, but the class has no idea how to do the thing with its own data by itself.
This is the antithesis of the very ideas that OOP promotes. Whether they are a good idea is debatable, but the fundamental conflict cannot be ignored.
Seven I fully agree with.
Seven I agree with but I don't think they're controversial.
Two I agree with but they're interesting in that I'm pretty sure that the ideals of them are not controversial, even if they're not as common in practice.
One I agree with the title, but not the description.
One might have been controversial back then, but it might as well be an axiom nowadays.
Two I fully disagree with.
Well, is this unpopular?
If you only know a single language, and nothing else, I would think you are just good at reminding stuff you read, like guides and examples, and not that you really know what you are doing.
Although I can understand when people don't know other paradigms.
How about: Unit testing can help to write "correct code".
When I read through this list rewording in such a way could be less controversial and opinionated.
Every piece of logic should be written at least twice and verified against each other.