Inheritance is a design pattern commonly used in object-oriented programming which allows you to model entities that inherit certain properties or functions from a parent class. This can be incredibly useful for modeling entities which have multiple types, such as different types of activities to show in a feed.
Relational databases don't support inheritance per-se, but with some effort we can arrange things with Prisma to give a pretty good approximation.
We have a few cases in our data design at Basedash where we have models which share commonality between them. Take bananas and oranges. They are distinct models with their own particular properties, but they have common ground. We’d like to model each of them as a type of a fruit. So fruit is the “parent model” and banana and orange are “child models”. They inherit from fruit. Our interest at Basedash has been an approach where we have a distinct table in our database for each of these models, and we set up our own “wiring” to keep them in order and maintain the parent-child arrangement. This is sometimes known as “Class Table Inheritance”, where you have one table per “class”.
To see what we mean, here's a very short article and diagrammed example: Class Table Inheritance
Diagram of “Class Table Inheritance” from martinfowler.com
To see what we do not mean, here’s a common alternative: Single Table Inheritance
Diagram of “Single Table Inheritance” from martinfowler.com
One key aspect of inheritance is that there can be multiple subclasses under a superclass. So, say you have a Fruit parent class with Banana and an Orange child classes. A Fruit can be either a Banana or an Orange, it can take one of multiple forms. That is polymorphism.
Many ORMs support polymorphic associations. Here's a few examples:
Another key aspect of inheritance is that things which are common get passed down from the parent, and things that are particular are stored on the child. When there can be more than one type of child, the particulars for that type are passed down to the child. The parent class /delegates/ its type to a child class.
So you have a Fruit, well what type of fruit? An Orange, say. The Fruit delegates its type to Orange.
The idea is that you can't have an Orange in isolation. The Orange record is paired with, and goes through life with, and should be inseparable from its corresponding Fruit record.
So, say Fruit has fields such as isRipe, and weight. And say Orange has a field particular to it called segmentCount. If you have an Orange, you can know how many segments it has, and you can also know if it is ripe by going to the Fruit record for that Orange.
Rails for instance has such a feature. Here's a quote from the Rails PR implementing delegated types explaining the concept:
With this approach, the "superclass" is a concrete class that is represented by its own table, where all the superclass attributes that are shared amongst all the "subclasses" are stored. And then each of the subclasses have their own individual tables for additional attributes that are particular to their implementation. This is similar to what's called multi-table inheritance in Django, but instead of actual inheritance, this approach uses delegation to form the hierarchy and share responsibilities.
Unfortunately, Prisma is behind on these fronts, though it seems they are actively considering such things. Here's a prominent thread on the topic: Support for a Union type
The conversation from said thread seems to have spurred an official example of how to manually arrange things to achieve delegated types:
This example felt good enough to us that we decided to try it out. And we decided to try it out first with our activity feed.
Basedash tracks such things such as edits to fields on records and deletions of records. We have an Edit model and a Deletion model. We wanted to "subclass" these models under an Activity model. So, to generate the activity feed, we would want to get all the Activity records and for each one, see what type it is (either Edit or Deletion) and then render each one with the combined fields from the child and the parent.
Here's the pattern we've gone with, which differs slightly from the Prisma delegated types example:
Things to note:
Things to note:
Note that we've gone with a simple findMany with an include directive for its simplicity and readability. The Prisma example does something a bit more sophisticated, which may be more performant: first executing a findMany on the parent and then mapping through those and querying for the child by id for each.
We’ve been quite happy with working with Prisma at Basedash, but this is a case where it seems a more mature ORM might be a better choice. Still, it’s nice that with a good example to follow and a bit more manual work we can have this inheritance functionality and put it to use in our codebase.
An index is a data structure you can add to your SQL database that allows for quick retrieval of certain information. For example, if you have a database of names and phone numbers, an index might be created on the name column so that the database could quickly be searched for a particular student's phone number. You can think of this in the same way that a physical phone book works.
If you're working on a startup, chances are you've got a lot of internal tools that you've built or are in the process of building. And if you're like most startups, those tools are probably a hot mess. What tools will startups use in the next few years? We have a prediction on trends, tech, and emerging ideas in the space.
Refactoring our tables to be virutalized was a huge undertaking, with a huge upside. It sped up table performance by 500% and allowed Basedash to load tables that had previously caused the app to crash.
Internal tooling can be a quick solution to satisfy requirements for colleagues that lack the technical knowledge to build their own custom software. Let's look at how we can beyond simply viewing admin panels, audit logs, and simple CRUD operations -- and into the world of building for the end users that work alongside us each day.
There are many different types of internal tools that you can build. You might want to create a reporting tool for your marketing team, or maybe you need a way to quickly get customer data visible for your customer support team. Or, any number of business apps to help your colleagues manipulate data.
You've built a solid DB, but your colleagues need to edit data without knowing SQL. Here's how to enabler them to make edits:
How we wrote our own utility with Typescript to take the Date primitive and transform it into a string for use inside of Basedash.
In customer support cases, we use Basedash to help get to the bottom of issues. With a bit of browsing, we can pull up Views, find user details, schema, table information, and take a look to see what the issue is.
A breakdown of the process of how the engineers at Basedash added the feature to allow workspaces to restrict signups based off of user email address.
Using our own product to query our databases speeds up our development time and gives us more opportunities to spot new ideas for features and improve our user's experience.
We recently added an easter egg to Basedash which shows ASCII art of our logo in the browser console. Here's how we we able to style our console.log message with CSS.
At Basedash we use Basedash itself for managing, adding, and removing feature flags for our product. These help use beta test new features, catch bugs, and get feedback before shipping new features.
I had the opportunity to chat with Liau Jian Jie, CTO & co-founder of Mobbin and talk about their migration from Firebase to SQL on Supabase earlier this year. Mobbin is a tool for designers to see and track UI flows from mobile applications to help with real-world inspiration for their own design work. I used it personally...
There aren’t many designers out there who would advocate for working with less or no information about the product they’re building. We want to know who is using our product, what their motivations are, what kind of frustrations they might have, what work environment are they in, and what other tools...
Recently, we refactored our codebase at Basedash to fetch our server data with React Query and optimize our REST API calls in the process. The transition to React Query allowed for better code readability and the optimization of our API calls resulted in half the number of data fetching API calls...
Startups can use whatever tools they want to do their job. We're not burdened by legacy contracts, enterprise-wide procurements, existing monolithic workflows, or the burden of training hundreds or thousands of staff for a new tool. We can change workflows on a dime. We can try something new...
See how removing barriers can change the way your team works.
No credit card required