Part of being a good UXer is collaborating with the developers on your team, right? I’ve learned so much from devs over the years, but it wasn’t until last year that I came across this gem of a technical concept. It’s such a game changer, I now teach it in the Object-Oriented UX Masterclass!
Have you ever seen a recipe app that lets users adjust the quantities of a recipe’s ingredients based on what they have on hand? If I want to bake shortbread cookies, but I only have 1/3 cup of butter in the fridge instead of 1 cup, how much of all the other ingredients do I need to make the recipe? Just take a look at this request from Reddit—that’s exactly the kind of app they’re looking for!
When we use some UX + developer magic and make sure data is well-structured, users can do things like instantly adjust all the quantities of their ingredients. Or they can sort by which recipes have the most butter. Or the most peaches. Or recipes with tons of butter and peaches!
All these user superpowers (and more!) are made possible by junction objects (also known as “bridge” or “join” objects). At first, leveraging junction objects feels brain-pretzeling, but with practice, they can help clean up our information architecture and tackle complexity with grace.
Warning! This is an advanced Object-Oriented UX article. If you are new to OOUX, this might be an article to skim through for now and come back to later. (And psst, if object maps are new to you, here’s the quick-start guide to help you get started with making your own. You might also want to check out the first two episodes of the OOUX Podcast.)
Ok, deep breath. Before we get into how to incorporate junction objects into an object map, we need to step away from colorful sticky notes and talk about databases.
Why use a junction object?
During the R of the ORCA process (relationships!), we OOUXers create more many-to-many relationships than we’d like to admit. I would even estimate that, more often than not, the relationship between any two given objects is a many-to-many.
A STUDENT has many CLUBS they are in.
A CLUB has many STUDENTS in it.
An ORDER has many PRODUCTS being ordered.
A PRODUCT has many ORDERS it’s on.
I could go on…
But what if we want extra attributes applied to an object while it’s in the context of another object? Let’s look at an example where designing for a junction object untangles that complexity.
Let’s take a meal-delivery service that teaches cooking. In this example:
A RECIPE has many INGREDIENTS (dozens).
And an INGREDIENT has many RECIPES (hundreds?).
What if we want specific amount metadata on our INGREDIENT depending on which RECIPE it’s nested within? We can’t just plop the amount metadata under INGREDIENT and call it a day. That leaves our metadata value static for the INGREDIENT instance throughout the system, and butter is not always 2 tablespoons. Sometimes, if you are lucky, it’s 2 cups.
(This is complicated stuff. Feel free to read those last couple sentences again!)
The only way we can capture those extra in-context attributes is by designing for a junction object. This is a tool developers use to create many-to-many relationships (thank you developers for making our many-to-many dreams come true) and this is what allows us to give that context-specific metadata a home in our object map. Junction objects make your object map more clear and more complete by representing specific (and important-to-capture!) combinations of nested objects.
Here’s how I recommend you represent junction objects.
Let’s look at another example, in database form. Say I have a table for an ENDANGERED SPECIES object and a table for a HABITAT object. Each table houses lots and lots of instances of each kind of object, and I need to map those SPECIES to their HABITATS. If each SPECIES only had 1 HABITAT, this job would be simple.
A SPECIES has 1 HABITAT.
A HABITAT has many SPECIES.
From a database design perspective, all I would need to do is add a HABITAT Foreign Key (unique identifier) to the SPECIES object. This way, I can tell the system, “The snow leopard lives in the High Alpine Himalayas & Foothills.”
But what if a SPECIES lives in many HABITATS? What about the clouded leopard, which lives in the High Alpine Himalayas & Foothills as well as the Sumatran & Borneo Rainforest? Do we just add a column in the SPECIES table for “Habitat Foreign Key 2?” That’s not very elegant, especially if a SPECIES might travel across nine HABITATS. What do our dedicated database developers do instead? They create a junction object. It looks something like this.
Now we have a dedicated place to store the metadata specific to the clouded leopards living in each habitat! If I want to show population metadata for each SPECIES within each HABITAT, junction objects make that possible. If I want to show that the clouded leopard populations are increasing in Borneo but decreasing in the Himalayas, junction objects can show that, too.
Putting junction objects into practice
When you discover a many-to-many relationship and the relationship has at least one attribute, this is an opportunity for a junction object. Catching them early means you’ll have a box for storing their necessary metadata instead of letting that information fall to the side because you didn’t have anywhere to put it. Plus, representing junction objects on your object map gives you a concrete way to talk to your team about something many designers don’t know how to recognize yet. Consider yourself ahead of the curve now, and please help spread the word!
What junction objects can do for you
Can you see the power and flexibility afforded by junction objects? With the dynamic metadata offered by junction objects, we can bake in some math behind the scenes. A recipe app user can instantly double all the quantities of their INGREDIENTS. Imagine how this might help us simplify permissions design! When a STUDENT can be the president of the Chess Club but just a member of the Horticulture Club, welp, we can add student role metadata to the STUDENTxCLUB junction object.
Users ultimately have a richer experience thanks to junction objects, but you’ll find more immediate value coming from your own team. Your developers will appreciate having an easier time building the system when you plan ahead for the junction table they’ll need to create. Not only are you paving the way for your dev counterparts, you’re able to capture important metadata they might have overlooked.
Now you have a new tool for better communication and collaboration on data puzzles! When we (UX designers) have more of these tools available for translating between the different disciplines on our team, the design and the development are both cleaner and tighter with fewer mistakes and missed opportunities.
I’d love to know what you think of junction objects, especially those of you with a technical background! Do you have any feedback on how I could better explain or leverage this concept? And for those of you who are encountering this concept for the first time—can you see this applying to your work? Are junction objects super confusing or a revelation? How do you handle scenarios like this today? Join the #OOUX discussion on Twitter; I’d love to hear your thoughts!
(P.s. Want to see more junction object fixes? Here’s a video from Cohort Four of the OOUX Certification program that can help illustrate more use cases. Enjoy nerding out!)