HN user

eeperson

335 karma
Posts1
Comments254
View on HN

Sorry, perhaps I should have been clearer. They don't grow completely out of making bugs (although they do tend to make fewer over time), they grow out of making solutions that look right but don't actually solve the problem. This is because they understand the problem space better over time.

Everybody produces bugs, but Claude is good a producing code that looks like it solves the problem but doesn't. Developers worth working with, grow out of this in a new project. Claude doesn't.

An example I have of this is when I asked Claude to copy a some functionality from a front-end application to a back-end application. It got all of the function signatures right but then hallucinated the contents of the functions. Part of this functionality included a look up map for some values. The new version had entirely hallucinated keys and values, but the values sounded correct if you didn't compare with the original. A human would have literally copied the original lookup map.

If you're in a project where buggy behavior wasn't introduced so much as grew (e.g. the behavior evolved A -> B -> C -> D -> E over time and a bug is reported due to undesirable interactions between released/valuable features in A, C, and E), then bisecting to find "when did this start" won't tell you that much useful.

I actually think that is the most useful time to use bisect. Since this is a situation where the cause isn't immediately obvious, looking through code can make those issues harder to find.

I know a lot of people want to maintain the history of each PR, but you won't need it in your VCS.

I strongly disagree. Losing this discourages swarming on issues and makes bisect worse.

You should always be able to roll back main to a real state. Having incremental commits between two working stages creates more confusion during incidents.

If you only use merge commits this shouldn't be any more difficult. You just need to make sure you specify that you want to use the first parent when doing reverts.

I've heard people say before that it is easier to reason about a linear history, but I can't a think of a situation where this would let me solve a problem easier. All I can think of is a lot of downsides. Can you give an example where it helps?

It's far harder to update multiple services to handle requests they should not handle, let alone update a deployment to allow those requests to happen.

I'm not sure I follow this. Doesn't this just mean that it is harder to make changes? Why would it be harder to make bad changes and not harder to make good changes?

Walls make great neighbors, just like multiple services make teams great at complying with an architecture constraint.

I'm not sure I follow this either. Why would multiple services make teams great at complying with an architecture constraint?

This always seemed strange to me. If your team can't be trusted not to make spaghetti in a monolith, what stops them from making distributed spaghetti in microservices? In theory the extra work of making an API call would give you smaller bowls of spaghetti. However, once you add some abstraction to making these calls it seems like developers are empowered to make the same mess. Except now it is slower and harder to debug.

CPM MagnaCut 5 years ago

Although beware, those pull through sharpeners are notorious for doing a terrible job sharpening knives. They take off far more material than needed and tend to produce an edge that isn't very sharp. YMMV.

Yes, a large part of Scala 3 was explicitly about improving ergonomics and making language features clearer to use. Some examples of this are:

- Greatly improved error messages [1]

- Revamped implicit syntax that makes it more straightforward to declare type classes and extension methods. [2]

- Simplified support for macros [3]

[1] https://www.scala-lang.org/blog/2020/05/05/scala-3-import-su...

[2] https://dotty.epfl.ch/docs/reference/contextual/type-classes...

[3] https://docs.scala-lang.org/scala3/guides/macros/index.html

Git will provide you with a default message for git merge without specifying any flags. This message includes the branch being merged. I don't think there is support in git to view history with the branches being marked explicitly. However, you can get something similar with:

    git log --pretty --oneline --graph --topo-order
That should at least group commits roughly by branch. Did that answer what you were asking?

If you use the default merge messages, can't you tell which was the branch that got merged? The second parent is the branch that got merged and its name will appear in the commit message on the merge commit. This is probably something that you could infer most of the time.

I'm almost certain this occurs with Hibernate as the JPA provider. I haven't tried this with other JPA providers but as far as I can tell from tutorials[1], stack overflow posts[2], and the JPA documentation[3], this is the default for JPA as well.

[1] https://www.objectdb.com/java/jpa/persistence/update

[2] https://stackoverflow.com/a/8307991

[3] https://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html#bnb...

EDIT: Oops I accidentally replied to this twice

the only natural way to work with the native way that SQL databases express writes - in-place updates to rows - is with a model that represents them as in-place updates

I strongly disagree with this for a few reasons. I actually think the command-oriented way is makes the most sense. The problem with in place updates is that:

- Your queries aren't views. What you queried out of the DB is a snapshot of what is in there. It may already be different. - The way you interact with a DB is command based. If you want to update a row that is a command that may fail.

The only way I feel that using mutable data would make sense is if you had some sort of 2-way syncing. But those are notoriously difficult to get right even without network trips in the middle.

Have you verified that? I'm pretty sure that occurs using the JPA API and Hibernate. I'm not sure if other JPA providers do this as well.

That is because "session.load(Person.class, 2)" line literally says "and track changes" - as article says.

I'm aware that that what occurs. That is my point. I'm responding to the previous posts statement "No calling a setter on an Entity doesn't automatically issue an sql UPDATE query". This is an example where calling a setter causes an update query to be run.

That is not how Hibernate or JPA is used normally. It is going out of standard way to achieve the thing you complain about.

What about this not not how Hibernate and JPA are used normally? Are you saying that setters are not normally used? Do you mean that people normally call update or merge to persist an Entity? If so, I agree that is what people normally do. However, when people do that they tend to accidentally introduce bugs. Usually this occurs when they update an entity and then do some validation on it. When the validation fails they think they can avoid sending he changes to the DB by doing nothing. However, that isn't true. They have to manually evict the entity from the session to prevent that from happening.

I'm not talking about "dirty checking". I'm talking about "automatic dirty checking". Take for example this code I got from this article[1]:

    SessionFactory  sessionFactory = HibernateUtil.getSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    Person person  = session.load(Person.class, 2); //loads Person object for id 2
    person.setAge(32);
    tx.commit();
    session.close();
    HibernateUtil.closeSessionFactory();
It results in an updated age for the person in the DB. However, EntityManager was never directly notified about the change in the person object.

[1] https://learnjava.co.in/automatic-dirty-checking-in-hibernat...

There are attempts to fix this with e.g. Graal, which effectively does the expensive initialization and reflection at compile time, but there are so many downsides and pitfalls right now with Graal that I don't consider it a serious solution to the problem. It's basically creating a new ecosystem, which means one primary motivation--to take advantage of the Java ecosystem--is much less compelling.

I'm not sure I understand what the downsides are for Graal and FAAS. There are some pitfalls around reflection but even those don't seem to hard to avoid. Is that what you are referring to?

This doesn't happen.. the database won't update until you ask the entity manager to persist the entity.

Doesn't this happen through automatic dirty checking?

Can't language features help solve some of those problems though? Improvements in static typing can help with algorithm implementations, reduce the amount of testing required, and make conflicting requirements more obvious.