มีแนวทางปฏิบัติที่ดีที่สุดสำหรับองค์กรแพ็คเกจ (Java) หรือไม่ [ปิด]


201

เมื่อไม่นานมานี้ฉันเห็นคำถามตอบที่นี่เกี่ยวกับองค์กร Java package ตัวอย่างเช่นmy.project.util, my.project.factory, my.project.serviceฯลฯ

ฉันหามันไม่พบในตอนนี้ดังนั้นฉันอาจถามคำถามเช่นกัน

มีแนวทางปฏิบัติที่ดีที่สุดเกี่ยวกับองค์กรของแพคเกจใน Java และสิ่งที่เกิดขึ้นในพวกเขา?

คุณจะจัดการชั้นเรียนของคุณในโครงการ Java ของคุณได้อย่างไร

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

ความคิดและความคิดเห็นของคุณได้รับการชื่นชม


74
ฉันไม่เห็นด้วยกับการปิดคำถามนี้ ฉันไม่เห็นด้วยว่าคำถามฝึกที่ดีที่สุดนั้นมักจะอิงจากประสบการณ์และความคิดเห็นเสมออย่างไรก็ตามฉันไม่เห็นด้วยกับคำถามเหล่านี้ที่ควรจะปิดใน Stack Overflow นี่คือการเขียนโปรแกรมที่ดีโดยใช้แนวปฏิบัติที่ดีที่สุดและการหาทางออกที่ดีที่สุดใช้ความคิดเห็นและประสบการณ์เหล่านี้ โปรดเปิดคำถามนี้อีกครั้ง
Cyntech

ผมขอแนะนำให้คุณอ่านบทความนี้: satisfice.com/blog/archives/5164 TL; DR ... แนวคิดทั้งหมดของ "แนวปฏิบัติที่ดีที่สุด" ใช้งานไม่ได้ ที่ดีที่สุดมันเป็นชื่อเรียกผิดมหันต์ที่เลวร้ายที่สุดมันเป็นอันตรายอย่างจริงจัง
สตีเฟ่นซี

คำตอบ:


174

การจัดระเบียบแพ็คเกจหรือการจัดโครงสร้างแพ็คเกจมักเป็นการสนทนาที่ร้อนแรง ต่อไปนี้เป็นคำแนะนำง่ายๆสำหรับการตั้งชื่อและการจัดทำแพคเกจ:

  • ปฏิบัติตามข้อกำหนดการตั้งชื่อแพ็กเกจ java
  • จัดโครงสร้างแพคเกจของคุณตามหน้าที่การทำงานรวมถึงบทบาททางธุรกิจ
    • แยกแพคเกจของคุณตามหน้าที่หรือโมดูลของพวกเขา เช่น com.company.product.modulea
    • การแยกย่อยเพิ่มเติมอาจขึ้นอยู่กับเลเยอร์ในซอฟต์แวร์ของคุณ แต่อย่าลงน้ำมากเกินไปถ้าคุณมีชั้นเรียนเพียงไม่กี่กล่องเท่านั้นมันสมเหตุสมผลแล้วที่จะมีทุกอย่างในแพ็คเกจ เช่นcom.company.product.module.webหรือcom.company.product.module.utilอื่น ๆ
    • หลีกเลี่ยงการลงเรือด้วยการวางโครงสร้าง IMO หลีกเลี่ยงการแยกบรรจุภัณฑ์สำหรับข้อยกเว้นโรงงานและอื่น ๆ เว้นแต่จะมีความต้องการเร่งด่วน
  • หากโครงการของคุณมีขนาดเล็กให้ง่ายด้วยแพ็คเกจไม่กี่ เช่นcom.company.product.modelและcom.company.product.utilฯลฯ
  • ลองดูที่บางส่วนของความนิยมโครงการมาเปิดออกมีในโครงการอาปาเช่ ดูว่าพวกเขาใช้โครงสร้างอย่างไรสำหรับโครงการขนาดต่างๆ
  • พิจารณาสร้างและแจกจ่ายเมื่อตั้งชื่อ (อนุญาตให้คุณแจกจ่าย api หรือ SDK ของคุณในแพ็คเกจอื่นดูที่ servlet api)

หลังจากการทดลองและการทดลองสองสามครั้งคุณควรจะสามารถสร้างโครงสร้างที่คุณคุ้นเคย อย่าได้รับการแก้ไขในอนุสัญญาเดียวเปิดรับการเปลี่ยนแปลง


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

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

เห็นด้วยกับคะแนนของคุณ เพียงแค่จุดเดียวที่จะเน้นเกี่ยวกับชื่อ บริษัท ในแพคเกจบางครั้ง บริษัท ได้รับผลิตภัณฑ์ที่ได้รับการขาย ฝ่ายบริหารต้องการลบชื่อ บริษัท นั่นอาจเป็นค่าใช้จ่าย
Tushar D

183

ฉันจัดระเบียบแพ็คเกจตามคุณลักษณะไม่ใช่ตามรูปแบบหรือบทบาทการนำไปใช้ ฉันคิดว่าแพ็คเกจชอบ:

  • beans
  • factories
  • collections

เป็นสิ่งที่ผิด

ฉันชอบเช่น:

  • orders
  • store
  • reports

ดังนั้นฉันสามารถซ่อนรายละเอียดการดำเนินการผ่านการมองเห็นแพคเกจ คำสั่งซื้อจากโรงงานควรอยู่ในordersแพ็คเกจดังนั้นรายละเอียดเกี่ยวกับวิธีสร้างคำสั่งซื้อจะถูกซ่อนไว้


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

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

คุณมีตัวอย่างของสิ่งนี้หรือไม่? ฉันกำลังใช้ Spring-MVC ฉันพบว่ามันยากที่จะจัดระเบียบด้วยคุณสมบัติ / โมดูลเนื่องจากสปริงใช้ config xml
Eric Huang Huang

2
@ ฉันยังจัดระเบียบโค้ดตามฟีเจอร์ต่าง ๆ แต่แนวทางปฏิบัติที่ดีที่สุดสำหรับคลาสพื้นฐานที่แชร์โดยฟีเจอร์ทั้งหมดคืออะไร
Marc

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

40

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

คำตอบยาว: ฉันเห็นด้วยกับส่วนใหญ่ของบทความนี้


2
แพคเกจย่อยทำลาย encapsulation "แพ็คเกจย่อย" เป็นแพคเกจอิสระที่สมบูรณ์แบบโดยตัวของมันเอง
Ricardo Gamba

21

ฉันชอบคุณสมบัติก่อนเลเยอร์ แต่ฉันคิดว่ามันขึ้นอยู่กับโครงการของคุณ พิจารณากองกำลังของคุณ:

  • การอ้างอิง
    ลองลดการพึ่งพาแพ็คเกจโดยเฉพาะระหว่างคุณลักษณะต่างๆ แยก API หากจำเป็น
  • การจัดทีมเป็นทีม
    ในบางองค์กรทีมทำงานในคุณสมบัติและในชั้นอื่น ๆ สิ่งนี้มีอิทธิพลต่อการจัดระเบียบรหัสใช้เพื่อทำให้ API เป็นระเบียบหรือสนับสนุนความร่วมมือ
  • การปรับใช้และการกำหนดเวอร์ชันการ
    ใส่ทุกอย่างลงในโมดูลทำให้การปรับใช้และการกำหนดเวอร์ชันง่ายขึ้น สิ่งที่แยกช่วยให้สามารถควบคุมปรับขยายได้และมีความพร้อม
  • ตอบสนองต่อการเปลี่ยนแปลง
    รหัสที่มีการจัดระเบียบอย่างดีนั้นง่ายกว่าการเปลี่ยนแปลงมากกว่าลูกโคลนขนาดใหญ่
  • ขนาด (คนและบรรทัดของรหัส)
    ยิ่งมีรูปแบบที่เป็นทางการ / เป็นมาตรฐานมากขึ้นเท่านั้น
  • ความสำคัญ / คุณภาพ
    รหัสบางรหัสมีความสำคัญมากกว่ารหัสอื่น ๆ API ควรมีความเสถียรมากกว่าการใช้งาน ดังนั้นจึงต้องแยกอย่างชัดเจน
  • ระดับของ abstraction และ entry point
    มันควรจะเป็นไปได้ที่คนนอกจะรู้ว่าโค้ดเกี่ยวกับอะไรและจะเริ่มอ่านอย่างไรจากการดูแผนผังแพ็กเกจ

ตัวอย่าง:

com/company/module
  + feature1/
    - MainClass          // The entry point for exploring
    + api/               // Public interface, used by other features
    + domain/
      - AggregateRoot
      + api/             // Internal API, complements the public, used by web
      + impl/ 
    + persistence/       
    + web/               // presentation layer 
    + services/          // Rest or other remote API 
    + support/            
  + feature2/
  + support/             // Any support or utils used by more than on feature
    + io
    + config
    + persistence
    + web

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

ฉันไม่ชอบชื่อ 'impl' หรือ 'support' แต่ช่วยแยกสิ่งที่มีความสำคัญน้อยกว่าออกจากส่วนสำคัญ (โดเมนและ API) เมื่อพูดถึงการตั้งชื่อฉันชอบที่จะเป็นรูปธรรมมากที่สุด หากคุณมีแพ็คเกจที่เรียกว่า 'utils' ที่มี 20 คลาสให้ย้ายStringUtilsไปที่ support / string HttpUtilเพื่อรองรับ / http และอื่น ๆ


13

มีแนวทางปฏิบัติที่ดีที่สุดเกี่ยวกับการจัดแพคเกจใน Java และสิ่งที่จะเกิดขึ้นหรือไม่?

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

(โปรดอ่านไม่มีแนวทางปฏิบัติที่ดีที่สุดสำหรับมุมมองเกี่ยวกับ "วิธีปฏิบัติที่ดีที่สุด" และผู้ที่ส่งเสริมพวกเขา)

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

(การพึ่งพาแบบวนรอบระหว่างคลาสในแพ็กเกจ / โมดูลนั้นใช้ได้ แต่วัฏจักรระหว่างแพ็กเกจมีแนวโน้มที่จะทำให้เข้าใจสถาปัตยกรรมของแอปพลิเคชันของคุณได้ยากขึ้นและอาจเป็นอุปสรรคต่อการใช้รหัสซ้ำโดยเฉพาะถ้าคุณใช้ Maven inter-package / inter-module dependencies หมายความว่าระเบียบที่เชื่อมต่อระหว่างกันทั้งหมดจะต้องเป็นสิ่งประดิษฐ์ Maven หนึ่งรายการ)

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


9

ฉันเคยเห็นบางคนโปรโมต 'แพ็คเกจโดยฟีเจอร์' เหนือ 'แพ็คเกจโดยเลเยอร์' แต่ฉันใช้วิธีการค่อนข้างน้อยในหลายปีที่ผ่านมาและพบว่า 'แพ็คเกจโดยเลเยอร์' ดีกว่า 'แพ็คเกจโดยฟีเจอร์'

ยิ่งไปกว่านั้นฉันได้พบว่าไฮบริดสลี: แพคเกจโดยโมดูลเลเยอร์แล้วคุณสมบัติ 'กลยุทธ์ทำงานได้ดีมากในทางปฏิบัติเพราะมันมีข้อดีของ' แพคเกจโดยคุณสมบัติ ':

  • ส่งเสริมการสร้างเฟรมเวิร์กที่ใช้ซ้ำได้ (ไลบรารีที่มีทั้งโมเดลและ UI)
  • อนุญาตให้ใช้งานเลเยอร์แบบ plug and play - เป็นไปไม่ได้กับ 'package by feature' เพราะมันวางเลเยอร์ implementations ในแพ็คเกจ / ไดเรกทอรีเดียวกันเป็นรหัสรุ่น
  • อื่น ๆ อีกมากมาย...

ฉันอธิบายในเชิงลึกที่นี่: โครงสร้างชื่อแพคเกจ Java และองค์กรแต่โครงสร้างแพ็คเกจมาตรฐานของฉันคือ:

revdomain.moduleType.moduleName.layer. [layerImpl] .feature.subfeatureN.subfeatureN + 1 ...

ที่ไหน:

revdomainย้อนกลับโดเมนเช่น com.mycompany

moduleType [app * | framework | util]

moduleNameเช่น myAppName ถ้าประเภทโมดูลเป็นแอปหรือ 'การเงิน' หากเป็นกรอบงานการบัญชี

layer [model | ui | persistence | ความปลอดภัย ฯลฯ ,]

layerImplเช่น., ประตู, jsp, jpa, jdo, hibernate (หมายเหตุ: ไม่ได้ใช้ถ้า layer เป็นแบบจำลอง)

คุณสมบัติเช่น. การเงิน

คุณสมบัติย่อยเช่นบัญชี

คุณสมบัติย่อย N + 1เช่นค่าเสื่อมราคา

* บางครั้ง 'แอป' ถูกปล่อยออกมาถ้า moduleType เป็นแอปพลิเคชัน แต่การใส่ไว้ในนั้นจะทำให้โครงสร้างแพ็กเกจสอดคล้องกันในทุกประเภทโมดูล


5

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

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

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

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