frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

Is the author of pdf-lib okay?

https://github.com/Hopding/pdf-lib
12•shreddit•47m ago•1 comments

Art of Roads in Games

https://sandboxspirit.com/blog/art-of-roads-in-games/
374•linolevan•14h ago•118 comments

Show HN: Algorithmically Finding the Longest Line of Sight on Earth

https://alltheviews.world
26•tombh•1h ago•7 comments

Vouch

https://github.com/mitchellh/vouch
885•chwtutha•1d ago•397 comments

Offpunk 3.0

https://ploum.net/2026-02-09-offpunk3.html
15•todsacerdoti•1h ago•0 comments

LispE: Lisp Interpreter with Pattern Programming and Lazy Evaluation

https://github.com/naver/lispe
61•PaulHoule•4d ago•11 comments

Clean Coder: The Dark Path (2017)

https://blog.cleancoder.com/uncle-bob/2017/01/11/TheDarkPath.html
17•andrewjf•4d ago•28 comments

Tessellation Kit (2016)

https://sciencevsmagic.net/tes/#0.5.0.1.aaaaaaaaa
8•surprisetalk•4d ago•1 comments

Show HN: A custom font that displays Cistercian numerals using ligatures

https://bobbiec.github.io/cistercian-font.html
101•bobbiechen•13h ago•21 comments

Every book recommended on the Odd Lots Discord

https://odd-lots-books.netlify.app/
102•muggermuch•12h ago•41 comments

Show HN: I created a Mars colony RPG based on Kim Stanley Robinson’s Mars books

https://underhillgame.com/
226•ariaalam•18h ago•71 comments

Apple XNU: Clutch Scheduler

https://github.com/apple-oss-distributions/xnu/blob/main/doc/scheduler/sched_clutch_edge.md
145•tosh•15h ago•26 comments

More Mac malware from Google search

https://eclecticlight.co/2026/01/30/more-malware-from-google-search/
202•kristianp•14h ago•139 comments

Ask HN: What are you working on? (February 2026)

160•david927•16h ago•525 comments

Quartz crystals

https://www.pa3fwm.nl/technotes/tn13a.html
82•gtsnexp•1d ago•20 comments

Custom Firmware for the MZ-RH1 – Ready for Testing

https://sir68k.re/posts/rh1-firmware-available/
51•jimbauwens•4d ago•18 comments

Reverse Engineering the Prom for the SGI O2

https://mattst88.com/blog/2026/02/08/Reverse_Engineering_the_PROM_for_the_SGI_O2/
93•mattst88•13h ago•20 comments

The Little Bool of Doom (2025)

https://blog.svgames.pl/article/the-little-bool-of-doom
113•pocksuppet•17h ago•41 comments

Werewolf Vflex Adapter Review

https://hagensieker.com/2026/02/05/werewolf-vflex-adapter-review/
9•geerlingguy•3d ago•0 comments

Experts Have World Models. LLMs Have Word Models

https://www.latent.space/p/adversarial-reasoning
107•aaronng91•17h ago•123 comments

GitHub Agentic Workflows

https://github.github.io/gh-aw/
263•mooreds•21h ago•125 comments

Roundcube Webmail: SVG feImage bypasses image blocking to track email opens

https://nullcathedral.com/posts/2026-02-08-roundcube-svg-feimage-remote-image-bypass/
148•nullcathedral•17h ago•53 comments

AI makes the easy part easier and the hard part harder

https://www.blundergoat.com/articles/ai-makes-the-easy-part-easier-and-the-hard-part-harder
354•weaksauce•12h ago•260 comments

Running Your Own As: BGP on FreeBSD with FRR, GRE Tunnels, and Policy Routing

https://blog.hofstede.it/running-your-own-as-bgp-on-freebsd-with-frr-gre-tunnels-and-policy-routing/
182•todsacerdoti•21h ago•72 comments

TSMC to make advanced AI semiconductors in Japan

https://apnews.com/article/semiconductors-tsmc-japan-taiwan-ai-11256f2bfde73ca23d08331ad138d6d5
180•dev_tty01•7h ago•127 comments

Toma (YC W24) Is Hiring Founding Engineers

https://www.ycombinator.com/companies/toma/jobs/oONUnCf-founding-engineer-ai-products
1•anthonykrivonos•13h ago

Claude’s C Compiler vs. GCC

https://harshanu.space/en/tech/ccc-vs-gcc/
281•unchar1•7h ago•240 comments

Show HN: Slack CLI for Agents

https://github.com/stablyai/agent-slack
85•nwparker•3d ago•25 comments

Dave Farber has died

https://lists.nanog.org/archives/list/nanog@lists.nanog.org/thread/TSNPJVFH4DKLINIKSMRIIVNHDG5XKJCM/
257•vitplister•1d ago•41 comments

Exploiting signed bootloaders to circumvent UEFI Secure Boot (2019)

https://habr.com/en/articles/446238/
126•todsacerdoti•20h ago•70 comments
Open in hackernews

Clean Coder: The Dark Path (2017)

https://blog.cleancoder.com/uncle-bob/2017/01/11/TheDarkPath.html
17•andrewjf•4d ago

Comments

andrewjf•4d ago
Author argues against strong typing systems and language features to prevent classes of bugs and instead encourages developers to "writing lots of tests" for things that a type system would prevent.

The authors thesis seems to be that it's preferable to rely on the programmer who wrote bugs to write even more bugs in tests in order to have some benefit over a compiler or type system that can prevent these things from happening in the first place?

So obviously it's an opinion and he's entitled to it, but (in my own opinion) it is so so so, on-its-face, just flat out wrong, I'm concerned that that it's creating developers who believe that writing so many tests (that languages and compilers save you time (and bugs) in writing) is a valid solution to preventing null pointer defeferences.

jddj•1h ago
The conversation at the time was commonly along these lines. Powerful type systems won, for the most part, and most of the discussion fell away.
ulrikrasmussen•1h ago
There's also another strong argument against favoring tests over types, which is maintainability. If I go ahead and change a variable type from being non-nullable to nullable, I instantly get a complete list of all the places where I have to handle that, which makes it much much faster to generalize the logic. But in a dynamic language, all tests that were written by the previous developer was written at a time when this variable was assumed to never be null and uses non-null values for all test vectors, so good luck using that to find the places that need to be fixed.

On top of that, every test that could have been omitted due to a type system incurs an extra maintenance tax that you have to pay when you change the API.

duesabati•53m ago
I think you you're missing the point though, he did not say that adding those constraints was a bad idea per se, but they are leading to a bad path. If the path is "just add more guard-rails" then we will get to a point where we lose the "soft" part of "software" and you'll find yourself restarting each time you need to change something because at that point the language you chose was already the first wall of a bad program architecture (ease of change).
kace91•1h ago
Your elevator should not have automatic doors, doors are restrictive. They stop you from quickly jumping out of the elevator if you decide that you actually want to stay at the first floor.

Sure, we’ve seen some pretty gnarly accidents, and there is no reasonable situation where risking death is a sane choice.

But ask yourself: is it the elevator's job to prevent an accident? If you think so, I suggest you never leave your home again, as safety is your own concern.

Like and subscribe for other posts like “knife handles? What an idiot” and “never wear a helmet you coward”.

xnorswap•1h ago
> “never wear a helmet you coward”.

Unironically the biggest flame-wars I ever saw on forums back in the day was on whether or not mandatory bike helmets made cycling safer or more dangerous.

archerx•52m ago
I can understand, I’ve had some awful bicycle accidents while not wearing a helmet and the helmet would have made no difference. My knees, hands and elbows have been through a lot but I have never hit my head. Even while skateboarding the one time I hit my head a helmet would not have helped. In hindsight I should have worn knee pads a lot more often but then I wouldn’t be able to tell if it’s gonna rain or not from the feeling in one of my knees :)

However if I had to ride on a public road with cars zooming pass me recklessly I would absolutely wear a helmet on a bicycle.

direwolf20•33m ago
And there are countries where everyone rides a bike, and they are not usually the ones with mandatory helmets. When you hit someone with a bike you are less likely to kill them than when you hit them with a car, so more bike riding means less deaths, without even considering the effects of air pollution.

Helmets are fine for sport riding, but inconvenient if you want to ride 5 minutes to the shops on a whim. And that kind of riding is usually less intense and safer, I presume, anyway. Football has helmets, walking doesn't.

meindnoch•1h ago
While I consider Uncle Bob a bad programmer, there is some merit to this article. This paragraph was particularly prescient:

>But before you run out of fingers and toes, you have created languages that contain dozens of keywords, hundreds of constraints, a tortuous syntax, and a reference manual that reads like a law book. Indeed, to become an expert in these languages, you must become a language lawyer (a term that was invented during the C++ era.)

And this was written before Swift gained bespoke syntax for async-await, actors, some SwiftUI crap, actor isolation, and maybe other things, honestly, I don't even bother to follow it anymore.

raverbashing•55m ago
Yeah once you get into Monofunctor or 'PorcelainPile<static const volatile String&>' lawyering you know you went too far
mrkeen•6m ago
TIL about Monofunctor.

Pretty nifty. It's for cases where your type is a container of something (as opposed to anything).

I.E. you can .map (or .Select if you're .NET-inclined) over the Chars in a String, but not some other type, because String can't hold another type.

https://hackage.haskell.org/package/mono-traversable-1.0.21....

repelsteeltje•22m ago
He has a point in that paragraph, but as a C++ developer I couldn't help being agitated by his passive aggressive comment:

> [...] (a term that was invented during the C++ era.)

...like it's some sort of relic, or was in 2017

ulrikrasmussen•1h ago
I disagree with the article, but also some of these examples are complete straw-men. In Kotlin you have nullable types, and the type checker will complain if you use it as a non-nullable type. But you can always just append !! after your expression and get exactly the same behavior as in Java and get a null pointer exception, you don't have to handle it gracefully as the author is suggesting. Tests checking that you gracefully handle nulls in a language without null types are fucking tedious and boring to write. I would take a language with null types over having to write such tests any day.

Kotlin's final-by-default is also just that - a default. In Java you can just declare your classes `final` to get the same behavior, and if you don't like final classes then go ahead and declare all of then open.

I also disagree with the author's claim that languages with many features requires you to be a "language lawyer", and that more simplistic languages are therefore better. It's of course a balance, and there are examples of languages like C++ and Haskell where the number of features become a clear distraction, but for simpler things like null types and final-by-default, the language is just helping you enforce the conventions that you would anyway need when working with a large code base. In dynamically typed languages you just have to be a "convention lawyer" instead, and you get no tool support.

repelsteeltje•4m ago
Your last sentence makes a very good point. And Uncle Bob's tool is to have loads of tests.

I suppose it's all just a balance: simplicity versus expressiveness, foot guns versus inflexibility, conciseness versus ceremony, dev velocity versus performance in production.

I'm okay with shifting some of the burden of common errors from developer into the language if that improves reliability or maintainability. But Martin has a point in that no guard rails can ever prevent all bugs and it can be annoying if languages force lots of new ceremony that seems meaningless.

raincole•1h ago
> Every time there’s a new kind of bug, we add a language feature to prevent that kind of bug.

That's why learning more academic, 'non-practical' aspects of computer science is sometimes beneficial. Otherwise very few will naturally develop the abstract thinking that allows them to see uncaught exception and null pointer are exactly the same 'kind of bug.'

Anyway the author got it completely upside down. The stricter mental model of static typing came first (in more academic languages like Haskell and Ocaml). Then Java etc. half-assed them. Then we have Swift and Kotlin and whatever trying to un-half-ass them while keeping some terminology from Java etc. to not scare Java etc. programmers.

n4bz0r•42m ago
As someone not familiar with Haskell and Ocaml, which parts of Java are poorly implemented?
theCodeStig•38m ago
There are many, but one particular example is the type syatem.
direwolf20•35m ago
Explain how
hmry•10m ago
Not OP, and not sure about OCaml and Haskell, but one small example where Java's type system is unhelpful/incorrect is subtype variance with mutation.

E.g. Java assumes List<Cat> is a subtype of List<Animal>. But this only holds when reading from the list. The correct behavior would be:

- `readonly List<Cat>` is a subtype of `List<Animal>`

- `writeonly List<Cat>` is a supertype of `List<Animal>`

- `readwrite List<Cat>` has no relationship with `List<Animal>`

But Java doesn't track whether a reference is readable or writable. The runtime makes every reference read-write, but the type checker assumes every reference is read-only.

This results in both

- incorrect programs passing the type checker, e.g. when you try to write an Animal to a List<Animal> (which, unbeknown to you, is actually a List<Cat>), you get a runtime exception

- correct programs not passing the type checker, e.g. passing a List<Animal> into an appendCat(List<Cat> output) function is a type error, even though it would be safe.

(Although all that is assuming you're actually following the Liskov substitution principle, or in other words, writing your custom subtypes to follow the subtyping laws that the type checker assumes. You could always override a method to throw UnsupportedOperationException, in which case the type checker is thrown out of the window.)

moring•1m ago
Did you mean arrays instead of lists? Arrays behave as you describe (with ArrayStoreException when you write a wrong value to an array). List<> is invariant WRT its type parameter.
repelsteeltje•33m ago
I suppose it's somewhat accurate to claim that Haskell and Ocaml historically preceded Java (or even Objective-C). But Java wasn't inspired by those academic languages, but C: a then widely used real-world language with only partial static types.

(Not saying Java's attempt to remedy C's problems wasn't half-assed — it was.) The trend to plug holes is primarily motivated by empirical evidence of bug classes. Not by elegance of academic research.

As Bjarne Stroustrup famously quipped:

> “There are only two kinds of languages: the ones people complain about and the ones nobody uses.”

Swift, Kotlin, Rust, C++ are attempt to become languages that everyone complains about, not Haskell or Ocaml.

fedeb95•1h ago
I get the point of the article. However, you can have both: programmers that write tests and don't override safety measures AND safety measures.
ZeroClickOk•56m ago
I understand what the author says, but in my experience, "Nullable Types" and "Open/Sealed Classes" are two different subjects and...

1) For "Nullable Types", I see that it is VERY good to think about if some type can be null or not, or use a type system that does not allow nulls, so you need some "unit" type, and appropriately handle these scenarios. I think it is ok the language enforces this, it really, really helps you to avoid bugs and errors sooner.

2) For "Open/Sealed Classes", my experience says you never (or very rarely) know that a class will need to be extended later. I work with older systems. See, I don't care if you, the original coder, marked this class as "sealed", and it does not matter if you wrote tons of unit tests (like the author advocates), my customer wants (or needs) that I extend that class, so I will need to do a lot of language hacks to do it because you marked as sealed. So, IMHO, marking a class as "open" or "sealed" works for me as a hint only; it should not limit me.

virtualized•38m ago
What I read between the lines: “I have such a fragile ego that I feel offended when a tool points out a mistake I made. I feel intellectually rewarded by doing the same busywork over and over again. I don’t want to change the way I do my work at all. I feel left behind when people other than me have great ideas about language design.”
direwolf20•31m ago
What I read between your lines: "I don't want to think about the code at all. It should only compile if it has no bugs. I don't like rapid prototyping. I feel stupid when people other than me feel they can program effectively with fewer safeguards."
lstodd•34m ago
I was rewriting a mod for Rimworld recently. As Rimworld is built on Unity, it's all some sort of C#. I heard people say it's a wrong kind of C#, but since a) I had no choice and b) I never wrote any C# before I cannot tell.

First, C# proudly declares itself strongly-typed. After writing some code in Zig (a project just before this one, also undertaken as a learning opportunity, and not yet finished), I was confused. This is what is called strong-typed? C# felt more like Python to me after Zig (and Rust). Yes there are types. No, they are not very useful in limiting expression of absurdity or helping expression of intent.

Second, test. How do you write tests for a mod that depends on an undocumented 12 year old codebase plus of half a dozen of other mods? Short answer - it's infeasible. You can maybe extract some kind of core code from your mod and test that, but that doesn't help the glue code which is easily 50-80% in any given mod.

So what's left? I have great temptation to extract that core part and rewrite it in Zig. If Unity's C#-flavor FFI would work between linux and windows, if marshalling data would not kill performance outright, if it won't scare off potential contributors (and it will of course), if, if...

I guess I wanted to say that the tests are frequently overrated and not always possible. If language itself lends a hand, even as small and wimpy as C#'s, don't reject it as some sort of abomination.

mrkeen•24m ago
> For example, in Swift, if you declare a function to throw an exception, then by God every call to that function, all the way up the stack, must be adorned with a do-try block, or a try!, or a try?.

Funnily enough, Uncle Bob himself evangelised and popularised the solution to this. Dependency Inversion. (Not to be confused with dependency injection or IOC containers or Spring or Guice!) Your call chains must flow from concrete to abstract. Concrete is: machinery, IO, DBs, other organisation's code. Abstract is what your product owners can talk about: users, taxes, business logic.

When you get DI wrong, you end up with long, stupid call-chains where each developer tries to be helpful and 'abstract' the underlying machinery:

  UserController -> UserService -> UserRepository -> PostgresConnectionPoolFactory -> PostgresConnectionPool -> PostgresConnection
(Don't forget to double each of those up with file-names prefixed with I - for 'testing'* /s )

Now when you simply want to call userService.isUserSubscriptionActive(user), of course anything below it can throw upward. Your business logic to check a user subscription now contains rules on what to do if a pooled connection is feeling a little flakey today. It's at this point that Uncle Bob 2017 says "I'm the developer, just let me ignore this error case".

What would Uncle Bob 2014 have said?

Pull the concrete/IO/dependency stuff up and out, and make it call the business logic:

  UserController:
      
      user? <- (UserRepository -> PostgresConnectionPoolFactory -> PostgresConnectionPool -> PostgresConnection)
      // Can't find a user for whatever reason? return 404, or whatever your coding style dictates

      result <- UserService.isUserSubscriptionActive(user)

      return result
The first call should be highly-decorated with !? or whatever variant of checked-exception you're using. You should absolutely anticipate that a DB call or REST call can fail. It shouldn't be particularly much extra code, especially if you've generalised the code to 'get thing from the database', rather than writing it out anew for each new concern.

The second call should not permit failure. You are running pure business logic on a business entity. Trivially covered by unit tests. If isUserSubscriptionActive does 'go wrong', fix the damn code, rather than decorating your coding mistake as a checked Exception. And if it really can't be fixed, you're in 'let it crash' territory anyway.

* I took a jab at testing, and now at least one of you's thinking: "Well how do I test UserService.isUserSubscriptionActive if I don't make an IUserRepository so I can mock it?" Look at the code above: UserService is passed a User directly - no dependency on UserRepository means no need for an IUserRepository.

matej-almasi•4m ago
It is a little weird to end an article calling for less safeguards in languages by a reference to a nuclear disaster caused by overriding safeguards.