แนวปฏิบัติที่เหมาะสมที่สุดสำหรับการตั้งชื่อไฟล์ Swift ที่เพิ่มส่วนขยายไปยังวัตถุที่มีอยู่คืออะไร


166

มันเป็นไปได้ที่จะเพิ่มส่วนขยายที่มีอยู่วัตถุประเภทสวิฟท์ใช้ส่วนขยายตามที่อธิบายไว้ในสเปคภาษา

ด้วยเหตุนี้จึงเป็นไปได้ที่จะสร้างส่วนขยายเช่น:

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

อย่างไรก็ตามวิธีการตั้งชื่อที่ดีที่สุดสำหรับไฟล์ต้นฉบับของ Swift ที่มีนามสกุลดังกล่าวคืออะไร

ในอดีตที่ผ่านมาการประชุมคือการใช้extendedtype+categoryname.mสำหรับชนิด Objective-C ที่กล่าวไว้ในวัตถุประสงค์-C คู่มือ แต่ตัวอย่างของ Swift ไม่มีชื่อหมวดหมู่และการเรียกมันString.swiftดูไม่เหมาะสม

ดังนั้นคำถามคือ: จากการStringขยายข้างต้นไฟล์ swift ควรจะเรียกว่าอะไร?


5
นี่ไม่ใช่คำถาม codereview - ฉันไม่สนใจตัวอย่างเฉพาะนี้ฉันต้องการทราบว่าแบบแผนการตั้งชื่อแบบรวดเร็วคืออะไร
AlBlue

2
ไม่มีแบบแผนการตั้งชื่อ สิ่งเดียวที่เราต้องดำเนินต่อไปคือหมวดหมู่จาก Objective-C ซึ่งตามClassName+ExtensionNameรูปแบบเสมอและฉันไม่เห็นคนจำนวนมากที่ยังใช้อยู่ นอกจากนี้ฉันพบว่า clunky แทนการกำหนดคลาสและส่วนขยายร่วมกันหรือให้ชื่อไฟล์ที่ดีกว่าเช่นFooAbleTypesและกำหนดอินสแตนซ์รวม
CodaFi

4
มีคือไม่มีการปฏิบัติในการตั้งชื่อเลย นี่เป็นความคิด: Extensions.swiftก้อนส่วนขยายทั่วโลกทั้งหมดเข้าด้วยกันในครั้งเดียว ด้วยวิธีนี้คุณจะไม่สูญเสียการติดตามพวกเขาและผู้มาใหม่ถึง codebase จะแจ้งให้ทราบทันที และฉันต้องการเก็บนามสกุลส่วนบุคคลไว้ในไฟล์ที่พวกเขาต้องการ
Andrew

1
ดังที่แอนดรูว์กล่าวว่ายังไม่มีการตั้งชื่อมาตรฐานดังนั้นคำถามนี้จึงถูกขอให้รับความคิดเห็นเป็นพิเศษเพื่อให้ชุมชนที่จัดตั้งขึ้นใหม่สามารถมาเสนอแนวคิด
AlBlue

1
ไฟล์ extension.swift ไฟล์เดียวเป็นวิธีที่จะไปในความคิดของฉัน จัดโครงสร้างภายในให้เป็นระเบียบ (ในแบบของคุณเอง) เพื่อค้นหาสิ่งที่คุณต้องการได้อย่างง่ายดาย ไฟล์เดียวนั้นง่ายต่อการคัดลอกหรือลิงค์จากหลายโครงการและไม่ลืมสิ่งต่าง ๆ
Yohst

คำตอบ:


202

ตัวอย่างส่วนใหญ่ที่ฉันได้เห็นเลียนแบบวิธีการ Objective-C ตัวอย่างส่วนขยายด้านบนจะเป็น:

String+UTF8Data.swift

ข้อดีคืออนุสัญญาการตั้งชื่อทำให้ง่ายต่อการเข้าใจว่าเป็นส่วนขยายและคลาสใดที่กำลังถูกขยาย

ปัญหาเกี่ยวกับการใช้งานExtensions.swiftหรือแม้กระทั่งStringExtensions.swiftว่าเป็นไปไม่ได้ที่จะอนุมานจุดประสงค์ของไฟล์ตามชื่อไฟล์โดยไม่ดูที่เนื้อหา

การใช้xxxable.swiftวิธีการที่ใช้โดย Java ทำงานได้ดีสำหรับโปรโตคอลหรือส่วนขยายที่กำหนดวิธีการเท่านั้น แต่อีกครั้งตัวอย่างข้างต้นจะกำหนดแอตทริบิวต์เพื่อที่UTF8Dataable.swiftจะไม่ใช้ไวยากรณ์มากนัก


2
แม้ว่าจะมีใครสามารถสรุปสิ่งที่จะถูกขยายโดยการประชุมการตั้งชื่อมันเป็น IHMO ภาวะแทรกซ้อนที่ไม่จำเป็น แทนที่จะเป็น <name> + <extention> .swift ไฟล์หลาย ๆ ไฟล์ฉันเก็บนามสกุล extension.swift ไฟล์เดียวที่โดยทั่วไปฉันใช้สำหรับแต่ละโครงการ ไฟล์ภายในถูกจัดระเบียบเพื่อให้ค้นหาคลาสเฉพาะที่ขยายนั้นทำได้ง่าย
Yohst

18
คำตอบนี้ <name> + <extention> .swift เป็นวิธีที่ Xcode ทำเมื่อสร้าง subclasses NSManagedObject สำหรับ Core Data ใน Xcode 8 ตัวอย่าง: Foo + CoreDataProperties.swift
Jerry Krinock

5
เกิดอะไรขึ้นถ้าส่วนขยายใช้หลายวิธี
AlexVPerl

2
แค่อธิบายให้ได้มากที่สุด ตัวอย่างเช่นหากคุณมีส่วนขยายในรูปภาพที่มีฟังก์ชั่นที่แตกต่างกันสำหรับการใช้ตัวกรองให้ตั้งชื่อรูปภาพ + ตัวกรอง การใช้ไฟล์ที่แตกต่างกันสำหรับกลุ่มที่เกี่ยวข้องกับฟังก์ชั่นเสริม จัดกลุ่มสิ่งต่าง ๆ ที่เกี่ยวข้องด้วยกัน แต่แยกสิ่งที่ไม่เกี่ยวข้องออกจากกัน ชีวิตจะดี
picciano

หากคุณใช้แบบแผนของExtendedType+Functionality.swiftมันเป็นการดีที่จะจัดเรียงStringส่วนขยายทั้งหมดเช่นลงในโฟลเดอร์ย่อยของตนเอง (เช่นStringหรือString Extensions ) ภายใต้Extensionsโฟลเดอร์หรือไม่? หรือจะเป็นการดีกว่าที่จะเก็บไฟล์นามสกุลทั้งหมดไว้ในระดับเดียวกันภายใต้Extensionsโฟลเดอร์?
Noah Wilder

9

ไม่มีการประชุม Swift ง่าย ๆ เข้าไว้:

StringExtensions.swift

ฉันสร้างหนึ่งไฟล์สำหรับแต่ละชั้นที่ฉันขยาย หากคุณใช้ไฟล์เดียวสำหรับทุกนามสกุลมันจะกลายเป็นป่าอย่างรวดเร็ว


8
ดูเหมือนจะไม่สามารถใช้งานได้อีกครั้งโดยเฉพาะ
เคลเลอร์

1
เมื่อเทียบกับ?
Mike Taverne

3
เมื่อเทียบกับไฟล์ (หรือคู่อย่างแน่นหนา) โดยเฉพาะของส่วนขยายคลาสที่ให้บริการวัตถุประสงค์เดียว (หรือสัมพันธ์กันอย่างชัดเจน) บางอย่างเช่น "StringExtensions" ดูเหมือนว่ามันอาจมีทุกอย่างตั้งแต่การฆ่าล้างด้วย String เพื่อวัตถุประสงค์ทั่วไปไปจนถึงตรรกะเฉพาะแอปซึ่งอาจไม่ใช่วิธีที่ดีที่สุดหากการใช้ซ้ำเป็นเรื่องที่น่ากังวล ระเบียบการตั้งชื่อโกโก้โน้มตัวไปทางฟังก์ชั่นมากกว่าการนำไปใช้ ฉันยืนยันว่า "StringExtensions" บ่งชี้หลัง ฉันต้องการคำตอบที่ได้รับการยอมรับอย่างแน่นอนใน ObjC แต่ใน Swift ดูเหมือนว่าจะเป็นวิธีที่ดีกว่าเนื่องจากโมดูล
Keller

2
นั่นทำให้รู้สึก ฉันคิดถึงแอพเดียวที่ใช้ซ้ำไม่ได้เป็นเรื่องน่ากังวล ตัวอย่างเช่นสมมติว่าฉันมีฟังก์ชั่นสตริงที่ไม่เกี่ยวข้องสองสามตัวที่ฉันต้องการใช้เป็นส่วนขยาย - ฉันสามารถสร้างไฟล์หนึ่งไฟล์และวางฟังก์ชั่นเหล่านี้ทั้งหมดไว้ที่นั่นหรือสร้างหนึ่งไฟล์ต่อหนึ่งฟังก์ชัน ฉันชอบความเรียบง่ายของไฟล์เดียวในกรณีนั้น แต่เหตุผลของคุณคือเสียง ขอบคุณ
Mike Taverne

สิ่งนี้สมเหตุสมผลอย่างยิ่งหากมีสิ่งที่เพิ่มเข้ามาที่นี่จะใช้กับสตริงทั้งหมด (เช่น 'trimRight ()' เป็นตัวอย่าง) หากเป็นสิ่งที่เฉพาะเจาะจงกับการใช้งานมากขึ้น (เช่น 'formatAccountNumber ()') ไฟล์นั้นควรเป็น 'Strings + AccountFormatting.swift' และควรกำหนดขอบเขตเฉพาะที่ใช้งานจริงเพื่อไม่เกะกะ API พื้นผิว 'Strings' ที่อื่น
Mark A. Donohoe

1

ฉันชอบStringExtensions.swiftจนกว่าฉันจะเพิ่มสิ่งที่มากเกินไปที่จะแยกไฟล์ลงในสิ่งที่ต้องการและString+utf8Data.swiftString+Encrypt.swift

การรวมไฟล์ที่คล้ายกันเข้าเป็นหนึ่งเดียวจะทำให้สิ่งปลูกสร้างของคุณเร็วขึ้น อ้างถึงOptimizing-Swift-Build-Times


1
นั่นคือแบบแผนการตั้งชื่อไฟล์สองแบบสำหรับสิ่งเดียวกัน ฉันคิดว่ามันไม่ดี
ความหมาย - เรื่อง

@ ความหมาย - เรื่องมันขึ้นอยู่กับ หลักการตั้งชื่อทั้งสองนั้นเป็นที่รู้จักและแนะนำโดย Apple Documents ทำตามที่คุณต้องการ
DawnSong

ฉันหวังว่าโปรแกรมเมอร์มากขึ้นจะมุ่งมั่นเพื่อความสง่างามโดยการ จำกัด การตั้งชื่อและรหัส [รูปแบบ] รูปแบบ
ความหมาย - เรื่อง

@ ความหมาย - เรื่อง Elegance มีสองด้านมันเป็นปัญหาการโต้เถียงคลาสสิกเกี่ยวกับวิธีการเขียนวงเล็บปีกกาในภาษา C เหมือน มันไม่สำคัญดังนั้นฉันไม่คิดว่าจำเป็นต้องเลือกและทำให้จำเป็นจนกว่าคนส่วนใหญ่จะยอมรับ
DawnSong

ฉันหมายถึงความสง่างามของความมั่นคง: ใช้วิธีหนึ่งในการตั้งชื่อส่วนขยายหรือวิธีหนึ่งในการวางเครื่องมือจัดฟันแบบหยิก จากนั้นฉันคิดว่ามันมีความแตกต่างที่วัดได้ในการอ่านรูปแบบวงเล็บปีกกาแบบต่างๆ ดังนั้นฉันไม่คิดว่ามัน 'เล็กน้อย' เลย
ความหมาย - เรื่อง

0

หากคุณมีชุดการปรับปรุงทั่วไปและเบ็ดเตล็ดที่ทีมตกลงร่วมกันให้รวมเข้าด้วยกันเป็น Extensions.swift ทำงานเป็นโซลูชันระดับแรก Keep-It-Simple อย่างไรก็ตามเมื่อความซับซ้อนของคุณเพิ่มขึ้นหรือส่วนขยายมีส่วนเกี่ยวข้องมากขึ้นจำเป็นต้องมีลำดับชั้นเพื่อห่อหุ้มความซับซ้อน ในกรณีเช่นนี้ฉันขอแนะนำตัวอย่างต่อไปนี้

ฉันมีระดับที่พูดกับฉัน back-end Serverที่เรียกว่า มันเริ่มขยายใหญ่ขึ้นเพื่อให้ครอบคลุมแอพเป้าหมายสองแบบ บางคนชอบไฟล์ขนาดใหญ่ แต่แยกออกเป็นส่วนขยายด้วยเหตุผล ความชอบของฉันคือทำให้แต่ละไฟล์ค่อนข้างสั้นดังนั้นฉันจึงเลือกโซลูชันต่อไปนี้ Serverเดิมทีสอดคล้องกับCloudAdapterProtocolและดำเนินการทุกวิธี สิ่งที่ฉันทำคือเปลี่ยนโปรโตคอลให้เป็นลำดับชั้นโดยทำให้มันอ้างอิงถึงโปรโตคอลรอง:

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

ในตัวServer.swiftฉันมี

import Foundation
import UIKit
import Alamofire
import AlamofireImage

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

Server.swiftจากนั้นเพียงใช้ API เซิร์ฟเวอร์หลักเพื่อตั้งค่าเซิร์ฟเวอร์และรับรุ่น API งานจริงแบ่งออกเป็นสองไฟล์:

Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift

เหล่านี้ใช้โปรโตคอลที่เกี่ยวข้อง

หมายความว่าคุณต้องมีการนำเข้าการประกาศในไฟล์อื่น (สำหรับ Alamofire ในตัวอย่างนี้) แต่มันเป็นโซลูชันที่สะอาดในแง่ของการแยกอินเทอร์เฟซในมุมมองของฉัน

ฉันคิดว่าวิธีนี้ใช้ได้ดีกับคลาสที่ระบุจากภายนอกเช่นเดียวกับของคุณเอง


0

ทำไมถึงมีการถกเถียงกันอยู่? ฉันควรใส่คลาสย่อยทั้งหมดลงในไฟล์ชื่อ _Subclasses.swift ผมคิดว่าไม่. Swift มีการเว้นวรรคชื่อตามโมดูล ในการขยายคลาส Swift ที่เป็นที่รู้จักกันดีนั้นต้องการไฟล์ที่เฉพาะเจาะจงกับวัตถุประสงค์ของมัน ฉันอาจมีทีมขนาดใหญ่ที่สร้างไฟล์ที่เป็น UIViewExtensions.swift ซึ่งไม่ได้มีจุดประสงค์และจะสร้างความสับสนให้กับผู้พัฒนาและสามารถทำซ้ำได้ง่ายในโครงการที่ไม่ได้สร้าง แบบแผนการตั้งชื่อวัตถุประสงค์ -C ทำงานได้ดีและจนกว่า Swift จะมีการเว้นวรรคชื่อจริงมันเป็นวิธีที่ดีที่สุดที่จะไป


ในกรณีของฉันฉันคิดว่ามันเหมาะสมที่จะมีไฟล์ชื่อ UIViewExtensions.swift หากส่วนขยายที่กำหนดไว้ในไฟล์นั้นเหมาะสมสำหรับคลาส UIView ใด ๆ / ทั้งหมดเช่นเมธอด 'placeIn (UIView)' ถ้าเป็นการใช้เฉพาะ (เช่นสำหรับส่วนหนึ่งของแอพ, พูดถึงการตกแต่งมุมมองที่กำหนดเองแล้วฉันจะทำ UIView + CustomDecoration.swift จุดคือคุณต้องพิจารณาการใช้งานก่อนที่จะสร้างลักษณะทั่วไปเช่นพูดไฟล์ที่เรียกว่า 'UIViewExtensions .swift ที่ไม่แสดงจุดประสงค์ 'เมื่อวัตถุประสงค์คือส่วนขยายทั่วไปสำหรับ UIViews ทั้งหมด
Mark A. Donohoe

0

แทนที่จะเพิ่มความคิดเห็นของฉันไปทั่วสถานที่ฉันกำลังแสดงความคิดเห็นทั้งหมดที่นี่ในคำตอบเดียว

โดยส่วนตัวแล้วฉันใช้วิธีไฮบริดที่ให้ทั้งการใช้งานและความชัดเจนที่ดีในขณะที่ยังไม่เกะกะพื้นที่ผิวของ API สำหรับวัตถุที่ฉันกำลังขยาย

ตัวอย่างเช่นสิ่งใดก็ตามที่สมเหตุสมผลที่มีอยู่ในสตริงใด ๆก็จะStringExtensions.swiftเป็นเช่นนั้นtrimRight()และremoveBlankLines()และ

อย่างไรก็ตามถ้าฉันมีฟังก์ชั่นส่วนขยายเช่นformatAsAccountNumber()มันจะไม่ไปในไฟล์นั้นเพราะ 'เลขที่บัญชี' ไม่ใช่สิ่งที่จะใช้กับสตริงใด ๆ / ทั้งหมดตามธรรมชาติและมีเหตุผลในบริบทของบัญชีเท่านั้น ในกรณีนี้ฉันจะสร้างไฟล์ที่เรียกว่าStrings+AccountFormatting.swiftหรือแม้กระทั่งStrings+CustomFormatting.swiftกับformatAsAccountNumber()ฟังก์ชั่นหากมีหลายประเภท / วิธีในการจัดรูปแบบจริง

ในความเป็นจริงในตัวอย่างสุดท้ายนั้นฉันออกคำสั่งทีมอย่างแข็งขันไม่ให้ใช้ส่วนขยายแบบนั้นในตอนแรกและจะกระตุ้นให้มีบางสิ่งเช่นAccountNumberFormatter.format(String)แทนที่จะเป็นสิ่งที่ไม่ได้สัมผัสกับStringพื้นผิว API เลยเนื่องจากไม่ควร ข้อยกเว้นจะเกิดขึ้นหากคุณกำหนดส่วนขยายนั้นในไฟล์เดียวกับที่ใช้ แต่จะไม่มีชื่อไฟล์เป็นของตัวเอง


0

ฉันต้องการที่+จะขีดเส้นใต้ข้อเท็จจริงที่มีส่วนขยาย:

String+Extensions.swift

และถ้าไฟล์มีขนาดใหญ่เกินไปคุณสามารถแยกมันสำหรับแต่ละวัตถุประสงค์:

String+UTF8Data.swift

String+Encrypt.swift

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.