A stray commit buried multiple levels deep cost me months

(droppedasbaby.com)

25 points | by offbyone42 1 hour ago

7 comments

  • magicalhippo 26 minutes ago
    I found the article very hard to follow. Then I read the domain name and it all made sense...

    Guess our pattern is different, not really felt the pain point the author is talking about. Or it's the language/framework, not sure whatever the example code is written in, but setting properties on entity records would never update the database in the ones I've used.

    When we did things more manually we'd make sure that methods like `create_main_records` would start a transaction if not in one, and only commit if it started the transaction. This way we could nest without worry. Our database supported nested transactions but using this pattern we didn't feel the need.

    • nine_k 4 minutes ago
      Tired: pass live DB model objects around, mutate them to accumulate random changes, call commit() five levels deep, experience the chaos as described by the author.

      Wired: fetch DB records and construct domain objects, pass them around, do mutation on the outermost level within an explicit transaction. (Typical best practice.)

      Inspired: "functional core, imperative shell".

  • hparadiz 31 minutes ago
    Feel like I've solved this non problem like 20 times.

    If your framework is holding your records in a collection and you keep track of phantoms that have been edited but not saved as they are edited then all this becomes a non issue. That way you do Collection->SaveTransaction or Collection->Save() and the collection does all the db commit, roll back nonsense.

    Anyway the examples I don't even know if I could call that an ORM. Use a better one.

  • Retr0id 55 minutes ago
    > DO NOT blame the framework

    Why not? Why should I be allowed to db.commit() midway through a transaction?

    • Stitch4223 45 minutes ago
      With great power comes great responsibility.
      • Retr0id 43 minutes ago
        Well, I don't want either. Give me a safe API!
      • saghm 35 minutes ago
        Yes, and the people who designed that API clearly were not worthy of of the responsibility of providing it
      • UqWBcuFx6NV4r 43 minutes ago
        This is like people saying that C is infallible and it’s those stupid lesser-developers that unlike me simply cannot wield its immense power. No. Usability matters. After all these years software development still has an ‘unfounded male confidence / posturing’ problem and it’s just cringeworthy
        • hackthemack 35 minutes ago
          I agree. No matter how complicated, or unnecessary, or unintuitive a piece of software or technology is... There is always this contingent of people who pop in and say "It is not that hard!" and furthermore tend to express a view of "I am superior because I figured out this obtuse thing, and you must be inferior because you have not figured it out".

          I do not know why that mentality exists in the industry, but I see it all the time... for the past 35 years.

    • jiggawatts 32 minutes ago
      Database engines I've worked with generally support nested transactions, so you can open a transaction, open another transaction, commit it, then roll back the outer transaction... and it's like nothing ever happened.

      This ability to compose transactions is their main benefit over other kinds of concurrency control!

      • manphone 12 minutes ago
        Many databases do not actually offer this or pretend to offer this, but it is really just one thing.
        • Groxx 0 minutes ago
          [delayed]
    • offbyone42 41 minutes ago
      Giving "I cut my finger with a knife, why is the knife so sharp?" energy. JKJK.

      I think the option should be there, but it needs to be used responsibly.

      • Retr0id 38 minutes ago
        What's the use case? I've never found myself wishing my transaction wasn't actually atomic.
      • p-e-w 17 minutes ago
        The option to make a transaction not be a transaction? What is it then?
  • eqvinox 35 minutes ago
    > # calls helpers that eventually call commit()

    Show, don't tell. The article should've included an example of these helpers.

    All in all, this feels poorly written, but also poorly thought out. The DB layer can and should throw an exception if you manually begin/commit inside a context manager. Please do blame it if it doesn't.

  • quamserena 38 minutes ago
    This is trivially preventable via affine types
  • khaledh 29 minutes ago
    If someone can trivially introduce bad state (or worse, data loss), then the API is clearly broken.
  • kburman 38 minutes ago
    [dead]