• 0 Posts
  • 65 Comments
Joined 2 years ago
cake
Cake day: December 2nd, 2023

help-circle










  • There is a bit more overhead when you can’t just overwrite a value in memory. But cpu time and memory space are some of the most cheap and straightforward resources to scale up compared to engineering time to resolve consistency bugs.

    There is also a performance hit associated with mutexes or locking required to ensure mutable structures are updated consistently, and many high-scale systems have moved to append-only logs and copy-on-write semantics - structures that leave already-written data in place - because mutability/locking doesn’t scale.


  • Oh, regarding copying data - immutable collections are based on https://en.m.wikipedia.org/wiki/Persistent_data_structure - when a change is applied, you get back a reference to a new data structures where as many inner references as possible are shared with the old one. So, all the parts that didn’t change, are not copied.

    For something like a Scala case class (similar to a record), o.copy(membername1 = newvalue) returns a new object, with a new membername1 reference, but all other member references are the same as the copied-from object. So it’s a shallow copy with minimal changes.

    you might see how default immutability as a policy makes this more predictable and able to be reasoned about - any mutable object in an object graph that has a shared reference in a copy may surprise you by suddenly changing state.

    Of course, that’s the situation everywhere, all the time, in default-mutable languages. How many people set a default value of a Python function argument to [] or {} and were baffled when things started breaking because the instance of the default value was mutated?


  • I guess, as a Scala enthusiast, it’s second nature to me - Scala incorporates immutable-by-default into its design so there are accommodations for it (.copy() methods on case classes, well-thought-out operators and methods on collections, “val” bindings, expression-oriented syntax).

    It also lets you have normal OO classes and mutable vars anytime you want them, so you’re not stuck in a corner like you may sometimes be in Haskell if you don’t know the applicable FP pattern.

    This helped me out quite a bit in a recent programming test for an employment screen – the challenge was to implement a time based key value store. One of the requirements that was revealed was that it needs to be able to back up and restore – this was as simple as storing the current root of the data in a list or map; it is effectively a snapshot.





  • Check my top level comment and several other replies on this post.

    One I’ll mention here is “Tasks for testing and refactoring”. “Task” is the key word - testing and refactoring isn’t a backlog item that the product manager gets to deprioritize. (haha, like the product manager even realizes they are supposed to manage the backlog). It’s part of ongoing continuous codebase improvement and done whenever and wherever it’s needed.

    I’ve been a software developer since 1997, I’d love to have a beer and shoot the shit with them!




  • Groovy’s ORM? I recall it being Hibernate under the hood and I had to fight with it to avoid common problems like hidden IO and N+1 query blowups (iterating over a set of results and then touching the wrong property means you are making another network call for each), learning its particular DSL for schema definition and associations, and not having a way to represent any but the simplest SQL constructs. The usual ORM stuff.

    To the extent that you can write a syntax-checked SQL statement and it deserializes the results into some collection of row objects, it’s fine. But that’s not the “ORM” part.