מבוא ל- ArchUnit

1. סקירה כללית

במאמר זה נראה כיצד לבדוק את הארכיטקטורה של מערכת באמצעות ArchUnit.

2. מה זה ArchUnit?

הקשר בין תכונות ארכיטקטורה לתחזוקה הוא נושא נחקר היטב בתעשיית התוכנה. הגדרת ארכיטקטורת סאונד למערכות שלנו אינה מספיקה. עלינו לוודא שהקוד המיושם עומד בו.

פשוט שים, ArchUnit היא ספריית בדיקה המאפשרת לנו לוודא כי יישום עומד במערך נתון של כללי אדריכלות. אבל, מהו כלל ארכיטקטוני? יתרה מכך, למה אנו מתכוונים ארכיטקטורה בהקשר הזה?

נתחיל עם האחרון. כאן אנו משתמשים במונח ארכיטקטורה להתייחס אליוהאופן שבו אנו מארגנים את השיעורים השונים ביישום שלנו לחבילות.

הארכיטקטורה של מערכת מגדירה גם כיצד חבילות או קבוצות חבילות - המכונות גם שכבות - אינטראקציה. במונחים מעשיים יותר, הוא מגדיר אם קוד בחבילה נתונה יכול לקרוא לשיטה בכיתה השייכת למערכת אחרת. לדוגמא, נניח שהארכיטקטורה של היישום שלנו מכילה שלוש שכבות: הַצָגָה, שֵׁרוּת, ו הַתמָדָה.

אחת הדרכים לדמיין את האינטראקציה של שכבות אלה היא באמצעות דיאגרמת חבילות UML עם חבילה המייצגת כל שכבה:

רק על ידי התבוננות בתרשים זה נוכל להבין כמה כללים:

  • שיעורי מצגת צריכים להיות תלויים רק בשיעורי שירות
  • שיעורי שירות צריכים להיות תלויים רק בשיעורי התמדה
  • שיעורי התמדה לא צריכים להיות תלויים באף אחד אחר

אם מסתכלים על הכללים האלה, כעת נוכל לחזור לענות על השאלה המקורית שלנו. בהקשר זה, כלל ארכיטקטוני הוא קביעה לגבי האופן שבו שיעורי היישומים שלנו מתקשרים זה עם זה.

אז עכשיו, איך נבדוק שהיישום שלנו עומד בכללים האלה? כאן איפה ArchUnit נכנס פנימה. זה מאפשר לנו לבטא את המגבלות האדריכליות שלנו באמצעות ממשק API שוטף ולאמת אותם לצד מבחנים אחרים במהלך בנייה רגילה.

3. ArchUnit הגדרת פרויקט

ArchUnit משתלב יפה עם JUnit מסגרת הבדיקה, וכך הם משמשים בדרך כלל יחד. כל שעלינו לעשות הוא להוסיף את ה- ארכיט-יוניט 4 תלות שתתאים לנו JUnit גִרְסָה:

 com.tngtech.archunit archunit-junit4 0.14.1 מבחן 

כמו שלה artifactId מרמז, תלות זו היא ספציפית עבור JUnit 4 מסגרת.

יש גם archunit-junit5 תלות אם אנו משתמשים JUnit 5:

 com.tngtech.archunit archunit-junit5 מבחן 0.14.1 

4. כתיבה ArchUnit בדיקות

לאחר שהוספנו את התלות המתאימה לפרויקט שלנו, נתחיל לכתוב את מבחני האדריכלות שלנו. יישום הבדיקה שלנו יהיה אפליקציית SpringBoot REST פשוטה ששואלת דרדסים. לשם פשטות, יישום בדיקה זה מכיל רק את בקר, שֵׁרוּת, ו מאגר שיעורים.

אנו רוצים לוודא שהאפליקציה הזו עומדת בכללים שהזכרנו קודם. אז נתחיל במבחן פשוט לכלל "שיעורי מצגת צריכים להיות תלויים רק בשיעורי שירות".

4.1. המבחן הראשון שלנו

השלב הראשון הוא ליצור קבוצה של שיעורי Java אשר ייבדקו אם הם מפרים כללים. אנו עושים זאת על ידי יצירת רגע ClassFileImporter בכיתה ולאחר מכן להשתמש באחד מאלה importXXX () שיטות:

JavaClasses jc = חדש ClassFileImporter () .importPackages ("com.baeldung.archunit.smurfs");

במקרה זה, JavaClasses מופע מכיל את כל המחלקות מחבילת היישומים הראשית שלנו וחבילות המשנה שלה. אנו יכולים לחשוב על אובייקט זה כאל אנלוגי לנבדק טיפוסי המשמש בבדיקות יחידה רגילות, מכיוון שהוא יהיה היעד להערכת הכללים.

כללים ארכיטקטוניים משתמשים באחת מהשיטות הסטטיות מה- ArchRuleDefinition הכיתה כנקודת ההתחלה שלה ממשק API שוטף שיחות. בואו ננסה ליישם את הכלל הראשון שהוגדר לעיל באמצעות API זה. נשתמש ב- שיעורים () השיטה כעוגן שלנו והוסף אילוצים נוספים משם:

ArchRule r1 = מחלקות () .that (). ResideInAPackage (".. מצגת .."). צריך (). OnlyDependOnClassesThat () .resideInAPackage (".. שירות .."); r1.check (jc);

שימו לב שאנחנו צריכים להתקשר ל חשבון() שיטת הכלל שיצרנו להפעלת הבדיקה. שיטה זו אורכת א JavaClasses יתנגד וישליך חריג אם יש הפרה.

כל זה נראה טוב, אבל נקבל רשימת שגיאות אם ננסה להריץ אותו כנגד הקוד שלנו:

java.lang.AssertionError: הפרת אדריכלות [עדיפות: MEDIUM] - כלל 'שיעורים השוכנים בחבילה' ..צגת .. 'צריכה להיות תלויה רק ​​בכיתות השוכנות בחבילה' ..שירות .. '' הופרה ( 6 פעמים): ... הושמטה רשימת השגיאות 

למה? הבעיה העיקרית בכלל זה היא onlyDependsOnClassesThat (). למרות מה שהכנסנו בתרשים החבילה, ליישום שלנו בפועל יש תלות בשיעורי JVM ובמסגרת האביב, ומכאן השגיאה.

4.2. שכתוב המבחן הראשון שלנו

אחת הדרכים לפתור שגיאה זו היא להוסיף סעיף שלוקח בחשבון את התלות הנוספת:

ArchRule r1 = מחלקות () .that (). ResideInAPackage (".. מצגת .."). צריך (). OnlyDependOnClassesThat () .resideInAPackage (".. שירות ..", "java ..", "javax .. "," org.springframework .. "); 

עם שינוי זה ההמחאה שלנו תפסיק להיכשל. גישה זו, לעומת זאת, סובלת מבעיות תחזוקה ומרגישה מעט פריצות. אנו יכולים להימנע מבעיות אלה המשכתבות את הכלל שלנו באמצעות noClasses () שיטה סטטית כנקודת ההתחלה שלנו:

ArchRule r1 = noClasses () .that (). ResideInAPackage (".. מצגת .."). צריך (). DependOnClassesThat () .resideInAPackage (".. התמדה .."); 

כמובן, אנו יכולים גם לציין כי גישה זו היא מכחיש מבוסס במקום ה מבוסס-היתר אחד שהיה לנו קודם. הנקודה הקריטית היא שבכל גישה שנבחר, ArchUnit בדרך כלל יהיו גמישים מספיק כדי לבטא את הכללים שלנו.

5. שימוש ב- סִפְרִיָהממשק API

ArchUnit הופכת את יצירת הכללים האדריכליים המורכבים למשימה קלה בזכות הכללים המובנים שלה. אלה, בתורם, ניתנים לשילוב, ומאפשרים לנו ליצור כללים באמצעות הפשטה גבוהה יותר. מחוץ לקופסא, ArchUnit מציע את ממשק API לספרייה, אוסף של כללים ארוזים מראש העוסקים בבעיות אדריכלות נפוצות:

  • אדריכלות: תמיכה בבדיקות כלל ארכיטקטורות בשכבות ובצל (aka משושים או "יציאות ומתאמים")
  • פרוסות: משמש לאיתור תלות מעגלית, או "מחזורים"
  • כללי: אוסף כללים הקשורים לשיטות קידוד מיטביות כגון רישום, שימוש בחריגים וכו '.
  • PlantUML: בודק אם בסיס הקוד שלנו עומד במודל UML נתון
  • הקפאת כללי הקשת: שמור הפרות לשימוש מאוחר יותר, ומאפשר לדווח רק על חדשות. שימושי במיוחד לניהול חובות טכניים

הכיסוי של כל הכללים הללו אינו מתחום ההקדמה הזו, אבל בואו נסתכל על ה- ארכיטקטורה חבילת כלל. בפרט, בואו נכתוב מחדש את הכללים בסעיף הקודם באמצעות כללי הארכיטקטורה בשכבות. השימוש בכללים אלה דורש שני שלבים: ראשית אנו מגדירים את שכבות היישום שלנו. לאחר מכן, אנו מגדירים אילו גישות שכבה מותרות:

LayeredArchitecture arch = layeredArchitecture () // הגדר שכבות. שכבה ("מצגת"). מוגדר על ידי (".. מצגת .."). שכבה ("שירות"). מוגדר על ידי (".. שירות .."). שכבה (" התמדה "). DefinedBy (" .. התמדה .. ") // הוסף אילוצים .whereLayer (" מצגת "). MayNotBeAccessedByAnyLayer () .whereLayer (" שירות "). MayOnlyBeAccessedByLayers (" מצגת ") .whereLayer (" התמדה ") .mayOnlyBeAccessedByLayers ("שירות"); arch.check (jc);

פה, layeredArchitecture () היא שיטה סטטית מה- אדריכלות מעמד. כאשר הוא מופעל, הוא מחזיר חדש אדריכלות שכבתית אובייקט, שבו אנו משתמשים כדי להגדיר שכבות שמות וקביעות בנוגע לתלות שלהם. אובייקט זה מיישם את ArchRule ממשק כדי שנוכל להשתמש בו בדיוק כמו כל כלל אחר.

הדבר המגניב בממשק ה- API המסוים הזה הוא שהוא מאפשר לנו ליצור בכמה שורות קוד כללים שאחרת ידרשו מאיתנו לשלב מספר כללים בודדים.

6. מסקנה

במאמר זה בחנו את יסודות השימוש ArchUnit בפרויקטים שלנו. אימוץ כלי זה הוא משימה פשוטה יחסית שיכולה להשפיע לטובה על האיכות הכללית ולהוזיל את עלויות התחזוקה בטווח הארוך.

כרגיל, כל הקוד זמין ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found