كيف أقوم ببناء تطبيق Java، وأين أضع فصولي الدراسية؟

StackOverflow https://stackoverflow.com/questions/7596

  •  08-06-2019
  •  | 
  •  

سؤال

في البداية، أعرف كيفية إنشاء تطبيق Java.لكنني كنت دائمًا في حيرة بشأن مكان وضع فصولي.هناك أنصار لتنظيم الحزم بطريقة موجهة بشكل صارم للمجال، والبعض الآخر منفصل حسب الطبقة.

أنا نفسي واجهت دائما مشاكل مع

  • تسمية،
  • وضع

لذا،

  1. أين تضع الثوابت الخاصة بمجالك (وما هو أفضل اسم لمثل هذه الفئة)؟
  2. أين تضع فئات للأشياء التي تتعلق بالبنية التحتية والمجال المحدد (على سبيل المثال لدي فئة FileStorageStrategy، التي تخزن الملفات إما في قاعدة البيانات، أو بدلاً من ذلك في قاعدة البيانات)؟
  3. أين تضع الاستثناءات؟
  4. هل هناك أي معايير يمكنني الرجوع إليها؟
هل كانت مفيدة؟

المحلول

لقد أصبحت حقًا أحب Maven تخطيط الدليل القياسي.

إحدى الأفكار الرئيسية بالنسبة لي هي الحصول على جذرين مصدريين - أحدهما لرمز الإنتاج والآخر لرمز الاختبار كما يلي:

MyProject/src/main/java/com/acme/Widget.java
MyProject/src/test/java/com/acme/WidgetTest.java

(هنا، يعد كل من src/main/Java وsrc/test/Java جذورًا مصدرية).

مزايا:

  • تتمتع اختباراتك بحق الوصول إلى مستوى الحزمة (أو "الافتراضي") إلى الفصول الدراسية قيد الاختبار.
  • يمكنك بسهولة تجميع مصادر الإنتاج الخاصة بك فقط في ملف JAR عن طريق إسقاط src/test/java كجذر مصدر.

إحدى القواعد الأساسية حول وضع الفصل والحزم:

بشكل عام، ستكون المشاريع جيدة التنظيم خالية من التبعيات الدائرية.تعلم متى تكون سيئة (ومتى تكون كذلك). لا)، والنظر في أداة مثل JDepend أو سونار ج التي سوف تساعدك على القضاء عليها.

نصائح أخرى

أنا من أشد المعجبين بالمصادر المنظمة، لذا أقوم دائمًا بإنشاء بنية الدليل التالية:

/src - for your packages & classes
/test - for unit tests
/docs - for documentation, generated and manually edited
/lib - 3rd party libraries
/etc - unrelated stuff
/bin (or /classes) - compiled classes, output of your compile
/dist - for distribution packages, hopefully auto generated by a build system

في /src أستخدم أنماط Java الافتراضية:أسماء الحزم التي تبدأ بالمجال الخاص بك (org.yourdomain.yourprojectname) وأسماء الفئات التي تعكس جانب OOP الذي تقوم بإنشائه مع الفصل (راجع المعلقين الآخرين).أسماء الحزم الشائعة مثل util, نموذج, منظر, الأحداث مفيدة أيضًا.

أميل إلى وضع ثوابت لموضوع معين في الفصل الدراسي الخاص بي، مثل ثوابت الجلسة أو ثوابت الخدمة في نفس الحزمة من فئات المجال.

حيث أعمل، نحن نستخدم Maven 2 ولدينا نموذج أصلي جميل جدًا لمشاريعنا.كان الهدف هو الحصول على فصل جيد بين الاهتمامات، وبالتالي قمنا بتحديد هيكل المشروع باستخدام وحدات متعددة (واحدة لكل "طبقة" تطبيق):- شائع:الكود الشائع المستخدمة في الطبقات الأخرى (على سبيل المثال ، I18N) - الكيانات:كيانات المجال - المستودعات:تحتوي هذه الوحدة على واجهات وتطبيقات DAOS - الخدمات - intf:واجهات للخدمات (على سبيل المثال ، userviser ، ...) - الخدمات - IMPL:تطبيقات الخدمات (على سبيل المثال ، userviceImpl) - الويب:كل شيء فيما يتعلق بمحتوى الويب (على سبيل المثال ، CSS ، JSPs ، JSF Pages ، ...) - WS:خدمات الويب

كل وحدة لها تبعياتها الخاصة (على سبيل المثال، يمكن أن تحتوي المستودعات على jpa) وبعضها على مستوى المشروع (وبالتالي فهي تنتمي إلى الوحدة المشتركة).من الواضح أن التبعيات بين وحدات المشروع المختلفة تفصل الأشياء (على سبيل المثال، تعتمد طبقة الويب على طبقة الخدمة ولكنها لا تعرف شيئًا عن طبقة المستودع).

كل وحدة لها الحزمة الأساسية الخاصة بها، على سبيل المثال إذا كانت حزمة التطبيق هي "com.foo.bar"، فلدينا:

com.foo.bar.common
com.foo.bar.entities
com.foo.bar.repositories
com.foo.bar.services
com.foo.bar.services.impl
...

تحترم كل وحدة البنية القياسية للمشروع المخضرم:

   src\
   ..main\java
     ...\resources
   ..test\java
     ...\resources

تجد اختبارات الوحدة لطبقة معينة مكانها بسهولة ضمن \src est...كل ما هو خاص بالمجال له مكانه في وحدة الكيانات.الآن يجب أن يدخل شيء مثل FileStorageStrategy إلى وحدة المستودعات، لأننا لا نحتاج إلى معرفة ما هو التنفيذ بالضبط.في طبقة الخدمات، نعرف فقط واجهة المستودع، ولا نهتم بالتنفيذ المحدد (فصل الاهتمامات).

هناك مزايا متعددة لهذا النهج:

  • الفصل الواضح بين المخاوف
  • كل وحدة قابلة للتجميع كجرة (أو حرب في حالة وحدة الويب) وبالتالي تسمح بإعادة استخدام التعليمات البرمجية بشكل أسهل (على سبيل المثال، يمكننا تثبيت الوحدة في مستودع maven وإعادة استخدامها في مشروع آخر)
  • أقصى قدر من الاستقلالية لكل جزء من المشروع

أعلم أن هذا لا يجيب على جميع أسئلتك، ولكن أعتقد أن هذا قد يضعك على الطريق الصحيح ويمكن أن يكون مفيدًا للآخرين.

يجب أن تكون أسماء الفئات دائمًا وصفية وواضحة بذاتها.إذا كان لديك مجالات متعددة للمسؤولية عن فصولك الدراسية، فمن المحتمل أن يتم إعادة هيكلتها.

وبالمثل بالنسبة لك الحزم.وينبغي تجميعها حسب مجال المسؤولية.كل مجال له استثناءاته الخاصة.

عمومًا، لا تتعرق حتى تصل إلى نقطة تصبح فيها ساحقة ومنتفخة.ثم اجلس ولا تقم بالبرمجة، فقط قم بإعادة هيكلة الفصول الدراسية، وقم بالتجميع بانتظام للتأكد من أن كل شيء يعمل.ثم تابع كما فعلت من قبل.

استخدم الحزم لتجميع الوظائف ذات الصلة معًا.

عادةً ما يكون الجزء العلوي من شجرة الحزمة الخاصة بك هو اسم المجال الخاص بك معكوسًا (com.domain.subdomain) لضمان التفرد، وبعد ذلك عادةً ما تكون هناك حزمة لتطبيقك.ثم قم بتقسيم ذلك حسب المنطقة ذات الصلة، لذلك FileStorageStrategy ممكن يدخل يقول com.domain.subdomain.myapp.storage, ، ومن ثم قد تكون هناك تطبيقات/فئات فرعية/أي شيء محدد com.domain.subdomain.myapp.storage.file و com.domain.subdomain.myapp.storage.database.يمكن أن تصبح هذه الأسماء طويلة جدًا، ولكن import يبقيهم جميعًا في أعلى الملفات ويمكن أن تساعد IDEs في إدارة ذلك أيضًا.

عادة ما تكون الاستثناءات في نفس الحزمة مثل الفئات التي ترميها، لذلك إذا كان لديك، على سبيل المثال، FileStorageException سوف تذهب في نفس الحزمة مثل FileStorageStrategy.وبالمثل، فإن الواجهة التي تحدد الثوابت ستكون في نفس الحزمة.

لا يوجد حقًا أي معيار على هذا النحو، ما عليك سوى استخدام الحس السليم، وإذا أصبح كل شيء فوضويًا للغاية، فأعد البناء!

الشيء الوحيد الذي وجدته مفيدًا جدًا لاختبارات الوحدة هو الحصول على أدلة myApp/src/ وأيضًا myApp/test_src/.بهذه الطريقة، يمكنني وضع اختبارات الوحدة في نفس الحزم مثل الفئات التي تختبرها، ومع ذلك يمكنني بسهولة استبعاد حالات الاختبار عندما أقوم بإعداد تثبيت الإنتاج الخاص بي.

اجابة قصيرة:ارسم بنية النظام الخاص بك من حيث الوحدات، مرسومة جنبًا إلى جنب، مع تقسيم كل وحدة عموديًا إلى طبقات (على سبيل المثال.عرض، نموذج، ثبات).ثم استخدم هيكل مثل com.mycompany.myapp.somemodule.somelayer, ، على سبيل المثال. com.mycompany.myapp.client.view أو com.mycompany.myapp.server.model.

استخدام المستوى الأعلى من الحزم للتطبيق وحدات, ، بالمعنى القديم لعلوم الكمبيوتر البرمجة المعيارية, ، ينبغي أن يكون واضحا.ومع ذلك، في معظم المشاريع التي عملت عليها، ينتهي بنا الأمر إلى نسيان القيام بذلك، وينتهي الأمر بفوضى من الحزم دون هيكل المستوى الأعلى.عادةً ما يُظهر هذا النمط المضاد نفسه كحزمة لشيء مثل "المستمعين" أو "الإجراءات" التي تجمع الفئات غير المرتبطة ببساطة لأنها تنفذ نفس الواجهة.

داخل الوحدة النمطية، أو في تطبيق صغير، استخدم الحزم لطبقات التطبيق.تتضمن الحزم المحتملة أشياء مثل ما يلي، اعتمادًا على البنية:

  • com.mycompany.myapp.view
  • com.mycompany.myapp.model
  • com.mycompany.myapp.services
  • com.mycompany.myapp.rules
  • com.mycompany.myapp.persistence (أو "dao" لطبقة الوصول إلى البيانات)
  • com.mycompany.myapp.util (احذر من استخدام هذا كما لو كان "متفرقًا")

داخل كل طبقة من هذه الطبقات، من الطبيعي تجميع الفئات حسب النوع إذا كان هناك الكثير.النمط المضاد الشائع هنا هو تقديم عدد كبير جدًا من الحزم ومستويات الحزمة الفرعية بشكل غير ضروري بحيث لا يوجد سوى عدد قليل من الفئات في كل حزمة.

أعتقد أن الأمر بسيط ولا تبالغ في التفكير فيه.لا تبالغ في التجريد والطبقة أكثر من اللازم.كل ما عليك فعله هو الحفاظ على نظافته، ومع نموه، تصبح إعادة هيكلته أمرًا تافهًا.واحدة من أفضل ميزات IDEs هي إعادة البناء، فلماذا لا تستفيد منها وتوفر طاقتك العقلية لحل المشكلات المتعلقة بتطبيقك، بدلاً من المشكلات الوصفية مثل تنظيم التعليمات البرمجية.

شيء واحد قمت به في الماضي هو أنني إذا قمت بتوسيع الفصل فسأحاول اتباع تقاليدهم.على سبيل المثال ، عند العمل مع Spring Framework ، سأحصل على فصول وحدة التحكم في MVC في حزمة تسمى com.mydomain.myapp.web.servlet.mvc إذا لم أقدم شيئًا ما أذهب إليه فقط.com.mydomain.domain لكائنات المجال (على الرغم من أنه إذا كان لديك عدد كبير من كائنات المجال، فقد تصبح هذه الحزمة غير عملية بعض الشيء).بالنسبة للثوابت الخاصة بالمجال، فأنا في الواقع أضعها كثوابت عامة في الفئة الأكثر صلة.على سبيل المثال، إذا كان لدي فئة "عضو" ولدي حد أقصى ثابت لطول اسم العضو، فإنني أضعه في فئة العضو.تقوم بعض المتاجر بإنشاء فئة ثوابت منفصلة ولكني لا أرى القيمة في تجميع الأرقام والسلاسل غير المرتبطة في فئة واحدة.لقد رأيت بعض المتاجر الأخرى تحاول حل هذه المشكلة عن طريق إنشاء فئات ثوابت منفصلة، ​​ولكن هذا يبدو مجرد مضيعة للوقت والنتيجة مربكة للغاية.باستخدام هذا الإعداد، سيقوم مشروع كبير يضم العديد من المطورين بتكرار الثوابت في كل مكان.

أحب تقسيم فصولي إلى حزم مرتبطة ببعضها البعض.

على سبيل المثال:نموذج للمكالمات المتعلقة بقاعدة البيانات

منظر الفصول التي تتعامل مع ما تراه

يتحكم فئات الوظائف الأساسية

فائدة أي متنوع.الفئات المستخدمة (عادةً الوظائف الثابتة)

إلخ.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top