Hacker Newsnew | past | comments | ask | show | jobs | submit | mrkeen's commentslogin

Because people like TFA pay them not to. It doesn't matter how much you hope Apple changes course - you vote with your wallet.

Yep, JavaScript got the bad version from Java too!

https://news.ycombinator.com/item?id=42816135


I read the article. Parent's comment about automation is spot on. TFA didn't describe any GUI interaction in detail, or even suggest that there was a way to achieve these goals without needing a meatbag to physically interact with the computer (and capture its output in /dev/meatbrain).

But at least TFA wrote up the criticism in text, even transcribing some of the screenshots.


It's too much of a stretch to call null an escape hatch, or to pretend that code reviews will somehow strip it out.

The OpenJDK HashMap returns null from get(), put() and remove(), among others. Is this just because it hasn't been reviewed enough yet?


> pretend that code reviews will somehow strip it out.

Code reviews 'somehow' strip out poorly thought out new uses of escape hatches.

For your example, it would be an use of get, put or remove without checking the result.


Just as bad if it's human. No information has been shared. The writer has turned idle wondering into prose:

> Once threads actually run concurrently, libraries (which?) that never needed locking (contradiction?) could (will they or won't they?) start hitting race conditions in surprising (go on, surprise me) places.


Property appreciates over time. It's a cheat-code for more money, not a wasteful expense.

It made no reference to the 'shared' in 'shared state'.

No mention of asynchrony, multithreading, or the race condition that TFA encountered.


The “attempt 2” was literally a state machine implementation which the author rejected because they didn’t know how to do it properly and so did it badly using a bunch of if then else logic.

This is one of those cases where software transactional memory really shines.

You can often take the naive solution and it will be the correct one. Your code will looks like your intent.

TFA's first attempt:

  async def drain_requests():
      while state != "closing":
          await asyncio.sleep(0.1)
      print("draining pending requests")
Got it. Let's port it to STM:

  let drain_requests = do
          atomically (
              do s <- readTVar state
                 when (s /= "closing")
                     retry )
          print("draining pending requests")
Thread-safe and no busy-waiting. No mention of 'notify', 'sleep'. No attempt to evade the concurrency issues, as in the articles "The fix: per-consumer queues - Each consumer drains its own queue and checks each transition individually."

In most STM models this is a busy-wait implemented with STM? Only Haskell blocks on `retry`

It's the definition of simple that's the problem. For any definition of simplicity you might have, someone has an equal and opposite definition.

Take these two alternatives:

  class UserService {
    PostgresDatabase db;
  }

  class UserService {
    IDatabase db;
  }
There are some coworkers who will veto the first example for being too complex, because it brings Postgres (and its state and connections and exceptions and mappings) into the scope of what otherwise could have been a service concerning Users.

There are some coworkers who will veto the second example for being too complex, because Postgres is all you use for now, and if you really need to use a second database, you can change the code then (YAGNI). Also the Interface gives you a pointless indirection that breaks IntelliSense so you can't just 'click-through' to follow the code flow.


I agree with your comment, but I disagree a both the example opinions... complex is the discussion :D

I heard something that helps better framing those discussions, use "familiar" instead of "simple".

An highly abstract way to access a database table, with ORM for example, can be simple because everyone is expecting it and knows how to do all tasks (changing schema, troubleshooting, managing transactions, etc.).

Doing userService.pgSql("select ....") in the same way can be simple.


One more opinion piece uselessly recommending "simplicity" with no code samples or concrete takeaways.

> It also shows up in design reviews. An engineer proposes a clean, simple approach and gets hit with “shouldn’t we future-proof this?” So they go back and add layers they don’t need yet, abstractions for problems that might never materialize, flexibility for requirements nobody has asked for. Not because the problem demanded it, but because the room expected it.

$100 says the "clean, simple" approach is the one which directly couples the frontend to the backend to the database. Dependencies follow the control flow exactly, so that if you want to test the frontend, you must have the backend running. If you want to test the backend, you must have the database running.

The "abstractions for problems that might never materialize" are your harnesses for running real business logic under unit-test conditions, that is, instantly and deterministically.

If you do the "simple" thing now, and push away pesky "future-proofing" like architecting for testing, then "I will test this" becomes "I will test this later" becomes "You can't test this" becomes "You shouldn't test this."


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: