ایجاد یک لایه حائل برای لایه تداوم

بازدید : 364

Service Builder لایفری لایه بندی مناسب قابلیت را در داخل یک اپلیکیشن پورتلت تقویت می کند. بطور کلی در زمان ساخت یک اپلیکیشن جداکردن لایه های گوناگون اپلیکیشن تمرین خوبی است: UI، مدل، تداوم و غیره. گاهی اوقات این جدایی، جدایی قضایا نامیده می شود. اگر به دلایلی بعداً راه بهتری برای انجام پیدا کنید با جدا نگهداشتن لایه ها تا حد امکان این توانایی را بدست می آورید تا اجرای هر لایه را به راحتتر تغییر دهید.

برای بعضی ها این کار به نظر غیر ضروری می رسد. اما اجازه بدهید یک مثال برایتان بزنم که چرا این کار مهم است و سپس سراغ چگونگی اجرای آن می رویم.

 

چرا لایه بندی مهم است

این مثال را در نظر بگیرید. شما یک اپلیکیشن طراحی شده ضعیفی دارید که شامل فقط دو لایه است: JSP ها و کلاس پورتلت. اپلیکیشن را با ایجاد action URL ها در JSP ها که با روش های گوناگون در داخل پورتلت مطابقت دارد گسترش می دهید. این روش ها از JDBC برای ارتباط با دیتابیس و انتخاب، وارد کردن، به روزآوری و حذف دیتا استفاده می کند. دیتابیس، اعتبار و کد رهیابی صفحه همه در پورتلت یا JSPهاستکه در فایل های بزرگ با منطق های زیادی در آنها نتیجه می دهد. پورتلت را نیز که می توانید تست می کنید و سپس تا مرحله تولید اجرا می شود.

در اولین روز استفاده یک باگ پیدا می شود. اپلیکیشن شما یک فیلد نام خانوادگی دارد و یک کاربر سعی کرده تا نام خانوادگی O’Bannon را وارد کند. چون تمام تعاملات دیتابیس را بطور دستی کد کرده اید فراموش کرده اید که گاهی اوقات لازم است از کاراکترهای مشخص فرار کنید. در این مورد آپوستروف (’) در آن اسم موجب شده که دیتابیس خطا دهد.

با طراحی ضعیفی که برای پورتلت استفاده کرده اید حالا مجبورید روش های Insert و Update کلاس پورتلت را تغییر دهید و کدی اضافه کنید که ارزش هایی را چک می کند که کاربران برای آپوستروف ها را وارد می کنند. این مثالی از طراحی دو قسمتی است: کد دیتابیس داخل پورتلت است بنابراین اجرای کد که با دیتابیس ارتباط برقرار می کند با کار و منطق نمایش در هم تنیده است. چون اخیراً روی این پورتلت کار کرده اید می دانید مشکل کجاست و می توانید آن را برطرف کنید و مجدداً اپلیکیشن را اجرا کنید.

کاربران با این اپلیکیشن چند ماه کار می کنند تا باگ دیگری پیدا شود. به نظر می رسد یک جایی در پورتلت ارتباط دیتابیس بسته نشده است و موجب می شود ارتباط سرور دیتابیس قطع شود.

زمان قابل توجهی می گذرد و شما روی پروژه دیگری هستید- بخاطر نمی آورید که دقیقاً چه کاری انجام دادید وقتی این یکی را نوشتید. مجبورید در تپه ی  بهم ریخته ای از کد در کلاس پورتلت برای یافتن مشکل تقلا کنید: کد دیتابیس که با همه نوع قابلیت های دیگر مثل عملکردهای Java Script، کد اعتبار فیلد، کد دسترسی به دیتابیس و غیره مخلوط شده است. آشفتگی ای که به سختی می توان آن را ابقا کرد. بعد از ساعت ها اشکال زدایی کردن بالاخره شرایطی را پیدا خواهید کرد که در آنجا ارتباط دیتابیس بسته نشده است.

تقریباً یک روز طول می کشد تا یک مشکل را پیدا کنید چون زیر کدهای زیادی مدفون شده که باید به لایه های مختلفی از منطق کد تفکیک می شد.

اگر بدرستی اپلیکیشن را لایه بندی کرده بودید کد UI در یک جا بود و منطق کار در جای دیگر بود و منطق تداوم در جای دیگر و شما یک پروژه قابل نگهداریتری داشتید. ممکن است تصمیم بگیرید که می توانستید از چیزی مثل Hibernate برای تداوم دیتابیس استفاده کنید و اینگونه فقط مجبور بودید کلاس های کمی را در یک لایه جایگزین کنید. انجام این کار همه مشکلات تداوم را حل می کرد چون Hibernate بطور اتوماتیک از کاراکترها و ارتباطات بسته فرار می کند. سپس ممکن است قدمی فرارت بردارید و منطق اپلیکیشن رشد یافته را به یک چارچوب MVC مثل Java Server Faces (JSF) یا Struts جایگزین نمایید. در هر ایجاد دوباره ساختار می توانید یک لایه اپلیکیشن را در یک زمان اصلاح کنید. اجازه بدهید ببینیم چگونه این کار را در لایه تداوم انجام دهیم.

 استفاده از دو لایه برای تداوم

در حالیکه بخش قبلی یک مثال ساده را شرح می دهد نشضان می دهد که چقدر مهم است که Service Builder جدایی مناسب قضایا را تقویت کند. برای تداوم دیتابیس دو تا از این لایه ها عبارتند از DAO و DTO. این دولایه بطور دستی می توانند توسط برنامه نویسان نوشته شوند و اغلب زمان زیادی صرف می شود تا کدها نوشته و از آنها اشکال زدایی شود. Service Builder هر دو لایه را بطور اتوماتیک تولید می کند ( شکل ۱٫۱ را ببینید) لایه ای که در آن بیشتر کار خواهید کرد لایه DTO است. این لایه با لایه خدمات صحبت می کند که بطور اتوماتیک تولید می شود و اجازه می دهد که با موضوعات مورد نیازی کار کنید که روی آنها پافشاری شده یا از دیتابیس بازیابی شده است. اینها کلاس های _Impl هستند که تولید کرده اید و به این دلیل است که آنها در پوشه src با دیگر کدهای پورتلت قرار گرفته اند. شما روشهای لایه DAO را فراخواهید خواند تا روشها را در لایه تداوم بخواهند تا تداوم واقعی را انجام دهند. این روش ها از تگ های <finder> تولید می شوند که در فایل service.xml قرار داده اید.

66928

شکل ۱٫۱ Service Builder برایتان همه چیز را از لایه پورتال UI تولید می کند. شما نیاز دارید تا برخی از این کدها را اصلاح/سفارشی کنید اما مجبور نخواهید بود که بیشتر آن را دست بزنید. بطور قابل توجهی این بهره وری برنامه نویس را افزایش میدهد. اجازه دهید ببینیم که این چطور کار می کند.

 

 

اگرچه هنوز آن را ایجاد نکرده اید این طراحی به یک فرم در پورتلت administrative دارد. این فرم به کاربران اجازه میدهد محصولات را وارد کنند که در یک جعبه انتخابی drop-down روی فرم ثبتنام در پورتلت ثبت نام نمایان خواهد شد. فقط دو فیلد از این فرم خواهند آمد (چون سومی یک کلید ابتدایی است که تولید شده است): نام محصول و لفافه شماره سریال به وسیله واحد تولید تنظیم شده است و می توان از آن برای اعتبار فیلد استفاده کرد. چگونه دیتایی که کاربر وارد کرده را به دیتابیس منتقل می کنیم؟

به یاد داشته باشید که شما به دنبال ایده اتصال سست هستید. این بدان معناست که نمی خواهید هیچ ورودی کدی به دیتابیس در منطق کارتان داشته باشید. منطق کار (وقتی به آن می رسید) نیاز خواهید داشت تا یک روش عمومی را فراخوانید که هیچ کاری با دیتابیس ندارد. این جایی است که لایه DTO در آن می آید. آن مثل یک حائل بین منطق کار و کد اصولی دیتابیس عمل می کند. Service Builder هر دو لایه را تولید می کند لایه DTO را به عنوان یک ریشه برایتان باقی می گذارد تا به محض اینکه خواستید اجرا کند.

اجرای لایهDTO

احتمالاً روشی را می خواهید که دو پارامتر در امضای روش برای ارزشهایتان دارد: نام محصول و لفافه شماره سریال محصول. اجازه دهید ایجادش کنیم. فایل PRProductionLocalServiceImpl.java را باز کنید. آن را در یک بسته تازه تولید شده بنام com.inkwell.internet.productregistration.service.impl. پیدا خواهید کرد.

این کلاس کلاس تولید شده را بنام PRProductLocalServiceBaseImpl گسترش می دهد (شکل ۱٫۲ را ببینید). اگر از یک ID (مثل Eclipse) استفاده می کنید که بطور اتوماتیک درک نمی کند هنگامی که ابزار دیگری به فایل اضافه می شود، ممکن است نیاز داشته باشید تا روی اسم پروژه کلیک کنید و F5 را فشار دهید تا پروژه رفرش شود تا این بسته را ببینید. اولین چیزی که در PRProductLocalServiceImpl  اجرا می کنید اضافه کردن یک محصول است.

بعد از اجرای اضافه کردن یک محصول، اجرای دیگر روشها ساده است.

66928-2

شکل ۱٫۲ Service Builder هر دو لایه DAO و DTO را تولید می کند. اینجا لایه DTO نشان داده شده که نمونه ای از لایه DAO دارد (ویژگی prProductPersistence) که در آن در زمان اجرا بوسیله Spring تزریق شده است.

 

 

 

اضافه کردن یک محصول

چیز عالی دیگری درباره طراحی Service Builder این است که هرگز مجبور نیستید به هیچ کلاسی که تولید می شود دست بزنید یا آن را اصلاح کنید. همه تزریق وابستگی Spring، مدیریت Hibernate session، و منطق query در کلاسهایی می ماند که مجبور نیستید ویرایش کنید. کد در یک کلاس اضافه می کنید که کلاس تولید شده را گسترش می دهد و اگر چیزی اضافه کنید که اینترفیس/ قرارداد اجرا را تغییر می دهد، آن تغییرات در همه زنجیره پخش می شود بنابراین قرارداد هرگز شکسته نمی شود. مثالی از این را بعداً خواهید دید.الان این فایل یک ریشه خالی است چون هنوز مجبورید هر چیزی را اجرا کنید. لیست زیر اولین روش را اجرا می کند که ارزش ها را به آن منتقل می کند و کد دیتابیس اصولی را فرا می خواند تا دیتا در دیتابیس باقی بماند.

 

 

 

 

لیست ۱٫۱   اضافه کردن یک محصول به دیتابیس

public PRProduct addProduct(PRProduct newProduct, long userId)
throws SystemException, PortalException {
PRProduct product = prProductPersistence.create(
counterLocalService.increment(
PRProduct.class.getName()));
resourceLocalService.addResources(
newProduct.getCompanyId(),
newProduct.getGroupId(), userId,
PRProduct.class.getName(),
product.getPrimaryKey(), false,
true, true);
product.setProductName(newProduct.getProductName());
product.setSerialNumber(newProduct.getSerialNumber());
product.setCompanyId(newProduct.getCompanyId());
product.setGroupId(newProduct.getGroupId());
return prProductPersistence.update(product, false);
}
docroot/WEB-INF/src/com/inkwell/internet/productregistration/service/impl/PRProductLocalServiceImpl.java

اولین کاری که انجام می دهید  در این روش ایجاد یک موضوع جدید PRProduct است. PRProduct اینترفیس (که از PRProductModel گرفته شده ) است و PRProductImpl (که PRProductModelImpl را گسترش می دهد) اجرا است. توجه داشته باشید که همه کاری که باید انجام دهید این است که اینجا اینترفیس را مشخص کنید چون یک الگوی طراحی کارخانه ای موضوع را برایتان ایجاد می کند، با استفاده از موضوع  prProductPersistence به این کلاس بوسیله Spring تزریق خواهد شد. اینترفیس و اجرای این موضوع هر دو بوسیله Service Builder بطور اتوماتیک تولید شده بود. چون لایفری ضد دیتابیس است بطور پیش فرض از هیچ روش{وسیله} خاص دیتابیسی تولید کلیدهای اصلی {اولیه} برای دیتابیس هایی که مدیریت می کند استفاده نمی کند.بهمین علت لایفری کارایی اش را برای تولید کلیدهای اصلی {اولیه}فراهم می کند هنگامی که نیاز دارید تا کد ضد دیتابیس تولید کنید. چون این تمرین لایفری است و ثابت شده است که در اجراهای بسیار بزرگ لایفری خوب عمل می کند ما اینجا تقاضا را دنبال می کنیم. توجه داشته باشید که اگر بخواهید Service Builder به شما اجازه می دهد که از وسیله دیتابیس برای تولیدکلید اصلی استفاده کنید؛ تمام اختیارات موجود در DTD برای فایل service.xml بصورت سند شده است، و این DTD را می توان در پوشه تعاریف در کد منبع لایفری پیدا کرد.

چون روش create که تولید شد به یک کلید اصلی نیاز دارد شما نیاز دارید تا کارایی counter لایفری را فرابخوانید تا این را تولید کند. در اینجا یک چیز خوب درباره اینکه چگونه این کار انجام می شود: counter بطور اتوماتیک در کلاسی که روی آن کار می کنید تزریق می شود. چرا؟ چون اگر با دیتابیس ها و Service Builder کاری کنید احتمالاً نیاز دارید از counter استفاده کنید تا موضوعات جدیدی که روی آن پافشاری خواهد شد ایجاد کنید.

بعد از resourceLocalService فراخوان کنید تا منابع ۲ باقی بماند. منابعی در لایفری استفاده می شود تا مجوزات را در موضوعاتی که روز آن پافشاری شده {باقی مانده} تعریف کنید. بعداً به الباقی آن خواهیم پرداخت؛ برای الان مهم است که توجه داشته باشید که نیاز دارید تا منابع را با موجودیهایتان ذخیره کنید.

همچنین بیاد داشته باشید که فیلدهای ID شرکت و ID گروه را به جدولتان اضافه کردیدتا پورتلت را پورتلت بدون نمونه کنید؛ و همچنین برای اینکه شما را قادر کند تا بعداً سیستم دسترسی های لایفری را ایجاد کنید. این دو متغیر نمونه به ترتیب پورتال و اجتماع/سازمان را دنبال می کند. بطور مثال یک کاربر پورتلت را به یک صفحه در اجتماع مهمان نمونه پیش فرض پورتال اضافه می کند. سپس کاربران شروع به اضافه کردن محصولات به دیتابیس می کنند. چون ID شرکت و ID گروه را به موجودیت محصول اضافه کرده اید کاربران می توانند پورتلت را به اجتماع، سازمان یا نمونه پورتال دیگری اضافه کنند و یکسری ثبت های برگشته بر اساس ID شرکت و ID گروه متفاوت خواهد بود. روش های یابنده ثبتهای برگشته را بوسیله ID شرکت و ID گروه فیلتر می کند.

این گونه ای است که چگونه لایفری به شما اجازه میدهد قرار دهید بطور مثال یک پورتلت Message Boards در اجتماع متفاوت و کاملاً محتوای متفاوتی در آنها دارد. شما همین کار را زمان نوشتن پورتلت انجام خواهید داد.

هنگامی که موضوع را دارید کار ساده ای است تا ارزشهای مناسب را در موضوع تنظیم کنید و سپس در دیتابیس آن را باقی بگذارید . سپس موضوعی را که در لایه ای که این روش در جایگاه اول فراخوانده شدایجاد شده است.

هنوز تمام نشده است. بیاد بیاورید هنگامی که در دو صفحه قبل گفتیم آیا تغییرات در قرارداد implementation/interface زنجیره را بطور اتوماتیک بوسیله Service Builder پخش می کند؟ شما فقط روی کلاس اجرا که –BaseImplclass گسترش می سابد کار می کردید. همه روشهایی که با Service Builder تولید می شوند در واسط کاربری و اجرا در کلاس _BaseImpl موجودیت دارند. اگر برنامه نویسان بخواهند کلاس بیشتری اضافه کنند آنها اضافه شده اند که مال خودتان را اضافه کنید: در کلاس _LocalServiceImpl.

چون یک روش جدید به یک کلاس اضافه کردید که یک واسط کاربری را اجرا می کند در واسط کاربری برای روشی که ایجاد کرده اید ریشه روش وجود ندارد. برای اینکه بدون خطا ادامه دهید دوباره باید Service Builder را اجرا کنید. همانطور که قبلاً دیدید این کار را با اجرای کار build-service انت می توان انجام داد. هنگامی که این کار را اجرا می کنید Service Builder واسط کاربری را دوباره تولید خواهد کرد که PRProductLocalService نامیده می شود تا یک ریشه را برای روشی که در کلاس اجرا ایجاد کردید شامل شود.

بطور کل این نقطه ای است که مردم سرشان را میخارانند و می گویند: این وارونه نیست؟ آیا گمان نمی رود که ابتدا واسط کاربری را تعیین کنید سپس اجرا را بنویسید؟

نظرات :0 نظر

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد.