TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Strict APIs vs. Forgiving APIs

54 pointsby ajabhishover 4 years ago

15 comments

misterdataover 4 years ago
Having used both stricter (Rust) and more loose programming languages (JS), I can add that stricter APIs have made me think more about edge cases than the less-strict APIs. In the less-strict languages I often find myself debugging some edge case, whereas in the stricter languages I am more often required to think about edge cases up front (including those that I know will not be relevant, so in some cases this causes more work than necessary!). Still I much prefer the stricter APIs.
Karellenover 4 years ago
I like Rusty Russell&#x27;s classic &quot;Hard to Misuse Interface Levels&quot;. The first couple of items are<p>0: Impossible to get wrong&#x2F;DWIM<p>1: Compiler&#x2F;linker won&#x27;t let you get it wrong<p>...through<p>9: Read the correct LKML thread and you&#x27;ll get it right - SET_MODULE_OWNER<p>...all the way up to 17. I&#x27;ll let you discover the rest yourself :-)<p><a href="https:&#x2F;&#x2F;ozlabs.org&#x2F;~rusty&#x2F;ols-2003-keynote&#x2F;img39.html" rel="nofollow">https:&#x2F;&#x2F;ozlabs.org&#x2F;~rusty&#x2F;ols-2003-keynote&#x2F;img39.html</a>
评论 #24927489 未加载
Joker_vDover 4 years ago
I think that&#x27;s a trick question. If &quot;substring()&quot; has &quot;substring(int start, int end)&quot; semantics, then I prefer the strict version: it must be 0 &lt;= start &lt; len(s), start &lt;= end &lt;= len(s), otherwise it&#x27;ll throw an exception.<p>But if the semantics is &quot;substring(int start, int length)&quot;, then I prefer the <i>partial</i> forgiveness <i>for the length</i> parameter: if start + length &gt; len(s), then assume length was actually len(s) - start; but if length &lt; 0, still throw an exception.
评论 #24920685 未加载
评论 #24920693 未加载
aimorover 4 years ago
In my experience forgiving APIs don&#x27;t play well together. I&#x27;ve inadvertently tried it and wind up having to make everything &#x27;forgiving in the same way&#x27;. Otherwise out-of-range inputs mean different things to different functions, and using multiple APIs requires tracking all the forgiving behavior.
z3t4over 4 years ago
Its not always binary. You want to throw an error at even the slight amount of error. This will annoy users, but over time as bugs and edge cases are fixed - it will lead to a very robust program.<p>Meanwhile you want to save time&#x2F;work for the caller. You dont want the caller to need many lines of boilerplate just to setup the call.
thamerover 4 years ago
For reference, this is what String.substring(int, int) does[1] in Java:<p><pre><code> public String substring(int beginIndex, int endIndex) { int length = length(); checkBoundsBeginEnd(beginIndex, endIndex, length); ... </code></pre> Where checkBoundsBeginEnd[2] does:<p><pre><code> static void checkBoundsBeginEnd(int begin, int end, int length) { if (begin &lt; 0 || begin &gt; end || end &gt; length) { throw new StringIndexOutOfBoundsException( &quot;begin &quot; + begin + &quot;, end &quot; + end + &quot;, length &quot; + length); } } </code></pre> (as it should, in my opinion).<p>[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;AdoptOpenJDK&#x2F;openjdk-jdk11&#x2F;blob&#x2F;f0ef2826d2116f4e0c0ed21f8d54fe9d0706504e&#x2F;src&#x2F;java.base&#x2F;share&#x2F;classes&#x2F;java&#x2F;lang&#x2F;String.java#L1872-L1881" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;AdoptOpenJDK&#x2F;openjdk-jdk11&#x2F;blob&#x2F;f0ef2826d...</a><p>[2] <a href="https:&#x2F;&#x2F;github.com&#x2F;AdoptOpenJDK&#x2F;openjdk-jdk11&#x2F;blob&#x2F;f0ef2826d2116f4e0c0ed21f8d54fe9d0706504e&#x2F;src&#x2F;java.base&#x2F;share&#x2F;classes&#x2F;java&#x2F;lang&#x2F;String.java#L3317-L3322" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;AdoptOpenJDK&#x2F;openjdk-jdk11&#x2F;blob&#x2F;f0ef2826d...</a>
madmax108over 4 years ago
As someone who writes APIs for a living, this is often something interesting that I find a lot of division on:<p>Say you have an API that is documented to accept params A,B or C i.e &#x2F;v1&#x2F;api?A=1&amp;B=2&amp;C=3<p>What should happen if you pass a param D to it? i.e. &#x2F;v1&#x2F;api?A=1&amp;B=2&amp;C=3&amp;D=4<p>The two most common schools of thought are:<p>1) Ignore D<p>2) Throw an error<p>Both present their own problems, esp. when D may be closely related to A,B,C. Interesting how API design also tends to side with personal preferences for strictness or leniency
评论 #24921631 未加载
评论 #24922058 未加载
评论 #24922846 未加载
postalratover 4 years ago
This may be unrelated but every time I see a timestamp as a string in json I wonder why. There is so much less to go wrong with a numeric unix timestamp yet 9 times out of 10 a developer will use a string.<p>If you are going to make things strict at least make it hard to mess up.
评论 #24925425 未加载
评论 #24922608 未加载
评论 #24923058 未加载
评论 #24922768 未加载
megousover 4 years ago
Something I read in the RFC for email message format (or maybe elsewhere, but I have it associated with email for some reason) is: to be strict in output that you produce, and lenient in the input you accept.<p>I think it makes some sense for data formats, if you want max compatibility of independently developed software that processes the data. Not sure about APIs though. Having them fail fast on unexpected input is pretty valuable.
评论 #24921014 未加载
评论 #24920379 未加载
评论 #24920442 未加载
CharlesWover 4 years ago
It seems like &quot;forgiving with warnings&quot; should be another option listed here. This also lets API creators do neat things like warn people ahead of time of future deprecations, etc.
dicroceover 4 years ago
If I had to choose I&#x27;d say prefer strict... But reading this made me wonder: what if you could be strict during development but switch to forgiving for deployment?
评论 #24921646 未加载
评论 #24920281 未加载
评论 #24920950 未加载
评论 #24927099 未加载
评论 #24921691 未加载
RocketSyntaxover 4 years ago
if it accepts a list of items [], but only a single string is provided &quot;&quot;, accept it
ajabhishover 4 years ago
What is preferred by API consumers?
评论 #24920261 未加载
m463over 4 years ago
obligatory link to postels law[1] and criticism<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Robustness_principle" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Robustness_principle</a>
kstenerudover 4 years ago
&gt; Suppose it&#x27;s the early 1990&#x27;s and you&#x27;re James Gosling implementing String.substring(int, int) for the first time. What should happen when the index arguments are out-of-range? Should these tests pass? Or throw?<p>It depends entirely on what the rules of the API are. Function signatures in most languages lack any form of compiler enforcement of rules, so you must implement them in code, and then list the rules in the function&#x27;s description. The strictness you apply doesn&#x27;t matter as much as your description of what argument range is allowed, and how the behaviour is affected.<p>For example, substring could allow overshoot with the description &quot;If the substring would go beyond the end of the string, the remainder of the string is returned&quot;.<p>What you should be concentrating on is the 80% use case of your API. What will 80% of your users need? If the lack of length overshoot support would be cumbersome to the 80%, you support overshoot. If it&#x27;s useless to the 80%, you leave it out. You can also implement things as layered APIs, with more general lower level functions, and then higher level functions that are more strict. Then the 20% can use the lower level functions for their esoteric use cases, and the 80% can stick to your easy-to-use and hard-to-screw-up high level API.