8. [TD]: لایه [metier]
واژگان کلیدی: معماری چندلایه، اسپرینگ، تزریق وابستگی.
![]() |
8.1. Support
![]() | ![]() |
پوشه [support / chap-08] حاوی پروژه اکلیپس برای این فصل است.
8.2. پیکربندی Maven
![]() |
پروژه [elections-metier-dao-jdbc] بر اساس پروژه [elections-dao-jdbc-01] خواهد بود. ما فایل JAR را از پروژه دوم در مخزن محلی Maven نصب خواهیم کرد:
![]() |
پس از انجام این کار، پیکربندی Maven برای پروژه Eclipse با نام [elections-metier-dao-jdbc] به شرح زیر است:
![]() |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.elections</groupId>
<artifactId>elections-metier-dao-jdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.7.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--DAO -->
<dependency>
<groupId>istia.st.elections</groupId>
<artifactId>elections-dao-jdbc-01</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- اسپرینگ بوت -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>test</scope>
</dependency>
<!-- آزمون Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- پلاگینها -->
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>config.AppConfig</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!--برای نصب آرتیفکت پروژه در مخزن محلی Maven -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
</plugin>
</plugins>
</build>
</project>
- خطوط ۲۱–۲۵: وابستگی به فایل JAR پروژه [elections-jdbc-01]. ما این خطوط را مستقیماً از فایل [pom.xml] در پروژهای که میخواهیم وارد کنیم، میگیریم:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.elections</groupId>
<artifactId>elections-dao-jdbc-01</artifactId>
<version>0.0.1-SNAPSHOT</version>
...
- خطوط ۲۶–۳۷: وابستگیهای مورد نیاز برای تست. اگرچه این موارد در فایل [pom.xml] پروژه [elections-jdbc-01] موجود هستند، ما مجبوریم آنها را دوباره وارد کنیم زیرا ویژگی [<scope>test</scope>] آنها به این معنی است که در JAR قرار داده شده در مخزن محلی Maven گنجانده نشدهاند؛
8.3. پیکربندی Spring
![]() |
package elections.metier.config;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
@Import({ elections.dao.config.AppConfig.class })
@EnableCaching
@ComponentScan(basePackages = { "elections.metier.service" })
public class MetierConfig {
}
- خط ۷: ما تمام بینهای تعریفشده در لایه [DAO] را وارد میکنیم؛
- خط ۸: کش فعال است. بیون [CacheManager] مجدداً تعریف نمیشود، زیرا قبلاً در لایه [DAO] تعریف شده است؛
- خط ۹: لایه [métier] بیینهای جدیدی را در بسته [elections.metier.service] تعریف میکند؛
8.4. رابط [IElectionsMetier]
![]() |
لایه [metier] دارای رابطی خواهد بود که در بخش 4.2 شرح داده شده است. برای مرور:
public interface IElectionsMetier {
public ListeElectorale[] getListesElectorales();
public int getNbSiegesAPourvoir();
public double getSeuilElectoral();
public void recordResultats(ListeElectorale[] listesElectorales);
public ListeElectorale[] calculerSieges(ListeElectorale[] listesElectorales);
}
8.5. کلاس پیادهسازی [ElectionsMetier]
![]() |
این کلاس رابط [IElectionsMetier] را پیادهسازی میکند. پیادهسازی پیشنهادی ساختار زیر را خواهد داشت:
package elections.metier.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import elections.dao.entities.ListeElectorale;
import elections.dao.service.IElectionsDao;
@Component
public class ElectionsMetier implements IElectionsMetier {
//نقطه دسترسی به لایه [dao] که توسط [Spring] ایجاد شده است
@SuppressWarnings("unused")
@Autowired
private IElectionsDao electionsDao;
//محاسبه کرسیهای کسبشده
@Override
public ListeElectorale[] calculerSieges(ListeElectorale[] listesElectorales) {
throw new RuntimeException("[calculerSieges] not yet implemented");
}
// فهرستها در انتخابات
@Override
public ListeElectorale[] getListesElectorales() {
throw new RuntimeException("[getListesElectorales] not yet implemented");
}
//ذخیره نتایج
@Override
public void recordResultats(ListeElectorale[] listesElectorales) {
throw new RuntimeException("[recordResultats] not yet implemented");
}
// تعداد کرسیهای قابل پر شدن
@Override
public int getNbSiegesAPourvoir() {
throw new RuntimeException("[getNbSiegesAPourvoir] not yet implemented");
}
// آستانه انتخاباتی
@Override
public double getSeuilElectoral() {
throw new RuntimeException("[getSeuilElectoral] not yet implemented");
}
}
- خط ۱۰: کلاس [ElectionsMetier] یک کامپوننت Spring است؛
- خط ۱۱: کلاس [ElectionsMetier] رابط [IElectionsMetier] را پیادهسازی میکند؛
- خطوط ۱۵–۱۶: تزریق بهار (Spring) یک مرجع به لایه [DAO]؛
- خطوط ۳۷ و ۴۴: تعداد صندلیهای قابل پر شدن و آستانه انتخاباتی در حافظه پنهان ذخیره میشوند؛
وظیفه: کلاس [ElectionsMetier] را بنویسید. از نظرات موجود استفاده کنید. تلاش نکنید استثناءهای نوع [ElectionsException] را که از لایه [DAO] پرتاب میشوند، با دستور try/catch بگیرید. ما اجازه میدهیم تا به لایه [UI] منتقل شوند. از آنجا که کلاس [ElectionsException] یک نوع استثنای بدون رسیدگی است، نیازی به رسیدگی به آن با استفاده از بلوک try/catch نیست.
8.6. کلاس تست
![]() |
کلاس تست JUnit شکل زیر را خواهد داشت:
package tests;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import dao.config.AppConfig;
import dao.entities.ElectionsException;
import metier.service.IElectionsMetier;
@SpringApplicationConfiguration(classes = MetierConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class Test01 {
//لایه [métier]
@Autowired
static private IElectionsMetier electionsMetier;
/**
* vérification 1 : méthode de calcul des sièges on fixe en dur les listes
*/
@Test
public void calculSieges1() {
// جدول ۷ فهرست نامزدها (نام، آرا) ایجاد میشود
// تعداد کرسیها را برای هر فهرست محاسبه میکنیم
//نتایج بررسی میشوند (کرسیها، آرا، حذفشدگان)
//موقت
throw new RuntimeException("[calculSieges1] not yet implemented");
}
/**
* vérification 2 : méthode de calcul des sièges on demande les listes à la
* couche [metier] puis on fixe en dur les voix
*/
@Test
public void calculSieges2() {
//آرایهٔ ۷ فهرست نامزدها در پایگاه داده ذخیره میشود
//آرا بهصورت کد سختکد شده هستند
//محاسبه کرسیهای کسبشده توسط هر فهرست
//نتایج بررسی میشوند (کرسیها، آرا، فهرستهای حذفشده)
//موقت
throw new RuntimeException("[calculSieges2] not yet implemented");
}
/**
* vérification 3 méthode de calcul des sièges on provoque une exception
*/
@Test(expected = ElectionsException.class)
// تستی بنویسید که یک استثنا از نوع [ElectionsException] را ایجاد کند
public void calculSieges3() {
//یک آرایه از ۲۵ فهرست نامزد ایجاد کنید، هر کدام با ۱ رأی
// تمام ۲۵ فهرست دارای تعداد آرای یکسان (۴ درصد) خواهند بود
//تخصیص کرسیها – معمولاً این باید منجر به ElectionsException شود
// با آستانه انتخاباتی ۵ درصد
//موقت
throw new RuntimeException("[calculSieges3] not yet implemented");
}
/**
* enregistrement des résultats de l'élection
*/
@Test
public void ecritureResultatsElections() {
// جدول فهرستهای هفت نامزد ایجاد میشود
//آراء بهصورت کد سختکد شده هستند
// تعداد کرسیهای کسبشده توسط هر فهرست را محاسبه کنید
//نتایج در پایگاه داده ذخیره میشوند
//فهرستها از پایگاه داده دوباره خوانده میشوند
//نتایج بررسی میشوند (کرسیها، آرا، نامزدهای حذفشده)
//موقت
throw new RuntimeException("[ecritureResultatsElections] not yet implemented");
}
}
وظیفه: چهار متد تست را با استفاده از نظرات (کامنتها) به عنوان راهنما بنویسید. به یاد داشته باشید که هنگام اجرای این متدها، فیلد [electionsMetier] در خط ۱۹ قبلاً مقداردهی شده است. بررسی کنید که تست JUnit با موفقیت انجام شود.
8.7. ایجاد آرشیو برای لایه [metier]
همانطور که برای لایه [DAO] انجام شد، آرشیو پروژه [elections-metier-dao-jdbc] را در مخزن محلی Maven قرار میدهیم:
![]() |
توجه: این عملیات ممکن است با شکست مواجه شود اگر پروژه Eclipse شما به جای JDK (مجموعه توسعه جاوا)، با JRE (محیط اجرایی جاوا) مرتبط باشد. برای بررسی این موضوع، دستورالعملهای بخش ۳.۱ را دنبال کنید. اگر متوجه شدید که پروژه شما به جای JDK، به JRE متصل است، پروژه خود را همانطور که در این بخش توضیح داده شده است، به JDK متصل کنید.
8.8. Conclusion
بیایید معماری کلی برنامه [Elections] را که در حال حاضر در حال ساخت آن هستیم، به یاد آوریم:
![]() |
ما لایههای [metier] و [dao] را ساختهایم. اکنون لایه [ui] را خواهیم ساخت. برای این لایه دو پیادهسازی پیشنهاد خواهیم داد:
- یک پیادهسازی «کنسول»
- یک پیادهسازی رابط کاربری گرافیکی











