ปัญหาเกี่ยวกับการหลีกเลี่ยงการเรียนการตั้งชื่อ Smurf กับ namespaces


39

ฉันดึงคำว่า smurf ตั้งชื่อจากที่นี่ (หมายเลข 21) ในการบันทึกทุกคนที่ไม่คุ้นเคยปัญหาที่ Smurf การตั้งชื่อคือการกระทำของ prefixing พวงของการเรียนที่เกี่ยวข้องกับตัวแปรอื่น ๆ ที่มีคำนำหน้าร่วมกันเพื่อให้คุณจบลงด้วยการที่ " SmurfAccountViewผ่านSmurfAccountDTOไปSmurfAccountController" ฯลฯ

วิธีแก้ปัญหาที่ฉันเคยได้ยินโดยทั่วไปคือการสร้าง smurf namespace และวางคำนำหน้า smurf โดยทั่วไปฉันใช้งานได้ดี แต่ฉันพบปัญหาสองอย่าง

  1. ฉันทำงานกับห้องสมุดที่มีConfigurationชั้นเรียน มันอาจจะได้รับการเรียกWartmongerConfigurationแต่ก็ใน namespace Wartmonger Configurationจึงเรียกว่าเพียงแค่ ฉันก็มีConfigurationคลาสที่สามารถเรียกSmurfConfigurationได้ แต่มันอยู่ในเนมสเปซ Smurf เพื่อที่จะซ้ำซ้อน มีสถานที่ในรหัสของฉันที่Smurf.Configurationปรากฏอยู่ด้านข้างWartmonger.Configurationและพิมพ์ชื่อที่ผ่านการรับรองครบถ้วนแล้วเป็น clunky และทำให้โค้ดอ่านน้อยลง มันจะดีกว่าที่จะจัดการกับSmurfConfigurationและ WartmongerConfiguration(ถ้ามันเป็นรหัสและไม่ห้องสมุดของฉัน)

  2. ฉันมีคลาสที่เรียกว่าServiceในเนมสเปซ Smurf ซึ่งอาจเรียกได้ว่าSmurfServiceเป็น Serviceเป็นส่วนหน้าของห้องสมุด Smurf ที่ซับซ้อนซึ่งดำเนินงาน Smurf SmurfServiceดูเหมือนชื่อที่ดีกว่าเพราะServiceไม่มีคำนำหน้า Smurf เป็นเรื่องธรรมดาอย่างไม่น่าเชื่อ ฉันยอมรับได้ว่าSmurfServiceชื่อสามัญไร้ประโยชน์อยู่แล้วและการกำจัด smurf ทำให้สิ่งนี้ชัดเจนยิ่งขึ้น แต่มันจะได้รับการตั้งชื่อRunner, Launcherฯลฯ และมันจะยังคงเป็น "รู้สึกดี" ให้ฉันเป็นSmurfLauncherเพราะผมไม่ได้รู้ว่าสิ่งที่Launcherไม่ แต่ฉันรู้ว่าสิ่งที่SmurfLauncherทำ คุณสามารถยืนยันว่าสิ่งที่Smurf.Launcherควรจะชัดเจนพอ ๆ กับSmurf.SmurfLauncherแต่ฉันเห็น `Smurf.Launcher เป็นคลาสที่เกี่ยวข้องกับการตั้งค่ามากกว่าคลาสที่เปิดตัวสเมิร์ฟ

หากมีวิธีการเปิดและปิดเพื่อจัดการกับทั้งสองอย่างนี้จะดี ถ้าไม่เป็นเช่นนั้นมีวิธีปฏิบัติทั่วไปอะไรบ้างที่จะลดความน่ารำคาญของพวกเขา?


3
ไม่Smurf.Launcherสเมิร์ฟเปิดตัวหรือไม่ก็เปิดSmurfJobหรือไม่? บางทีมันอาจจะถูกเรียกว่าSmurf.JobLauncher?
Blorgbeard

2
มันเป็นรหัสกลิ่นเพื่อตั้งชื่อคลาส XService, XManager และอื่น ๆ สิ่งเหล่านี้ไม่ได้มีความหมายอะไรเลย มันเหมือน Util หากคุณกำลังอ่านชื่อไฟล์อะไรก็ตามที่อยู่ในนั้นหรือหายไป ไม่มีทางรู้ถ้าคุณมองเข้าไปข้างใน ฉันเปลี่ยนชื่อจาก SmurfService เป็นอย่างอื่นอย่างสมบูรณ์
Daniel Kaplan

1
มันเปิดตัวจริงSmurfJobหรือเรียกใช้พวกเขาทางเทคนิคเพื่อให้สอดคล้องกับภาษาของเอกสาร Smurf ในแง่ของการที่และคำตอบอื่น ๆ ฉันจะเปลี่ยนชื่อไปSmurfService SmurfJobRunnerดูเหมือนว่าหมายเลข 1 ไม่มีความละเอียดภาษาที่ดีที่สุดที่ฉันคาดหวัง ฉันสามารถดูกรณีที่จะมีSmurfConfigurationจะมีการโทรที่ถูกต้อง แต่ในกรณีของฉันฉันคิดว่าดีที่สุดคือแม้จะมีความยุ่งยากของConfiguration Wartmonger.Configuration
Daniel Koverman

6
ฉันพยายามที่จะเข้าใจว่าทำไมคุณถึงมีคลาสเดียวที่ใส่ใจเกี่ยวกับการกำหนดค่าทั้ง Wartmongers และ Smurfs เลย
Donal Fellows

ทำไมSmurf.ConfigurationและSmurfConfigurationรู้สึกแตกต่าง แน่นอนมันไม่ใช่ตัวละครพิเศษใช่ไหม? (ย่อให้สั้นลงConfigหากความยาวเป็นปัญหา) Smurf.Configurationมีปัญหาใด ๆ ที่SmurfConfigurationไม่มีหรือไม่
Pablo H

คำตอบ:


16

คุณยกระดับคะแนนที่ดี

  1. เมื่อพิจารณาถึงการมีคลาสที่ซ้ำกันคุณสามารถนามแฝงคลาสใน C # ใช้ตัวอย่างเช่นusing ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;ดูโพสต์นี้ใน StackOverflow คุณไม่ได้ระบุภาษาการเขียนโปรแกรมของคุณ แต่ฉันได้อนุมานจากสิ่งที่คุณเขียน เพื่อที่คุณจัดการกับสองโครงการที่แตกต่างกันคุณสามารถนามแฝงพวกเขาเป็นSmurfConfigurationและWartmongerConfigurationซึ่งจะปลดปล่อยความคลุมเครือเมื่อบริโภคทั้งในชั้นเรียน

  2. เนื่องจากบริการเปิดรับแอปพลิเคชันภายนอกฉันไม่เห็นปัญหาในการสร้างแบรนด์บริการด้วยชื่อแอปพลิเคชันของคุณดังนั้นในกรณีนี้SmurfServiceจะใช้ได้เนื่องจากจะทำให้กลุ่มบริการในแอปพลิเคชันใช้งานไม่ได้

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


5
นามแฝงทำให้ยุ่งเหยิง แทน Smurf.Service ตอนนี้คุณมี SmurfService = Smurf.Service ดังนั้นคุณอาจจะเคยมี SmurfService เป็นชื่อของสิ่งแรก พวกเขามีสถานที่ แต่ไม่ใช่สำหรับปัญหาเฉพาะนี้ แต่อาจจะเป็นคำตอบที่ดีที่สุดในการแก้ไขปัญหาที่ไม่มีคำตอบ :)
gbjbaanb

ได้โดยง่าย C # ในตัวผมออกมาในคำถามของฉัน แต่ฉันจริงในปัจจุบันการจัดการกับ Java org.apache.smurfville.wartmonger.configurationและ โชคไม่ดีที่นี่ไม่อนุญาตให้ใช้นามแฝง 2 เป็นจุดแข็งดังนั้นฉันจะรักษาแบรนด์ของ Smurf ไว้สำหรับการให้บริการ
Daniel Koverman

25

จุดของเนมสเปซคือเพื่อให้คุณสามารถมีคลาสที่มีชื่อเดียวกันจากไลบรารีที่แตกต่างกันโดยไม่มีการชนกัน เมื่อคุณต้องการใช้คลาสที่มีชื่อเดียวกันจากทั้งสองคุณจำเป็นต้องลบความกำกวมโดยนำหน้าหนึ่งหรือทั้งสองด้วยขอบเขตเนมสเปซ

ที่กล่าวมามันไม่เลวเลยที่มีคลาส Smurf มากมายหาก Smurf บอกบางอย่างเกี่ยวกับชั้นเรียน ชื่อคลาสควรเป็นคำอธิบายที่เพียงพอที่จะให้ข้อมูลเกี่ยวกับสิ่งที่คลาสทำ

      Session
       ^   ^
      /     \
DBSession   HttpSession

ในทำนองเดียวกันDBSessionอาจใช้DBRequestวัตถุที่ส่งกลับDBResponseวัตถุ HttpSessionอาจยังทำงานบนHttpRequestและHttpResponseวัตถุ

เหล่านี้เป็นชั้นเรียน Smurf โดยมีวัตถุประสงค์

พวกเขาอาจอาศัยอยู่ในMyCompanyเนมสเปซ แต่MyCompanyHttpSessionและMyCompanyDBSessionไม่ให้ข้อมูลใด ๆ กับคุณมากกว่าที่เคยมีมา ในกรณีนี้ให้วาง Smurf และทำให้เป็น namespace

MyCompany.HttpSession

3

ฉันเคยเจอกับความสับสนแบบเดียวกันนี้มาก่อนและมันมักจะเป็นคำถามที่ว่าเรารวมถึงสิ่งที่มันเป็นส่วนหนึ่งของชื่อ

คุณพูดถึงSmurfConfigurationและWartmongerConfigurationกำหนดค่าประเภทที่มีศักยภาพ คุณแสดงให้เห็นว่าคุณเอาคำคุณศัพท์ (ชนิด) เพื่อ namespace Configurationเพื่อให้สิ่งที่คุณกำลังเหลือเป็นเพียงวานิลลา ฉันจะหลีกเลี่ยงการทำเช่นนั้น

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

ลองจินตนาการว่าในแอปคุณนำเข้าStrawberry.IceCreamชั้นเรียนและจากนั้นเริ่ม instantiating IceCreamโดยตรงจาก

var ic = new IceCream(); //actually I'm strawberry ice cream

สิ่งนี้อาจดูดีและดีจนกระทั่งถึงเวลาที่คุณจะจบการนำเข้าIceCreamคลาสอื่น ตอนนี้คุณกลับไปที่ปัญหาดั้งเดิมที่ต้องแยกความแตกต่างระหว่างพวกเขาซึ่งเป็นปัญหา สิ่งที่คุณต้องการตลอดคือ:

var sic = new StrawberryIceCream();
var cic = new ChocolateIceCream();

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


2

เป็นกฎง่ายๆที่ดีว่าถ้าคุณมีคำนำหน้าร่วมกันในชั้นเรียนจำนวนมากพวกเขาอาจสมควรไปที่เนมสเปซของตัวเอง เพื่อจัดการกับปัญหาเมื่อคุณต้องการใช้คลาสที่มีชื่อคล้ายกันจากสองเนมสเปซ:

1) นามแฝงของนามแฝงแม้ว่าฉันจะทำให้มันสั้นและตรงประเด็น, ตัวย่อตามธรรมชาติใด ๆ , แม้อาจจะเป็นเพียง 1 ตัวอักษร:

using Sm = Smurf;
using W = Wartmonger;

จากนั้นนำหน้าคำนำหน้าทุกที่ที่ใช้และอินสแตนซ์ชื่ออย่างเหมาะสม:

Sm::Configuration smConf; 
W::Configuration wConf;

2) นามแฝงของชั้นเรียนตามคำแนะนำในคำตอบอื่น ๆ

using SmConf = Smurf.Configuration;

3) ห้องสมุดใด ๆ ที่คุณสามารถควบคุมได้โปรดอย่าใช้คำว่า 'การกำหนดค่า' ใช้อรรถาภิธาน: เช่น 'การตั้งค่า', 'แบบจำลอง', 'พารามิเตอร์' อาจมีความหมายต่อบริบทมากขึ้นเช่น: หาก Smurf เป็นโมดูลการวิเคราะห์เชิงตัวเลขบางประเภทที่คุณเขียนไว้บางที 'พารามิเตอร์' อาจจะดีกว่าสำหรับการกำหนดค่า ใช้คำศัพท์เฉพาะที่เกี่ยวข้องกับบริบทของโมดูลเพื่อประโยชน์ของคุณเพื่อหาชื่อที่ไม่ซ้ำใครที่มีความเป็นเอกลักษณ์แม้จะผสมกับชื่ออื่น ฉันรู้สึกว่านี่อาจเป็นคำตอบสำหรับคำถาม OP 2

4) รหัส Refactor เพื่อให้คุณไม่ต้องผสมการใช้การกำหนดค่าจากสองที่ต่างกัน รายละเอียดนั้นขึ้นอยู่กับคุณ

5) รวมการกำหนดค่าทั้งสองเป็นหนึ่งก่อนที่คุณจะผ่านเข้าไปในชั้นเรียน ใช้คลาส conf ที่รวมกันเพื่อเป็นตัวแทน:

struct Conf {
    SmurfConfiguration smurf;
    WartmongerConfiguation wart;
}

ชื่อตัวแปรสมาชิกแบบสั้นตอนนี้ประสบความสำเร็จเช่นเดียวกับนามแฝงคลาส / เนมสเปซ


0

ดูเหมือนว่าแปลกที่เพิ่มจุดหนึ่งไปยังชื่อรบกวนคุณ

Wartmonger.Configuration configuration = Wartmonger.Configuration .new();

// vs

WartmongerConfiguration configuration = WartmongerConfiguration.new();

หากทั้งสองSmurfและWartmongerการกำหนดค่าใช้ร่วมกันในที่เดียว แต่แยกกันพวกเขาจะใช้ในหลายสถานที่ - แล้ว namespace เป็นวิธีที่ดีอย่างแน่นอน

มี namespace จะให้ความเป็นไปได้ที่จะใช้ชื่อ "สะอาด" ในรหัสภายในที่มีคำนำหน้าคุณท้ายใช้SmurfConfigurationภายในSmurfService's รหัสภายในซึ่งสามารถกลายเป็นน่ารำคาญทุกครั้งที่คุณจะเปิดรหัสที่

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