Which is the preferred option (or please feel free to suggest any other alternate)?
Is it ok to use Option 1 which is shorter but needs the first argument name to explain what the function does or should the function name be self explanatory even without the first argument name?
Option 1 is much more Swifty, while Option 2 sounds like coming from an old Obj-C library.
Functions should be self explanatory with all required arguments. Allowing call site to include function arguments is one of the best design for clarity. Thereās no good reason not to take advantage of that.
I do not agree with @Lantua on this one. Well, maybe I do, but probably not. It depends on context.
A function should be named such that its base name explains what it does. update is a poor name on its own, unless it clearly updates self. If this is a method on a type, say, Image, then image.update() may be a great name. But if it's a free function, better name it so it better reflects what it does.
You state that the purpose of the function is to update an image status, but you also pass it an image status as an argument.
If this is updating (mutatin) its argument, maybe the function instead should be a method on ImageStatus.update. Or, if it is a setter function, maybe it instead should be a property?
Thank @sveinhal I have some concurrent code in my model class Service
class Service {
struct ImageStatus { }
private var imageStatus: ImageStatus
@MainActor
func update(imageStatus: ImageStatus) { }
}
Question:
I have one more scenario where I have processTransactions(_ transactions: [Transaction]) Transaction is not my class should I extend it and add my custom logic in it or is processTransactions ok?
This Swift.org - API Design Guidelines part of the Swift API Design Guideline answers the questions but it is relatively hard to grasp especially when English is not your first language.
In this case I would say that:
func updateImageStatus(ImageStatus) { }
or even
func update(_ status: ImageStatus) { }
// Probably most of the time passed parameter would be self-explanatory.
service.update(imageStatus)
fits better
It's very similar to the
x.addSubview(y)
In addition, if you will take a look at the API that has update method on Apple Documentation you will find that non of them use argument label.
Yea, rereading the call site; update(imageStatus: ...) does sound like youāre updating something with image status, rather than updating the image status with the new value.
My second point still stands, that one should take advantage of the arguments, even if not for stating the function's primary purpose.
Ah yes, the guideline does say to omit type names in particular because they are generally known by the reader (if they arenāt, they should read previous lines and work their way down anyway). I forgot about that part.
So I think update(_:) does fit this particular case.
Always take a grain of salt when looking up Apple's API, though. Albeit being much rarer nowadays, some are remnants of the Obj-C designs.
If it isnāt confusing with other functions with similar names, maybe just process(_:)?
I think this is the most relevant guideline in the context of your question:
Include all the words needed to avoid ambiguity for a person reading code where the name is used.
For example, consider a method that removes the element at a given position within a collection.
extension List {
public mutating func remove(at position: Index) -> Element
}
employees.remove(at: x)
If we were to omit the word at from the method signature, it could imply to the reader that the method searches for and removes an element equal to x , rather than using x to indicate the position of the element to remove.
employees.remove(x) // unclear: are we removing x?
I think there is an (maybe slight) ambiguity in both of your functions: are you updating a image status that currently is the given value, or are you changing the image status to the given value. To disambiguate, the second function with preposition "to" as argument label should be a better option:
class Service {
func updateImageStatus(to newImageStatus: ImageStatus)
}
Having "ImageStatus" in the function's name is good because the function is not defined in ImageStatus. But if the function is in ImageStatus, then the function's name should omit it:
Thanks @wowbagger I think that is a good suggestion definitely adds more clarity, it is interesting how trying to improve the name results in improving the design
Interesting, but not surprising. Choosing a good name means you have to understand the intent. Communicating that intent relies not just on the name, but also how that name fits into the larger context.
class Service {
struct ImageStatus { }
@MainActor
var imageStatus: ImageStatus {
didSet { }
}
}
One alternative would be to expose the imageStatus and do the side-effects in the didSet. So the call site would be clear.
let service = Service()
let newImageStatus = Service.ImageStatus()
service.imageStatus = newImageStatus
The func update(imageStatus:)seemed a lot like func setImageStatus(_:) which seems to be usually handled with property observers in swift. (instead of the getter/settter method common in, say, the java language)