API DesignDon't try to guess
I was reviewing some code, and I ran into the following snippet. Take a look at it:
public void AddAttachment(string fileName, Stream stream)
{
ValidationMethods.AssertNotNullOrEmpty(fileName, nameof(fileName));
if (stream == null)
throw new ArgumentNullException(nameof(stream));
string type = GetContentType(fileName);
_attachments.Add(new PutAttachmentCommandData("__this__", fileName, stream, type, changeVector: string.Empty));
}
private static string GetContentType(string fileName)
{
var extension = Path.GetExtension(fileName);
if (string.IsNullOrEmpty(extension))
return "image/jpeg"; // Default fallback
return extension.ToLowerInvariant() switch
{
".jpg" or ".jpeg" => "image/jpeg",
".png" => "image/png",
".webp" => "image/webp",
".gif" => "image/gif",
".pdf" => "application/pdf",
".txt" => "text/plain",
_ => "application/octet-stream"
};
}I don’t like this code because the API is trying to guess the intent of the caller. We are making some reasonable inferences here, for sure, but we are also ensuring that any future progress will require us to change our code, instead of letting the caller do that.
In fact, the caller probably knows a lot more than we do about what is going on. They know if they are uploading an image, and probably in what format too. They know that they just uploaded a CSV file (and that we need to classify it as plain text, etc.).
This is one of those cases where the best option is not to try to be smart. I recommended that we write the function to let the caller deal with it.
It is important to note that this is meant to be a public API in a library that is shipped to external customers, so changing something in the library is not easy (change, release, deploy, update - that can take a while). We need to make sure that we aren’t blocking the caller from doing things they may want to.
This is a case of trying to help the user, but instead ending up crippling what they can do with the API.
More posts in "API Design" series:
- (29 Jan 2026) Don't try to guess
- (04 Dec 2017) The lack of a method was intentional forethought
- (27 Jul 2016) robust error handling and recovery
- (20 Jul 2015) We’ll let the users sort it out
- (17 Jul 2015) Small modifications over a network
- (01 Jun 2012) Sharding Status for failure scenarios–Solving at the right granularity
- (31 May 2012) Sharding Status for failure scenarios–explicit failure management doesn’t work
- (30 May 2012) Sharding Status for failure scenarios–explicit failure management
- (29 May 2012) Sharding Status for failure scenarios–ignore and move on
- (28 May 2012) Sharding Status for failure scenarios

Comments
Comment preview
Join the conversation...