سؤال

أفكر إذا كنت بحاجة حقًا إلى طبقة خدمة.

أنا أستخدم Spring + Hibernate لتطبيق Swing Swing Desktop ، وفي هذه اللحظة لدي طبقة واجهة المستخدم الرسومية/Swing-طبقة الخدمة-> طبقة DAO. أستخدم الربيع فقط للحصول على دعم transactional وللحقن IOC

أفضل الممارسات تقول إن عليّ أن أكتب خدمة لاستخدام DAOs ، ووضع جميع إدارة المعاملات في الخدمة.

لكنني أدرك أنه في كثير من الأحيان ، تكرر طبقة الخدمة فقط أساليب DAO ، لذلك على سبيل المثال:

// a DAO example
@Repository
public class CustomerHibernateDAO extends BaseHibernateDAO implements CustomerDAO {

 public List<Customer> findAllCustomerILikeName(String name){
  return getSession()
   .createCriteria(Customer.class)
   .add(Restriction.ilike("name", name))
   .list();
 }
}

// Customer service to use this dao...
@Service
@Transactional
public class CustomerService {

 @Autowired
 CustomerDAO customerDAO;

 // Why i can't call DAO instead the service?
 public List<Customer> getAllCustomersByName(String name){
      return customerDAO.findAllCustomerILikeName(name);
 }

}

هذا هو الاستخدام اللغوي لطبقة الخدمة ... السبات هو db-agnostic ، الربيع هي tecnology-agnostic: إذن ، أنا حقا بحاجة إليها؟

ماذا عن فئة الخدمة الفريدة لإدارة كل DAO ؟؟ أعتقد أن هذا قد يكون حل وسط جيد ، أم أن ممارسة سيئة؟

أعلم أن puttransactional على dao هو وسيلة سيئة ، لكن في هذه اللحظة يجب أن أكتب الخدمات فقط لـ puttransactional عليها ...

تعديل

المزيد من Infos حول تطبيقي.

طلبي هو برنامج إدارة ويدير تسجيل المستخدم والمنتجات والطلب وأشياء أخرى مثل تلك. في الممارسة العملية ، يحتوي على الكثير من القراءة-> تحرير-> حفظ الكيان أو إنشاء-> تحرير-> حفظ العمليات ، وبفضل السبات ، تتم إدارة هذه العمليات من قبل واحد DAO معظم الوقت ، لأن Hibernate مع Manyto. .. Collection و Cascade.Save_Update يسمح بحفظ كيانين أو أكثر في نفس العملية المستمرة.

لذلك ، على سبيل المثال ، في العناصر الخاصة بي Jframe حيث يمكنني إدراج أو تحرير أو إنشاء عنصر (منتج للبيع) هناك:

public ItemFrame(){
 // the constructor
 itemService=springAppContext.getBeans(ItemService.class);
}

public boolean validateForm(){
 // test if the gui is correctly filled by user
}

public boolean save(){
 // create an Item entity taking value from swing gui(JTextField etc)
 Item item=new Item();
 item.setName(nameTextField.getText());
 item.setEtc...
 // ItemService ' save method is a wrap around itemDao.save(item)...
 itemService.save(item);
}

private void saveItemActionPerformed(ActionEvent evt){
 // When i press SAVE button
 if(validateForm()){
  save();
 }
}

هذا ما لدي في معظم الحالات ، لذلك أعتقد أنني وقعت في نفقات الدم-antipattern ...

شكرًا.

هل كانت مفيدة؟

المحلول

إذا كانت طبقة الخدمة الخاصة بك تكرر DAO ، فأنت لا تستخدم طبقة الخدمة على الإطلاق. لقد ارتكبت نفس الخطأ في عدد قليل من طلباتي ، كنت أتساءل "لماذا تبدو طبقة الخدمة قبيحة للغاية ، وهي Duplicationg Dao" ...

يجب أن تكون طبقة الخدمة واجهة للتطبيق الخاص بك ، وهذا يعني أن بعض الأساليب ليست هي نفسها في DAO وفي الخدمة ، ولكن الجزء الرئيسي يختلف اختلافًا كبيرًا. لا أستطيع أن أقول هذا دون عرض بقية الكود الخاص بك ، ولكن بسؤالك (وهو ما هو نفس الشيء كما كانت أسئلتي قبل بضعة أشهر) ، يبدو لي أنك تستخدم نموذج مجال فقر الدم antepattern. في نموذج مجال الفقر ، يحتوي النموذج الخاص بك على حقول و getters فقط ، لا توجد طرق حقيقية (سلوك) ، والتي تنتهك المبادئ الأساسية الموجهة للكائنات (كائن == بيانات + سلوك) ... ربما يكون سلوكك في شيء يشبه البرنامج النصي المعامل في الخدمة طبقة ، ولكن يجب أن تكون في النموذج الخاص بك (طبقة المجال).

الطريق للخروج من هذا هو استخدام نموذج المجال الغني (تم حقن الفاصوليا للنموذج عبر configible). قد تقول ، أن هذا ينتهك نمط الطبقات وسيكون صحيحًا على الأرجح. لكنني مقتنع بأننا يجب أن نفكر في تطبيقنا (Domain+Dao+Service) كمكون واحد (انظر Alistair Cockburn الهندسة المعمارية سداسية/موانئ ومحولات).

سيكون تطبيق Swing App/Web الخاص بك عميلًا لمكونك الأساسي ، ويمكنك بعد ذلك تبديله دون أي قيود (كل ما هي بيانات ModieFies في جوهرها).

ولكن هناك قيود/عيب مع هذا النهج. إذا كنت ستستخدم نوعًا من الأمان (أمان الربيع) أو السجلات النشطة عبر Hibernate ، فبإمكانك أن تتواصل مع جميع العملاء عبر DTO (وليس الكيانات نفسها) ، لأنه عند الاتصال بالكيان ، قد يتصل بالخدمة ، والتي ستشمل نفسها عبر نفسها عبر المعاملات ويمكنه تعديل قاعدة البيانات (تجاوز الأمان الخاص بك).

آمل أن أكون قد خمنت الهندسة المعمارية الخاصة بك ، إن لم يكن ، أنا آسف لاختراع العجلة هنا ، ولكن هذا المنشور قد يساعد شخصًا لا يعرف هذا (كما كان الحال قبل عث قليلة).

تعديل

إلى تحريرك: حتى في تطبيق CRUD البسيط ، يجب أن تكون هناك نوع من الإجراءات في طبقة الخدمة - على سبيل المثال التحقق من الصحة (وليس التحقق من الصحة "هذا رقم" ، ولكن بعض التحقق من صحة الأعمال). يجب أن يكون هذا في عرضك ، لأنه إذا قمت بتغييره ، فستكون لديك نسخ ولصقها مرة أخرى. عندما تنظر إلى التعليمات البرمجية الخاصة بك ، يجب أن تسأل Qeusting "إذا قررت كتابة عميل رفيع (عرض في متصفح الويب)" ، هل هناك أي رمز ، سأضطر إلى نسخه؟ إذا كانت الإجابة نعم ، يجب عليك إنشاء طريقة خدمة لهذه المكالمة عن بُعد.

الشيء الآخر الذي يجب عليك/يمكنك القيام به على طبقة الخدمة هو الحجم التلقائي (هل المستخدم في هذا الدور يسمح بحذف هذا الإدخال). سيتعين عليك الحصول على طبقة خدمة لجميع كياناتك تقريبًا ، لأن المستخدم البسيط يجب أن يكون قادرًا على تحرير (حذف) إدخالاته ، ولكن ربما لا ينبغي حذف المستخدمين الآخرين. لكن المستخدم في مسؤول الدور يمكنه القيام بذلك.

مثال رمز (جزء من واجهة خدمة المقالة في تطبيقي (أمان الربيع)):

@Secured("ROLE_EDITOR")
public void save(ArticleDTO selectedArticle, ArticleDetailsDTO selectedArticleDetails);

في خدمة التعليق ، يمكن للجميع حفظ تعليقاتهم على المقالات ....

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

نصائح أخرى

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

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

DAO هو للوصول إلى بيانات. الخدمة لمنطق العمل. اجعلهم منفصلين وستكون أكثر سعادة على المدى الطويل.

في النهاية ، ستحتاج إلى تنسيق السلوك بين العديد من DAO. يمكنك أيضًا تقديم بعض التعقيد لقواعد عملك (على سبيل المثال: لا تحديث [هذا] ، إذا كان [ذلك] في حالة معينة). هذا هو المكان الذي تأتي فيه طبقة الخدمة في متناول يدي.

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

بدلا من إنفاذ

ui -> service -> DAO

لكل عملية ، فكر في السماح على حد سواء

ui -> DAO
ui -> service -> DAO

هذا الأخير يستخدم لعمليات أكثر تعقيدًا

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