תכנון מחדש של הארכיטקטורה של התכנה
-
זהירות!! יצא לי קצת ארוך..
אני מנסה כרגע לעשות חשיבה מחודשת, ולתכנן את התכנה שלי מאפס.
מדובר בתכנה להצגת תוכן של ספרים, עם יכולת חיפוש בינונית (כרגע..).
מדובר על משהו בסגנון של פרוייקט השו"ת (דהיינו שמציג את התוכן של הספר ממש, ולא PDF כמו באוצה"ח ודומיו), אך שאמור להיות הרבה יותר פשוט, בלי כל מיני אופציות מסובכות (שלפעמים רק מקשות על החיים.. כיון שלפעמים מרוב עצים לא רואים את היער..), אלא יהיו בה 2 טאבים: האחד כולל את עץ הספרים דרכו ניתן לנווט ישירות ולהציג את תוכן הספר/פרק וכו' המבוקש. השני - מסך חיפוש, עם כל מיני אופציות לחיפוש, ותצוגת תוצאות החיפוש.
כל זה כבר קיים כרגע ועובד לא רע.. אלא שאני רוצה לשפר את זה, כיון שכרגע זה נתמך רק במע' הפעלה של 64 סיביות, עקב זה שהאובייקטים שמכילים את תוכן הספרים - גדולים מדי.. כמו כן, אני רוצה להוסיף תמיכה בהערות שוליים, דבר שכרגע לא קיים. לכן אני מנסה לתכנן את הכל שוב מההתחלה.בעקרון יש ב' סוגי ספרים:
א. ספר שהניווט בו הוא על פי דפים ועמודים, ולא על פי התוכן (כמו למשל ברכות דף מד עמוד ב, וכדו')
ב. ספר שהניווט בו הוא על פי פרקים ופסקאות, ולא כ"כ משנה באיזה עמוד זה נמצא (כמו למשל בראשית פרק ב פסוק א, או ברכות פרק ו משנה א וכדו').
כמובן שאפשר לשלב בין ב' הדברים, אך נראה לי שבד"כ זה לא כ"כ נצרך.לשם כך אני מתכנן אובייקט בשם ספר שיכיל את המזהה, שם הספר, והתוכן שלו. התוכן יכול להכיל או ליסט של עמודים וכו' או ליסט של פרקים וכו'.
באפשרות של העמודים - כל עמוד יכיל מזהה, ואוסף של שורות, כל שורה תכיל מזהה ואוסף של מילים, כל מילה תכיל מזהה ואוסף של אותיות, כל אות תכיל מזהה, תוכן האות, מאפיין עיצוב (כגון מודגש, קו תחתון וכו') ואוסף של הערות (אם קיימות, וכמובן כל הערה מכילה גם מילים, ואותיות וכו').
באפשרות של הפרקים - כל פרק יכיל מזהה, את שם הפרק וכן אופציה של כותרת (דהיינו תיאור קצר על תוכן הפרק), וכן את הVALUE שלו. הVALUE יכול להכיל או רשימה של פרקים נוספים (במקרה שיש תת פרקים, כגון משניות, פסוקים, הלכות וכדו'), או את התוכן ישירות (במקרה בו אובייקט ה"פרק" הוא בעצם משנה או פסוק או הלכה), דהיינו ליסט של מילים המכילות אותיות (על הדרך שנתבאר באופן הקודם).
אני רוצה שהאובייקטים יהיו כמה שיותר גנריים, ולכן אני לא רוצה לעשות כמו שעשיתי מקודם (פרק, פסקה, תת-פסקה וכדו') אלא אובייקט אחד שיכול לשמש לי גם לפרק שרק מכיל רשימה של פרקים, וגם לפרק שמכיל ישירות את התוכן. כמובן שבשביל זה אני צריך שהVALUE יהיה מסוג גנרי שממש ממשק מסוים (כדי להבטיח שמשתמשים בסוג מתאים ולא באובייקטים אחרים..) או שגם ה"פרק"ים וגם ה"מילים" יירשו מאותו אבא, והוא יהיה מהסוג של האבא.
עד כאן נראה לי הכל טוב ויפה. אם זה נראה מיותר או עקום או כל דבר אחר - אשמח לשמוע הערות והארות!!כדי לאפשר טעינה איטית, ולא לטעון מראש את כל הספרים, אני רוצה לבנות אינדקס שיודע למפות כל ID לאיזה ספר (כמובן גם כאן ע"פ הID של הספר) הוא שייך. כמו כן, לבנות לכל ספר אינדקס נפרד, שKEY שלו מכיל את כל הID שקיימים בו, והVALUE מכיל את הפניה למיקום של האובייקט עצמו בזכרון (בין אם זה פרק/עמוד/שורה/מילה/אות/הערה).
כך שכאשר המשתמש בוחר בתפריט בספר מסוים - התכנה מיד תחפש לאיזה ספר הID הזה שייך, ותטען את אובייקט הספר והאינדקס שלו. ואז היא תיגש ע"פ האינדקס של הספר לID הרצוי - ותציג את התוכן.
האינדקס נועד כדי לאפשר גישה מהירה יותר לתוכן הספר, במקום להתחיל הרצה של חיפושים מקוננים על כל ספר כדי למצוא ID של מילה, שורה או פסקה.
העניין הוא שאני חושב שיותר נכון זה לטעון את האובייקט של הספר, רק לאחר שהמשתמש בחר בו, ורק אז לטעון את האינדקס שלו, וגם את האובייקט "ספר" הרלוונטי.
**השאלה שלי היא:**הרי האינדקס מחזיק בסה"כ מצביע למיקום בזכרון של האובייקט הרלוונטי. והרי כיון שהאובייקט לא קיים בזכרון כל הזמן, אלא אני טוען אותו רק כאשר המשתמש בוחר בו, א"כ לכאו' המיקום משתנה, והמיקום אליו מצביע האינדקס כבר לא נכון, לא? שהרי בשעה שאני יוצר את האינדקס, באמת האובייקט קיים בזכרון, ואז הוא באמת מחזיק את ההפניה הנכונה, אולם לאחר מכן אני עושה סריליזציה, והזכרון משתחרר. ולאחר מכן כאשר אעשה דיסרילזציה ואטען אותו שוב, המחשב יקצה לו מקום אחר, א"כ ההפניה של האינדקס כבר לא תהיה נכונה?! או שמא אני טועה..
אם כן, האם ישנה דרך לעשות זאת? או שבכלל אני עובד מסורבל?אשמח לשמוע עצות, הארות והערות!
תודה רבה לכל מי שקרא עד לכאן.. וכמו כן, תודה רבה רבה מראש לכל מי שיקדיש מזמנו ויגיב.
אברהם.פורסם במקור בפורום CODE613 ב29/06/2016 12:47 (+03:00)
-
שוב אני מריח שמישהו רוצה לפתח דטה בייס, ואני שואל בשביל מה??? בשביל פרוייקט של ספרים??? או שאתה חברה לפיתוח מסדי נתונים (שזה לגיטימי לגמרי בעיני אבל לא נראה לי שספרים זה כר ניסיון טוב).
קח לך את אלסטיקס סערצ' אם אתה רוצה לפתח מנגנון חיפוש יעיל מדהים ומהמם, אפילו הכלי המיושן SQL סערבער, גם יכול לעזור....
את כל הכאבי ראש הללו שלך, לוקח הדטה בייס על עצמו בלי נדר... ואתה חופשי להתעסק בלוגיקה של התוכנה בצורה נקייה.פורסם במקור בפורום CODE613 ב29/06/2016 12:59 (+03:00)
-
יש לך חוש ריח מפותח :lol:
אני פשוט הולך בעקבות רחמים שטען בתוקף בפורום, שבשביל לאפשר חיפוש בספרים - אין צורך בשום דטה בייס, ושזה סתם מיותר ומכביד.פורסם במקור בפורום CODE613 ב29/06/2016 13:26 (+03:00)
-
לא מבין את ארכיטקט בקשר לDB, לדעתי התוכנה הזו לא צריכה בכלל מסד נתונים. כי היא מאוד סטטית. הכל קבוע (יחסית, לא שאי אפשר להוסיף ספרים אבל בגדול אין CRUD).
אני לא מבין כ"כ את הכיוון שלך אברהם, אתה מנסה לעשות שהכל מתועד באובייקטים ובד בבד להיות אופליין. אני לא רואה פה כמעט צורך בOOP.
אני הייתי עושה
א. שמירה בדיסק של הספרים בצורה שתאפשר קריאה אקראית (תכף אסביר).
ב. ביצוע מיפוי בין כל סוג חלוקה בספר לבין מיקום בדיסק, למשל ברכות>דף>22 (מזהה ספר>מזהה חלוקה>ערך) == קובץ 50 פוזיציה 35600. את המיפוי הזה הייתי גם שומר בדיסק וגם מעלה לזיכרון תמיד.
ג. מיפוי ממש דומה אבל הפוך, בין ספר ומיקום לכל סוג חלוקה, כמו מזהה ספר,מיקום>סוג יחידה,יחידה.
ד. מילון של Distinct של כל המילים שבכל המאגרים, לליסט של מזהה+מיקום כמו תפוח: (ברכות:15264, שמות:412). גם את המילון הזה הייתי שומר על דיסק, וטוען כל פעם בטעינת התוכנה לזיכרון.
ה. בדיסק עצמו הייתי שומר את הטקסט בצורה עשירה כלומר עם סימנים שקל להמירם לעיצוב. וגם סימנים שיקלו על הסורק החד פעמי בהכנסת ספר לדעת את סוג היחידה.
ו. בחיפוש מילים כל שהם כל הקומבינציות מול המילון של אות ד. בהתקבל התוצאות, לברר את המיקום הידידותי של כל תוצאה (מברכות:15264 לברכות דף כג) ע"י מילון של אות ה. לטעון מהמיקום המדוייק את התוצאה שמופיעה על המסך (אפשר לחסוך את היתר אבל לא קריטי) ולפענח אותה (מהסימנים העשירים ומסימני היחידות) ע"י פונקציה מתאימה.סליחה שאני מחרבש הכל...
ארכיטקטורה זה כמו הסיפור עם האב הבן והחמור...פורסם במקור בפורום CODE613 ב29/06/2016 13:33 (+03:00)
-
גם אם משתמשים במסד נתונים צריך להשתמש בו בחכמה..
זה לא הולך שמחפשים בתוך שדה TEXT רגיל.
אני מביא פה מבנה של החיפוש של הפרום הזה.
CREATE TABLE IF NOT EXISTS `phpbb_search_wordlist` ( `word_id` mediumint(8) unsigned NOT NULL, `word_text` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '', `word_common` tinyint(1) unsigned NOT NULL DEFAULT '0', `word_count` mediumint(8) unsigned NOT NULL DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ALTER TABLE `phpbb_search_wordlist` ADD PRIMARY KEY (`word_id`), ADD UNIQUE KEY `wrd_txt` (`word_text`), ADD KEY `wrd_cnt` (`word_count`); ALTER TABLE `phpbb_search_wordlist` MODIFY `word_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT; CREATE TABLE IF NOT EXISTS `phpbb_search_wordmatch` ( `post_id` mediumint(8) unsigned NOT NULL DEFAULT '0', `word_id` mediumint(8) unsigned NOT NULL DEFAULT '0', `title_match` tinyint(1) unsigned NOT NULL DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ALTER TABLE `phpbb_search_wordmatch` ADD UNIQUE KEY `unq_mtch` (`word_id`,`post_id`,`title_match`), ADD KEY `word_id` (`word_id`), ADD KEY `post_id` (`post_id`);
פורסם במקור בפורום CODE613 ב29/06/2016 13:35 (+03:00)
-
קח לך את אלסטיקס סערצ' אם אתה רוצה לפתח מנגנון חיפוש יעיל מדהים ומהמם, אפילו הכלי המיושן SQL סערבער, גם יכול לעזור....
האלסטיקס נראה באמת משהו טוב לא הכרתי אותו..
יש לך ניסיון איתו?
אפשר לשלב אותו בקלות עם דוטנט?פורסם במקור בפורום CODE613 ב29/06/2016 13:38 (+03:00)
-
קח לך את אלסטיקס סערצ' אם אתה רוצה לפתח מנגנון חיפוש יעיל מדהים ומהמם, אפילו הכלי המיושן SQL סערבער, גם יכול לעזור....
האלסטיקס נראה באמת משהו טוב לא הכרתי אותו..
יש לך ניסיון איתו?
אפשר לשלב אותו בקלות עם דוטנט?אפשר הכל בדוט נט, אלסטיקס נועד בשביל המטרות הללו של חיפוש, זה כלי עם אפשרויות אדירות, דורש כמובן למידה, אבל זה שווה את האלפי שעות שאתה עלול לבזבז על פיתוח מנגנון חיפוש לבד אם אתה לא עובד איתו.
פורסם במקור בפורום CODE613 ב29/06/2016 13:47 (+03:00)
-
@דוד ל.ט.
אני לא מבין כ"כ את הכיוון שלך אברהם, אתה מנסה לעשות שהכל מתועד באובייקטים ובד בבד להיות אופליין. אני לא רואה פה כמעט צורך בOOP.
אתה צודק ממש! אני באמת הרגשתי שזה קצת מיותר.
מאידך, לא בדיוק הבנתי איך אני שומר את הטקסט בצורה עשירה? ע"י קובץ XML עם נתוני מטה דטה? או שמא בתוך הסטרינג להכניס * לפני הדגשה וכדו'? כמו כן, איך אני אסמן את המיקומים של הקובץ (החלוקה לפרקים עמודים וכו') בשביל הסריקה של המיפוי?
מה זה "מילון של Distinct"? מחיפוש קצר בגוגל הבנתי שזאת מתודה להסרת כפולים??@דוד ל.ט.
ארכיטקטורה זה כמו הסיפור עם האב הבן והחמור...
לא מכיר את הסיפור
MAT - לא הבנתי מה פירוש השורה הבאה:
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
תודה רבה רבה לכולם על ההשקעה בתשובות!!
פורסם במקור בפורום CODE613 ב29/06/2016 15:18 (+03:00)
-
מאידך, לא בדיוק הבנתי איך אני שומר את הטקסט בצורה עשירה? ע"י קובץ XML עם נתוני מטה דטה? או שמא בתוך הסטרינג להכניס * לפני הדגשה וכדו'?
כן.
תוכל להשתמש בJSON או כל פורמט שאתה רוצה. אבל אתה צריך לשמור את המיקומים של הבית הפיזי פר כל חלוקה מכל סוג כדי לאפשר גישה אקראית.
למשל אם הקובץ נראה ככה:{"Items":[{"typeUnit":15,"value":"22","display":null},{"Value":"בן בג בג אומר...","Formats":null},{"typeUnit":15,"value":"23","display":null},{"Value":"בן הא הא אומר...","Formats":null}]}
אז אתה צריך לבנות טבלה שבה יש מזהה ספר, מזהה יחידה, ערך ומיקום של ה{ לפי תו מתחילת הקובץ, וככה אתה יכול לשלוף אקראית כל מקטע.
קל לי לדבר, זה טיפה מורכב, אבל אין לי ספק שזה הדרך וזה לא כ"כ קשה, אבל קשה.
בדוגמה שלי זה די אובייקטלי אבל תוכל לעבוד בכל דרך כמו שאמרת עם כוכביות סולמיות וכל מה שבא לך.כמו כן, איך אני אסמן את המיקומים של הקובץ (החלוקה לפרקים עמודים וכו') בשביל הסריקה של המיפוי?
אתה מכין קוד שהעבודה שלו תהיה לסרוק ספר כתוב ולמפות כל מקום שמתחיל יחידה חדשה, לשמור את מזהה הספר (ברכות), סוג היחידה (פרק), ערך (3) ומיקום בקובץ (124005).
מה זה "מילון של Distinct"? מחיפוש קצר בגוגל הבנתי שזאת מתודה להסרת כפולים??
הכוונה פשוטה, במילון אי אפשר שיהיו ערכים כפולים, כך שמילה שמופיעה המון כמו "את" יהיה לה רשימה ארוכה מאוד של ספרים ומיקומים, אבל עדיין מפתח יחיד במילון.
ארכיטקטורה זה כמו הסיפור עם האב הבן והחמור...
לא מכיר את הסיפור
אמא שלי סיפרה לי כשהייתי קטן... https://en.wikipedia.org/wiki/The_miller,_his_son_and_the_donkey
אין לי כח לספר כעתפורסם במקור בפורום CODE613 ב29/06/2016 16:23 (+03:00)
-
נזכרתי בסיפור (אחרי שראיתי את ההפניה לויקיפדיה..) :lol:
@דוד ל.ט.אבל אתה צריך לשמור את המיקומים של הבית הפיזי פר כל חלוקה מכל סוג כדי לאפשר גישה אקראית.
למשל אם הקובץ נראה ככה:{"Items":[{"typeUnit":15,"value":"22","display":null},{"Value":"בן בג בג אומר...","Formats":null},{"typeUnit":15,"value":"23","display":null},{"Value":"בן הא הא אומר...","Formats":null}]}
אז אתה צריך לבנות טבלה שבה יש מזהה ספר, מזהה יחידה, ערך ומיקום של ה{ לפי תו מתחילת הקובץ, וככה אתה יכול לשלוף אקראית כל מקטע.
קל לי לדבר, זה טיפה מורכב, אבל אין לי ספק שזה הדרך וזה לא כ"כ קשה, אבל קשה.אתה מתכוון לשמור את המיקום של הbyte (אין לי מושג איך לדעת מהו בדיוק הbyte שהוא תופס :?: ) או כמו שכתבת בהמשך "מיקום של התו { מתחילת הקובץ" ?
ומדוע לשמור את המיקום של { מתחילת הקובץ, אשמור כבר את המיקום של המילה עצמה מתחילת הקובץ?בכל אופן, כדי ליצור JSON כמו שבנית, צריך קודם להמיר את המסמך לאובייקטים כמו שניסיתי לתכנן, אלא שלאחר שאני עושה להם סריליזציה, לא צריך שוב לטעון אותם לאובייקטים אלא פשוט ישירות לגשת לסטרינג של הJSON ולשלוף את המידע הדרוש. או שהתכוונת לומר שאין משמעות לאובייקטים, אלא העיקר שתהיה לי צורת סימון ברורה, כדי שאוכל אח"כ לשלוף את המידע מתוכה?
תודה רבה רבה על הזמן והטרחה בכתיבת התשובה! (אני יודע מעצמי שקשה למצוא זמן לענות..)פורסם במקור בפורום CODE613 ב29/06/2016 17:01 (+03:00)
-
תו, לא בית, כי בקידוד UTF כל תו הוא כמה בתים. בעצם תשתמש עם מה שאתה רוצה אבל בעקביות מול הReader.
לשמור את מיקום המילה? גם... זה המילון... אבל חשוב לשמור את מיקום היחידה כי ככה אתה טוען אותה בשלמות ובאלגנטיות. מה שכבתי מה{ זה בהתאם לפורמט שלך כמובן העיקר שלא יחסר לך שום מידע כשטען את הקטע הזה.
בקשר לJSON אפשר לעושת עם אובייקטים אבל ממש לאו דוקא. האובייקטים לא יהיו כפי שתיארת שהם מנסים לדעת הכל על מה שמתרחש אלא סה"כ כלי תיאור מה נמצא איפה.
פורסם במקור בפורום CODE613 ב29/06/2016 17:08 (+03:00)
-
@avr416
אנסה [size=150:3t2z1rnu]ואעדכן[/size:3t2z1rnu].אני כתבתי בכתב רגיל :lol:
אז ככה, זה אכן סיפור קצת מורכב, התחלתי לעשות את זה, אך עצרתי באמצע כיון שכרגע אני לא כ"כ מתעסק עם תכנות עד סוף ה'זמן'. (אם כי אני עדיין מתגעגע וקופץ לפה מדי פעם לראות מה חדש ) לא סתם דוד התלונן שמשעמם פה..
אך אל דאגה!! אני מתכוון לחזור לזה (בלנ"ד) ואז כשהפרוייקט יהיה מוכן - אעדכן באיזה צורה עשיתי זאת.לבינתיים אתה יכול לראות כאן איך בפרוייקט הזה הם מימשו את הדטה בייס שלהם. תחת המאפיין text הם מחזיקים את התוכן. בש"ס למשל הם מחזיקים מערך של מערכים נוספים, כל מערך הוא עמוד, וכל מערך מכיל אוסף של סטרינגים, שכל סטרינג הוא שורה. תחת המאפיין sectionNames הם שומרים את המידע איך קוראים לכל חלוקה (דף, שורה). זה ממש מזכיר את מה שדוד הציע.
פורסם במקור בפורום CODE613 ב30/07/2016 23:27 (+03:00)