346. CSAML - C# Application Markup Language

[מבוסס על הפוסט הזה]
למי שיצא לעבוד עם 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
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
Console.WriteLine("Hello, C#");
}
}
}

שימו לב לפורמט חסר המבנה החופשי הזה – לא ניתן לסבול אותו בסביבות מחשוב מודרניות: תסתכלו על רצף המילים "public static void Main". מהן המילים האלו? איך הן קשורות אחת לשנייה? אין שום דרך לדעת. מהבעיות הללו התחמקו בימי ALGOL, אבל כיום כבר לא ניתן להתעלם מהן.

מצד שני, הסתכלו על הבהירות של התוצאות כאשר הקוד השקול מבוטא בSyntax שמייצג דיוק והתחשבות. זהו קובץ CSAML עם ההצהרות של הnamespace הנוכחי:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<CsamlFile xmlns="http://schemas.microsoft.com/winfx/2010/xaml/csaml"
xmlns:x="http://schemas.microsoft.com/winfx/2010/xaml">
<NamespaceDeclaration Identifier="MyNamespace">
<ClassDeclaration Identifier="MyClass"
Access="Public">
<MethodDeclaration Identifier="Main"
Access="Public"
Modifier="Static"
ReturnType="{x:Type void}">
<InvocationExpression
MemberAccess="System.Console.WriteLine">
<InvocationExpression.ArgumentList>
<Literal Type="{x:Type string}"
Value="Hello, CSAML! " />
</InvocationExpression.ArgumentList>
</InvocationExpression>
</MethodDeclaration>
</ClassDeclaration>
</NamespaceDeclaration>
</CsamlFile>

כפי שבוודאי תשימו לב, רוב שמות ה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>
<Assignment LValue="A">
<Assignment.Expression>
<MultiplicationExpression>
<Multiplication.Multiplier>
<Literal Type="{x:Type Int32}"
Value="5" />
</Multiplication.Multiplier>
<Multiplication.Multiplicand>
<AdditionExpression Augend="B">
<AdditionExpression.Addend>
<Multiplication.Multiplier>
<Literal Type="{x:Type Int32}"
Value="27" />
</Multiplication.Multiplier>
<MultiplicationExpression Multiplicand="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>
<Assignment LValue="i">
<Assignment.Expression>
<Literal Type="{x:Type Int32}"
Value="0" />
</Assignment.Expression>
</Assignment>
</StatementExpressionList>
</ForLoop.Initializer>
<ForLoop.Condition>
<BooleanExpression>
<LessThanExpression LeftSide ="i">
<LessThanExpression.RightSide>
<Literal Type="{x:Type Int32}"
Value="1000" />
</LessThanExpression.RightSide>
</LessThanExpression>
</BooleanExpression>
</ForLoop.Condition>
<ForLoop.Iterator>
<StatementExpressionList>
<PreIncrementExpression Identifier="i" />
</StatementExpressionList>
</ForLoop.Iterator>
<ForLoop.EmbeddedStatement>
<IfStatement>
<IfStatement.Condition>
<BooleanExpression>
<InvocationExpression MemberAccess="IsPrime">
<InvocationExpression.ArgumentList>
<Variable Identifier="i" />
</InvocationExpression.ArgumentList>
</InvocationExpression>
</BooleanExpression>
</IfStatement.Condition>
<IfStatement.EmbeddedStatement>
<StatementList>
<PreIncrementExpression Identifier="j" />
</StatementList>
</IfStatement.EmbeddedStatement>
</IfStatement>
</ForLoop.EmbeddedStatement>
</ForLoop>

בהמשך נראה עוד שימושים מדהימים לCSAML.

בסופו של הדבר הכוח האדיר של שפה זו היא שהיא מאפשרת לנו להרחיב ולתקן את האפליקציה שלנו ללא שינוי קוד!

שבוע סקמלי טוב.

שתף