11

Situation: several developers working remotely on different section/modules of a SPA. As a result they may accidentally introduce HTML elements with the same id. What are the common ways to avoid that situation (without refusing id-usage if possible) before final assemblage?

My shallow guesses:

  • pre-arrange id for all names(a bit ridiculous but...)

  • structure names with architecture e.g. for an app/collection/model dedicate a name like app-collection-model

  • refuse using ids in general or use only for large modules?

Nik Terentyev
  • 2,270
  • 3
  • 16
  • 23

7 Answers7

3

Try to avoid using ID's except where absolutely necessary. When referencing HTML snippets from CSS or JS, stick to classes instead of IDs. Your CSS and JS shouldn't really care (separation of concerns) about the exact structure of the DOM or how many 'foo' elements are on the page... they just want to style or act on whatever 'foo' elements are there which classes are perfectly suitable for.

You can't avoid ID's entirely though... for example, marking up your HTML to support accessibility will require the use of IDs... but these IDs and references to them will be constrained to the same HTML file (or SPA template) so go ahead and make them verbose/lengthy to avoid conflicts if you feel a conflict is possible with any of them.

Of course this doesn't totally solve your problem. By focusing on classes you avoid the possibility of generating invalid HTML and everything blowing up but you still have the collaboration problem of making sure people aren't unexpectedly screwing up each other's work by using the same class names. In many cases, you'll actually want the same classes to be used across pages. In cases where you want to ensure there are no conflicts (for example, having common button or typography styles across the site), however, you could wrap each HTML template in something like <div class='name-of-this-template'>...</div> and then in your CSS/JS selectors, scope the selector to only match within that template: .name-of-this-template .a-class-used-within-the-template.

Robert Levy
  • 28,747
  • 6
  • 62
  • 94
  • 2
    +1 for noting the problems that can occur from collisions with class names. FWIW, I've handled this problem by scoping containers (e.g. a class on a parent wrapper, as you suggested) or well-qualified IDs, like `document-editor-save-button` (which is extra typing, but removes most ambiguity). I will also generate an ID prefix on the fly if needed and prepend it to the element/references to the element. This removes all ambiguity. – Tim M. Jul 13 '14 at 02:40
3

If you are writing the same HTML code again and again with different IDs you are doing something wrong.

Nowadays, there are many ways of creating reusable HTML components that do not need IDs.

What I think is wrong:

For big projects (multiple teams involved or big amount of views) I don't think writting again and again raw HTML is a good idea.

That approach means: duplication of code and pain to refactor in the future (think about a restyle of the application in 2 years). That's why there are so many UI frameworks out there that help to create reusable components where HTML is written only once and used anywhere. At the end, your application will require a few components: table, popup, form, submenu, tabs..

The goal is to create a framework with those components that a developer can use to create a view without the need of actually writing any HTML code.

My point is: HTML code should be written once and only once in big projects. Obviously the fact that it's written once doesn't mean that it can only be rendered in one place, it can be anywhere in the application.

My suggestion:

Data-binding to the rescue!

If doing a big change is not possible, convention is the way to go. The one that you propose could make sense but be careful, every time that you change the structure all your IDs will be wrong!

margabit
  • 2,924
  • 18
  • 24
  • I can't totally agree with you. `If you are writing the same HTML code again and again with different IDs you are doing something wrong.` This is not always true. If you have multiple screens with the same fields on it you likely have the same id's(screen 1: relation, screen 2: Orders.. both will have a field `name` on it and probably the same id). – GuyT Jul 17 '14 at 12:47
  • @GuyT I updated my answer to clarify my thoughts. Sorry if I didn't explain myself! – margabit Jul 17 '14 at 13:10
  • Now I agree with you :). In the current project we don't even use HTML(only JS) but let DOJO do the markup.. – GuyT Jul 17 '14 at 13:17
  • :) Exacly! That's the thing, reusable components centralizes UI problems like that to one single place. – margabit Jul 17 '14 at 13:23
  • And another fact is that is easier to sell to a customer. You could use the argument that they can switch to another framework without problems ;) – GuyT Jul 17 '14 at 13:26
  • @margabit The problem I've encountered with auto generated IDs is that they can be a pain to write automated unit tests against e.g. having a load of sections with ids which share the same naming convention can make life difficult if trying to assert sections in automated tests. This is why I try to encourage sensible names (note that I'm not saying conventions are bad its just that they can cause problems in my experience!) – Ben Smith Jul 17 '14 at 17:00
2

When a project is being developed in parallel by multiple teams the key factor in it's success is communication between the teams.

The teams should get together at set intervals to discuss cross-cutting concerns (e.g. naming strategies for ids). For instance if using the Scrum agile development methodology, the teams would meet periodically in a "Scrum of Scrums" meeting to discuss such an issue.

By having a conversation the teams will be able to agree on a naming convention (and document the agreed convention for future reference) which best suits the components being developed at that time (and when I say best at that time, I mean simplest and most easy to read whilst avoiding any naming clashes). Hence your suggestion to "pre-arrange" id's whilst work is being carried out in parallel isn't as ridiculous as you may think!

Ben Smith
  • 19,589
  • 6
  • 65
  • 93
  • I'd argue that project wide naming patterns is not an appropriate topic for scrum meetings. If you're going to solve the problem entirely via naming patterns, that's fine but those conventions are something that need to be a documented artifact (probably even checked in with the code) because if somebody screws up 5 years later once the code in being maintained by different people, duplicate IDs can result in bugs that may be difficult to catch. – Robert Levy Jul 14 '14 at 12:20
  • @RobertLevy A "Scrum of Scrum" meeting's purpose is to co-ordinate development amongst parallel teams. If the teams are working in the same domain (i.e. the creation of UI components) then a conversation about IDs is relevant. The result of these meetings would be to evolve and document (yes, the Scrum process does create documents) the naming conventions used. I totally agree that documentation of standards is important. My answer is emphasisng that I believe that standards should be evolved/developed over time. – Ben Smith Jul 14 '14 at 12:27
2

In one of my projects we got into this exact problem. Our quick solution and part of our next code maintenance/refactor cycle is to use identifiable html elements inherit the attributes of the JavaScript container with templates.

Let me go in more detail.

  • We use Backbone.Marionette with Handlebars templating. For each template we have a custom View class (we extended Backbone.Marionette with more features as we went on) associated to each template. This View class has an ID and UI elements. The UI elements are compiled in the template, therefore we never have to change the HTML unless we change the UI element name in the view class itself. Therefore, we can change our Id of the UI element however we want and won't affect anything (almost).

  • Since we use views for each widget, you can be sure their identifier or name or however you want to call it, is unique. We use that as a base for our Id's in our UI elements. This allows us Widget reuse.

  • _.uniqueId() from the Underscore library is also used a lot for CollectionViews.

Hope I helped, cheers!

AlexandruB
  • 678
  • 3
  • 15
2

If your code(problem) really big, and you can't refactor it, you can try validate your css/html for find repeat id's before each commit. But it's possible answer for very bad situations.

Good solution - using tools like bem (http://bem.info/)

Aleksey
  • 88
  • 6
  • any articles how bem is better than other instruments? – Nik Terentyev Jul 19 '14 at 00:49
  • 1
    I not use bem, but I use some ideas from them: I use only long-name classes without ID's and difficult selectors. It's give me good browser performance, code readable and tree-structure (with SCSS 3.3 - jsbin.com/vohekupa/2/edit). It's true for bem, oocss etc. Full bem say "put each widget in different folder" that guarantee different names on filesystem level. BEM is Yandex's (Russian Google) project that made for working thousands developers together and give answer for many questions. It have a good community and various instruments, but it's monster. For more info: vimeo.com/38346573 – Aleksey Jul 21 '14 at 20:33
2

Give each developer (or module) or unique id-prefix.

For instance, if developer X is developing a module Y, his prefix should be one of x_, y_ or xy_.
Assuming x_ was picked, IDs created by him would look like x_foo, x_bar, x_thing etc.

Advantages:

  1. Avoids colliding IDs (obviously).

  2. While integrating modules, the IDs clearly indicate where they belong.
    This provides improved readability, and that is pristine!!

  3. Writing x_something is irritating enough to avoid overindulgence in ID usage.
    At the same time, it is not so irritating that no one will use them.

Disadvantages:

  1. It'll make at least some developers unhappy. (Some are less flexible than others.)
    A possible remedy is to ask them to change IDs to the x_ form,
    only towards the end of development, just before integration.
    Until then, they may use prefix-less ID names.

  2. Some modules depend on other modules. Before integration,
    appropriate ID names must be shared and correctly used.
    While this may take some additional time, it would (hopefully) be worth it.

Community
  • 1
  • 1
Sumukh Barve
  • 1,414
  • 15
  • 12
  • Changing something at the end of development (before going to production?) doesn't sound like a good idea to me. You will too easily overlook something. For integration tests, the namespaced ids already need to be in place. – Bergi Jul 20 '14 at 18:59
  • I agree. By "During integration", I must have meant "just before integration". I'll fix the answer. Thanks. – Sumukh Barve Jul 20 '14 at 21:35
1

I would prefer to see ids used only to specify modules, widgets, main sections etc. This will lead less id's in general and most of your naming to be created by your business logic. You also end up structuring your classes & tags with a sort of localised hierarchy like: #specialWidget h3 {} #specialWidget p {} and you just select your handlers like - $('#specialWidget .some-btn').click() and never like $('#someBtn').click() because it just get's messy and too specific.

Past that, testing and continuous integration are your best bet to catch things like this.

Dylan
  • 4,703
  • 1
  • 20
  • 23
  • Why would you use an ID for that instead of a class? What happens if you want to have 2 `specialWidget`s on the page? Also, there are important places where you *must* use IDs individual elements such as when implementing accessibility or even just specifying the `for` attribute on `label` elements. – Robert Levy Jul 14 '14 at 12:14
  • I didn't mean to imply that there weren't cases where it's necessary to specify by id. Just that on the whole people tend to overuse them and a simple approach to lessen the amount and maintain convention is to move them up the hierarchy. You would definitely use a class for any multiples, and there are libraries that will force you to use ids. You will need a convention for these cases also. – Dylan Jul 14 '14 at 16:05