ขอบเขตระดับแพ็กเกจ Java มีประโยชน์หรือไม่


11

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

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

เช่นฉันอาจมีแบบจำลอง Mission และฉันต้องการเครื่องมือ Mission อื่น ๆ เท่านั้นเช่น MissionServices ของฉันเพื่อใช้วิธีการบางอย่าง อย่างไรก็ตามฉันลงเอยด้วย Missions.models และ Missions.services เป็นแพ็คเกจของฉันดังนั้น MissionModel และ MissionService จึงไม่ใช่ขอบเขตของแพ็คเกจเดียวกัน ดูเหมือนว่าจะไม่มีสถานการณ์ที่แพคเกจบรรจุสิ่งที่ฉันต้องการให้มีสิทธิ์ในการยกระดับอย่างเหมาะสมโดยไม่ต้องมีหลายสิ่งที่ฉันไม่ต้องการได้รับสิทธิ์เหล่านั้น และฉันไม่ค่อยรู้สึกถึงประโยชน์ของการกำหนดขอบเขตของวิธีการที่จะปรับเปลี่ยนสถาปัตยกรรมโปรเจคของฉันให้วางทุกอย่างในแพ็คเกจเดียวกัน บ่อยครั้งที่มุมมองหรือการผกผันของการควบคุมบางอย่างกลับกลายเป็นวิธีที่ดีกว่าสำหรับปัญหาใด ๆ ที่ฉันพิจารณาโดยย่อว่าการกำหนดขอบเขตของแพ็กเกจ

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

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


การทดสอบความคิด: โปรแกรม Java จะมีลักษณะอย่างไรหากคุณไม่มีแพ็คเกจ อาจเป็นได้ว่าคุณไม่ได้ดูหรือทำงานกับโปรแกรม Java ขนาดใหญ่
Robert Harvey

ดูรหัสสำหรับและjava.util.String java.util.Integer


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

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

คำตอบ:


2

ตลอดทั้งjava.util.*แพคเกจมีกรณีที่รหัสถูกเขียนด้วยการป้องกันระดับแพคเกจ ตัวอย่างเช่น bit of java.util.String- a constructor ใน Java 6 :

// Package private constructor which shares value array for speed.
String(int offset, int count, char value[]) {
    this.value = value;
    this.offset = offset;
    this.count = count;
}

หรือวิธี getCharsนี้:

/** Copy characters from this string into dst starting at dstBegin. 
    This method doesn't perform any range checking. */
void getChars(char dst[], int dstBegin) {
    System.arraycopy(value, offset, dst, dstBegin, count);
}

เหตุผลนี้เป็นเพราะนักออกแบบของรหัส (และjava.util.*สามารถคิดว่าเป็นห้องสมุดที่ค่อนข้างใหญ่) ต้องการความสามารถในการทำงานที่รวดเร็วขึ้นในราคาที่สูญเสียความปลอดภัยต่าง ๆ (ตรวจสอบช่วงในอาร์เรย์เข้าถึงโดยตรงไปยังสาขาอื่น ๆ ที่บ่งบอกถึงการนำไปปฏิบัติแทนที่จะเป็นส่วนต่อประสานการเข้าถึง 'ที่ไม่ปลอดภัย' ไปยังส่วนต่าง ๆ ของคลาสที่ได้รับการพิจารณาว่าไม่เปลี่ยนรูปแบบโดยวิธีสาธารณะ)

ด้วยการ จำกัด วิธีการและฟิลด์เหล่านี้เพื่อให้เข้าถึงได้โดยคลาสอื่น ๆ ในjava.utilแพ็คเกจเท่านั้นทำให้การเชื่อมต่อระหว่างกันใกล้ชิดกันยิ่งขึ้น

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

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


1
ฉันดู java.util และเห็นว่า อย่างไรก็ตามฉันก็สังเกตเห็นว่ามันเป็นห้องสมุดขนาดใหญ่ ตอนนี้ดูเหมือนว่าห้องสมุดที่มีขนาดใหญ่มักไม่ค่อยเขียนโดยไม่ใช้แพ็คเกจย่อย และเป็นส่วนย่อยของแพ็คเกจย่อยที่นำไปสู่ข้อ จำกัด ฉันไม่ได้บอกว่า java.util ผิด แต่ดูเหมือนว่าพวกเขาจะได้รับแพคเกจขนาดใหญ่เพียงเพราะพวกเขามีโปรแกรมเมอร์ที่ดีมากพวกเขาสามารถไว้วางใจที่จะทำทุกอย่างด้วยการห่อหุ้มค่อนข้าง จำกัด ภายในแพ็คเกจ ฉันรู้สึกไม่มั่นใจที่มีศักยภาพมากในการทำสิ่งที่ไม่ดีต่อนักพัฒนาโดยเฉลี่ยที่อาจใช้งานแพ็คเกจที่คล้ายกันได้
dsollen

1
@dsollen หากคุณขุดในฤดูใบไม้ผลิและไฮเบอร์เนตหรือห้องสมุดขนาดใหญ่ที่คล้ายกันคุณจะพบสิ่งที่คล้ายกัน มีหลายครั้งที่คุณต้องมีเพศสัมพันธ์อย่างใกล้ชิด หนึ่งควรมีโอกาสรหัสตรวจสอบการส่งและให้แน่ใจว่าทุกอย่างถูกต้อง หากคุณไม่ต้องการการเชื่อมต่อที่ใกล้กว่านี้หรือไม่เชื่อใจตัวแปลงสัญญาณอื่นเลยเขตข้อมูลสาธารณะหรือแพคเกจหรือเขตข้อมูลหรือวิธีการป้องกันจะไม่เหมาะสมเสมอไป อย่างไรก็ตามนั่นไม่ได้หมายความว่ามันไม่มีประโยชน์

ในระยะสั้นฉันจะถูกล่อลวงให้ทำแพ็คเกจที่ จำกัด มากขึ้นและไม่ต้องกังวลเกี่ยวกับระดับของการเพิ่มประสิทธิภาพ (ซึ่งเป็นเพียงขยะในโครงการ 95%) สำหรับความต้องการในชีวิตประจำวันของฉัน ดังนั้นคำถามที่ตามมาของฉันจะกลายเป็นขอบเขตระดับแพ็คเกจที่มีศักยภาพการเพิ่มประสิทธิภาพที่เฉพาะเจาะจงมากที่ใช้เฉพาะใน API ขนาดใหญ่ที่มีการใช้อย่างกว้างขวางหรือไม่ IE เพียงผู้ยิ่งใหญ่เท่านั้นที่ต้องการหรือต้องการที่จะผ่อนคลายการปกป้องในระดับนั้น มีเหตุผลที่โปรแกรมเมอร์ที่ดีทำงานกับ API 'มาตรฐาน' ที่มีฐานผู้ใช้ขนาดเล็กกว่าหรือไม่?
dsollen

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

2
@dsollen ไม่ได้เกี่ยวกับประสิทธิภาพ (แม้ว่าจะเป็นเหตุผลหนึ่งที่ทำให้มีการใช้งาน) แต่เป็น encapsulation คุณทำเพื่อหลีกเลี่ยงการทำซ้ำรหัสInteger.toString()และString.valueOf(int)สามารถแบ่งปันรหัสโดยไม่เปิดเผยให้โลกเห็น java.utilชั้นเรียนกับการทำงานในคอนเสิร์ตเพื่อให้มีขนาดใหญ่ทั้งของการทำงานมากกว่าการเรียนของแต่ละบุคคลที่มีเกาะแก่ตนเองอย่างสิ้นเชิง - พวกเขาอยู่ด้วยกันในแพคเกจและส่วนแบ่งการทำงานการดำเนินงานที่ผ่านการกำหนดขอบเขตระดับแพ็กเกจ

5

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

เนื่องจากการทดสอบ junit มีแพ็คเกจเดียวกับ item-under-test จึงสามารถเข้าถึงรายละเอียดการใช้งานเหล่านี้ได้

ตัวอย่าง

  public class MyClass {
    public MyClass() {
        this(new MyDependency());
    }

    /* package level to allow junit-tests to insert mock/fake implementations */ 
    MyClass(IDependency someDepenency) {...}
  }

มันเป็นที่ถกเถียงกันอยู่ว่านี่เป็นการใช้ "ดี" หรือไม่ แต่มันก็เป็นประโยชน์


2
ผมมักจะใส่ในแพคเกจการทดสอบที่แตกต่างกันมิฉะนั้นผมพบว่าผมออกจากวิธีการที่สำคัญบางอย่างอยู่ในขอบเขตเริ่มต้นซึ่งไม่อนุญาตให้คนอื่นจะเรียกมันว่า ...
Soru

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

ยกระดับprotectedขอบเขตของแพคเกจทำไม? protected มีการเข้าถึงแพคเกจแล้ว มันเป็นเรื่องแปลก ๆ แต่ฉันคิดว่าพวกเขาไม่ต้องการการประกาศขอบเขตแบบผสมเช่นprotected packagescope void doSomething()(ซึ่งต้องใช้คำหลักใหม่ด้วย)
tgm1024 - โมนิก้าถูกทำร้าย

2

ไม่ใช่ทุกอย่างที่มีประโยชน์โดยเฉพาะอย่างยิ่งเป็นค่าเริ่มต้นในโลกที่ผู้คนมักจะใช้ชื่อของแพคเกจประราวกับว่าพวกเขาเป็นแพคเกจย่อย เนื่องจาก Java ไม่มีสิ่งใดเป็นแพคเกจย่อยดังนั้น xyinternals จึงไม่สามารถเข้าถึง xy ได้มากกว่าชื่อ ab Package ชื่อจะเหมือนหรือต่างกันดังนั้นการจับคู่บางส่วนจึงไม่แตกต่างจากการไม่มีอะไรเหมือนกัน

ฉันเดาว่านักพัฒนาดั้งเดิมไม่เคยคาดหวังว่าจะมีการใช้การประชุมและต้องการให้สิ่งต่าง ๆ เรียบง่ายโดยไม่ต้องเพิ่มความซับซ้อนของแพ็คเกจแบบลำดับชั้นแบบ Ada

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

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


ฉันพบว่า Java 9 ความคิดเห็นที่น่าสนใจ ฉันคิดว่าความสามารถในการรับรู้แพคเกจ herachies และกำหนดขอบเขตแพคเกจอย่างใดอย่างหนึ่งเมื่อเทียบกับแพคเกจผู้ปกครองบางส่วน (ใช้คำอธิบายประกอบ?) จะดี
dsollen

1
@dsollen บางที แต่ความชอบครั้งแรกของฉันคือการที่เราจะเริ่มต้นด้วยแผ่นยางที่ทำด้วยทองคำ ขั้นตอนแรกที่ดีกว่าเพื่อความชัดเจน (ซึ่งนำมาซึ่งความปลอดภัยในระดับหนึ่ง) ในความคิดของฉันก็คือการประดิษฐ์คำหลักขอบเขตแพคเกจจริง อาจเป็น "แพ็คเกจ" :)
tgm1024 - โมนิก้าถูกทำร้าย

2

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

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

**MissionManager.jar** - an application which uses the Java Service Provider Interface to load some implementation of missions, possible provided by a 3rd party vendor.

**missions-api.jar** - All interfaces, for services and model
    com...missions
        MissionBuilder.java   - has a createMission method
        Mission.java - interface for a mission domain object
    com...missions.strategy
        ... interfaces that attach strategies to missions ...
    com...missions.reports
        .... interfaces todo with mission reports ....

   **MCo-missionizer-5000.jar** -  provides MCo's Missionizer 5000 brand mission implementation.
       com...missions.mco
                  Mission5000.java - implements the Mission interface.
       com...missions.strategy.mco
              ... strategy stuff etc ...

โดยใช้ระดับแพ็คเกจใน Mission5000.java คุณสามารถมั่นใจได้ว่าไม่มีแพ็คเกจอื่นหรือส่วนประกอบเช่น MissionManager สามารถจับคู่กับภารกิจที่ไม่เหมาะสม นั่นเป็นเพียง "บุคคลที่สาม" ที่ให้ส่วนประกอบจาก "M co" จริง ๆ แล้วมีการใช้ตราสินค้าพิเศษของภารกิจ Mission Manager ต้องเรียกใช้ MissionBuiler.createMission (... ) และใช้อินเตอร์เฟสที่กำหนดไว้

ด้วยวิธีนี้หากองค์ประกอบการดำเนินการตามภารกิจถูกแทนที่เรารู้ว่าผู้ดำเนินการของ MissionManager.jar ไม่ได้หลีกเลี่ยง api และใช้การดำเนินการของ MCo โดยตรง

ดังนั้นเราสามารถแลกเปลี่ยน MCo-Missionizer5000.jar กับผลิตภัณฑ์คู่แข่ง (หรืออาจเป็นแบบจำลองสำหรับการทดสอบหน่วยภารกิจผู้จัดการ)

ในทางกลับกัน MCo สามารถทำการ hidding ความลับทางการค้าที่เป็นกรรมสิทธิ์ของผู้ฝึกสอนได้

(สิ่งนี้เกี่ยวข้องกับการบังคับใช้แนวคิดความไม่แน่นอนและความเป็นนามธรรมในองค์ประกอบเช่นกัน)


-1

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

แต่เราใช้กฎการเข้าถึงของเราเองตามลำดับชั้นของแพ็คเกจและชื่อแพ็คเกจที่กำหนดไว้ล่วงหน้า

หากคุณสนใจในรายละเอียด google สำหรับ "CODERU-Rules"

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