การตั้งชื่อส่วนต่อประสานใน Java [ปิด]


324

ภาษา OO ส่วนใหญ่นำหน้าชื่ออินเตอร์เฟสด้วยตัวพิมพ์ใหญ่ I ทำไม Java ไม่ทำเช่นนี้? อะไรคือเหตุผลที่ไม่ปฏิบัติตามอนุสัญญานี้

เพื่อแสดงให้เห็นถึงสิ่งที่ฉันหมายถึงถ้าฉันต้องการที่จะมีส่วนติดต่อผู้ใช้และการใช้งานของผู้ใช้ฉันมีสองตัวเลือกใน Java:

  1. Class = ผู้ใช้ส่วนต่อประสาน = UserInterface
  2. Class = UserImpl, Interface = ผู้ใช้

ที่ไหนในภาษาส่วนใหญ่:

Class = ผู้ใช้ส่วนต่อประสาน = IUser

ตอนนี้คุณอาจยืนยันว่าคุณสามารถเลือกชื่อที่สื่อความหมายได้มากที่สุดสำหรับการใช้งานของผู้ใช้และปัญหาจะหายไป แต่ Java ของการผลักดันวิธี POJO กับสิ่งต่าง ๆ และคอนเทนเนอร์ IOC ส่วนใหญ่ใช้ DynamicProxies อย่างกว้างขวาง สองสิ่งเหล่านี้เข้าด้วยกันหมายความว่าคุณจะมีอินเทอร์เฟซมากมายกับการใช้งาน POJO เดียว

ดังนั้นฉันเดาว่าคำถามของฉันจะลดลงไปที่: "มันคุ้มค่าหรือไม่ที่จะต้องปฏิบัติตามระเบียบการตั้งชื่อส่วนต่อประสานที่กว้างขึ้นโดยเฉพาะอย่างยิ่งในที่ที่ Java Frameworks ดูเหมือนจะมุ่งหน้าไปหรือไม่?"


61
"ที่ไหนในภาษาส่วนใหญ่"? ภาษาใดบ้างที่นอกเหนือจาก. net
wds

2
ชุมชนภาษาที่แตกต่างกันมีการตั้งชื่อที่แตกต่างกันและสิ่งนี้เป็นจริงมาเป็นเวลานานนาน การค้นหาว่าอนุสัญญาการตั้งชื่อเกิดขึ้นได้อย่างไรในบางครั้งการวิจัยชาวบ้านเป็นหลัก
David Thornley

4
Eclipse เป็นค่าเริ่มต้นที่สำคัญที่ใช้ Java ด้วยการตั้งชื่อสไตล์ IFoo wiki.eclipse.org/Naming_Conventions
David Leonard

2
ถ้าคุณดูที่ชื่อของการเชื่อมต่อใน Android SDK (Java เช่นกัน) คุณจะเห็นว่าพวกเขาใช้ในการประชุมของการมีคำว่าอินเตอร์เฟซบนจุดสิ้นสุดของชื่ออินเตอร์เฟซเช่นNetworkInterface, DialogInterfaceฯลฯ
sandalone

21
คำถามนี้จะเป็นอย่างไร "ปิดไม่สร้างสรรค์" เมื่อเป็นที่นิยมและเป็นที่สนใจของผู้คนมากมาย?
inor

คำตอบ:


329

ฉันไม่ต้องการใช้คำนำหน้าบนอินเตอร์เฟส:

  • คำนำหน้าเจ็บอ่านง่าย

  • การใช้อินเตอร์เฟสในไคลเอนต์เป็นวิธีที่ดีที่สุดในการเขียนโปรแกรมดังนั้นชื่ออินเตอร์เฟสควรสั้นและน่าใช้มากที่สุด การใช้งานคลาสควรเป็นสิ่งที่ไม่ดีเพื่อลดการใช้งาน

  • เมื่อเปลี่ยนจากคลาสนามธรรมเป็นอินเตอร์เฟสการเขียนโค้ดด้วยคำนำหน้าฉันหมายถึงการเปลี่ยนชื่อการเกิดขึ้นทั้งหมดของคลาส --- ไม่ดี!


12
เห็นด้วยอย่างสิ้นเชิง. อีกหนึ่งปุ่มเพื่อพิมพ์หากคุณใช้การเติมข้อความอัตโนมัติ ไฟล์มากมายที่เริ่มต้นด้วย I.
Kalecser

85
IDE ที่เหมาะสมจะทำให้การเปลี่ยนรหัสในแบบที่คุณอธิบายง่าย นอกจากนี้เมื่อเปลี่ยนจากคลาสนามธรรมเป็นอินเทอร์เฟซฉันค่อนข้างแน่ใจว่าลูกค้าของคุณจะต้องคอมไพล์ใหม่
Allain Lalonde

63
สุดสายที่นี่ แต่: มันไม่สำคัญเลยถ้า IDE ทำให้การเปลี่ยนชื่อของสิ่งที่ง่าย โค้ดที่ใช้อินสแตนซ์ของบางประเภทไม่ควรสนใจหากเป็นประเภทอินเตอร์เฟสหรือคลาสหรืออะไรก็ตาม เช่นนี้การเปิดเผยรายละเอียดดังกล่าวในชื่อประเภทนั้นไม่มีจุดหมายและเป็นอันตรายต่อความเข้าใจ ประเภทและสัญญาที่เปิดเผยนั้นเป็นเรื่องสำคัญ!
ColinD

11
นอกจากนี้หากคุณกำลังไปตามเส้นทางของ IFoo ไม่ควรเป็น CFoo สำหรับการนำไปใช้และแน่นอนว่าล้มเหลว
Robin

57
"คำนำหน้าเจ็บอ่านง่าย" เป็นเรื่องส่วนตัว เช่นเดียวกับอนุสัญญาการตั้งชื่อส่วนใหญ่ มันมีความสำคัญมากกว่าที่ทีมของคุณตกลงในข้อตกลงเกี่ยวกับสิ่งที่ต้องทำเพื่อให้รหัสฐานสอดคล้องกัน
dreadwail

121

มีความแตกต่างระหว่างจริง ๆ :

class User implements IUser

และ

class UserImpl implements User

ถ้าเรากำลังพูดถึงการตั้งชื่ออนุสัญญา?

โดยส่วนตัวแล้วฉันไม่ต้องการนำหน้าอินเทอร์เฟซด้วยIเพราะฉันต้องการเข้ารหัสให้อินเทอร์เฟซและฉันคิดว่ามันสำคัญกว่าในแง่ของการตั้งชื่อ ถ้าคุณโทรหาอินเตอร์เฟสIUserIUserแล้วผู้บริโภคที่ตอบสนองความต้องการทุกระดับที่จะรู้ว่ามัน ถ้าคุณเรียกชั้นเรียนUserImplแล้วเท่านั้นระดับและภาชนะ DI ของคุณรู้เกี่ยวกับการมีส่วนร่วมและผู้บริโภคเพียงแค่รู้ว่าพวกเขากำลังทำงานร่วมกับImplUser

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

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO

ฉันคิดว่าคุณต้องการทราบ DAO ของมันเนื่องจากอธิบายการทำงานทั่วไปโดยไม่จำเป็นต้องเปิดชั้นเรียน ถ้าฉันดูไฟล์คลาสในโครงการมันง่ายที่จะดู DAO ทั้งหมดโดยค้นหา * DAO
Patrick

6
DAO เป็นรูปแบบที่รู้จักกันดีสำหรับการเข้าถึงฐานข้อมูลดังนั้นการมีรูปแบบในชื่อทำให้ง่ายต่อการทราบว่าคลาสทำได้เพียงแค่ดูที่ชื่อ PS มันจะดีกว่าที่จะปฏิบัติตามสัญกรณ์อูฐอย่างเคร่งครัด ( "AccountDao") เช่นในmina.apache.org/changes-between-2x-and-1x.html
Esko Luontola

4
เครื่องหมาย @ มันไม่เหมือนกับการให้ฉันระบุอินเทอร์เฟซ DAO บอกคุณว่าคลาสหรืออินเทอร์เฟซเป็นวัตถุสำหรับการเข้าถึงข้อมูลบัญชีซึ่งเป็นสิ่งที่วัตถุทำ มีฉันบอกคุณมีอินเตอร์เฟซของตนซึ่งมีอะไรจะทำอย่างไรกับวัตถุเอง แต่ความหมายของภาษา
tddmonkey

ในขณะที่คุณนำเสนอคำนำหน้าของมันจะต่อท้ายคำต่อท้าย
Andrei Rînea

3
@Andrei: ไม่มันเป็นความหมาย ("DAO") กับการตกแต่งที่ไม่จำเป็นของภาษาสิ่งประดิษฐ์ ("ฉัน" ในอินเทอร์เฟซความจริงซึ่งกล่าวถึงในรหัสต่อไป "อินเทอร์เฟซ IFoo ... ")
Dirk

75

อาจมีหลายสาเหตุที่ Java ไม่ได้ใช้ IUser Convention

  1. ส่วนหนึ่งของวิธีการเชิงวัตถุคือคุณไม่ควรรู้ว่าลูกค้ากำลังใช้อินเทอร์เฟซหรือคลาสการใช้งานหรือไม่ ดังนั้นแม้แต่ List คืออินเตอร์เฟสและ String เป็นคลาสจริงวิธีอาจถูกส่งผ่านทั้งสองวิธี - มันไม่สมเหตุสมผลที่จะแยกความแตกต่างระหว่างอินเตอร์เฟส

  2. โดยทั่วไปแล้วเราจะชอบการใช้งานอินเทอร์เฟซในรหัสลูกค้า (เช่น List to ArrayList เป็นต้น) ดังนั้นจึงไม่มีเหตุผลที่จะทำให้ส่วนต่อประสานนั้นโดดเด่นเป็นข้อยกเว้น

  3. ระเบียบการตั้งชื่อ Java ชอบชื่อที่ยาวกว่าซึ่งมีความหมายตามจริงต่อคำนำหน้าสไตล์ฮังการี ดังนั้นรหัสนั้นจะสามารถอ่านได้มากที่สุด: รายการแสดงถึงรายการและผู้ใช้แทนผู้ใช้ - ไม่ใช่ IUser


72

นอกจากนี้ยังมีการประชุมอื่นที่ใช้โดยโครงการโอเพ่นซอร์สมากมายรวมถึง Spring

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

โดยส่วนตัวฉันไม่ชอบคำนำหน้า "ฉัน" ด้วยเหตุผลง่ายๆว่าเป็นตัวเลือกในการประชุม ดังนั้นถ้าฉันใช้ IIOPConnection หมายความว่าอินเตอร์เฟสสำหรับ IOPConnection จะเกิดอะไรขึ้นถ้าคลาสไม่มีคำนำหน้า "ฉัน" ฉันจะรู้ได้อย่างไรว่ามันไม่ใช่อินเทอร์เฟซ .. คำตอบที่นี่คือไม่เพราะการประชุมไม่ได้ปฏิบัติตามเสมอไปและการรักษาพวกเขาจะสร้างงานเพิ่มเติม


ฉันชอบสิ่งนี้เนื่องจากมันยังช่วยให้คุณอยู่ในโหมดการใช้อินเทอร์เฟซสำหรับการพึ่งพาจากภายนอกแทนที่จะเชื่อมโยงคลาสต่างๆ
Matt Briggs

47

ดังที่ผู้โพสต์คนอื่นกล่าวว่าโดยทั่วไปแล้วมันจะดีกว่าที่จะมีอินเตอร์เฟสที่กำหนดความสามารถที่ไม่ใช่ประเภท ฉันมักจะไม่ "ใช้" บางอย่างเช่น "ผู้ใช้" และนี่คือเหตุผลที่ "IUser" มักไม่จำเป็นจริงๆในวิธีที่อธิบายไว้ที่นี่ ฉันมักจะเห็นคลาสเป็นคำนามและอินเทอร์เฟซเป็นคำคุณศัพท์:

class Number implements Comparable{...}  
class MyThread implements Runnable{...}
class SessionData implements Serializable{....}

บางครั้งคำคุณศัพท์ไม่สมเหตุสมผล แต่โดยทั่วไปแล้วฉันยังคงใช้อินเทอร์เฟซสำหรับลักษณะการทำงานแบบจำลองการกระทำความสามารถคุณสมบัติ ฯลฯ ... ไม่ใช่ประเภท

นอกจากนี้หากคุณเป็นเพียงผู้ใช้เพียงคนเดียวและเรียกมันว่าผู้ใช้แล้วประเด็นของการมีอินเตอร์เฟซ IUser คืออะไร? และถ้าคุณจะมีผู้ใช้หลายประเภทที่ต้องใช้อินเทอร์เฟซทั่วไปสิ่งที่ต่อท้าย "I" กับอินเทอร์เฟซช่วยให้คุณประหยัดในการเลือกชื่อของการใช้งาน?

ฉันคิดว่าตัวอย่างที่เป็นจริงมากขึ้นคือผู้ใช้บางประเภทต้องสามารถลงชื่อเข้าใช้ API เฉพาะ เราสามารถกำหนดอินเทอร์เฟซการเข้าสู่ระบบแล้วมีคลาส "ผู้ใช้" กับ SuperUser, DefaultUser, AdminUser, AdministrativeContact ฯลฯ suclasses ซึ่งบางส่วนจะหรือไม่ใช้อินเทอร์เฟซการเข้าสู่ระบบ (Loginable?) ตามความจำเป็น


ฉันคิดว่าตัวอย่างที่คุณให้ไว้เพื่อรองรับ "อินเทอร์เฟซในฐานะคำคุณศัพท์" นั้นเบ้เนื่องจากอินเตอร์เฟสเหล่านั้นมีจุดประสงค์เพื่อให้เหมือนมิกซ์อิน (หรือลักษณะ) มากขึ้น อินเทอร์เฟซนั้นดีสำหรับทั้งคำคุณศัพท์และคำนาม - แต่อาจไม่ใช่สำหรับindefinite transitive verbs 8 ^ P
Stevel

สิ่งนี้อาจมีการเปลี่ยนแปลงในปีที่ผ่านมา oracle docu อนุญาตให้ส่วนต่อประสานเป็นประเภท: [ลิงก์] docs.oracle.com/javase/tutorial/java/IandI/interfaceAsType.html
karlihnos

38

บ๊อบลีกล่าวอีกครั้งหนึ่งในการนำเสนอ:

จุดอินเทอร์เฟซคืออะไรถ้าคุณมีการนำไปใช้เพียงครั้งเดียว

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

จากนั้นจะชัดเจน: คลาสดั้งเดิมของคุณถูกเรียกว่าผู้ใช้ ส่วนต่อประสานของคุณตอนนี้เรียกว่าผู้ใช้ บางทีคุณอาจมี UserProdImpl และ UserTestImpl หากคุณออกแบบแอปพลิเคชันของคุณได้ดีทุกคลาส (ยกเว้นแอพที่สร้างอินสแตนซ์ผู้ใช้) จะไม่เปลี่ยนแปลง

เพื่อให้ชัดเจน -> การปรับใช้ User Interface UserImpl


18
การใช้ส่วนต่อประสานจะช่วยในการทดสอบการพัฒนาขับเคลื่อน เราพบปัญหามากมายเกี่ยวกับ Domain Model และการทดสอบเพราะเราตัดสินใจที่จะไม่ใช้อินเทอร์เฟซ เพื่อนของฉันเคยกล่าวไว้ว่า: "ทุกอย่างเป็นอินเทอร์เฟซมันจะช่วยคุณในระยะยาว"
hooknc

4
การเยาะเย้ยและสนับสนุนพร็อกซี่ง่าย ฉันแน่ใจว่ามีเหตุผลอื่นที่จะให้อินเทอร์เฟซเช่นกัน
MetroidFan2002

3
อย่างที่ฉันเพิ่งพูดกับเพื่อนร่วมงานมันไม่มีค่าใช้จ่ายในการแนะนำอินเทอร์เฟซในขณะนี้ แต่สามารถประหยัดเวลาได้มากในภายหลัง
tddmonkey

2
หากคุณอาจมีการใช้งานอื่น ๆ ในอนาคตอันใกล้นี้อินเตอร์เฟสจะเป็นข้อดี
Stef

3
ฉันไม่ชอบอาร์กิวเมนต์ "ฉันอาจต้องการอีกนัยหนึ่งในอนาคต" ฉันชอบแนวทางของ YAGNI: อย่าวางแผนสำหรับสิ่งที่ยังไม่เกิดขึ้น
David Lavender

24

ใน C # มันคือ

public class AdminForumUser : UserBase, IUser

Java จะพูดว่า

public class AdminForumUser extends User implements ForumUserInterface

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


22
บางทีฉันอาจจะ coder Java ไม่ดี แต่ผมชอบสไตล์ C # หมายถึงการเชื่อมต่อทั้งหมดเริ่มต้นด้วย 'ฉัน' คำนำหน้า :)
davs

7
ฉันไม่แน่ใจว่าคุณและคนอื่น ๆ จะได้รับแบบแผนนี้จากที่ไหน ไม่ชัดเจนในห้องสมุด Java ...
ChiefTwoPencils

6

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

ยกตัวอย่างเช่นในกรณีของคุณผมเพียง แต่คาดว่าจะเห็นหากผู้ใช้เท่านั้นที่คุณตั้งใจจะมีคือIUser Userหากคุณวางแผนที่จะมีผู้ใช้หลายประเภท - NoviceUser, ExpertUserและอื่น ๆ - ฉันคาดว่าจะเห็นUserอินเทอร์เฟซ (และบางทีAbstractUserคลาสที่ใช้ฟังก์ชั่นทั่วไปบางอย่างเช่นget/setName() )

ฉันยังอยากจะคาดหวังว่าอินเตอร์เฟซที่กำหนดความสามารถ - Comparable, Iterableฯลฯ - จะตั้งชื่อเช่นนั้นและไม่ชอบหรือIComparableIIterable


หากผู้ใช้คนเดียวที่คุณตั้งใจจะมีคือผู้ใช้ทำไมไม่เพียงใช้ผู้ใช้แทนส่วนต่อประสาน
Carighan

3
ในสถาปัตยกรรมไคลเอนต์ / เซิร์ฟเวอร์บางตัวฝั่งไคลเอ็นต์จำเป็นต้องรู้อินเตอร์เฟสโดยไม่จำเป็นต้องมีการใช้งานเซิร์ฟเวอร์แบบหนา
David Koelle

5

ตามหลักการของ OO ที่ดีรหัสของคุณควร (เท่าที่สามารถนำไปใช้ได้จริง / เป็นไปได้) ขึ้นอยู่กับ abstractions มากกว่าคลาสที่เป็นรูปธรรม ตัวอย่างเช่นโดยทั่วไปควรเขียนวิธีดังนี้:

public void doSomething(Collection someStuff) {
    ...
}

กว่านี้:

public void doSomething(Vector someStuff) {
    ...
}

หากคุณทำตามแนวคิดนี้ฉันจะยืนยันว่ารหัสของคุณจะสามารถอ่านได้มากขึ้นถ้าคุณตั้งชื่ออินเทอร์เฟซเช่น "ผู้ใช้" และ "BankAccount" (ตัวอย่าง) แทนที่จะเป็น "IUser", "UserInterface" หรือรูปแบบอื่น ๆ

รหัสเพียงบิตเดียวที่ควรสนใจเกี่ยวกับคลาสคอนกรีตจริงคือสถานที่ที่คลาสคอนกรีตถูกสร้างขึ้น ทุกอย่างอื่นควรเขียนโดยใช้ส่วนต่อประสาน

หากคุณทำเช่นนี้ชื่อคลาสที่ "น่าเกลียด" ที่เป็นรูปธรรมเช่น "UserImpl" ควรถูกซ่อนไว้อย่างปลอดภัยจากรหัสที่เหลือซึ่งสามารถดำเนินการต่อโดยใช้ชื่ออินเตอร์เฟส "nice"


แต่ทำไมต้องสร้างส่วนต่อประสานที่ตรงกันสำหรับทุก ๆ ชั้นในโปรแกรมของคุณเมื่อคุณต้องการเพียงส่วนต่อประสานสำหรับหนึ่งหรือสองอย่าง
LegendLength

3

= v = คำนำหน้า "ฉัน" ยังใช้ในกรอบประตูซึ่งฉันคุ้นเคยกับมันอย่างรวดเร็ว โดยทั่วไปฉันยินดีต้อนรับการประชุมใด ๆ ที่ทำให้ชื่อคลาส Java สั้นลง มันเป็นเรื่องยุ่งยากแม้ว่าทุกอย่างจะมีตัวอักษรภายใต้ "ฉัน" ในไดเรกทอรีและใน Javadoc

การเข้ารหัสแบบ Wicket คล้ายกับ Swing ในอินสแตนซ์ควบคุม / วิดเจ็ตจำนวนมากนั้นถูกสร้างเป็นคลาสภายในที่ไม่ระบุชื่อพร้อมการประกาศเมธอดแบบอินไลน์ น่ารำคาญมันแตกต่างจาก Swing ใน 180 °ใน Swing นั้นใช้คำนำหน้า ("J") สำหรับคลาสการใช้งาน

ส่วนต่อท้าย "Impl" เป็นตัวย่อที่มีความละเอียดอ่อนและไม่เป็นสากล ถ้าอย่างน้อยเราก็ไปด้วย "Imp" มันจะน่ารักกว่า (และสั้นกว่า) "Impl" ใช้สำหรับ IOC โดยเฉพาะ Spring ดังนั้นเราจึงติดอยู่กับตอนนี้ ได้รับ schizo เล็กน้อยตาม 3 อนุสัญญาที่แตกต่างกันในสามส่วนที่แตกต่างกันของ codebase หนึ่งแม้ว่า


0

นี่เป็นรูปแบบการตั้งชื่อที่กว้างขึ้นในแง่ที่แท้จริงหรือไม่? ฉันอยู่ด้าน C ++ มากกว่าและไม่ขึ้นกับ Java และผู้สืบทอด ชุมชนภาษาจำนวนเท่าใดที่ใช้การประชุม I

หากคุณมีแบบแผนการตั้งชื่อมาตรฐานของร้านที่ไม่ขึ้นอยู่กับภาษาที่นี่ให้ใช้ ถ้าไม่ใช่ให้ไปที่แผนการตั้งชื่อภาษา

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