ChatGPT解决这个技术问题 Extra ChatGPT

What's the best practice for naming Swift files that add extensions to existing objects?

It's possible to add extensions to existing Swift object types using extensions, as described in the language specification.

As a result, it's possible to create extensions such as:

extension String {
    var utf8data:NSData {
        return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    }
}

However, what's the best naming practice for Swift source files containing such extensions?

In the past, the convention was to use extendedtype+categoryname.m for the Objective-C type as discussed in the Objective-C guide. But the Swift example doesn't have a category name, and calling it String.swift doesn't seem appropriate.

So the question is: given the above String extension, what should the swift source file be called?

This isn't a codereview question - I don't care about this particular example, I want to know what the swift naming convention is.
There is no naming convention. The only thing we have to go on are categories from Objective-C, which always followed the ClassName+ExtensionName format, and which I don't see too many people still using. Besides, I find that clunky in lieu of just defining classes and extensions together, or giving the file a better name like FooAbleTypes and defining instances in aggregate.
There is no naming practice yet. Here's a thought: lump all global extensions together in a single Extensions.swift. That way, you won't lose track of them and newcomers to the codebase will immediately notice them. And I'd prefer to keep one-off extensions private to the file they're needed in.
As Andrew says, there is no standard naming practice yet - hence this question was asked to specifically get opinions so that a newly formed community can come to some suggested ideas.
A single extensions.swift file is the way to go in my opinion. Keep the structure inside it organized (in your own way) to find what you need easily. A single file is easy to copy or link to from a variety of projects and not forget stuff.

p
picciano

Most examples I have seen mimic the Objective-C approach. The example extension above would be:

String+UTF8Data.swift

The advantages are that the naming convention makes it easy to understand that it is an extension, and which Class is being extended.

The problem with using Extensions.swift or even StringExtensions.swift is that it's not possible to infer the purpose of the file by its name without looking at its contents.

Using xxxable.swift approach as used by Java works okay for protocols or extensions that only define methods. But again, the example above defines an attribute so that UTF8Dataable.swift doesn't make much grammatical sense.


Though one can infer what is being extended by the naming convention, it is IHMO a needless complication. Rather than tons of +.swift files, I keep a single extensions.swift file that I generally use for each project. The file internally is organized such that finding a particular class that is extended is easy.
This answer, +.swift, is indeed the way Xcode does it when creating NSManagedObject subclasses for Core Data in Xcode 8. Example: Foo+CoreDataProperties.swift.
What if the extension implements multiple methods?
Just be as descriptive as possible. For example, If you have an extension to Image that includes different function for applying filters, name it Image+Filters.swift. It's fine to use different files for related groups on extended functions. Group related things together, but keep unrelated things separate. Life will be good.
If you are using the convention of ExtendedType+Functionality.swift, is it good practice to sort all String extensions, for example, into their own subfolder (i.e. String or String Extensions) under the Extensions folder? Or is it better to just store all extension files on the same level under the Extensions folder?
X
Xys

I prefer having a + to underline the fact it contains extensions :

String+Extensions.swift

And if the file gets too big, you can then split it for each purpose :

String+UTF8Data.swift

String+Encrypt.swift


M
Mike Taverne

There is no Swift convention. Keep it simple:

StringExtensions.swift

I create one file for each class I'm extending. If you use a single file for all extensions, it will quickly become a jungle.


This doesn't seem particularly re-usable.
As compared to?
As compared to a singly (or tightly coupled) file of class extensions that serve a single (or expressly relatable) purpose. Something like "StringExtensions" sounds like it could contain everything from general purpose String sanitization to app-specific logic- which might not be the best approach if reuse is a concern. Cocoa naming convention leans towards function, rather than implementation. I'd argue that "StringExtensions" indicates the latter. Naming convention aside, I prefer the accepted answer, certainly in ObjC, but in Swift it seems like an even better approach due to modules.
That makes sense. I was thinking more of a single app where reuse wasn't a concern. For example, say I have a few unrelated string functions that I want to use as extensions - I could create one file and put all these functions there, or create one file per function. I like the simplicity of a single file in that case. But your reasoning is sound. Thanks.
This makes complete sense, provided the things that are added here would naturally apply to all strings (i.e. 'trimRight()' as an example). If it's something that is more use-case-specific (i.e. 'formatAccountNumber()'), then the file should be 'Strings+AccountFormatting.swift' and it should be scoped to only where it is actually used as to not clutter up the 'Strings' surface API elsewhere.
D
DawnSong

I prefer StringExtensions.swift until I added too much things to split the file into something like String+utf8Data.swift and String+Encrypt.swift.

One more thing, to combine similar files into one will make your building more faster. Refer to Optimizing-Swift-Build-Times


That's having two file naming conventions for the same thing. I think that's bad.
@meaning-matters It depends. The two naming convention are both well-known and recommended by Apple Documents. Do as you wish.
I wish more programmers would strive for elegance by limiting naming and code [formatting] variations.
@meaning-matters Elegance has two sides, it's like a classical controversial problem about how to write curly braces in C-like languages. It's trivial, so I don't think it's necessary to choose one and make it mandatory until most people agree to do so.
I meant the elegance of consistency: using one way to name extensions, or one way to place curly braces. Then I do think there's a measurable difference in readability of different curly brace styles; so I don't think it's 'trivial' at all.
M
Mark A. Donohoe

Rather than adding my comments all over the place, I'm surfacing them all here in one answer.

Personally, I take a hybrid approach that gives both good usability and clarity, while also not cluttering up the API surface area for the object that I'm extending.

For instance, anything that makes sense to be available to any string would go in StringExtensions.swift such as trimRight() and removeBlankLines().

However, if I had an extension function such as formatAsAccountNumber() it would not go in that file because 'Account Number' is not something that would naturally apply to any/all strings and only makes sense in the context of accounts. In that case, I would create a file called Strings+AccountFormatting.swift or maybe even Strings+CustomFormatting.swift with a formatAsAccountNumber() function if there are several types/ways to actually format it.

Actually, in that last example, I actively dissuade my team from using extensions like that in the first place, and would instead encourage something like AccountNumberFormatter.format(String) instead as that doesn't touch the String API surface area at all, as it shouldn't. The exception would be if you defined that extension in the same file where it's used, but then it wouldn't have it's own filename anyway.


F
Faisal Memon

If you have a team-agreed set of common and miscellaneous enhancements, lumping them together as an Extensions.swift works as Keep-It-Simple first level solution. However, as your complexity grows, or the extensions become more involved, a hierarchy is needed to encapsulate the complexity. In such circumstances I recommend the following practice with an example.

I had a class which talks to my back-end, called Server. It started to grow bigger to cover two different target apps. Some people like a large file but just logically split up with extensions. My preference is to keep each file relatively short so I chose the following solution. Server originally conformed to CloudAdapterProtocol and implemented all its methods. What I did was to turn the protocol into a hierarchy, by making it refer to subordinate protocols:

protocol CloudAdapterProtocol: ReggyCloudProtocol, ProReggyCloudProtocol {
    var server: CloudServer {
        get set
    }
    func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void)
}

In Server.swift I have

import Foundation
import UIKit
import Alamofire
import AlamofireImage

class Server: CloudAdapterProtocol {
.
.
func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void) {
.
.
}

Server.swift then just implements the core server API for setting the server and getting the API version. The real work is split into two files:

Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift

These implement the respective protocols.

It means you need to have import declarations in the other files (for Alamofire in this example) but its a clean solution in terms of segregating interfaces in my view.

I think this approach works equally well with externally specified classes as well as your own.


T
Tom Condon

Why is this even a debate? Should I put all my sub classes into a file called _Subclasses.swift. I think not. Swift has module based name spacing. To extend a well known Swift class needs a file that is specific to its purpose. I could have a large team that creates a file that is UIViewExtensions.swift that express no purpose and will confuse developers and could be easily duplicated in the project which would not build. The Objective-C naming convention works fine and until Swift has real name spacing, it is the best way to go.


In my case, I think it makes perfect sense to have a file called UIViewExtensions.swift provided the extensions defined in that file would make sense for any/all UIView classes, such as a 'placeIn(UIView)' method. If it is use-specific (i.e. just for a portion of the app, say around custom view decoration, then I would do UIView+CustomDecoration.swift. Point is you have to consider usage before making a generalization like saying a file called 'UIViewExtensions.swift that express no purpose' when the purpose is general extensions for all UIViews.

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now