I love when I return to some project after few years, realize I need some new feature, write the function name only to find out that the exactly the same function already exists and does what I want. When I choose the same name after so long it means there is some serious consistency in my naming conventions. Feels good.
Sometimes i write a little function, think "hmm, i remember i did something like this before", do a search, and find a function with the same name, and exactly the same implementation. That is always really pleasing!
I have one frontend naming habit that might be worth sharing. The root element of my react components always have a className that matches the component name exactly (ie capitalized). All other classNames are uncapitalized. Makes navigation pretty easy in browser dev tools.
The component heirarchy tool in React Devtools (https://chrome.google.com/webstore/detail/react-developer-to...) lets you select something in the page and then click a button to go to it's component definition in the code (if your sourcemaps are working properly). It's the angled brackets in the right hand side panel - https://imgur.com/a/ufCPsMo It's very useful.
I find the react Component view occasionally useful for diagnosing state issues, but most of the time I'm just twiddling CSS from the Element view. YMMV, of course.
Somewhere else on my blog is an article about using BEM with content management systems (which is my area of specialization). I basically endorsed your exact practice, but with __content models__.
The idea being that a content model could have multiple presentations (views), but still relies on a single core .... data model. So the Block is that data model and the modifier is the view.
> If you’re the first person on the project, use camelCase; it’s easier to select camelCased text in an IDE than it is hyphenated text
Doesn't this go against the conventions of the most popular CSS libraries that your code will likely be used with? It's a pain and ugly that JavaScript and CSS don't use the same conventions though.
So, worth explaining (as I've told other folks here), my experience is in enterprise content management, usually building good ol' fashioned websites that are running on .net and getting content from a CMS. For the entirety of my career, I never ONCE worked with a CSS library. Every single one of my clients (who were on the Fortune 500 list, usually) had too unique of a design and too many different types of pages for us to bring in an external CSS library.
So, for that reason, when I wrote these guidelines internally some years ago, we weren't concerned in the least with what CSS libraries were doing because we didn't use them. We were concerned with consistency, more than anything
We went with camelCase because we liked that it was the same convention we followed in our JavaScript, AND it was easy to select stuff in the IDE.
Even WITH there being a VSCode extension, I still wouldn't change my reasoning because that kinda breaks the guidance of, "least disruptive to the team." I wouldn't want to have a project that required some IDE extension to keep teammates productive the way they want.
ALL THAT SAID, as I explained in the start of the guidelines, they are just that...guidelines. The goal is to be consistent and not have teammates present or future curse your name. So developers should really favor team cohesiveness over my opinions based on my specific experience.
Yep, it would be nice if HTML/XML/CSS/Javascript/YAML/JSON/SQL identifiers were all standardised as it's not uncommon to see all of them in the same project.
Is the iterator un-used within the body of the loop to do more than address a collection?
If it is actually used, it suggests that it's representing more than just an iterator and should be named appropriately.
If it isn't used within the body of the loop then it's purely for the sake of iterating across a collection (or just looping a given number of times) and should be named i.
Generally, I'd recommend trying to query elements in a test using accessible selectors, if possible. For example, look for the input[type=email] or button[aria-label~="Submit"]. That helps prevent people from forgetting to update or accidentally removing these often invisible properties.
I'd especially recommend testing-library for this purpose, which allows you to easily query by e.g. role and the accessible name of an element: https://testing-library.com/
To be totally honest, I originally didn't have any guidance around having a class name for .qa (this was a gist long before I made it a blog post and I'd been sharing the gist with teams for years). I had a boss point out that sometimes for [reasons] he would have to add selectors to things just for Selenium tests, and when that happened, he like using .qa because then it was obvious to him and anyone else it had to be deleted later.
BTW, the _reason_ he had to add classnames was because we worked in enterprise content management and there were all sorts of situations where, for WHATEVER reason, we couldn't change the markup, or we could only modify the markup in VERY specific ways via the CMS. So finding a way to stick `qa` on an element was a more straightforward path than writing some ridiculous selector like `body > div > div > header ~ article:first-child`
Suffice to say, YES, I agree that adding a class just so you can run a test is bad, but, we hit situations where we had to, and when that happened, it was worth while to have a convention for knowing how to identify classes that served just that purpose.
The general ideas are fine, but the examples are pretty outdated. For modern SPA, CSS naming has become largely obsolete. A lot of the JS code shows the principles it is supposed to well but sadly includes other cruft.
All of the examples are within the last 2 years. My area of specialization is enterprise content management; I build the CMS AND the front-end for very large companies that use decoupled CMSs and web sites. And very often, the web app is a typical server-side .net app where a front-end team has written static HTML and handed it off to back-end developers to be sliced into views. So all of this stuff kinda comes from over a decade of doing THAT; it's fair to say that maybe this doesn't all apply if you're an app dev.
But even when I DO build SPAs (like I am for one client), I still use CSS in traditional stylesheets as much as possible because any inline styling that doesn't invoke the CSSOM directly like it should seems like a massive waste of DOM resources ... and also I feel like I lose out on reusability that way.
That "clean code for typescript" is really good. I may drop a link to it in mine. I wasn't trying to be exhaustive. I was just trying to set a good baseline for where to go ;)
Your code example for isHot() seems round the wrong way; also doing something like “return temperature > 100” is probably more idiomatic than using if/else just to return true/false.
Thanks. That's one of those where I have probably 100 cases in code I've written over the years and I can't find a single one when I actually needed it. I'm open to better examples.
This is enabled by tooling. The tooling is largely still using classes under the hood. If you know how to use the underlying tech well you can solve problems your framework of choice doesn’t solve for you.
Not every web page is an SPA.
. Mant projects are small enough that frameworks are overkill, but good practice is still useful. Sites that are mostly content probably shouldn’t be built as if they were SPAs anyway (although many are now).
Not necessarily. I often use native Web Components when I need to write a quick website SPA or not. Native web components also gives you component scoped styles without having to use any tools which alters the class names.
I think that it is really limiting to approach typescript as recommended by this repository :| typescript has a really nice and powerful type system which is not fully used in these examples
Mostly good but I hate getProperty names. If a method returns the temperature call it temperature() not getTemperature(). If the private data member has to have a different name, _temperature or some similar convention will do.
In JS (and in any expression-inside-html front end framework) this leads to the hugely common bug
if (this.finished) { ...
or
<div v-if="showMainContent>...
With your convention, these could easily be functions, but they are never evaluated without parens. Nor is any error thrown. Instead, the fact that the function exists is truthy and you get the true case always.
In our teams's js code we even include "get" for "is" properties (getIsEnabled() rather than isEnabled()) so that it's perfectly obvious if you're ever using a function without calling it.
Except it's also likely, perhaps more so, that `this.finished` is `undefined`, which results in fundamentally the same problem but in the opposite direction of truthiness.
In which case I still see it as just a personal preference. The prefix of "is" becomes reassurance that something is intended to have a boolean value, which may be more important.
Of course it goes without saying that both of these things are (usually) addressed by a system like Typescript.
The situation is symmetric if there's just a getter and a setter for a state variable, but perhaps sometimes temperature() does a measurement and there's no way to set it because it isn't a controllable quantity (for a thermostat I can set my desired temperature but it will take time for the room to warm or cool to that temperature).
That's valid and maybe I'll update the guide to explain a bit more when/where I have found getProperty() useful:
I often do it when I end up having to have parity in API request: a get AND a set. If there's more than one thing i'm doing with temperature, it's helpful to show WHAT I'm doing with it, specifically. I'll noodle on your thoughts a bit and see how I can incorporate them.
For js and qa needs I’d recommend custom html data attributes instead of using classes (data-js=, data-qa=). It’s a much clearer separation of concerns.
I've tried that approach in the past. The reason I didn't promote it in the guide is because data attributes, in my experience, were more verbose than what we needed.
They were useful in cases where we needed to pass in additional information (e.g. data-qa="onClick"). But what we found was
- whether class or attribute, it was the same dependency on markup
- selecting with [data-qa] was the same specificity as .qa
- selecting with [data-qa] was just a little more verbose than the teams liked
But, this isn't me arguing against data attributes. I'm just stating that my experience went in the direction where we didn't see any huge benefit.
They're guidelines so, by all means, take what works, throw away the rest. This was a small guideline about how to name stuff, not build entire apps. So if that's the thing that doesn't work for your workstream, my feelings aren't hurt. Thanks for reading it, though, and sharing your thoughts.
You still have to name some classes even if you use component scoped styles, however it is usually pretty straight forward. I quite often just name my classes something like: link, action, title, label, etc.
Also when I’m writing forms, I usually name every field e.g. email-field so and then assign them in the grid using the class name:
I was being a bit facetious, I meant you don’t have to put much thought because when they’re scoped or in modules you can just name them the way you’re naming them. Complex CSS naming rules (like BEM style) seem dated to me.
This is actually super bad practice. I really dislike scoped css.
When I see devs using scoped css the class names always end up like `.box` or `.name`.
Having to think about classnames and writing Sass makes me much more aware of the structure of the components I'm styling.
Also scoped CSS kinda makes you skip the steps of thinking about your component in the bigger picture of your site, since you don't care about having meaningful and unique classnames, then you're much less inclined to think about good guidelines like OP's conventions. What does it matter? Since we can just put a `.box` in the scoped <style> and call it a day.
Frankly I think only JS oriented devs like scoped CSS and frontend who love html/css and the challenges of architecturing good CSS don't egt any benefit out of styled components (since you're using atomic css like Tailwind and/or BEM-style which always "scopes" classnames with the component name.
In general any solid guidelines makes CSS instantly 10x better and that's all most projects needs, and it's often what most projects lack.
SuitCSS works great with Vue in my experience, and can even be linted with postcss-bem-linter :
I'm the original author.... and what I can say is that my area of specialization is content management; creating the CMS and the websites that consume from the CMS. So I'm not doing "app development"; I'm doing traditional website development and scoped CMS is not on the table. This little guide for naming things is something I used with teams for YEARS as we were building very large websites for very large companies.
Suffice to say, the SuitCSS convention is extremely close to what we've put into use over the years.
Yeah, SuitCSS's main distinction with OP's (excellent) guidelines is that it specifically mentions components, and using the "PascalCase" format of the component's name, as the root classname for the component's root and child elements (eg. `.ProductDetails` `.ProductDetails-footer` `.ProductDetails is-selected` etc, optionally with an app wide prefix like `.cg-ProductDetails`). It's very convenient when you search in editor like VSCode and you find all the matching CSS/JS files together (when they are not "single file components").
When I wrote the guidelines, it really was all about, "be consistent". camelCase is my preference, but really, go with what makes sense and is least disruptive.
I actually REALLY like SuitCSS' recommendation and I definitely wouldn't object to it.
I intentionally didn't address project architecture (folder names, file names) because ... to be honest... I still haven't quite figured that out.
But I'm going to think on it and maybe add something to the guidelines that echos your suggestion.
In math and Haskell, sure, but this is wrong, not just pedantic. They are functions. The language docs call them functions. The keyword to create them is “function”.