Meaningful return values
I consistently see return values messed up in people’s API design. Fortunately, there are some hard and fast rules to follow that make return values really hard to fuck up.
- Only return True/False for a single condition. It is not an acceptable contract to say ‘Return True on success, False on failure.’ What is acceptable is ‘Return True on success, False if key does not exist.’ You’d still throw exceptions for invalid arguments or state.
- Try to avoid returning from methods that mutate a public property on the instance you are calling the method on. If foo.Frobnicate() mutates foo by changing foo.Bar (which is public), do not return a value- let the caller query foo.Bar. It makes it more clear that Frobnicate is mutating and not just returning a value the caller can assign (a better design may be to NOT mutate and let the caller assign the result). Make mutation the clear contract, not a side effect.
- Except if you consistently return self/this. For certain objects, it may make sense to mutate and return the object being mutated. So you can string together calls, like you do on strings: foo.Frobnicate().Spam().Eggs(), which would mutate foo 3 times. Obviously if an object is immutable (like a string, or .NET IEnumerable) this is good design, but it can be unclear that the object is being mutated unless it is a core part of the object’s contract.
- Do not have a return value if you don’t need it (private methods). If you have a private method, and no caller is using the return value, don’t have a return value! It generally means your contract is unclear, or your methods are doing too much, and your implementation needs some work.
Pay close attention to how your return values work when you design your API’s and you’ll have a very easy way to detect code smell.