Android topics — 18: מציגים פרויקט באמצעות ראיות


בעיה, דרישה מדידה, ארכיטקטורה, בדיקות, מגבלה והדגמה קצרה

מפת המעבדות · המסד שעליו מבוססת הדוגמה

בסוף המעבדה תלמיד אחר יכול לפתוח את פרויקט topics, להבין איזו בעיה מסך הספרים פותר, להריץ אותו, לאתר את רכיבי הקוד המרכזיים, ולבדוק טענה אחת חשובה: Favorite של Ada נשמרת אחרי restart. התוצר הוא ארבעה מסמכים קצרים וצילום ראיה בענף codex/project-evidence. קוד האפליקציה עצמו לא משתנה בענף הזה.

בסיס ההשוואה הוא codex/room-persistence. זה מכוון: כאשר מלמדים אפיון, תיעוד והצגה, ה־diff יכול להיות תיעוד שמסביר מערכת קיימת שנבדקה. אל תתארו תכונה עתידית בלשון עבר ואל תכתבו “עובד” בלי תרחיש ותוצאה שניתן לשחזר.

1. מתחילים מהבעיה ומהתוצאה הנצפית

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

flowchart LR
    A[Open app] --> B[Load books]
    B --> C[Save Ada]
    C --> D[Restart process]
    D --> E[Load books]
    E --> F[Ada shows Saved]

בענף התוצאה, docs/requirements.md מגדיר שש דרישות עם מזהים R1–R6. למשל:

מזהה דרישה בדיקת קבלה
R2 סימון נצמד לזהות ספר, לא למיקום שורה סמן Ada, גלול הרחק וחזור, טען מחדש וסובב; Ada נשארת מסומנת
R3 Favorite נשמרת מקומית אחרי Saved ★, עצור את התהליך, פתח וטען שוב; Ada עדיין Saved ★
R4 שדרוג סכימה שומר מידע צור מסד v1 עם ID 7, שדרג ל־v2, וקרא ID 7 עם note ריק

טבלת הדרישות אינה רשימת API. היא קושרת פעולת משתמש → תוצאה שאפשר לצפות בה. R4 אינה גלויה במסך, לכן קושרים אותה לבדיקת migration. אם תשובה לבדיקה תלויה ב”כנראה”, חסר קריטריון קבלה או ראיה.

2. מציירים מי מחזיק כל מצב

docs/architecture.md מציג זרימת נתונים אחת. קראו אותה מול הקוד שב־app > kotlin+java > com.example.topics:

flowchart LR
    U[Tap] --> A[Activity + Adapter]
    A --> V[BooksViewModel]
    V --> R[FavoritesRepository]
    R --> D[FavoriteDao]
    D --> DB[(Room database)]
    DB --> D
    D --> R
    R --> V
    V --> S[BooksUiState]
    S --> A

MainActivity מטפלת ב־View Binding, לחיצות וציור מצב. BooksViewModel מחזיקה את מצב המסך. FavoritesRepository מעבירה עבודת Room ל־Executor ומחזירה snapshot ל־main thread. FavoriteDao מבצעת את השאילתה וה־transaction. BookAdapter מצייר את הספר לפי ID; הוא לא שומר אמת במסך ממוחזר.

הוסיפו למסמך טבלת אחריות לכל רכיב: “מה הוא מחזיק” ו”מה הוא לא מחזיק”. הגבול השני חשוב לא פחות מן הראשון. למשל, Activity אינה מריצה SQL, ו־DAO אינה מחליטה מה להציג בשגיאה. מתחת לתרשים רשמו גם מודל נתונים: טבלת favorites, מפתח ראשי bookId, גרסת סכימה 2 ועמודת note עם ברירת מחדל. זה מאפשר לבוחן לעבור מן התרשים לשורת קוד ולבדיקה.

3. מתעדים החלטה עם מחיר, לא רק שם תבנית

ב־docs/architecture.md כל החלטה כוללת סיבה ומחיר:

החלטה סיבה מחיר/גבול
Room במקום Set בזיכרון סימון צריך לשרוד סיום תהליך סכימה ו־migration דורשות תכנון ובדיקות
Executor יחיד עבודת DB מחוץ ל־main וסדר פעולות ברור אינו פתרון כללי לכל עומס במקביל
@Transaction ל־toggle קריאה וכתיבה כפעולה אטומית במסד אינו פותר תחרות בין מכשירים בענן

המשפט “השתמשנו ב־MVVM כי זו ארכיטקטורה טובה” אינו מסביר החלטה. הסבירו איזה באג או קושי חלוקת האחריות מונעת. בדוגמה הזאת, הסימון אינו נודד ל־ViewHolder אחר בזמן מיחזור, ו־Activity חדשה אחרי סיבוב יכולה לצייר מצב שמגיע מן ViewModel/מסד.

4. בונים תיק ראיות שאפשר לבדוק מחדש

ב־docs/verification.md כתובה הפקודה :app:connectedDebugAndroidTest, סוג המכשיר וארבע הבדיקות שרצו ב־28 בספטמבר 2026: בדיקת UI של מיחזור/טעינה/סיבוב, בדיקת migration מ־v1 ל־v2, בדיקת toggle במסד ובדיקת template שלא הוסרה. בדוח JUnit שנוצר באותה ריצה הופיעו 4 tests,‏ 0 failures,‏ 0 errors.

בנוסף בוצע מסלול ידני: התקנת APK, שמירת Ada, force stop, פתיחה מחדש וטעינת ספרים. הצילום docs/evidence/favorite-after-restart.png מציג את המצב הסופי Saved ★. הצילום לבדו אינו מוכיח שקרה restart; רצף הפעולות והבדיקה האוטומטית משלימים את הראיה. בדיקת migration מתחילה מ־1.json ישן — התקנה נקייה של v2 לא הייתה בודקת את אותו דבר.

ב־Search Everywhere פתחו את README.md ואת הקבצים ב־docs/ בענף התוצאה. אלו קבצי שורש שעשויים לא להופיע בתצוגת Android של Android Studio. README.md נותן הוראות הפעלה ומגבלות; requirements.md קושר דרישות לבדיקות; architecture.md קושר רכיבים לנתונים; verification.md אומר מה בדיוק נבדק. אין להעתיק את מסקנת הבדיקות לפרויקט אחר בלי להריץ אותן שם.

5. מציגים שלוש דקות בלי להסתיר מגבלה

docs/demo-script.md מציע סדר קצר:

  1. 0:00–0:30: בעיית הקורא ודרישת ההתמדה.
  2. 0:30–1:30: טעינה, שמירה, גלילה ו־restart מול המסך האמיתי.
  3. 1:30–2:20: הצבעה על Activity → ViewModel → Repository → DAO → Room וחזרה ל־UI.
  4. 2:20–3:00: בדיקות migration/UI, ואז מגבלה אמיתית: שגיאת כתיבה למסד עדיין אינה מוצגת למשתמש.

למגבלה יש הצעת תיקון קונקרטית: תוצאת success/error טיפוסית ב־Repository, הצגת שגיאה למסך והחלטת Retry בטוחה. לא מתקנים אותה במסמך בלבד; המסמך מונע טענה לא מדויקת לגבי גרסה נוכחית. המטרה היא שהצופה יוכל לשאול “איך אתה יודע?” ולקבל קובץ, בדיקה ותרחיש רלוונטיים.

6. מעבירים לפרויקט של התלמיד

בחרו תכונה אחת שכבר עובדת בפרויקט שלכם. צרו README.md וארבעה קבצים קצרים תחת docs/, או מסמך שקול עם אותם חלקים. לכל טענה מרכזית כתבו:

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

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

שאלות בדיקה

  1. איזו ראיה מוכיחה ש־Favorite נשמרה אחרי תהליך חדש, ואיזו ראיה רק מראה את המסך הסופי?
  2. כיצד מבדילים בין בדיקת migration ובין התקנה חדשה של סכימה v2?
  3. מה חסר אם במסמך ארכיטקטורה יש שמות רכיבים אבל אין מקור אמת או כיוון זרימת מידע?
  4. איזה חלק בהדגמה שלכם הייתם מקצרים אם נשארה דקה אחת, ומה עדיין חייב להיאמר?