CRUD APIs are Poor Design

Поделиться
HTML-код
  • Опубликовано: 24 янв 2025

Комментарии • 106

  • @anikaitmakkar989
    @anikaitmakkar989 Месяц назад +156

    Can we have a detailed video, where you refactor a CRUD based API based on the suggested principles

    • @CodeOpinion
      @CodeOpinion  Месяц назад +47

      Great suggestion!

    • @majormartintibor
      @majormartintibor Месяц назад +17

      @@CodeOpinion would love that, please do it!

    • @marcwinner567
      @marcwinner567 Месяц назад

      Yeah please do this. @CodeOpinion. It works really help a lot

    • @H0b0Gamers
      @H0b0Gamers Месяц назад +1

      Second this.

    • @southpole76
      @southpole76 Месяц назад

      i don't think it's refactoring, it's adding a domain layer and hiding the CRUD access behind a repository

  • @joelv4495
    @joelv4495 Месяц назад +48

    💯. From a business perspective, we don't "create a shipment", we "SHIP an order".

    • @dyto2287
      @dyto2287 Месяц назад +8

      ......after you create a record of the shipment in your database and create additional shipment status events while it's ongoing.
      Cmon, stop thinking this must be one object.

    • @ds-pc9ys
      @ds-pc9ys Месяц назад

      Dont forget about domain. You might create a shipment if youre a logistics company.

    • @glhays6832
      @glhays6832 Месяц назад

      What type of perspective is that. "I got order" , "ship it". Nothing more nothing less. What do you need a system for, with that perspective. 😂

    • @ds-pc9ys
      @ds-pc9ys Месяц назад

      @@glhays6832 Think about the domain of a shipping or freight company. Off the top of my head- You might pack a single container with one or more orders from one or more customers. Or a situation where a shipment could consist of many containers that need to be tracked individually AND collectively.

    • @marna_li
      @marna_li 13 дней назад

      You highlight a thing that Derek talks about again and again: Developers being data-centric, rather than behavior centric. Or technology-centric. And that divorces the code solution from the reality and how users look at the domain.

  • @robotrabbit5817
    @robotrabbit5817 Месяц назад +10

    Dude, there is so much nuance in everything about business software. I read so much stuff about software development and DDD and watched a lot of videos especially from your channel. And I am honest here. A lot of the time think I understood what you and those books are telling me and then I start programming at work on a real system and I make mistakes just to realize a few weeks later down the line that I was already told the solution to the problem. I am not sure how the rest does it, but everytime this happens I realize that I do not fully understand the underlying problems of the topics you and the books are talking about. I think this is why experience matters.
    I am grateful for your work on the channel. Thanks

  • @Rick104547
    @Rick104547 Месяц назад +6

    Currently working on a microservices application that just crud for the most part. It's horrible, the UI around it has alot of logic in it because its basically a big leaky abstraction.
    So now my team is busy consolidating the microservices and designing the endpoints around behavior instead of crud based endpoints. The UI is getting simpler every iteration and as a bonus faster.
    It works for tests as well, we used to have tests for every single method but that was just dumb. Now we test behaviors and sure the tests are larger in scope but the actually test things that are of value and they give us alot of freedom to refactor.
    The only one that seems to have a problem with it is weirdly enough our solution architect. This slows down our efforts a bit but we still get it done.

  • @transientwaveform1475
    @transientwaveform1475 Месяц назад +13

    Louder for the people in the back!!! Systems built this way are wildly irresponsibly engineered in the real world, and yet it's so pervasive now because nobody challenges it because they assume it's "best practice" due to the tutorials they followed!!

  • @allenbythesea
    @allenbythesea Месяц назад +27

    I've been opposed to the CRUD/REST paradigm since its inception. These concepts push business logic up into the UI instead of in the api/business layer. Glad to see others coming around as well.

    • @CodeOpinion
      @CodeOpinion  Месяц назад +7

      Agree'd. I advocate for hypermedia a lot to guide UI/clients but there is so much pushback or dismissal of it, I think it's too far gone.

    • @ing50c
      @ing50c Месяц назад +2

      At its worst, it’s downright dangerous.
      I’ve worked at places where the data model was exposed as-is in this CRUD fashion, with nothing in place to enforce sanity.
      So if you had an Order entity, some other developer could come along and just PATCH it with a different customer ID.
      Zero encapsulation with the power entirely in the hands of the caller. It was a nightmare to work with.

    • @allenbythesea
      @allenbythesea Месяц назад

      @@ing50c yes! I've said the same thing many times and been shouted down. Basically with CRUD and REST you are exposing your inner structures. Its crazy to me that people are just realizing what was obvious from the start. I blame those who just follow the blogs and don't think for themselves. So many times their retort to my argument was 'well such and such does it'.

    • @robotrabbit5817
      @robotrabbit5817 Месяц назад +1

      Dude I just found out that this is exactly one of those problems i facing with an app we have.

    • @southpole76
      @southpole76 Месяц назад

      Pushing business logic into the UI seems like a very bad idea. What if there are more than just one client.

  • @TheCardSlayer
    @TheCardSlayer Месяц назад +7

    What would an API example look like in these cases?

  • @vuhoang5903
    @vuhoang5903 Месяц назад +6

    I've been learning and exposed to CRUD apps since day 1, and this opens a new horizon for me.

  • @majormartintibor
    @majormartintibor Месяц назад +20

    I agree with you Derek, but would love to see how you design APIs that are not "CRUD/REST" for supporting business processes.

    • @Coburah
      @Coburah Месяц назад +4

      Can't speak for Derek, but what my company does is use CQRS. All commands are pretty much self explanatory in terms of what they do and they all are executed with POST. They all accept tailor made input parameters for that particular command. Examples:
      POST api/users/createUser
      POST api/orders/updateShippingAddress
      POST api/orders/cancel
      All queries are done via GET in typical REST fashion.
      Simple.

    • @CodeOpinion
      @CodeOpinion  Месяц назад +11

      I plan on creating another video detailing that as I think it's a good idea if I can find an example that's primarily CRUD and change it to illustrate.

    • @svorskemattias
      @svorskemattias Месяц назад

      @@Coburah I'm even doing queries with POST.

    • @Coburah
      @Coburah Месяц назад

      @@svorskemattias sure, why not? REST dogma gives nothing imo. If the command is properly named, it should be apparent what it does. We use commands (POST) for queries that are more like "computations".

    • @svorskemattias
      @svorskemattias Месяц назад

      @@Coburah
      I use POST mostly to just reduce my mental overhead. I don't need caching. There's always a body for parameters, no need to use queryparams or URL-segments for that.
      I only use GET when it's the browser that natively uses the URI, like for an IMG-tag.

  • @rommellagera8543
    @rommellagera8543 Месяц назад +3

    He is proposing Event Driven design, but CRUD exist behind it or with it
    How can you create an order without entering who made the order and list of items to order, and how will you do it without CRUD?

    • @ArcRCG
      @ArcRCG Месяц назад +4

      Your DB or ORM already implements the CRUD interface, what I've found while working is that sometimes REST APIs act just like proxies to a DB, there is little to no logic in the app and is mostly plagued of conversions between HTTP to the DB driver or ORM, and because of this basically all the logic is spread but mostly living in the UI.
      When using something like CQRS you create a proper interface for your business and internally you call all the CRUDy like interfaces.
      In Spanish CRUD sounds similar to the word "crudo" which means "raw" and that is basically the idea I have about CRUD in my mind. They are just raw interfaces which you need to compose to build your business interfaces. Don't expose raw interfaces directly to your clients.

    • @rommellagera8543
      @rommellagera8543 Месяц назад

      @ArcRCG that's the point of CRUD API, direct mapping to DB, for simple non message queue app, this is a good easy to follow/maintain approach
      For processing outside standard CRUD, I just use something like POST api/order/proceed-to-payment
      Since it is related to order, it is under api/order end-point, this way the next guy will have an easy time searching things
      Kindly explain what is difficult or downside of using this approach

    • @ArcRCG
      @ArcRCG Месяц назад

      @@rommellagera8543 yeah but why develop a CRUD API in the first place, I mean, why code it if you are just going to replicate the behavior of the next layer? Just put a software that already automatically maps that like Prisma or PostgREST and call it a day, you'll probably need another layer in front of it but why make it CRUDy again?
      I had a coworker that was in charge of creating a new version of a backend API, he knew the business really well but he didn't map the business logic to proper commands and queries, and just delegated another coworker to create a skeleton of a CRUD interface for each table. He missed the design part, so what happened later is that all tables and fields where exactly mapped to the endpoints and fields of the API, and because we had to start working in another stuff, the API rapidly started being polluted with unplanned endpoints and the CRUD endpoints just started to serve no purpose and begin growing in size with each requirement that it just made for a franken-CRUD-CQ like interface. He had the opportunity to make a good interface but he just followed the CRUD mentality and everything was fckdup quickly.
      What really blows my mind is that it was a GraphQL API and GraphQL already provides the separation between Commands(mutations in GQL) and Queries(well, this has the same name in GQL).
      I'm not saying CQRS is a silver bullet and CRUD serves no purpose, but please think carefully how you are going to design your API, most of the time there is no way to go back after clients start using the API

  • @larsh8560
    @larsh8560 Месяц назад +4

    Vendors: "Our standard system have this great API you can use."
    Me: "That pile of turd? That's basically an APi wrapping CRUD operations on your database"

  • @buriedstpatrick2294
    @buriedstpatrick2294 Месяц назад +4

    I think CRUD is so prevalent because the first thing a lot of developers are taught to make is a TODO list app.

  • @lost-prototype
    @lost-prototype Месяц назад +3

    There are so many usual suspects of problems in CRUD systems, and it causes people to become so fixated on superficial DRY, high coupling, loss of context... The end is basically change data capture and never ending tack-ons to recapture lost context.
    CQRS/business operations.... Those are the way to go. Simple transaction scripts. Lean flows, even if there's a bit of duplication.
    You can always maintain multiple rich domain models.
    The bonus once you follow all the advice? Simpler test cases, higher level of certainty in the system.

    • @atanas-nikolov
      @atanas-nikolov Месяц назад

      What does your API look like with CQRS? Action endpoints, like /api/createUser?

  • @GabrielSoldani
    @GabrielSoldani Месяц назад +2

    It probably doesn’t help that HTTP and REST were designed at a time that the Web that was mostly used to publish and consume documents, not to drive business processes.

  • @funkdefied1
    @funkdefied1 9 дней назад

    I love the square peg round hole. It’s been my intuition for a while, but I haven’t heard someone say it.
    I love thinking about my APIs as actions, RPC style

    • @CodeOpinion
      @CodeOpinion  8 дней назад

      RPC gets a bad name and I don't really think of it as RPC so much really.

  • @cloudbaud7794
    @cloudbaud7794 Месяц назад +4

    Need an end to end example

  • @marcwinner567
    @marcwinner567 Месяц назад +2

    Hey Derek! Great video as always! I think it would be beneficial to some of us viewers to see the difference in actual code to really nail the idea. Could you do that?

    • @CodeOpinion
      @CodeOpinion  Месяц назад +1

      Yes good suggestion, I will!

  • @adambickford8720
    @adambickford8720 Месяц назад +10

    CRUD is so predominant because many times, that's all you genuinely need. In fact, it might even be the majority and you *should* use it if it makes sense. If you're just going to essentially validate the input of your endpoint and persist it... do that. Don't invent some abstraction (DDD, OOP, etc) 'just in case' or for the sole purpose of semantic decoupling.
    Sometimes a cigar is just a cigar.

    • @CodeOpinion
      @CodeOpinion  Месяц назад +4

      Fully agree, except on the "it might even be the majority", Not so sure about that. Let CRUD be CRUD where that's truly what it is. However in my experience, in large business systems, that's not at all what it is.

    • @adambickford8720
      @adambickford8720 Месяц назад +2

      @@CodeOpinion I think it depends on the systems. I've worked on a lot of systems that have pages to essentially CRUD entities/data that are used in the actual business workflows in the app. Between that and pages of tabular/reporting views, they often end up with more 'surface area' than the business flows themselves.

    • @Coburah
      @Coburah Месяц назад +1

      @@adambickford8720 I agree with this sentiment: CRUD fits neatly when you have essentially "forms for entities". Just load the "form", update in UI, send back to backend to persist. I guess the problem is that people then reuse that "form data" for other purposes...

  • @PragmaticIT
    @PragmaticIT Месяц назад

    As for me we need crud too. What about process: "manager create order with many mistakes". Describe how it work in our approach. Or what about fake order created by someone... Maybe we still need some crud api?

  • @IvanyaKosmos
    @IvanyaKosmos Месяц назад +1

    another end of the spectrum is full blown RPC with hundreds of methods to support each business process operation, which is also bad because it overwhelms clients with interface scale. as always truth is somewhere in between…

    • @ArcRCG
      @ArcRCG Месяц назад

      namespaces my friend

  • @ardenfraser1068
    @ardenfraser1068 Месяц назад

    I think CRUDs prevalence speaks more to a lack of business analysis that usually comes with software projects where a businesses core focus is not on software. Also tight time frames make it difficult to argue the need for 6 endpoints were previously 1 would suffice.

  • @Minolrx
    @Minolrx Месяц назад

    Isn't it supposed to have another layer ? Another layer above the crud layer ?

  • @Dan-codes
    @Dan-codes Месяц назад

    As a CRM engineer for a logistics company, this is interesting.

  • @PhillippeLevidad
    @PhillippeLevidad Месяц назад

    Great video as always! At the end, you asked why CRUD is so dominant in software development. I think it's because there are so many tutorials on building CRUD-based systems, and people are often just looking for step-by-step guides. The discussions you present are more philosophical and less practical in the sense that you're not always showing exactly *how* to implement something.
    A good example is how people often request videos where you refactor bad examples into good ones. This isn't a critique-I love these discussions. I get why you don't always show a practical code approach: "it depends." There isn't a single right way to do things, and your channel is called "Code Opinion" for a reason. Still, the abundance of CRUD examples and the lack of non-CRUD ones might be why it's so prevalent.

  • @DevBartek
    @DevBartek Месяц назад +1

    It would be great if you will extend your comment on Entity Service pattern. Some enterprise consulting companies promote "Entity Service API" concept or "API Led Conectivity" concept.
    They promise that move 3-layer Architecture (Presentation, Logic, Data) to API world (Experience API, Process API, System/Data API) is silver bullet idea.
    For me, it adds another technology layer with same coupling problems and spaghetti move from database to Entity Service APIs.

  • @Leo-tf7gu
    @Leo-tf7gu Месяц назад

    Ruby on Rails with it's Active Record ORM advocated this more than anything else.

  • @a-yon_n
    @a-yon_n Месяц назад +1

    0:43 Actually a PUT request is an upsert operation. If the resource exists, it replaces it, otherwise it inserts it. This makes it different from a PATCH request when updating. A PUT request always carries the whole data of the resource since it may end up being an insert operation, while a PATCH request usually carries partial data since it only modifies a part of the resource. A PUT request will always succeed, while a PATCH request may fail if the resource does not exist.

  • @ashlynnantrobus5029
    @ashlynnantrobus5029 Месяц назад

    I think I'm missing something, because to me it sounds like you're just describing a pub-sub system. Which if that's the case, yeah. But it's also like saying that a microwave isn't very good for cooking because it doesn't Cook steak very well. The problem isn't the microwave, the problem is trying to cook a steak in it

  • @istovall2624
    @istovall2624 Месяц назад

    i like crud based systems and then distributed events based off those, but i think that defining the crud event in smaller terms is appropriate. for example, update_user is too broad, update_user_email_by_admin is much better, and also update_user_email_by_user is much better, both are updates, and follow a crud pattern but are very fine grained because different events need to transpire based off of each action, which is essentially no different than what you described (i think???)

  • @ian2neko
    @ian2neko 25 дней назад

    Not entirely get it, business processes come in many different terms, ways or path (different apps or UI):
    user/admin cancel shipment, user/admin amend shipment, add shipment, split shipment, shipment status change.... etc.
    At the end of the day, they translate to Create, Update or Delete.

    • @stingray5
      @stingray5 16 дней назад

      So if I want to cancel a shipment in your API do I call DELETE /shipment/id or PATCH /shipment/id? You are forcing your service clients to know how a business operation maps to your database record. Maybe the business at first thought it was fine to remove the shipment record from the database immediately when shipment are canceled but later decided they would rather not delete it but mark it as canceled. Would have been better to encapsulate the concept in the first place with an API like /cancelshipment/id where clients don't have to know if this operation actually deletes or updates a record (and if an update, they don't need to know what status field on the record means canceled). This makes it obvious to service clients what business capabilities your service actually supports and encapsulates how it works so that internal changes don't ripple out to all clients.

    • @ian2neko
      @ian2neko 15 дней назад

      @@stingray5 Ok thanks I understand it better now. Then lets say I have different kinds of cancel shipment with slightly different logics:
      Customer Cancel - update status to Cancel
      Staff Cancel - update status to Cancel
      Logistics Cancel - update status to "Not yet shipped"
      Manager Cancel - internal log and DELETE
      IT Cancel - IT audit log and DELETE
      Shall I create different endpoints and call UPDATE or DELETE inside the endpoint logic?

  • @funkdefied1
    @funkdefied1 9 дней назад

    I think CRUD caught on because REST caught on, and REST caught on because HTTP won. All the HTTP verbs lend themselves to working on a certain resource, and these resources map pretty well to database objects.

  • @KeithGraves
    @KeithGraves Месяц назад

    I think I might be one of the few people who actually prefers the old SOAP APIs instead of REST APIs, but being able to define your own methods always made more sense to me than just having the CRUD actions of REST.

  • @viliuszurauskas4315
    @viliuszurauskas4315 Месяц назад +1

    Entities can have status property which could easily control the flows for different shipment stages. A PUT is supposed to update or create (if record doesn't exist). So you could easily use PUT and control the flow with status.

    • @stingray5
      @stingray5 16 дней назад

      They could but you are coupling your service clients to how you represent state in your database. What if shipments later become complex enough that "status" is better represented by several different fields on the shipment record. Now your clients have to change to account for this. It would have been better to have an API that represents what you are actually trying to do (like /cancelshipment) and let the service decide how to represent the underlying state change. This type of encapsulation allows your services to evolve independently.

  • @smaug9833
    @smaug9833 Месяц назад

    CRUD is useful to learn when you're a beginner, but it's not how a good production server operates.
    The front-end should have flexibility on how it talks to the backend, establishing a good contract is important and it should be evolved from time to time.

  • @shmupful
    @shmupful Месяц назад

    It seems like a very important principal. Personally for me, an actual concrete example would be very helpful for understanding the idea and it's benefits

  • @ke30_
    @ke30_ Месяц назад

    In OO, this is where a bridge pattern shines.

  • @patolorde
    @patolorde Месяц назад

    i have a hard time modeling this

  • @jntaca
    @jntaca Месяц назад

    CRUD APIs are suitable for master (clients, products ) and configuration tables. Any update is pusblshed into an event channel.
    Transactional APIs trigger worflows and processes that modify transactional tables.
    Personally, I don't like microservices because of data integrity issues, I prefer to break the system into isolated modules/services that can rely on DB transactions / commitis and rollbacks.

  • @essamal-mansouri2689
    @essamal-mansouri2689 Месяц назад +1

    Big fan of all your videos!

  • @waltervandergeest5425
    @waltervandergeest5425 Месяц назад

    I think you are addressing an archicetural problem and mix it up with an implementation technology. Your event driven solution can be fed by a crud api as well. I only agree with the fact that over time your api needs to change as the world changes around you. So what? Then change it. The api should not be written in stone…

  • @FaridAdamgrino
    @FaridAdamgrino Месяц назад +3

    The real issue here is the architecture of the system and not CRUD. You should not directly expose database tables through APIs. Also from the example you gave with CURD, one would fall into that trap if they don't do proper domain modelling or do not do proper abstractions; leaving "all logic to CRUD.

  • @kahnfatman
    @kahnfatman Месяц назад

    It depends. And people are lazy to think and shied away from making crucial decisions. Cover-my-assssssets strategy implemented from top to bottom.

  • @Kubkochan
    @Kubkochan Месяц назад +1

    one of the best videos

  • @ryanmorris5709
    @ryanmorris5709 Месяц назад

    Yes yes this is the quintessential issue with some systems!

  • @aslkdjfzxcv9779
    @aslkdjfzxcv9779 Месяц назад +1

    i like crud.

  • @ianmarteens
    @ianmarteens Месяц назад

    Yesssir! Wholeheartedly agreed.

  • @williamalves5282
    @williamalves5282 Месяц назад

    this video really opened my eyes lol

  • @cathrerinezetadrones3169
    @cathrerinezetadrones3169 Месяц назад

    Absolutely can relate!

  • @Nir4023
    @Nir4023 Месяц назад +1

    Great, need a video like this about authentication flows, refresh mechanism, OIDC and OAuth

    • @CodeOpinion
      @CodeOpinion  Месяц назад +2

      Elaborate a bit more on what you mean.

    • @Nir4023
      @Nir4023 Месяц назад

      @CodeOpinion like the way most resources tell you to use jwt as if it is the standard or silver bullet for all situations, without pointing out the trade-offs one should be making and the specifications for each platform and the bigger architecture of the system like how now you can have a client component, a server component, a server action and, remote backend and a 3rd party intégration all in one single small app.
      We need more content explaining how context is king in various topic that are victim to the crowds mentality and chasing the shiny things!

  • @christianrazvan
    @christianrazvan Месяц назад

    Yea..much talk but little example

  • @Benjamin-Chavez
    @Benjamin-Chavez Месяц назад

    lol what?

  • @JohnHall
    @JohnHall Месяц назад

    Meh. This is just about where the business logic is. If you are able to update your APIs and deploy quickly, then putting business processes in here is fine. If you cannot... Many non-tech businesses are trying to limit the need to involve programmers in business rules. CRUD APIs are merely a symptom of a problem of limited programmer resources.