Postel’s law:
Be conservative in what you do, be liberal in what you accept from others.
“Lazy” code (per The Pragmatic Programmer):
Be strict in what you will accept before you begin, and promise as little as possible in return.
I’m developing a finance (asset pricing, etc.) framework for Python. Question: when designing the API for the framework, what factors should I consider when I assess the tradeoff between being strict and being liberal re: inputs?
Example:
I have the following method that downloads stock prices from Yahoo.
def historical_prices(ticker, start=None, end=None, data='d', convert=True):
# Do stuff
For the date arguments (start
& end
), I could:
- Be strict, and only allow a string of ISO format YYYY-mm-dd, or
- Be liberal and accept datetime objects, strings (of specified formats), etc.
3
It is going to be easier to accept the strict input, and reject any other forms, because you will have only one case to consider.
It really depends on your customers’ requirements. Do they need flexibility of input, i.e. Internationalization, or can they work comfortably with a single format.
1
Be strict in what you accept. The be liberal in what you accept, and be strict what you return, is based on a world of independent agents, for instance SMTP servers. If a mail server sends you a faulty email, and you can rescue it, that’s better than a cryptic error to the sender of the mail.
However, when you’re designing an API to be consumed by other programmers, it’s different story. They get immediate feedback when they provide wrong input. The other option of guessing what they mean is very dangerous. If you accept 14-12 as december fourtheenth, and 14-10 as october fourteenth, what will your program do with 10-12? Better to be strict, and error with one of them, that way your program will behave in a predictable manner, which is much more important than being able to accept everything.
2
I would code the main function with a specific format as the input. If there is a request to add more formats etc then create a function to overload the name that converts the date object etc into your format before calling your main function.