Naming Things is Hard: Keeping Context in Mind

Well, look at this naming stuff turning into a series Smile

Nothing that you name in coding exists in a vacuum. It will all be used and referenced in a certain way, and this should inform the names you choose. Here's some examples:

Boolean Members

Boolean members on classes should usually be given names starting with 'Is' or 'Has' to indicate their boolean-ness, but boolean helper methods within a class should not. So for example:

if (CustomerIsEntitledToAMassiveDiscount(customer))
{
    // Do something
}

// ...

private bool CustomerIsEntitledToAMassiveDiscount(Customer customer)
{
// Figure it out… }

CustomerIsEntitledToAMassiveDiscount here encapsulates the logic which makes that decision. This makes the purpose of the if statement clear and provides an English-language description for the blob of logic which makes the determination. As a helper method of that type (which is the 'Encapsulate Conditionals' type from Clean Code, by the way), it will always be called by an if statement, and as such should be named in a way appropriate to that context, i.e. the context of being presented as the body of a readable sentence which starts with the word 'if'.

Alternatively, how would we name a property on Customer which encapsulated the same logic? The context is again informative; our property will still be used in if statements, but always via a member of a variable [probably] named 'customer'. That means it doesn't need the word 'Customer' in it. Which gives us…? customer.IsEntitledToAMassiveDiscount. Again, note that that makes a readable English-language statement when used as the body of a sentence beginning with the word 'if'.

'Parenting'

What's wrong with this picture?

public interface ICustomerService
{
    IEnumerable<BankAccountDetails> GetCustomerBankAccountDetails(int customerId);

    Address GetCustomerDefaultDeliveryAddress(int customerId);

    IEnumerable<Address> GetCustomerAddresses(int customerId);

    int GetCustomerInsideLegMeasurementInCm(int customerId);
}

...or this one?

namespace LetteringRendering
{
    public interface ILetterRenderingLetterRenderer
    {
        Letter RenderLetter(LetterRenderingData letterRenderingData);
    }
}

Both examples have redundant qualifiers. Implementations of the interface in the first example will provide information (some of it quite personal) about Customers; they will be used via a variable named [probably] 'customerService'. The service therefore establishes the context of the operations as that of the 'Customer', and we don't need the word 'Customer' in every method.

The namespace and interface names in the second example establish their contexts as related to letter rendering; the interface name therefore doesn't need 'LetterRendering' in it. The interface method will be used via implementations named (can you guess?) 'letterRenderer' or 'renderer' or similar, and will be used to assign a variable named something like 'letter' or 'renderedLetter'; it therefore doesn't need the word 'Letter' in it - what else is an ILetterRenderer going to render if not a Letter? Similarly, I don't think the parameter name needs 'letterRendering' in it - it can simply be named 'data'; the context established by the method to which it belongs already tells us that it's related to letter rendering.

What about the LetterRenderingData type? I shall leave that to you to discuss with yourself - if you reach a conclusion let me know what you think with a comment Smile

Print | posted @ Thursday, January 8, 2015 11:58 AM

Comments on this entry:

No comments posted yet.

Post A Comment
Title:
Name:
Email:
Comment:
Verification: