DCSIMG
May 2007 - Posts - IHateSpaghetti {code}

IHateSpaghetti {code}

VSX, DSL and Beyond by Eyal Lantzman

Syndication

Coding / Architecture

Extensibility /DSL

Projects

Articles

May 2007 - Posts

We had interesting problem @work. We use serviced components as distributed transactions backend and we tried to use ReadCommited synchronization level to boost performance.

 

However we use some product that requires Serialized synchronization level – this is a problem because you can't run on single transaction (unless it uses serialized synchronization level).

So we thought of the following solution – run the components that requires serialized as RequiredNew (instead of Required – meaning, each instance of the services component will use a new transaction, instead of sharing existing one).

 

So far are you with me? Hope so.

 

OK so we have to different transaction but how can we control the commit / abort process if we need to run both of them using data calculated in each stage on different transactions? (see the flow below for example).

 

We need to write a little bit of code. But before that lets define the problems, the tools we have and than come up with a solution.

 

The problem: synchronizing two transactions – commit together / rollback together.

 

General flow

 

  1. Run code on T1
  2. Run code on T2
  3. Run code on T1
  4. Run code on T2
  5. if has error rollback T2 + T1
  6. else commit T2 + T1

The tools at our disposal: ContextUtil , [AutoComplete]

-          ContextUtil – setting done bit and consistent bit (more info)

-          [AutoComplete] – method level attribute that automatically sets the bits (on exception aborts trasaction) (more info)

 

The solution:

Manually use SetComplete / SetAbort in T2 context, in order to commit / rollback T2, without using AutoComplete attribute.

The Code in charge of T2 must provide commit / rollback public methods (they will use SetComplete / SetAbort inorder to run on T2 context).

 

Code snippet:

[Transaction(TransactionOption.Required)]
[Guid("....")]
public class Tran1 :ServicedComponent
{
  [AutoComplete]
  public void DoWork()
  {
    string data = GetDataOnTran1();
    using (Tran2 tran2 = new Tran2)
    {
      try{
      //do work with data from transaction 1 on transaction 2
      //becarefull about using resources that haven't been commited yey
      //such as tables with FK
      string processedData = tran2.DoWork(data)
      
      //process data returned from transaction 2 on transaction 1
      string evenMoreProcessedData = DoMoreWork(processedData);

      //processes data again on trasaction 2
      data = tran2.DoMoreWork(evenMoreProcessedData );

      //Manualy commit data on trasaction 2 (trasaction 1 not commited yet)
      tran2.CommitData();

      }
      catch
      {
        //notice the manul rollback of transaction 2
        tran2.RollbackData();
        
        throw;
      }
    }
  }

  private string DoMoreWork(string someWork)
  {
    ...
  }
}


[Transaction(TransactionOption.RequiredNew)]  //new trasaction
[Guid("....")]
public class Tran2 :ServicedComponent
{
  //no autocomplete here
  public string DoWork()
  {
    ...      
  }

  private string DoMoreWork(string someWork)
  {
    ...
  }

  public void CommitData()
  {
    //notice that when using context util methods, they run in CONTEXT of the transaction, meaning on transaction 2
    ContextUtil.SetComplete();
  }

  public void RollbackData()
  {
    //notice that when using context util methods, they run in CONTEXT of the transaction, meaning on transaction 2
    ContextUtil.SetAbort();
  }
}

 

Final remarks:

The solution is not bullet proof – in case of error/timeout when T2 is already committed, there's no way to perform rollback and we get inconsistent data (T1 will perform rollback). However  this is better that nothing

Posted by Eyal | with no comments
תגים:,

Another step for making .NET multiplatform "developer friendly" language.

the relavent post.

 

(Mono is the "non microsoft" implementaion to .NET available for multiple platforms.)

 

Posted by Eyal | with no comments
תגים:

This was posted on infoq.

it's aprox. half an hour long and quite nice.

Posted by Eyal | with no comments
תגים:

MS plans for the future, as i can see, are to focus on (BIO)SCIENCE sector, by providing them better support in data handling, modeling and language.

http://research.microsoft.com/towards2020science/downloads/T2020S_Roadmap.pdf

 

Will be nice to read in 13 years and compare the goals vs reality ;-)

Posted by Eyal | with no comments
תגים:

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

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

 

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

 

הבעיה הראשונה - איפיון לא חד משמעי. כולנו קיבלנו במייל את התמונה שהלקוח רואה בחזון שלו דבר אחד, איש המכירות מוכר לא דבר אחר, המאפיין מגדיר את מה שמגדיר והמפתח עושה בכלל משהו אחר (לטוב או לרע). הבעיה בזה שהלקוח או המאפיין (שנניח שמייצג אותו נאמנה ומכיר את המערכת לעומקה) מעורבים בשלב מאוחר יחסית, אחרי שהQA עברו על הUC/מודול כבר עשרות פעמים ומצאו את רוב הבאגים (בתקווה, כמובן) והמתפחים תיקנו אותם (כאן שוב התקווה מתבקשת). ואז מתחיל ספור הספגטי שאני כ"כ שונא (הכוונה כפי שכותרת הבלוג מציינת - קוד ספגטי). מתחילים פאטצ'ים, שנויים וכל מיני קומבינות שמביאות את איכות התוצר לא לאותה רמה אלמלא היו מפתחים את הUC בהבנה מלאה (כולל הרקע הלא בהכרח פונקציונאלי של אותו המסך), כלומר TOP TO BOTTOM. מתחילים בUI - מייצרים MOCUPים שהלקוח (או אדם מטעמו) יקבל תחושה של איך התוצר הסופי יראה ומה יכולתיו. רב המצבים שבהם הלקוח התכוון לא' וקיבל ב' ימנעו בשיטת עבודה זו. השיטה גם מכוונת לכך שהשלב הבא יהיה כתיבת תסריטי בדיקה אוטומטייים. אחרי הDD, שאר הקוד כבר פחות או יותר יכתוב את עצמו.

 

נעבור לארכיטקטורה, גם כאן אני לא אתשמש במלים כגון SOA, SaS, Messaging ושות'

הבעיה השניה - תשתיות חסרות או ירושה קצרה מידי. בפרוייקט הנוכחי שאני נמצא בו, הושקע הרבה זמן ומאמץ בתשתיות שמספקות את רוב צרכי המערכת וזה מצויין אבל אפשר גם יותר טוב. רובינו מפתחים בN-TIER או לכל הפחות מפרידים את הקוד לASSEMBLYים. לדעתי חייבת להיות לכל שכבה שאחראית על סוג עבודה ספציפי (כגון: BL, DAL וכד') מחלקה בסיסית (גם אם היא ריקה) שכולם יורשים ממנה. במידה ובעתיד צריך לספק מימוש או יכולת לכל המחלקות באותה רמה יוסיפו אותה בהמחלקה שכולם יורשים. אני יודע שאני לא ממציא שום גלגל ואני בטח שלא החמישי מGoF אבל לא מעט פעמים הדברים הפשוטים נשכחים בשלב הראשון והחל מאותו הרגע כל שינוי, במיוחד בפרוייקט מרובה בני אדם (שלכול אחד מהם הרבה UC באחריותם) ידחה (לפעמים בצדק ולפעמים לא) בגלל שלא אוהבים לגעת במה שעובד(מכאן אנחנו חוזרים שוב לנושא הספגטי).

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

 

הבעיה השלישית - הבעיה הזאת שייכת מבחינתי לבעיה השניה אבל בשביל להדגיש את החשיבות אני הפרדתי אותה. כמה פעמים יצא לכם לכתוב קוד שעושה פעולות CRUD(אולי משתמש בEnterprise Library או בתשתית שאתה כתבתם) ? כמה פעמים יצא לכם לכתוב רכיבים שמציגים ועורכים מידע מיישות / דאטאסט ? לא מעט נכון ? הבכן בפרוייקטים מרובי שנות אדם (שמרבים לבזבז חלק ניכר מהשנים האלה על יצירה של רכיבים כאלה בדיוק ובדיקתם) כדאי לשקול יצירה אוטמטית של קוד.

הכלים כבר קיימים עוד מdotNet 1.0 וכיום רק משתכללים יותר ויותר (גם מסתכים אבל זה סיפור אחר). הכלי הכי פשוט בעיניי הוא CodeSmith (עבור מפתחי asp.net השימוש יהיה מאוד מוכר ופשוט). הבעיה איתו  שהוא תומך ביצירה של קוד בלי יכולות של עדכון במקרה והיה שינוי בתבנית. בעיה ? אולי בdotNet 1.x כיום יש לנו partial class ולכן אנחנו יכולים פשוט להוסיף קוד בpartial class במקום אחר ולא לגעת בקוד המיוצר, כך שבמקרה של תיקון/שכלול תבנית, הקוד של התבנית הישנה פשוט יוחלף.

הכלים היותר חדשים הינם DSLTools וGAT. לא יצא לי להכנס לעומקם אבל ממה שראיתי היכולות הנפלאות שהם מוסיפים מומרים בסיבוכיות די גדולה ורמת מומחיות די גבוהה שתידרש מאנשי הפיתוח שיפתחו תשתית אלו (כן מבחינתי אלא תשתיות !). אבל אני מאמין שהם יכנסו לMainstream בשנים הקרובות.

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

 

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

אשמח לתגובות והערות !

Posted by Eyal | 2 comment(s)