HNHacker News
TopNewBestAskShowJobs

B-Con

3,384 karma · joined January 15, 2012

Geek who likes Go, Linux, cryptography, and tinkering.

More about me: http://bradconte.com/about

My reading list: * tptacek * sdevlin * NateLawson * sweis * cryptbe * moxie * pbsd * cperciva * daeken * tytso * andrewbinstock (editor of drdobbs) * FiloSottile * matttproud

submissionscomments
B-Con··on Revisiting Interface Segregation in Go
> 3. Allows you to assert expectations on it.

I think this is the crux that separates Fowler's mock, spy, and stub: Who places what expectations.

Fowler's mock is about testing behavioral interaction with the test double. In Fowler's example, the mock is given the expectations about what APIs will be used (warehouseMock.expects()) then those expectations are later asserted (warehouseMock.Verify()).

Behavioral interaction encodes some of the implementation detail. It asserts that certain calls must be made, possibly with certain parameters, and possibly in a certain order. The danger is that it is somewhat implementation specific. A refactoring that keeps the input/output stable but achieves the goal through different means must still update the tests, which is generally a red flag.

This is what my original statement referred to, the interaction verification. Generally the expectations are encoded in the mock itself for ergonomics sake, but it's technically possible to do the interaction testing without putting it in the mock. Regardless of exactly where the assertion logic goes, if the test double is testing its interactions then it is a Fowler mock.

(As an example: An anti-pattern I've seen in Python mocks is asserting that every mocked object function call happens. The tests end up being basically a simplified version of the original code and logic flaws in the code can be copied over to the tests because they're basically written as a pseudo stack trace of the test case.)

In contrast, a stub is not asserting any interaction behavior. In fact it asserts nothing and lets the test logic itself assert expectations by calling the API. ie:

> 3. Allows you to make assertions on that change in state. (e.g. fetch record and assert it has changed)

How is that change asserted?

A Fowler stub would be:

> myService = service.New(testDB.New()) > myService.write("myKey", 42) > assert(myService.read("myKey") == 42)

A Fowler mock would be:

> testDB = testDB.New() > testDB.Expect(write, "myKey", 42) > myService = service.New(testDB) > myService.write("myKey", 42) > testDB.Verify()

These concepts seem distinct enough to make mock a simple.

Fowler's spy seems to sit half-way between mock and stub: It doesn't assert detailed interaction expectations, but it does check some of the internals. A spy is open-ended, you can write any sort of validation logic, whereas a mock is specifically about how it is used.

I have used spys in Go basically whenever I need to verify side effect behavior that is not attainable via the main API.

By Fowler's definition, nocks are a niche test double and I suspect that what many folks would call a mock are not technically a mock.

B-Con··on Revisiting Interface Segregation in Go
Yes, this is absolutely dependent on the design S3 client.

The reality of development is we have to merge different design philosophies into one code base. Things can get messy. 100% agreed.

The approach I advocate for is more for a) organizing the code you do own, and b) designing in a way that you play nice with others who may import your code.

B-Con··on Revisiting Interface Segregation in Go
There are different definitions of the term "mock". You described the generic usage where "mock" is a catch-all for "not the real thing", but there are several terms in this space to refer to more precise concepts.

What I've seen:

* "test double" - a catch-all term for "not the real thing". What you called a "mock". But this phrasing is more general so the term "mock" can be used elsewhere.

* "fake" - a simplified implementation, complex enough to mimic real behavior. It probably uses a lot of the real thing under the hood, but with unnecessary testing-related features removed. ie: a real database that only runs in memory.

* "stub" - a very thin shim that only provides look-up style responses. Basically a map of which inputs produce which outputs.

* "mock" - an object that has expectations about how it is to be used. It encodes some test logic itself.

The Go ecosystem seems to prefer avoiding test objects that encode expectations about how they are used and the community uses the term "mock" specifically to refer to that. This is why you hear "don't use mocks in Go". It refers to a specific type of test double.

By these definitions, OP was referring to a "fake". And I agree with OP that there is much benefit to providing canonical test fakes, so long as you don't lock users into only using your test fake because it will fall short of someone's needs at some point.

Unfortunately there's no authoritative source for these terms (that I'm aware of), so there's always arguing about what exactly words mean.

Martin Fowler's definitions are closely aligned with the Go community I'm familiar with: https://martinfowler.com/articles/mocksArentStubs.html

Wikipedia has chosen to cite him as well: https://en.wikipedia.org/wiki/Test_double#General .

My best guess is that software development co-opted the term "mock" from the vocabulary of other fields, and the folks who were into formalities used the term for a more specific definition, but the software dev discipline doesn't follow much formal vocabulary and a healthy portion of devs intuitively use the term "mock" generically. (I myself was in the field for years before I encountered any formal vocabulary on the topic.)

B-Con··on Revisiting Interface Segregation in Go
I generally advise to avoid introducing interfaces strictly for testing. Instead, design the data types themselves to be testable and only use interfaces when you expect to need differing implementations. ie, avoid premature abstraction and you get rid of a whole class of problems.

For example, if you only use S3, it is premature abstraction to accept an interface for something that may not be S3. Just accept the S3 client itself as input.

Then the S3 client can be designed to be testable by itself by having the lowest-level dependencies (ie, network calls) stubbed out. For example, it can take a fake implementation that has hard-coded S3 URLs mapped to blobs. Everything that tests code with S3 simply has to pre-populate a list of URLs and blobs they need for the test, which itself can be centralized or distributed as necessary depending on the way the code is organized.

Generally, I/O is great level to use an interface and to stub out. Network, disk, etc. Then if you have good dependency injection practicies, it becomes fairly easy to use real structs in testing and to avoid interfaces purely for testing.

Related reading from the Google style guide, but focused specifically on the transport layer: https://google.github.io/styleguide/go/best-practices.html#u...

B-Con··on Revisiting Interface Segregation in Go
If you add a method to an interface, you break every source file that uses a concrete type in place of the interface (ie, passes a struct to a function that takes an interface) unless you also update all the concrete types to implement the new method (or you update them embed the interface, which is yucky).

For a public interface, you have to track down all the clients, which may be infeasible, especially in an open ecosystem.

B-Con··on Facts about throwing good parties
This is the kind of minor celebrity Internet encounter that delights my day but is impossible to explain to anyone else. :-D
B-Con··on Why aren't smart people happier?
My own personal reflections, that I realize may not be true for everyone.

Hypothesis: Living in the moment and being content is a key aspect of happiness. The more you know, the smarter you are, the harder it is to live in the moment or be content.

1) The more you understand, the more problems you see.

When you understand little, everything is ind of random. You have minimal expectations. The more you understand, the more connections you make, the more you see how things could be and how far away they are from an ideal state. You focus more on the potential, and thus the future, than on the present.

2) The more you understand, the less novelty there is.

The first time you play video game in a particular genre (or watch a movie, etc), you take it all in and experience as it is. Little interactions are delightful, as your brain is happy to see two things make an unexpected connection.

After you complete a few, you understand how the system works. The balances and trade-offs that make up the nature of the genre. When you start a new one, you instantly start breaking it apart into a mental spreadsheet, rather than experiencing the literal thing in front of your face. The unexpected elements become expected because you know how even the unexpected stuff tends to work.

The more of life you experience, the less novelty there is to any part of it.

3) The more you understand, the easier it is to live in the future.

"I should try this", "I should do that". You get locked into intellectual responsibilities with long-term goals. The short term becomes just a nuisance to achieve long-term goals. You aren't only not living in today, you aren't even living in tomorrow, you're actually living 6-24 months from now.

4) The more you understand, the less of a point you see.

If you're a pattern solving machine, eventually you realize there's no bottom to find. There's always just another chaotic pattern to pick apart. Another thing to learn. The same things play out over and over again, mildly differently. You can't fix the majority of the problems you see. You can barely understand yourself.

You're good at min/max-ing problems. But what's the ultimate thing to min/max? You have no idea.

So you ask yourself, what's the point to the whole process? Simply maximizing brain chemistry? You know you can't just focus on happy brain chemicals because that will also ruin your life (ie, heroin).

5) The more you understand, the less you hope in magic.

Some optimism depends on magical thinking. "Maybe this will work out because X will happen!" Except X can't happen. But if you believe it could happen, you are genuinely more happy.

The more you understand, the more quickly you can solve all known aspects of a problem and get left with the parts that can't be solved. You know all the things that can't happen to fix a problem. The world isn't magical. Medicine isn't magic, doctors aren't magic, technology isn't magic, politicians aren't magic, problems don't just disappear over night.

B-Con··on Why aren't smart people happier?
> Asking why smart people aren't happier is a bit like asking why people who can jump high aren't more empathetic. There's no direct link between the two, you have to dip out to the material conditions.

I think the reason to expect a correlation is simple: Intelligence should produce a better ability to recognize patterns and identify the most useful ones. In a chaotic world, the things that can lead to a desired outcome are not always clear. It takes time and reasoning to cut through the noise and figure out how to get things done. There is absolutely a reason to suspect that reasoning faster and abstractly would make this easier, and thus produce more overall rewards.

Anytime intelligence is not associated with something, I interpret that to mean the topic is likely not a "hard" min/max problem.

Turns out, most of the human aspect of life is not a hard min/max problem.

B-Con··on Facts about throwing good parties
Dave Barry is a humor writer. I've followed him for 20 years and this is absolutely his style of writing, perhaps even paraphrased from one of his pieces.

Hats off to OP if this is their original writing, it nails his style.

B-Con··on NASA pushes back after Kim Kardashian claims the 1969 moon landing was fake
https://www.bbc.com/news/articles/ckg1epp73ppo

An article, for those who don't want to watch the submission's video.

B-Con··on Amazon says it didn't cut people because of money. But because of 'culture'
> Large companies should just fund startups and acquire them when the product has shipped

I mean, that's basically what big tech has been doing for the left 15 years., not then people get upset that "Foo Corp doesn't innovate, it only acquires".

B-Con··on Tinkering is a way to acquire good taste
Knives are a great example. Any chance it was this guy?

https://youtu.be/pagPuiuA9cY

I've watched like 3 hours of his videos on sharpening because he's pragmatic, approachable, and scientific, and now I actually understand how to sharpen a knife and why it works.

B-Con··on Meta is axing 600 roles across its AI division
I skimmed and somehow missed this. Thanks.
B-Con··on Criticisms of “The Body Keeps the Score”
To be fair, from a functionality standpoint, AWS hosts like 1/3 of the value that a layperson gets from the Internet, which is all that a non-technical person really cares/things about. ie "the Internet" essentially refers to the top 10-30 services they use.

Which is uncomfortably pragmatic. Many people can go weeks while only directly interacting with a handful of Internet-based services, most of which are presented as apps.

I'm waiting for the day that the lines blur even further and people start saying "my Apple doesn't work" when AWS goes down and 1/3 of their iPhone apps stop working. Or the day that ISPs stop acting as carriers and the Internet truly factions.

B-Con··on Meta is axing 600 roles across its AI division
FAIR?

FAANG typo, or is there a new acronym?

B-Con··on Fallout from the AWS outage: Smart mattresses go rogue
I want to see the postmortem, although I'm sure we never will.

> Eight Sleep's system, which relies on backend servers for everything from real-time adjustments to data syncing, had no fallback. "It's unacceptable," fumed one early complainant on X, echoing the frustration of many who shelled out for "seamless" smart sleep only to face analog purgatory.

I'm guessing that this is a typical "smart" device setup where the cloud is essentially a tunnel between the app and the device that also saves a copy of all transmitted state for backup and data mining. The simplest design from the company's POV, but the worst design for resilience.

The real question: Was this an explicit or implicit product decision? ie, was it an explicit PM decision that local comms didn't match product requirements, or did they outsource it to the lowest bidder and have no idea this was a ticking time bomb, or did eng have to cut features to make some deadline, etc? If Eight Sleep doesn't have an at least an internal postmortem then someone should lose their job.

As a user, I would prefer the devices communicate locally and use a cloud tunnel only as backup. But this means engineering has to support two communication stacks, which is obviously more expensive than one. And the local network option is probably harder to build since cloud-based has so much tooling available.

My baseline expectation - that I can't believe I'm actually typing out - is that an appliance should operate as expected without Internet access. My only smart device is a door lock because a PIN is easier than a house key for our lifestyle, but even that isn't connected to Wi-Fi.

B-Con··on Fallout from the AWS outage: Smart mattresses go rogue
A cold mattress with a warm top blanket is one of the irrational joys of life. A warm blanket is more satisfying when you have something cool to contrast it with.
B-Con··on What Americans die from vs. what the news reports on
Bruce Schneier said something (multiple times in his books, blog, etc) that really stuck with me as a young adult.

Basically: If something is in the news, it's rare enough that you don't have to worry about it. Once the news stops reporting on it, that's when you worry.

B-Con··on Microsoft only lets you opt out of AI photo scanning 3x a year
They should always allow you to delete your remote data. The left switch thrown should always be able to be "off".

They can put a giant warming in front of the last "off" click or whatever, not it needs to be there.

This reeks of MS thinking very MS-centric and hoping they fortunately retain some users.

B-Con··on Without data centers, GDP growth was 0.1% in the first half of 2025
GDP is a known silly metric, but it's easy to define and measure, so we keep using it.

I'm often reminded of the quote: "A man marries his housekeeper and that country’s GDP falls".

GDP is uncomfortably linked to granularity of measurement as well as the number of times money changes hands to accomplish a task. Split a pipeline over more businesses boundaries and suddenly GDP is "bigger" despite no change in value or utility.

B-Con··on I turned the Lego Game Boy into a working Game Boy
People in the USA have been picking them up for weeks from Costco. I got mine ~2 weeks ago.
B-Con··on I only use Google Sheets
Chat supports rooms with chat threads without autodisappear. Everyone is in various rooms for their local team, broader team, org, and cross functional stuff. The net effect is Slack-like.

There's also the ticket system. Sheets are commonly used by various PMs and TPMs for high level tracking, but IC eng stick with the tickets.

It works fine.

B-Con··on Why your outdoorsy friend suddenly has a gummy bear power bank
Airplane mode + 10k battery lasts ~6-12 days, depending on the person and the phone.

There are roughly 1 or 2 thousand attempted "thru" hikes per year, who hike from southern to northern border of the USA over the course of 3-5 months. Far more "section" hikers, who will do a 1-4 week segment of a larger trail.

Such folks often resupply food and recharge their battery banks every few days.

To be fair, we'd generally call it backpacking rather than hiking. But the premise of the article was backpackers, so I didn't bother distinguishing.

B-Con··on Why your outdoorsy friend suddenly has a gummy bear power bank
Probably not. The community is always hungry for ways to trim weight, any new offering in the field is interesting, but since the battery is one of the most critical items, well, people tend to be conservative and stick to established models.

Most ultralight folks go light so they can cover more ground while being more comfortable. Experienced ultralighters consider how a weight reduction introduces risk against that goal, rather than simply "lighter is always better". Aka, don't go "stupid light".

An ultralighter is basically guaranteed to use their phone for navigation. A surprise battery failure may cut a trip short and possibly risk their well-being, both of which go against the goal.

It's not recommended to use battery models that haven't been extensively tested because there are conditions in the backcountry that you may not think about or be able to test beforehand, such as performance in cold conditions, whether the IPX rating really holds up, whether it's possible to brick the device accidentally by pressing the wrong button combination, etc.

A common recommendation is the Nitecore nb10000[1] for 10k of battery, and if you want 20k then bring two. (One of the Anker 20k models is also popular.) Bringing two 10ks is ~0.3 oz heavier than one 20k (per manufacturer specs), but it gives you charging parallelism (shortening down your recharging time by N hours, if your trip requires that you recharge midway) and device redundancy, both of which help you move faster with more reliably.

Related, it is also recommended to only use a battery bank that you have personally used for a few full charge cycles beforehand, to smoke out manufacturing defects.

[1]: https://nitecorestore.com/products/nitecore-nb10000-gen-2-qc...

[2]: https://nitecorestore.com/products/nitecore-nb20000-gen-3-du...

B-Con··on Few of Waymo's most serious crashes were Waymo's fault
The cars behind the waymo and hit it were at fault for the collision.

My guess is that the ambiguity is about the trade-off: "even if no one should hit you for slamming on the brakes, is it a good risk to take over a cat?"

B-Con··on Google has eliminated 35% of managers overseeing small teams in past year
> I am obviously not disputing your experience, but wanted to mention that this was not the standard pattern. The standard pattern for forced conversion at L6 (Staff) was either 6 or 7 reports (I don't remember exactly).

Given more reports and forced to be on the EM track.

I think 4 is still OK for L6 (L7 can have up to 19!).

> I don't want to be overly pedantic, but there's no Principal EM on Google eng ladders and so it's not entirely clear which level you're referring to.

I meant L7 EM - I have no idea why I wrote Principal (probably because I was moving too fast), and now it's too late to edit.

B-Con··on Google has eliminated 35% of managers overseeing small teams in past year
GOOG has made a systemic push to eliminate the role starting ~3 years ago. At that time my M was a staff level IC TLM with 4 reports who was forcibly converted to EM.

In those last 3 years I've only seen TLMs used to assist an overloaded EM.

The pattern I've seen is something like:

    Principal EM
    |- Staff EM (7 reports, project A)
    |- Staff EM (8 reports, project B)
    |- Staff IC (projects A, B, C)
    |- Senior IC (projects A, B)
    |- Senior IC (project C)
    |- Mid level IC (project C)
    |- Mid level IC (project C)
Maybe project C was just reorged under the Principal EM or maybe it's a speculative side project. But those last three are clearly clustered, there's no good line manager fit and the principal EM feels disconnected from the 2 mid level ICs. Project C is a bit of an island and projects A and B are taking up most of the EM's time.

So the Principal EM deputizes Senior IC on project C as a TLM until things have changed enough that there can be a dedicated EM. Eventually the TLM converts to EM, a new EM is brought in, or there's a reorg, etc.

Of the two times I saw saw it happen locally, both converted back to ICs after a year or two and noted that the role felt like being 70% IC and 70% EM.

Nowadays the TLM role doesn't exist so the principal would delegate most of the technical responsibilities of the M role, giving them nearly full control of project C, but would not give them a formal role. (I've been that senior IC for project C.)

(Edit for formatting.)

B-Con··on Writing a good design document
As a design reviewer, I think all design authors should internalize this concept:

> But a good doc will lay out the problem and mental models in a way that the solution that took weeks of hard thought to invent will be clear to the reader by the time the doc presents it.

Perhaps my favorite quote is: "If I had more time, I would have written a shorter letter."

Design docs should make complex things simple. They should not be a dumping ground for all the intellectual hardships and false starts the engineer went through. It may still worth capturing this, but that should be in another doc, or at least an appendix. Keep the path forward simple and understandable.

B-Con··on Vibe code is legacy code
That hiring is by US companies moving at US speeds, who greatly eclipse the growth rate of EU companies, which is the point OP was making.
B-Con··on Sign in with Google in Chrome
I've maintained one vanity email for about 15 years. I use it for literally everything. I unsubscribe from everything.

It gets some typical low effort spam that the spam filters easily screen out, other than that it's pretty quite.

← PreviousPage 2 of 22Next →