Hacker News new | ask | show | jobs
by kerkeslager 2552 days ago
> `is_foolike` to me, implies `test_for_abstract_quality_foo`.

Yes, which is why when `is_foolike` tests that a string starts with 'foo', that's rather unexpected. If `is_foolike` actually describes the intention of the function, then the function testing for the string beginning with 'foo' is a bug, because it doesn't do what it's intended to do.

Referring to "the quality of starting with 'foo'" as "abstract quality foo" isn't hiding implementation details, it's being opaque about what a function does.

Put another way, "what a function does" isn't its implementation. "How a function does what it does" is its implementation.

> `starts_with_foo` implies an assertion a string beginning with a particular prefix

Yes, exactly. Because that is what it is intended to do, we hope, since that's what it does. That's NOT the implementation: there are plenty of different ways to implement testing whether a string starts with 'foo', and the name `starts_with_foo` isn't coupled to any of them.

> The point being that even though, in this (again) entirely fictitious example, the intention of the method is different from it's implementation

Yes. `starts_with_foo` is also different from the implementation, while still describing the intention of the method.

Could you explain to me why you think `starts_with_foo(x)` describes the implementation `x.startswith('foo')` and not some other implementation (such as `x[:3] == 'foo'`)?

1 comments

Ok, I’m curious. Let’s say that I want to fall into that if statement if my product is named something like “foo”, costs under $100, isn’t discontinued, and has sold over 100 units in the last month. Fine, you can say now I have overcomplicated the domain and I should go back to requirements, but these complicated things do happen. Surely it’s acceptable to name my function “isFooLike” rather than “startsWithFooAndCostsLessThan...” etc, especially if I suspect management may change some of those figures later?

If that’s acceptable, why is an IsFooLike which only checks one condition unacceptable, even though it (imo) expresses the same intention?

> Ok, I’m curious. Let’s say that I want to fall into that if statement if my product is named something like “foo”, costs under $100, isn’t discontinued, and has sold over 100 units in the last month. Fine, you can say now I have overcomplicated the domain and I should go back to requirements, but these complicated things do happen. Surely it’s acceptable to name my function “isFooLike” rather than “startsWithFooAndCostsLessThan...” etc, especially if I suspect management may change some of those figures later?

The idea with naming is to capture as much of the meaning of the function as possible, and 'isFooLike' doesn't really capture any meaning (what does it mean to be like a foo?). In business, there are typically names for the topics, like `is_profitable_transaction` or `meets_sales_targets`, which may indeed encompass some very complex logic, but are a coherent idea, so naming is usually a bit easier than this. But you're right, sometimes the requirements are bad and you don't have a chance to go back to requirements before a deadline. In those cases, I don't think the naming matters much because no name you come up with is going to represent the concept. So I guess `is_foolike` might be the best you could come up with, but it's certainly not good code. I'd also be less likely to pull out a function in the first place because it's a premature abstraction: if the abstraction isn't coherent enough to be named well, we probably don't understand it well enough yet to abstract it out.

> If that’s acceptable, why is an IsFooLike which only checks one condition unacceptable, even though it (imo) expresses the same intention?

It's not the same intention.

In the more complex case, you have a bad name because the name doesn't describe the (overly complex) intention of the code, but there isn't a better one.

In the second case, you have something that does a clear thing, so you should name it what it does. For a more complex case, you're not going to be able to capture every nitpicky detail of what the function does in the name, so you have to describe it in a broader concept. But with a short simple function like this, there really isn't an excuse for using a vague description.

I think you're still ignoring my explanation that what a function does and intends to do is different from how it does it. So I'm going to again insist that the two of you answer these questions to prove they actually understand my points before disagreeing with me:

1. I'm claiming that in correctly-working code, the intention of the code IS what it does. Is there a case where code would do something other than it's intended to do, and this isn't a bug or at least misleading code?

2. I'm claiming that what a function does is not the same as its implementation. Why are you claiming `starts_with_foo(x)` coupled to the implementation `x.startswith('foo')` and not `x[:3] == 'foo'`?

This is a really, really terrible way to name functions, or anything. I have seen code that tried to put the spec in the name, and it was awful.

A name that is long enough to tell you all you might need to know about what the thing named does is too long to be usable at all.

A name needs to be long enough to distinguish it from the other things being named. That's what naming means. If it also gives you a hint about which thing, of the things named, it really does, that makes it perfect.

Anything beyond that adds cognitive load, making it exponentially worse with each syllable added.