Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 3 min read

Absolute Beginner Tips: CRUD Is a Template, Not the Law

One of my biggest struggles when I first started developing projects for my portfolio was understanding that CRUD was a template, not a law. I remember starting my first dashboards using the same basic structure everywhe

One of my biggest struggles when I first started developing projects for my portfolio was understanding that CRUD was a template, not a law. I remember starting my first dashboards using the same basic structure everywhere: GetAll, GetById, Create, Update, and Delete. And honestly, there is nothing wrong with that. It's a great starting point.

However, as I progressed through my projects, I realized that not every endpoint needed to return an entire object. In one of my projects, I needed several additional GET endpoints, and some of them didn't need to return complete objects at all. They only needed to return a specific quantity, a count, or a small piece of information. This is where combining DTOs with more specific queries becomes really useful. Instead of retrieving an entire model from the database and sending all its information to the frontend, you can use a DTO to return only the data you actually need. This means less unnecessary data transfer, lighter responses, and potentially better performance.

Another interesting case is the UPDATE operation. Updating an object doesn't always mean sending the entire model back and forth. Sometimes, you only need to update a specific part of it. You can create more specialized update operations instead of relying on one generic endpoint that handles every possible change. Yes, it takes a little more work to implement and maintain, but your application can benefit from more focused operations and less unnecessary processing.

A Practical Example

Let's imagine a website where users can create posts. Each post can have two states: Draft and Published.

You could start with something like this:

getAll(): Promise<Post[]> {
    // Returns all posts without any filtering.
}

getAllOfUser(userId: string): Promise<Post[]> {
    // Returns all posts belonging to a specific user.
}

Both methods work, but they return the entire Post model, even when the frontend doesn't need all that information.

Instead, you can separate your endpoints based on what the frontend actually needs:

getAllOfUserDraftsForList(userId: string): Promise<ListPostDto[]> {
    // Returns lightweight DTOs containing only the necessary
    // information about the user's draft posts.
}

getAllOfUserPublishedForList(userId: string): Promise<ListPostDto[]> {
    // Returns lightweight DTOs containing only the necessary
    // information about the user's published posts.
}

getByIdOfUser(userId: string, postId: string): Promise<ReturnPostDto> {
    // Returns the post details needed when the user
    // wants to view or edit a specific post.
}

With this approach, you have more control over the data flow. Your listing endpoints don't need to return the entire post content, metadata, and every other property. They only return what is necessary to display the list.

When the user wants to see a specific post, you can provide a more complete DTO with all the information required for that operation. You can also optimize your database queries to retrieve only the columns you actually need instead of loading the entire entity every time.

Of course, this doesn't mean you should create a different endpoint for every single situation. The idea is to understand what your frontend actually needs and design your API around those requirements.

So, what's the lesson? Start with CRUD. It's a good template and gives you a solid foundation. But as your frontend evolves and your application becomes more complex, adapt your API to your actual needs. Don't be afraid to create specific endpoints, use DTOs, or rethink how your update operations work.

The goal isn't to create as many endpoints as possible. It's to create endpoints that serve a clear purpose.

CRUD is a template, not the law

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.