Qual é a melhor prática para nomear arquivos Swift que adicionam extensões a objetos existentes?

165

É possível adicionar extensões aos tipos de objetos Swift existentes usando extensões, conforme descrito na especificação do idioma .

Como resultado, é possível criar extensões como:

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

No entanto, qual é a melhor prática de nomeação para arquivos de origem Swift que contêm essas extensões?

No passado, a convenção era extendedtype+categoryname.mpara o tipo Objective-C, conforme discutido no guia Objective-C . Mas o exemplo Swift não tem um nome de categoria, e chamá-lo String.swiftnão parece apropriado.

Portanto, a pergunta é: dada a Stringextensão acima , como deve ser chamado o arquivo de origem rápido?

AlBlue
fonte
4
Esta não é uma questão de revisão de código - não me importo com esse exemplo específico, quero saber qual é a convenção de nomenclatura rápida.
AlBlue
2
Não há convenção de nomenclatura. A única coisa que precisamos seguir são as categorias do Objective-C, que sempre seguiram o ClassName+ExtensionNameformato e que não vejo muitas pessoas ainda usando. Além disso, acho isso desajeitado em vez de apenas definir classes e extensões em conjunto, ou dar ao arquivo um nome melhor FooAbleTypese definir instâncias de forma agregada.
CodaFi 11/10
4
Não é nenhuma prática de nomeação ainda. Aqui está um pensamento: agrupe todas as extensões globais juntas em uma única Extensions.swift. Dessa forma, você não os perderá e os recém-chegados à base de código os notarão imediatamente. E eu preferiria manter one-off extensões privadas para o arquivo eles são necessários no.
Andrew
1
Como Andrew diz, ainda não existe uma prática padrão de nomeação - portanto, essa pergunta foi solicitada para obter opiniões especificamente para que uma comunidade recém-formada possa ter algumas idéias sugeridas.
AlBlue
1
Um único arquivo extensions.swift é o caminho a percorrer na minha opinião. Mantenha a estrutura dentro dela organizada (do seu jeito) para encontrar o que você precisa com facilidade. Um único arquivo é fácil de copiar ou vincular a partir de uma variedade de projetos e não esquecer as coisas.
Yohst 25/02

Respostas:

202

A maioria dos exemplos que vi imitam a abordagem Objective-C. A extensão de exemplo acima seria:

String+UTF8Data.swift

As vantagens são que a convenção de nomenclatura facilita a compreensão de que é uma extensão e qual classe está sendo estendida.

O problema com o uso Extensions.swiftou mesmo StringExtensions.swifté que não é possível inferir a finalidade do arquivo pelo nome sem examinar o conteúdo.

Usar a xxxable.swiftabordagem usada pelo Java funciona bem para protocolos ou extensões que definem apenas métodos. Mas, novamente, o exemplo acima define um atributo para que UTF8Dataable.swiftnão faça muito sentido gramatical.

picciano
fonte
1
Embora se possa inferir o que está sendo estendido pela convenção de nomenclatura, o IHMO é uma complicação desnecessária. Em vez de toneladas de arquivos <name> + <extention> .swift, mantenho um único arquivo extensions.swift que geralmente uso para cada projeto. O arquivo é organizado internamente, de modo que é fácil encontrar uma classe específica que é estendida.
Yohst 25/02
18
Esta resposta, <name> + <extention> .swift, é realmente a maneira que o Xcode faz ao criar subclasses NSManagedObject para Core Data no Xcode 8. Exemplo: Foo + CoreDataProperties.swift.
Jerry Krinock
4
E se a extensão implementar vários métodos?
AlexVPerl
2
Seja o mais descritivo possível. Por exemplo, se você tiver uma extensão para a imagem que inclui uma função diferente para aplicar filtros, nomeie-a como imagem + filtros.swift. É bom usar arquivos diferentes para grupos relacionados em funções estendidas. Agrupe as coisas relacionadas, mas mantenha as coisas não relacionadas separadas. A vida será boa.
Picciano
Se você estiver usando a convenção de ExtendedType+Functionality.swift, é uma boa prática classificar todas as Stringextensões, por exemplo, em sua própria subpasta ( Stringou seja String Extensions) na Extensionspasta? Ou é melhor apenas armazenar todos os arquivos de extensão no mesmo nível na Extensionspasta?
Noah Wilder
8

Não existe uma convenção Swift. Mantenha simples:

StringExtensions.swift

Eu crio um arquivo para cada classe que estou estendendo. Se você usar um único arquivo para todas as extensões, ele rapidamente se tornará uma selva.

Mike Taverne
fonte
8
Isso não parece particularmente reutilizável.
Keller
1
Em comparação com?
Mike Taverne
3
Em comparação com um arquivo isolado (ou fortemente acoplado) de extensões de classe que atendem a um único objetivo (ou expressamente relacionável). Algo como "StringExtensions" parece que poderia conter tudo, desde a limpeza geral de String de uso geral até a lógica específica do aplicativo - que pode não ser a melhor abordagem se a reutilização for uma preocupação. A convenção de nomenclatura de cacau se inclina mais para a função do que para a implementação. Eu diria que "StringExtensions" indica o último. Além da convenção de nomenclatura, prefiro a resposta aceita, certamente no ObjC, mas no Swift parece uma abordagem ainda melhor devido aos módulos.
Keller
2
Isso faz sentido. Eu estava pensando mais em um único aplicativo em que a reutilização não era uma preocupação. Por exemplo, digamos que tenho algumas funções de string não relacionadas que desejo usar como extensões - eu poderia criar um arquivo e colocar todas essas funções lá ou criar um arquivo por função. Eu gosto da simplicidade de um único arquivo nesse caso. Mas seu raciocínio é sólido. Obrigado.
Mike Taverne
Isso faz todo sentido, desde que as coisas adicionadas aqui se apliquem naturalmente a todas as strings (por exemplo, 'trimRight ()'). Se for algo mais específico de caso de uso (por exemplo, 'formatAccountNumber ()'), o arquivo deve ser 'Strings + AccountFormatting.swift' e deve ter o escopo definido apenas para onde é realmente usado para não bagunçar o API de superfície 'Strings' em outro lugar.
Mark A. Donohoe
1

Eu prefiro StringExtensions.swiftaté adicionar coisas demais para dividir o arquivo em algo como String+utf8Data.swifte String+Encrypt.swift.

Mais uma coisa, combinar arquivos semelhantes em um só tornará sua construção mais rápida. Consulte Optimizing-Swift-Build-Times

DawnSong
fonte
1
É ter duas convenções de nomenclatura de arquivos para a mesma coisa. Eu acho isso ruim.
significado-importa
@ significado-importa Depende. As duas convenções de nomenclatura são conhecidas e recomendadas pela Apple Documents. Faça como quiser.
DawnSong
Desejo que mais programadores se esforcem pela elegância limitando as variações de nomes e códigos [formatação].
Significado-importa
O significado de elegância tem dois lados, é como um problema clássico e controverso sobre como escrever chaves nos idiomas C. É trivial, então não acho necessário escolher um e torná-lo obrigatório até que a maioria das pessoas concorde em fazê-lo.
DawnSong
Eu quis dizer a elegância da consistência: usar uma maneira de nomear extensões ou uma maneira de colocar chaves. Então acho que há uma diferença mensurável na legibilidade de diferentes estilos de chaves; então eu não acho nada trivial.
Significado-importa
0

Se você tiver um conjunto acordado em equipe de aprimoramentos comuns e diversos, agrupá-los como um Extensions.swift funcionará como uma solução de primeiro nível de Manutenção simples. No entanto, à medida que sua complexidade aumenta ou as extensões se tornam mais envolvidas, é necessária uma hierarquia para encapsular a complexidade. Em tais circunstâncias, recomendo a prática a seguir com um exemplo.

Eu tive uma aula que fala com meu back-end, chamada Server. Começou a crescer para cobrir dois aplicativos de destino diferentes. Algumas pessoas gostam de um arquivo grande, mas apenas se separam logicamente com extensões. Minha preferência é manter cada arquivo relativamente curto, então escolhi a seguinte solução. Serveroriginalmente conforme CloudAdapterProtocole implementou todos os seus métodos. O que fiz foi transformar o protocolo em uma hierarquia, fazendo-o se referir a protocolos subordinados:

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

Em Server.swiftque tenho

import Foundation
import UIKit
import Alamofire
import AlamofireImage

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

Server.swiftentão apenas implementa a API do servidor núcleo para configurar o servidor e obter a versão da API. O trabalho real é dividido em dois arquivos:

Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift

Eles implementam os respectivos protocolos.

Isso significa que você precisa ter declarações de importação nos outros arquivos (para Alamofire neste exemplo), mas é uma solução limpa em termos de segregação de interfaces na minha opinião.

Eu acho que essa abordagem funciona igualmente bem com classes especificadas externamente e com as suas próprias.

Faisal Memon
fonte
0

Por que isso é mesmo um debate? Devo colocar todas as minhas subclasses em um arquivo chamado _Subclasses.swift. Eu acho que não. Swift possui espaçamento de nome baseado em módulo. Para estender uma classe Swift conhecida, é necessário um arquivo específico para sua finalidade. Eu poderia ter uma grande equipe que cria um arquivo que é o UIViewExtensions.swift que não tem propósito algum e confunde os desenvolvedores e pode ser facilmente duplicado no projeto que não seria criado. A convenção de nomenclatura Objective-C funciona bem e até Swift ter espaçamento de nome real, é o melhor caminho a percorrer.

Tom Condon
fonte
No meu caso, acho que faz todo sentido ter um arquivo chamado UIViewExtensions.swift, desde que as extensões definidas nesse arquivo façam sentido para qualquer / todas as classes UIView, como um método 'placeIn (UIView)'. Se for específico do uso (ou seja, apenas para uma parte do aplicativo, digamos em torno da decoração de exibição personalizada, eu faria o UIView + CustomDecoration.swift. O ponto é que você deve considerar o uso antes de fazer uma generalização, como dizer um arquivo chamado 'UIViewExtensions .swift que não tem propósito 'quando o objetivo é extensões gerais para todos os UIViews.'
Mark A. Donohoe
0

Em vez de adicionar meus comentários em todo o lugar, eu os estou colocando aqui em uma resposta.

Pessoalmente, adoto uma abordagem híbrida que oferece boa usabilidade e clareza, além de não sobrecarregar a área de superfície da API para o objeto que estou estendendo.

Por exemplo, qualquer coisa que faça sentido estar disponível para qualquer string seria StringExtensions.swiftcomo trimRight()e removeBlankLines().

No entanto, se eu tivesse uma função de extensão, como formatAsAccountNumber()ela não entraria nesse arquivo, porque 'Número da conta' não é algo que se aplicaria naturalmente a todas / todas as strings e só faz sentido no contexto das contas. Nesse caso, eu criaria um arquivo chamado Strings+AccountFormatting.swiftou talvez Strings+CustomFormatting.swiftcom uma formatAsAccountNumber()função se houver vários tipos / maneiras de realmente formatá-lo.

Na verdade, nesse último exemplo, eu dissuito ativamente minha equipe de usar extensões como essa em primeiro lugar e, em vez disso, incentivaria algo como AccountNumberFormatter.format(String)isso, pois isso não afeta a Stringárea da superfície da API, como deveria. A exceção seria se você definisse essa extensão no mesmo arquivo em que é usada, mas não teria seu próprio nome de arquivo.

Mark A. Donohoe
fonte
0

Prefiro +sublinhar o fato de que ele contém extensões:

String+Extensions.swift

E se o arquivo ficar muito grande, você poderá dividi-lo para cada finalidade:

String+UTF8Data.swift

String+Encrypt.swift

Xys
fonte