2

For example, suppose if I had a Character class and an inventory, before taking out a weapon to use it, it's probably a good idea to check if that weapon exists first, so I might have a method called has(GameObject weapon); that returns a boolean. I can then use it in an if statement like this:

if character.has(sword):
    # rest of code here

I like this because it almost sounds like English and flows better. However, I could also have a method called check_inventory(GameObject weapon); that does the same thing, but doesn't flow as well, for example:

if character.check_inventory(GameObject Weapon)
    # rest of code 

Which approach is better? In the second example, does it break encapsulation to suggest we are checking a collection of some type?

4
  • has() is pretty broad. Can you compromise and use something like hasInventoryItem()? Mar 13, 2019 at 21:09
  • 2
    "has" does flow better. But, it might be ambiguous. For example, what if you are checking if a Character had a particular Spell or Feat (I play some D&D, your terminology might differ). How would you check that? So you might want to be a but more specific, like hasItem(), hasAbility(), etc...
    – user949300
    Mar 13, 2019 at 21:11
  • Once upon a time there was this language in which people were supposed to code by writing english sentences that everybody could understand.... cobol, isn’t it ? was it really so much more practical?
    – Christophe
    Mar 14, 2019 at 6:40
  • @DanPichelman - No compromise necessary, it's was a thought I had while reading an article.
    – user327264
    Mar 14, 2019 at 14:40

5 Answers 5

4

While its nice to be able to make the code write sentences, outside of limited situations it becomes impractical.

For a start English is too vague to separate clearly things like character.Has(sword) and character.Has(measles) with single words.

Secondly if(character.Has(sword)) reads nicely but, say we want to check the character the monster is attacking or something.

monster.IsAttacking.Has(sword)

Makes less sense. Its simply clearer to use longer terms that always make sense, but dont read as sentences eg.

monster.AttackTarget.Inventory.Any(i=> i is Sword)

You do see this form in things like test frameworks, mocks or Linq, for example.

4
  • 4
    In a strongly typed language, character.Has(sword) and character.Has(measles) could work fine. But may be pushing it.
    – user949300
    Mar 13, 2019 at 23:42
  • good point, although of course the method name may lose meaning if you overload it for different purposes
    – Ewan
    Mar 14, 2019 at 8:19
  • Although I would argument that "IsAttacking" should be renamed "Victim" or "VictimBeingAttacked" or "TargetOfAttack": if monster.TargetOfAttack.Has(sword) reads pretty nicely as a sentence. Even monster.TargetOfAttack is pretty self explanatory too. Naming things is hard. Mar 14, 2019 at 19:17
  • @user949300: You are correct. A strongly typed language with multiple overloads of "Has" accepting different arguments would work. I've found most people: 1) Ignore method overloads unless you explicitly tell them to look; 2) Don't look at the names of the Types for arguments of overloads (even though I tell them to look at those names); 3) Do not ever look at the names of arguments to methods; and 4) Do not think the names of variables have anything to do with the method names that follow after the . character. Not that I'm frustrated by this or anything... Mar 14, 2019 at 19:19
2

I have seen that unit testing libraries try hard to make code read nicely. I assume this is to help non programmers understand and maybe write tests. For regular code I have not seen much of this and it doesn't seem terribly helpful.

I have a feeling that programmers don't actually read code left to right like a book but instead skip around a lot. So the fact that code reads like a sentence may not actually be very helpful.

One thing that is very important is using names that can be spoken properly. For example a variable called 'passwd' is harder to say than 'password' which makes communication with others harder when you can't properly say the name.

1

has is better than check_inventory. In most languages it is the convention that methods (and properties) which return a boolean should be phrased as a yes/no question.

0

In addition to other answers, you can go further and apply "Tell, don't ask" approach.

character.AttackWith(sword)

Then if character hasn't sword, attack will have no affect - do nothing or something else based on your logic.

3
  • I'd actually suggest weapon = character.bestWeaponVs(monster); character.attackMonsterWith(monster, weapon);
    – user949300
    Mar 14, 2019 at 6:15
  • Doesn't this just push the problem to a different place? For the check will be inside of AttackWith now. Mar 14, 2019 at 6:49
  • 1
    @ChristianHackl, I would say remove problem from the consumer of character. Now the class who is actually responsible for knowing it's inventory can make a decision.
    – Fabio
    Mar 14, 2019 at 7:14
0

It's good to design your program for readability, but keep your audience in mind.

Your audience is programmers. Of course, they'll appreciate a fluent interface like character.has(sword), but more important is that they'll understand the semantics of your code. And the wording has() can too easily be interpreted in many different ways.