I've been recently asked this question in an interview and this was my answer:
Pure unit tests and shallow rendering idea
For ReactJS in particular, there are many testing libraries that allow you to do shallow rendering (enzyme for example), that means that if you have a composed component, the test won’t actually render that inner component so you can’t make assertions on that. If you want to cover those internal components you need to write specific tests for each part.
<div> <Form> <Username /> <Email /> </Form> </div>
With this structure, if you want to write a test for this component, the first
div will be rendered but the custom
Form component won’t, neither the
If you follow this pattern, you will soon end up with a set of pure unit tests that are really confusing and hard to follow.
Kent C. DoddsThe less your tests resemble the way your software is used, the less confidence they can give you.02:35 AM - 18 Feb 2018
Tests should resemble the way the software is used. Even though is not pure unit tests (technically you can call it integration test), at the end of the day the only thing that matters is that you can ship your app with confidence.
Image by Gerd Altmannfrom Pixabay
Top comments (138)
80 characters per line is a common one. I feel that this is an old practice from technical limitations that lived on. I do not go overboard with extremely long lines of code, but with widescreen monitors, 80 characters seems a bit limiting.
It's not just a technical issue. longer lines are harder for the human mind to parse out. In text, 50-60 characters are ideal. I think more than 80 in code is pushing it. Having said that, I agree that it's not something to be too dogmatic over. We have our linter set to 125 cpl.
I'm pretty fond of 80 characters being the limit.
Over 80 characters per line means project is written in some ancient language. For example Java.. or other older strongly typed language where it's occasionally impossible to make code nice & readable 😅
That, or there is some bigger issues in code structure.
I have heard of the 50-60 being ideal, but I thought that was more for reading sentences than text in general. I could be wrong though, I haven't looked at the studies on it.
My coworkers use huddled terminals in an i3 workspace and with Vim, they appreciate having 80 characters per line.
same here, 80 chars are visible in 3 columns at 1080p; and also 1 vim column + browser without triggering the "small screen websites format". By the way, i3 + nVim is perfect
I prefer 120 characters, and stay pretty strict on that limit. 80 chars definitely is not enough, but I do like having a hard limit on line length.
I appreciate code that has an 80 char limit, means I can put two code panes next to each other without having to put the font eyebleedingly small
If I remember correctly that stemmed from the COBOL era where a punch card only had a certain number of characters across plus a blank column (the fourth I think?) for the sorting wheel to put cards in order.
I don't think I've ever adhered to a certain number of characters in C#.
Plus, in the 80s graphic cards the standard text mode was 80 columns X 24 lines.
Erm, nobody insists on that anymore so no, not common at all - it's long been revised to 120.
Yeah, multiple screens are common nowadays. Super long line is not encouraged. For easy reading I prefer 120~130.
80 characters per line is horribly outdated, it would make most of my code look ugly especially in a more verbose language like PHP.
120 characters per line is fine, that's much more okay.
It has another use case: showing code on a presentation (you need to increase the base font size) keeps your code formatted and in the screen.
I think 80 is just for encouraging good practices. Some people tend to ignore soft recommendations like "don't go overboard", but will follow hard limits.
I question anything too religious around small files and tiny methods. Sometimes the better choice is to toss another method in the class so it’s easy to find rather than stash it away elsewhere in the codebase.
I think modern IDEs are pretty smart to walk you to the file/class which encaosulates the method.
For me the method length limit is imposed by the response to simple question - "What the method accomplishes?". If you are not able to answer without using AND ..this.. AND ..that. AND ... multiple times, then it is time to better encapsulate the logic and maybe change the project's design.
My counter to this is that with any suitably large product, having a logical folder structure that you religiously stick to, regardless of file size/content† , you can reliably find the content that you are looking for. Okay you occasionally deal with a silly file, but its better than having someone recreate something and have inconsistency between what should be functionally identical.
For small/informal project then I understand the convenience, but otherwise i feel it can add to problems long-term, especially when working with big/multiple teams.
† have a single exported const in a file for all I care
Use an ide, preferrably a jetbrains one.
Spaces over tabs
Team tab here.
I don't see the advantage of tabs, is just a character that you can't differentiate from another just by looking. To me is like having to A that looks the same but are a different unicode. I like to think that in the future, when we solve all big problems, this will be one of the big wars WWX maybe, just after the big WWIX of Vim/Emacs.
You can render tabs as any width, while spaces are fixed. This is really useful for formats like yaml (which forces you to use space, btw) where it can get very clumsy with small width of white space
I would like that the "r"s of my name looked like flaming swords and the "o"s like eagles, but the main purpose of written language is to visually recognize what is in there and to agree on that. You can't see the difference between a tab and a bunch of spaces, that should be the first priority, everything goes after that, including style; btw, you can use multiple spaces in yaml and in any language I know of, if you are reading code with a single space indentation you should murder the one who wrote it, I think that even a judge would understand. Even 2 spaces are questionable, to me 4 are ideal and 8 like the Linux Kernel guidelines is going too far.
With tabs you can render them as you like ;p even as 3 or 7 spaces :)
I found this article helpful in understanding the difference: dev.to/alexandersandberg/why-we-sh...
The argument exposed there "accessibility by default" is flawed, accessibility needs of few are often opposed for the needs of the many. If you have trouble seeing 4 space indents, almos all editors have vertical lines, different colors, font size, space markers, etc. Is a weak argument for tabs. no 2 different characters should look alike, and unless you want to use tabs for all spacing, to me tabs are out. If I see a blank character I know what it is and can even estimate how many. That's why we use text editors and not word processors in the first place or let all just use MS Word or Libreoffice Write to program.
Spaces over tabs for fixed width fonts. Tabs over spaces for proportional fonts. This way the indenting is consistent.
I used to be strongly for tabs over spaces, nowadays I strongly prefer spaces over tabs, yet I am slightly annoyed by the fact that it's now more difficult for me to customize just how wide the indentation is.
Why I now prefer spaces, is that once the indentation is in place, it won't just go haywire on different machines. E.g.:
This kind of a thing would be regularly painful with tabs.
It's quite annoying when people just reply with a link instead of even sharing the gist of it and then the link for additional reference.
Tell this information to people writing PEP-8,
gofmtand other such things. It's valuable feedback, but since fighting about formatting is not worth the time I use tools to auto-format everything and they will force the codebases to use spaces.
I didn't care about this argument until I read about the accessibility issues surrounding the use of spaces for those who are visually impaired.
TDD. In any environment which is somewhat agile you will have evolving requirements. Evolving requirements means evolving code or even design.
This means that you will end up writing a lot of test code which gets thrown away.
You should totally write unit tests for your code. And you should think how to split your code to make it testable. But don't put the carriage before the horse.
Interesting! I couldn't disagree more :) to give you the confidence to refractor and improve your code (making it more readable, maintainable and easier to extend) you need good resting coverage. And if you use TDD for a while you realise that it actually makes the process of writing deep internal functions in your software faster, because of the much tighter feedback loop as you make changes.
So curious. When you write your code, do you end up writing it and structuring it correctly on the first go?
My process is always write some code, evaluate the abstractions, write some more code and see if the abstractions present are still good enough. This sometimes means that I need to refactor something pretty much immediately after I have written it because I made an assumption about something or I forgot about something. Or I realize that I have repeated functionality which needs to be dried.
In other words, when I write code, the first 40% of the effort is quite fluid and subject to change.
This does not mean that I start without having a solution in my head, or a plan. It doesn't mean I haven't thought about the problem. But the reality is that my solution are never 100% on point.
And that is exactly what TDD is supposed to support. You write a test that describes stepwise functionality until you have your application. Then you can refactor, change, rewrite as you desire and the tests still describe your use case.
I find people who are strongly against TDD tend to be the people who have been exposed to it wrongly.
The only people I think have a healthy view of TDD are those who say it's useful but not as a religious dogma. Essentially, anyone but obsessives and dismissives, which is true for any technology or methodology.
Take one of my personal projects. 100% TDD developed. Which -while not perfectly designed- lends itself to a very easy to understand, compose and modify structure and through TDD is forced to evolve positively.
Yeah, this is interesting. Like anything it doesn't apply 100% of the time. The place where TDD works well is once you know what you're doing! Because otherwise, of course, you can end up testing things in the wrong place, as you realise things won't work and have to refactor them.
But in the case of bug fixing and adding simpler cases, where your tests are already there, writing a failing test first is an amazing habit to get into.
I think the counter argument to the whole 'but I'll have to keep rewriting my tests!' is, if you're not sure how to structure stuff, write the acceptance / integration test first - because you probably won't have to change that - and then start trying to work out how to satisfy that. Once you have something working, you can start TDDing with your unit tests until it is complete :)
While I wouldn't push anyone towards TDD, I would strongly push people away from integration test based development. The testing is not fine grained enough and test only a "walking skeleton", they are slower and they allow for terrible design. It's very easy to write integration tests which pass with a mess of interdependent code but very hard to do it with unit tests.
The major benefit of (Unit)TDD is that is pushed you to think about separation of concerns, ergo, good design.
Cool. I am trying to do as Uncle Bob says ;) I want integration tests to check that the code does as the end-user needs, regardless of its internal structure.
Agree that doing ONLY end-to-end / integration tests is a bad idea, as you say.
I used to be super against testing, more so testing every edge case. Until I worked on a large project and was tasked with refactoring a complex and extremely important part of our application.
Being able to make changes confidently backed up by the tests is an amazing feeling.
Once you've had that feeling - you realise how precarious things felt before!
Would you not change the test first to reflect the impending code refactor? Do you only see value in refactoring production code and not unit tests?
The whole point of TDD is to give you confidence in what you a writing.
My point is that tests have a tendency to solidify existing code.
If the code is changing before it's even released, this is time wasted.
Write the code, solve the use cases, then write your tests. Before you have something concretely written, things are in flux and writing tests at that point is a waste of time.
That said, sometimes I break this philosophy. Sometimes I write unit tests immediately after I have written a small component.
But to take tdd as an overall approach to development would be hard to justify in my opinion. Maybe exceptions are if you are writing machine control software, or mission critical application. But in such cases you are probably using waterfall.
Sorry but I have to disagree. A large point of TDD is to allow for this. You write a test that describes the functionality that you want, then write the implementation. After you can refactor, change, rewrite the implementation as much as you want and the test it still valid. If you need to change the functionality then this can be done be first updating the tests.
If you work in an agile environment as you suggested you should be creating small, potentially shippable products. So once you have implemented something, it shouldn't be changing too much especially before you release, as it will have been agreed before brought into sprint.
I don't understand the benefit of doing the tests first, the important thing is to test everything possible, doing the test first is very weird to me; I think that it depends of how you solve a problem, your mental frame it may work for you but to force it to everyone I think is a mistake. Is like forcin to make a drawing when you take notes or to make a mind map, do it if it helps but force someone who doesn't is just cumbersome. And agile is not always best or even possible.
It probably sounds wishy washy but I hate (and my team hate) HAVING to do TDD - preferring to have it as another tool in the toolbox, to be used when the requirement supports it. I find TDD works really well when I know just what I want, i.e. I need a class for a report that can print, download via csv or display onscreen - I can take what was requested, write tests and then make sure that my code works all nicely. But sometimes dev is a bit more exploratory - the exact solution provided is one that we have to feel our way towards, where the requirements themselves are not completely certain and you have users who need to spend some time actually working with a rough version of the feature to refine their own requirement, TDD doesn't help. One could argue that this would necessitate a prototype stage as part of requirements (that occurs before dev starts) but when that prototype needs to be functional and it would be quicker (or more resource efficient) to show something in real code rather than building a completely separate prototype, tests first is a really big hindrance to exploring solutions.
DRY is a goal unto itself or Copying and Pasting Code is BAD!
My mantra is, don't try to DRY before you are WET (Writing it Every Time).
Having good tests can go a long way towards ensuring duplicated code continues to function correctly after modifications.
And consolidating duplicated code too early can result in an abstraction that serves too many roles.
Different parts of your code will change at different speeds and for different purposes. If you force two parts to change at the same speed and for the same purpose even if they wouldn't had they not been DRY'd up, you will box yourself into corners that are hard to get out of.
Look for the patterns in your code before you start consolidating replication.
Let your application's patterns reveal themselves to you naturally instead of trying to force them prematurely under the banner of "DRY".
Sometimes small amounts of duplicate code is okay. When the alternative involves creating complicated abstractions and couplings, you'd be better off keeping it simple and having some code that does roughly the same thing in multiple places.
"Don't Deploy to Production on Fridays!"
This one drives me around the bend. Especially the smug self-satisfaction that's exudes from the developers who say it.
I'm not saying that they should deploy on a Friday - by the sounds of it most of them have insufficient test coverage, extended (1 hour +) deployment times and a very slow release cadence (once a week?). For them to deploy on a Friday under these conditions would be madness.
What annoys me is the lack of shame when they say it. They don't even sound like they want to deploy on a Friday, like they know that their pipeline is slow and flakey and that they aren't really doing CI let alone CD and they're perfectly happy about it because, lol, management won't let them so what are you going to do?
I'm sorry, that was a bit of a rant. It's just that it makes me angry when I see people noticing the broken windows and laughing about them rather than fixing it. "Don't deploy to production on a Friday" isn't a slogan for you to put on a t-shirt and lol about on Twitter -- it's an embarrassment to our profession.
The problem with deploying on a Friday is that if something goes wrong after the fact, nobody's there to fix it. By deploying on a Friday you are guaranteeing that any problem will take at least 3 days to be fixed, unless there are people on call (or employees free time is completely disregarded). I don't see anything wrong with advising against that.
I have no problem with you or anyone else choosing not to deploy on a Friday. It's your life, you know your codebase and your production systems better than anyone else. Life is messy and imperfect.
If you're telling other people not to do it, as some sort of blanket rule, and think that it's an hilarious precondition of working as a developer... I find that really sad. We should be trying to make deployments delightful and easy so that they can happen at 5pm on a Friday without anyone worrying.
If you think that's impossible, I'd ask you to read around the subject and broaden your horizons.
Here, this is Charity Majors, who explains it all better than I can.
(Charity is my hero)
Yeah, I've always taken it as a given that internal business applications deploy on Friday evening, public (non-revenue generating) apps deploy on a Monday/Tuesday during the day, and public (revenue generating) apps deploy during lowest use.
"Don't deploy on Fridays" is honestly new (within the last 5 years) to me. We all know the danger is something goes wrong... but that's why you test it first.
If the internal app is messed-up, that gives you 2 days without users, and a strong incentive to get the PO to make the call on whether or not something is critical. If it's not critical, enjoy your weekend. If it is, yep, the team's working for the weekend. Then you REALLY need to retrospect on your testing practices, and how this critical flaw made it to prod.
If low usage occurs at 2AM EST on a revenue generator, then that's just when the deployment needs to happen. You better believe I've tested that thing into the ground, cause nobody wants to wake the whole team up for a problem.
I'm the last person to say it's OK to take developer's personal time, and the first one to say "let's try and avoid late nights" but sometimes the nature of the job calls for it, just like doctors and lawyers. The key is the employer recognizing it and arranging comp time, late starts, etc.
If you're afraid of deploying to production for any reason (not just anxious... everyone should have a little anxiety any time prod changes... it keeps us on our toes and away from the "Just push to prod, it'll be fine" mentality), then there's something off in the process that needs to be addressed.
Addendum: This is all assuming they aren't in a CI/CD environment... which many MANY places are not. A lot of places deploy at the end of a sprint, and God help you if you're in a monthly, bi-monthly or quarterly release shop. Again... the testing should be there to allay those fears though.
David, most apps nowadays aren't built as a single monolithic systems directly under the team's control. There are many moving parts, many components, and many backend services which are involved in bringing just one app into production-readiness. Of course we all want to test and QA our apps thoroughly–that's due diligence and we wouldn't be doing our jobs otherwise. But I think it's useful to keep in mind that not every integration point, not every interaction, might have been tested. And if something unexpected pops up, you could be stuck debugging it late on a Friday evening, tired and hungry. That's not a great way to end the week.
That's also why I like the techniques of blue-green deploys, and canary deploys–we let the new release soak for a bit and fix issues on the fly–preferably near the start of the day when we're fresh.
C# Style guidelines. I don't like having the opening bracer on its own line:
Also, I refuse to have a dangling comma.
Ugh. No. Gross. I think internally it makes my brain expect something to follow the last item, but nothing does.
Old thread, but in JS, the dangling comma is actually mandatory in our style guide. It makes edits easier - you can reorder or delete the last item without changing other lines. I think your point about expecting something else is valid.
For functions and methods, including anonymous lambda functions, I keep the opening brace on the next line by itself. For objects and everything I put the opening brace on the line with the declaration.
Will 'favoriteThings' even compile with that final comma?
Oof, 6 months old buuuuttt. Yes, it does compile. Just like js, it's there for convenience when editing. You can't however do that in object initializers e.g.:
(on mobile, fingers crossed for formatting)
That code should be as few lines as possible. There's an element of refactoring that is important so that it's efficient, but it should also be understandable.
I believe you shouldn't write code as if you're going to be the one dealing with it, but someone underneath your level of understanding.
“I didn't have time to write a short function, so I wrote a long one instead.” - Mark Twain :)
Daily SCRUM standups. It's just micromanagement in disguise. You can instead do 2x a week instead and save some development time
Sorry to hear that. The daily meeting is not for micromanaging at all. If you have the feeling, it is that way, then well, you are doing it wrong.
Write comments in every function, and at the beginning of every class. Sometimes the projects will go really complicated, then you must roll over again every class you write just to look what it does.
What you need to do is create a structure and a walk through tutorial when things out of hands.
Code comments can be like deodorant for code smells. If you feel like writing a comment to clarify something, first try to change to structure of the code itself to make things more clear. Most of the time, simple (and safe) rename refacterings can be enough. After that try putting boolean expressions in properly named variables. If your happy about the naming you then can extract a method out of it so you can hide some of the implementation so the reader of your code doesn't have to mentally parse every tiny detail to get the big picture.
If you always so this your code will read like a story. Digging deeper you will find technical implementation but at the higher level it should be understandable by first time readers without having to peek at the lower levels. It takes a lot of practice and discipline tough.
My least favorite practice is a function that looks pure but actually has side effects.
I don't think that's considered best practice at all. Lol
But yes, that sucks.
Yoda conditions. A lot of PHP projects write
if(42 == $value)instead of
if($value == 42), to avoid the mistake of forgetting an equal sign and getting an
if($value = 42)statement with an assignment in it, that thus will alway be true.
Except that in PHP, you need to write
if(42 === $value), otherwise you are vulnerable to shady automatic type conversions. And those projects also write
if(42 !== $value),
if(42 < $value), etc, for symmetry, even though there are no mistakes to avoid in these cases. The result is code that is annoying to read, and you have to train yourself to not forget to reverse the operands, when you already trained yourself to not forget the third equal sign. It simply has no benefit.
A lot of C code, that I have come across, also has this issue, and for the same reason, "to avoid the mistake of forgetting an equal sign".