[מבוסס על הפוסט הזה] למי שיצא לעבוד עם WPF, יצא בוודאי להתקל בXAML (Extensible Application Markup Language) – זהו תקן שמשחק תפקיד חשוב בWPF ומאפשר לנו לבנות יישומים בצורה שניתנת להרחבה בצורה פשוטה.
רובנו לא מכירים, אבל החל מFramework 4.0, נוספה תמיכה בתקן דומה שנקרא CSAML (C# Application Markup Language, נהגה לעתים כScammel) – זהו תקן המהווה אלטרנטיבה לSyntax של C# המבוסס על Xmlו-XAML. למעשה, CSAML משתמש בSyntax של הProperty Element של XAML בשביל לייצג הצהרות מסובכות.
שפה זו בעצם יוצרת מיזוג בין C# וXml ומייצגת קפיצה משמעותית בהתפתחות של שני התקנים, ואף מייצג פיתוח שטרם נראה כמוהו ב”Xmlיזציה” של מידע טקסטואלי.
כעת נראה מספר דוגמאות לשימוש בCSAML:
הסתכלו על התוכנית Hello World עם הSyntax המיושן של C# שכולנו מכירים:
1
2
3
4
5
6
7
8
9
10
namespaceMyNamespace
{
publicclassMyClass
{
publicstaticvoidMain()
{
Console.WriteLine("Hello, C#");
}
}
}
שימו לב לפורמט חסר המבנה החופשי הזה – לא ניתן לסבול אותו בסביבות מחשוב מודרניות: תסתכלו על רצף המילים "public static void Main". מהן המילים האלו? איך הן קשורות אחת לשנייה? אין שום דרך לדעת. מהבעיות הללו התחמקו בימי ALGOL, אבל כיום כבר לא ניתן להתעלם מהן.
מצד שני, הסתכלו על הבהירות של התוצאות כאשר הקוד השקול מבוטא בSyntax שמייצג דיוק והתחשבות. זהו קובץ CSAML עם ההצהרות של הnamespace הנוכחי:
כפי שבוודאי תשימו לב, רוב שמות הElementים כן מבוססים על הספציפיקציה של שפת C#, כך שכל מתכנת C# שמכיר את השמות מהספציפיקציה, יכול להתחיל לתכנת בCSAML באופן מיידי.
ע"י כך שנשענת על המבנה ההיררכי של Xml, שפת CSAML מסוגלת לוותר על על הסוגריים המסולסלים, הסוגריים המרובעים וסוגריים שמאפיינים את הSyntax המוכר של C#. כפי ששמתם לב בקובץ לעיל, סוגריים מסולסלים שמורים לשימוש שלהם בהרחבה של XAML, כמו x:Type.
למעשה, CSAML מסוגלת להעיף כל Symbol שקיים בSyntax המוכר של C#. למשל, שימו לב להשמה הבאה בSyntax הישן של C#:
1
A = 5 * (B + 27 * C);
בלי יותר מדי בעיות, הSyntax הזה מתרגם לCSAML הזה:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<ExpressionStatement>
<AssignmentLValue="A">
<Assignment.Expression>
<MultiplicationExpression>
<Multiplication.Multiplier>
<LiteralType="{x:Type Int32}"
Value="5" />
</Multiplication.Multiplier>
<Multiplication.Multiplicand>
<AdditionExpressionAugend="B">
<AdditionExpression.Addend>
<Multiplication.Multiplier>
<LiteralType="{x:Type Int32}"
Value="27" />
</Multiplication.Multiplier>
<MultiplicationExpressionMultiplicand="C"/>
</AdditionExpression.Addend>
</AdditionExpression>
</Multiplication.Multiplicand>
</MultiplicationExpression>
</Assignment.Expression>
</Assignment>
</ExpressionStatement>
היתרון של ייצוג כזה ברור:
בגלל שאין צורך (ואפילו אסור) שימוש בסוגריים, המתכנת מרכיב את הCSAML תוך התחשבות זהירה בבעיה.
יש סיכוי גדול יותר ששגיאות קימפול לא יופיעו.
הקומפיילר הופך להיות הרבה יותר יעיל, בגלל שכל הצהרה, "פורסרה" ע"י המתכנת.
הנה עוד דוגמה לבעיה האבסורדית האולי הכי ידועה לשמצה בכל תכנות C# מסורתי: לולאת הfor:
1
2
3
4
5
6
7
for (i = 0, j = 0; i < 1000; i++)
{
if (IsPrime(i))
{
j++;
}
}
בCSAML האוסף של הSymbolים והנקודות-פסיק הנ"ל ננטש לטובת מבנה יפהפה שיכול לגרום למתכנת המודרני להתמוגג מאושר:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<ForLoop>
<ForLoop.Initializer>
<StatementExpressionList>
<AssignmentLValue="i">
<Assignment.Expression>
<LiteralType="{x:Type Int32}"
Value="0" />
</Assignment.Expression>
</Assignment>
</StatementExpressionList>
</ForLoop.Initializer>
<ForLoop.Condition>
<BooleanExpression>
<LessThanExpressionLeftSide ="i">
<LessThanExpression.RightSide>
<LiteralType="{x:Type Int32}"
Value="1000" />
</LessThanExpression.RightSide>
</LessThanExpression>
</BooleanExpression>
</ForLoop.Condition>
<ForLoop.Iterator>
<StatementExpressionList>
<PreIncrementExpressionIdentifier="i" />
</StatementExpressionList>
</ForLoop.Iterator>
<ForLoop.EmbeddedStatement>
<IfStatement>
<IfStatement.Condition>
<BooleanExpression>
<InvocationExpressionMemberAccess="IsPrime">
<InvocationExpression.ArgumentList>
<VariableIdentifier="i" />
</InvocationExpression.ArgumentList>
</InvocationExpression>
</BooleanExpression>
</IfStatement.Condition>
<IfStatement.EmbeddedStatement>
<StatementList>
<PreIncrementExpressionIdentifier="j" />
</StatementList>
</IfStatement.EmbeddedStatement>
</IfStatement>
</ForLoop.EmbeddedStatement>
</ForLoop>
בהמשך נראה עוד שימושים מדהימים לCSAML.
בסופו של הדבר הכוח האדיר של שפה זו היא שהיא מאפשרת לנו להרחיב ולתקן את האפליקציה שלנו ללא שינוי קוד!