Apa praktik terbaik untuk memberi nama file Swift yang menambahkan ekstensi ke objek yang ada?

165

Dimungkinkan untuk menambahkan ekstensi ke jenis objek Swift yang ada menggunakan ekstensi, seperti yang dijelaskan dalam spesifikasi bahasa .

Akibatnya, dimungkinkan untuk membuat ekstensi seperti:

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

Namun, apa praktik penamaan terbaik untuk file sumber Swift yang berisi ekstensi tersebut?

Di masa lalu, konvensi digunakan extendedtype+categoryname.muntuk tipe Objective-C seperti yang dibahas dalam panduan Objective-C . Tetapi contoh Swift tidak memiliki nama kategori, dan memanggilnya String.swiftsepertinya tidak tepat.

Jadi pertanyaannya adalah: mengingat Stringekstensi di atas , apa yang harus disebut file sumber cepat?

AlBlue
sumber
4
Ini bukan pertanyaan codereview - Saya tidak peduli dengan contoh khusus ini, saya ingin tahu apa konvensi penamaan cepat.
AlBlue
2
Tidak ada konvensi penamaan. Satu-satunya hal yang harus kita jalani adalah kategori dari Objective-C, yang selalu mengikuti ClassName+ExtensionNameformat, dan yang saya tidak melihat terlalu banyak orang masih menggunakan. Selain itu, saya menemukan bahwa kikuk sebagai pengganti hanya mendefinisikan kelas dan ekstensi bersama, atau memberikan nama file yang lebih baik FooAbleTypesdan mendefinisikan contoh dalam agregat.
CodaFi
4
Ada adalah ada praktek penamaan belum. Inilah pemikiran: benjolan semua ekstensi global menjadi satu Extensions.swift. Dengan begitu, Anda tidak akan kehilangan jejak mereka dan pendatang baru ke basis kode akan segera menyadarinya. Dan saya lebih suka menyimpan ekstensi satu kali untuk file yang mereka perlukan.
Andrew
1
Seperti yang dikatakan Andrew, belum ada praktik penamaan standar - maka pertanyaan ini diminta untuk secara khusus mendapatkan pendapat sehingga komunitas yang baru terbentuk dapat datang ke beberapa ide yang disarankan.
AlBlue
1
File extension.swift tunggal adalah cara menurut saya. Jaga struktur di dalamnya terorganisir (dengan cara Anda sendiri) untuk menemukan apa yang Anda butuhkan dengan mudah. Satu file mudah disalin atau ditautkan dari berbagai proyek dan tidak melupakan hal-hal.
Yohst

Jawaban:

202

Sebagian besar contoh yang saya lihat meniru pendekatan Objective-C. Ekstensi contoh di atas adalah:

String+UTF8Data.swift

Keuntungannya adalah bahwa konvensi penamaan memudahkan untuk memahami bahwa itu adalah ekstensi, dan Kelas mana yang sedang diperluas.

Masalah dengan menggunakan Extensions.swiftatau bahkan StringExtensions.swiftadalah bahwa tidak mungkin untuk menyimpulkan tujuan file dengan namanya tanpa melihat isinya.

Menggunakan xxxable.swiftpendekatan seperti yang digunakan oleh Java berfungsi baik untuk protokol atau ekstensi yang hanya mendefinisikan metode. Tetapi sekali lagi, contoh di atas mendefinisikan atribut sehingga UTF8Dataable.swifttidak masuk akal secara tata bahasa.

picciano
sumber
1
Meskipun orang dapat menyimpulkan apa yang sedang diperluas oleh konvensi penamaan, itu adalah IHMO komplikasi yang tidak perlu. Daripada berton-ton file <nama> + <ekstensi> .swift, saya menyimpan satu file extension.swift yang biasanya saya gunakan untuk setiap proyek. File secara internal diatur sedemikian rupa sehingga menemukan kelas tertentu yang diperluas mudah.
Yohst
18
Jawaban ini, <name> + <extention> .swift, memang cara Xcode melakukannya saat membuat subkelas NSManagedObject untuk Data Inti di Xcode 8. Contoh: Foo + CoreDataProperties.swift.
Jerry Krinock
4
Bagaimana jika ekstensi mengimplementasikan banyak metode?
AlexVPerl
2
Bersikaplah sejelas mungkin. Misalnya, Jika Anda memiliki ekstensi untuk Gambar yang mencakup fungsi berbeda untuk menerapkan filter, beri nama Image + Filters.swift. Tidak masalah menggunakan file yang berbeda untuk grup terkait pada fungsi yang diperluas. Kelompokkan hal-hal terkait bersama-sama, tetapi pisahkan hal-hal yang tidak terkait. Hidup akan baik.
picciano
Jika Anda menggunakan konvensi ExtendedType+Functionality.swift, apakah praktik yang baik untuk mengurutkan semua Stringekstensi, misalnya, ke dalam subfolder mereka sendiri (yaitu Stringatau String Extensions) di bawah Extensionsfolder? Atau lebih baik menyimpan semua file ekstensi pada level yang sama di bawah Extensionsfolder?
Noah Wilder
8

Tidak ada konvensi Swift. Sederhana saja:

StringExtensions.swift

Saya membuat satu file untuk setiap kelas yang saya perpanjang. Jika Anda menggunakan satu file untuk semua ekstensi, itu akan dengan cepat menjadi hutan.

Mike Taverne
sumber
8
Ini sepertinya tidak dapat digunakan kembali.
Keller
1
Jika dibandingkan dengan?
Mike Taverne
3
Dibandingkan dengan file tunggal dari ekstensi kelas yang melayani satu tujuan (atau yang jelas terkait). Sesuatu seperti "StringExtensions" terdengar seperti itu bisa berisi semuanya, mulai dari sanitasi String tujuan umum hingga logika khusus aplikasi - yang mungkin bukan pendekatan terbaik jika penggunaan kembali menjadi masalah. Konvensi penamaan kakao condong ke arah fungsi, bukan implementasi. Saya berpendapat bahwa "StringExtensions" menunjukkan yang terakhir. Mengesampingkan konvensi, saya lebih suka jawaban yang diterima, tentu saja di ObjC, tetapi di Swift sepertinya pendekatan yang lebih baik karena modul.
Keller
2
Itu masuk akal. Saya lebih memikirkan satu aplikasi di mana penggunaan kembali tidak menjadi masalah. Misalnya, saya memiliki beberapa fungsi string yang tidak terkait yang ingin saya gunakan sebagai ekstensi - saya dapat membuat satu file dan meletakkan semua fungsi ini di sana, atau membuat satu file per fungsi. Saya suka kesederhanaan satu file dalam kasus itu. Tapi alasanmu bagus. Terima kasih.
Mike Taverne
Ini masuk akal, asalkan hal-hal yang ditambahkan di sini secara alami akan berlaku untuk semua string (yaitu 'trimRight ()' sebagai contoh). Jika itu adalah sesuatu yang lebih spesifik-penggunaan-kasus (yaitu 'formatAccountNumber ()'), maka file tersebut harus 'Strings + AccountFormatting.swift' dan harus dibatasi hanya di tempat yang sebenarnya digunakan untuk tidak mengacaukan API permukaan 'Strings' di tempat lain.
Mark A. Donohoe
1

Saya lebih suka StringExtensions.swiftsampai saya menambahkan terlalu banyak hal untuk membagi file menjadi sesuatu seperti String+utf8Data.swiftdan String+Encrypt.swift.

Satu hal lagi, menggabungkan file serupa menjadi satu akan membuat bangunan Anda lebih cepat. Rujuk ke Mengoptimalkan-Cepat-Build-Times

DawnSong
sumber
1
Itu memiliki dua konvensi penamaan file untuk hal yang sama. Saya pikir itu buruk.
maknanya penting
@ arti-penting Itu tergantung. Kedua konvensi penamaan ini terkenal dan direkomendasikan oleh Apple Documents. Lakukan apa yang kamu mau.
DawnSong
Saya berharap lebih banyak programmer akan berusaha untuk keanggunan dengan membatasi variasi penamaan dan kode [format].
Makna penting
@ arti-penting Elegance memiliki dua sisi, ini seperti masalah kontroversial klasik tentang cara menulis kurung kurawal dalam bahasa mirip-C. Itu sepele, jadi saya pikir tidak perlu untuk memilih satu dan membuatnya wajib sampai kebanyakan orang setuju untuk melakukannya.
DawnSong
Maksud saya keanggunan konsistensi: menggunakan satu cara untuk memberi nama ekstensi, atau satu cara untuk menempatkan kurung kurawal. Lalu saya pikir ada perbedaan yang dapat diukur dalam keterbacaan gaya kurung kurawal yang berbeda; jadi saya tidak berpikir itu 'sepele' sama sekali.
maknanya penting
0

Jika Anda memiliki perangkat tambahan umum dan aneka yang disetujui tim, menyatukannya sebagai Extensions.swift berfungsi sebagai solusi tingkat pertama Keep-It-Simple. Namun, saat kompleksitas Anda tumbuh, atau ekstensi menjadi lebih terlibat, diperlukan hierarki untuk merangkum kompleksitas. Dalam keadaan seperti itu saya merekomendasikan praktik berikut dengan sebuah contoh.

Saya memiliki kelas yang berbicara dengan back-end saya, dipanggil Server. Itu mulai tumbuh lebih besar untuk mencakup dua aplikasi target yang berbeda. Beberapa orang menyukai file besar tetapi secara logis terpisah dengan ekstensi. Preferensi saya adalah menjaga setiap file relatif singkat sehingga saya memilih solusi berikut. Serverawalnya sesuai CloudAdapterProtocoldan menerapkan semua metodenya. Apa yang saya lakukan adalah mengubah protokol menjadi hierarki, dengan membuatnya merujuk pada protokol bawahan:

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

Di Server.swiftsaya miliki

import Foundation
import UIKit
import Alamofire
import AlamofireImage

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

Server.swiftkemudian hanya mengimplementasikan API server inti untuk mengatur server dan mendapatkan versi API. Karya nyata dibagi menjadi dua file:

Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift

Ini menerapkan protokol masing-masing.

Ini berarti Anda harus memiliki deklarasi impor di file lain (untuk Alamofire dalam contoh ini) tetapi ini adalah solusi bersih dalam hal memisahkan antarmuka dalam pandangan saya.

Saya pikir pendekatan ini bekerja sama baiknya dengan kelas yang ditentukan secara eksternal serta Anda sendiri.

Faisal Memon
sumber
0

Mengapa ini bahkan menjadi perdebatan? Haruskah saya meletakkan semua sub-kelas saya ke dalam file yang disebut _Subclasses.swift. Saya pikir tidak. Swift memiliki spasi nama berbasis modul. Untuk memperluas kelas Swift yang terkenal membutuhkan file yang khusus untuk tujuannya. Saya dapat memiliki tim besar yang membuat file yang UIViewExtensions.swift yang menyatakan tidak ada tujuan dan akan membingungkan pengembang dan dapat dengan mudah diduplikasi dalam proyek yang tidak akan dibangun. Konvensi penamaan Objective-C berfungsi dengan baik dan sampai Swift memiliki spasi nama asli, itu adalah cara terbaik untuk melakukannya.

Tom Condon
sumber
Dalam kasus saya, saya pikir masuk akal untuk memiliki file bernama UIViewExtensions.swift asalkan ekstensi yang ditentukan dalam file itu masuk akal untuk setiap / semua kelas UIView, seperti metode 'placeIn (UIView)'. Jika itu khusus penggunaan (yaitu hanya untuk sebagian dari aplikasi, katakan sekitar dekorasi tampilan kustom, maka saya akan melakukan UIView + CustomDecoration.swift. Intinya adalah Anda harus mempertimbangkan penggunaan sebelum membuat generalisasi seperti mengatakan file yang disebut 'UIViewExtensions .segera yang menyatakan tidak ada tujuan 'ketika tujuannya adalah ekstensi umum untuk semua UIViews
Mark A. Donohoe
0

Daripada menambahkan komentar saya di semua tempat, saya memunculkan semuanya di sini dalam satu jawaban.

Secara pribadi, saya mengambil pendekatan hybrid yang memberikan baik kegunaan dan kejelasan, sementara juga tidak mengacaukan area permukaan API untuk objek yang saya perpanjang.

Misalnya, apa pun yang masuk akal untuk tersedia untuk string apa pun akan masuk StringExtensions.swiftseperti trimRight()dan removeBlankLines().

Namun, jika saya memiliki fungsi ekstensi seperti formatAsAccountNumber()itu tidak akan masuk dalam file itu karena 'Nomor Akun' bukanlah sesuatu yang secara alami berlaku untuk semua / semua string dan hanya masuk akal dalam konteks akun. Dalam hal ini, saya akan membuat file bernama Strings+AccountFormatting.swiftatau mungkin bahkan Strings+CustomFormatting.swiftdengan formatAsAccountNumber()fungsi jika ada beberapa jenis / cara untuk memformatnya.

Sebenarnya, dalam contoh terakhir itu, saya secara aktif mencegah tim saya untuk menggunakan ekstensi seperti itu di tempat pertama, dan sebagai gantinya akan mendorong sesuatu seperti AccountNumberFormatter.format(String)bukan yang tidak menyentuh Stringarea permukaan API sama sekali, sebagaimana seharusnya. Pengecualiannya adalah jika Anda mendefinisikan ekstensi itu di file yang sama di mana ia digunakan, tapi itu tidak akan memiliki nama file itu sendiri.

Mark A. Donohoe
sumber
0

Saya lebih suka harus +menggarisbawahi fakta bahwa itu berisi ekstensi:

String+Extensions.swift

Dan jika file terlalu besar, Anda dapat membaginya untuk setiap tujuan:

String+UTF8Data.swift

String+Encrypt.swift

Xys
sumber