استخدام لغة البرمجة CSCS للتطوير عبر الأنظمة الأساسية

نشرت: 2022-03-10
ملخص سريع ↬ في هذه المقالة ، يشرح فاسيلي كابلان كيف يمكنك استخدام لغة البرمجة النصية لتطوير تطبيقات الهاتف المحمول عبر الأنظمة الأساسية. ستجد أمثلة في كل من iOS و Android تتضمن وضع عناصر واجهة مستخدم على الشاشة و SQLite وطلبات الويب وتحليل JSON.
هدفنا ليس بناء منصة ؛ أن يتم عبورها جميعًا.

- مارك زوكربيرج

CSCS (البرمجة النصية المخصصة في C #) هي لغة برمجة نصية مفتوحة المصدر مطبقة في C #. إنها تشبه إلى حد بعيد JavaScript من الناحية النحوية ، ولكن لديها أيضًا بعض أوجه التشابه مع Python. بعض أوجه التشابه هذه هي الكلمات الرئيسية في بناء if…elif…else المعروف جيدًا ، ولديها أيضًا نفس تعريف النطاق المتغير كما هو الحال في Python (على سبيل المثال ، سيكون المتغير المحدد داخل كتلة if أو داخل حلقة مرئيًا أيضًا بالخارج) .

على عكس JavaScript و Python ، فإن المتغيرات والوظائف في CSCS غير حساسة لحالة الأحرف. الهدف الأساسي من CSCS هو السماح للمطور بكتابة أقل قدر ممكن من الكود . أيضًا ، يتم استخدام نفس الرمز لكل من تطوير iOS و Android. بالإضافة إلى ذلك ، يمكن استخدام CSCS لتطوير أنظمة Windows و Mac و Unity.

ملاحظة : يمكنك قراءة المزيد حول كيفية استخدام Microsoft لـ CSCS في منتج Maquette (بناءً على الوحدة) هنا.

يمكن إضافة CSCS إلى مشروعك عن طريق تضمين كود مصدر C # في مشروع Visual Studio Xamarin. على عكس معظم اللغات الأخرى ، لديك ملكية كاملة لشفرة مصدر CSCS ويمكنك بسهولة إضافة وظائفها أو تعديلها. سأقوم بمشاركة مثال على ذلك لاحقًا في المقالة.

أيضًا ، سوف نتعلم كيفية بدء استخدام CSCS واستخدام بعض الميزات الأكثر تقدمًا التي تمت تغطيتها في مقالات أخرى. من بين هذه الميزات ، سنصل إلى خدمة الويب عبر طلبات الويب مع تحليل سلسلة JSON ، وسنستخدم أيضًا SQLite على iOS و Android.

أسهل طريقة للبدء هي تنزيل عينة من مشروع باستخدام CSCS والبدء في اللعب بملف start.cscs . هذا ما سنفعله في القسم التالي: إنشاء تطبيق iOS / Android باستخدام واجهة المستخدم الرسومية الأساسية والأحداث.

المزيد بعد القفز! أكمل القراءة أدناه ↓

"مرحبا بالعالم!" في CSCS

لنبدأ بمثال بسيط نسبيًا لرمز CSCS الذي ينشئ شاشة بها بعض الأدوات:

 AutoScale(); SetBackgroundColor("light_green"); locLabelText = GetLocation("ROOT", "CENTER", "ROOT", "TOP"); AddLabel(locLabelText, "labelText", "Welcome " + _DEVICE_INFO_ + " " + _VERSION_INFO_ + " User!", 600, 100); locTextEdit = GetLocation("ROOT", "LEFT", labelText, "BOTTOM"); AddTextEdit(locTextEdit, "textEdit", "Your name", 320, 80); locButton = GetLocation(textEdit,"RIGHT",textEdit, "CENTER"); AddButton(locButton, "buttonHi", "Hello", 160, 80); function buttonHi_click(sender, arg) { name = getText(textEdit); msg = name != "" ? "Hello, "+ name + "!" : "Hello, World!"; AlertDialog("My Great App", msg); }

تُظهر الصورة أدناه واجهة المستخدم الناتجة على جهاز iPhone بالإضافة إلى جهاز Android بعد النقر فوق الزر "مرحبًا" وعدم كتابة أي شيء في حقل "تحرير النص":

مرحبا بالعالم!" على iPhone (يسار) و Android (يمين)
"مرحبا بالعالم!" على iPhone (يسار) و Android (يمين) (معاينة كبيرة)

دعنا ننتقل بإيجاز إلى الكود أعلاه. يبدأ باستدعاء الوظيفة AutoScale() ، وما يفعله ذلك هو إخبار المحلل اللغوي أن أحجام عناصر واجهة المستخدم مرتبطة بحجم الشاشة ، أي سيتم تغيير حجمها تلقائيًا (ستبدو الأداة أكبر على الشاشات الأكبر وأصغر على الشاشات الصغيرة شاشات). يمكن أيضًا تجاوز هذا الإعداد لكل عنصر واجهة مستخدم.

لاحظ أنه ليست هناك حاجة لإنشاء معالج خاص بنقرة زر. إذا قمت بتحديد وظيفة بالاسم widgetName_click() ، فسيتم استخدامها كمعالج عندما ينقر المستخدم على عنصر واجهة مستخدم يسمى widgetName (ليس بالضرورة أن يكون زرًا ، يمكن أن يكون في الواقع أي عنصر واجهة مستخدم). لهذا السبب سيتم تشغيل زر الوظيفة buttonHi_click() بمجرد أن ينقر المستخدم على الزر.

ربما لاحظت أن واجهة المستخدم الرسومية مبنية بالكامل في التعليمات البرمجية. يتم ذلك عن طريق توفير موقع عنصر واجهة تعامل نسبي عند إضافته. التنسيق العام لأمر الموقع هو كما يلي:

 location = GetLocation(WidgetX, HorizontalPlacement, WidgetY, VerticalPlacement, deltaX=0, deltaY=0, autoResize=true);

لذلك ، يمكنك وضع عنصر واجهة تعامل مع عناصر واجهة مستخدم أخرى على الشاشة. حالة خاصة لعنصر واجهة المستخدم هي أداة "ROOT" ، والتي تعني الشاشة الرئيسية.

بعد إنشاء موقع ، تحتاج إلى تقديمه كوسيطة لأي من الوظائف التالية:

  • AddLabel ،
  • AddButton ،
  • AddCombobox ،
  • AddStepper ،
  • AddListView ،
  • AddTextView ،
  • AddStepper ،
  • AddImageView ،
  • AddSlider ،
  • AddPickerView ،
  • وما إلى ذلك وهلم جرا.

كل ما سبق له نفس الهيكل:

 AddButton(location, newWidgetname, initialValue, width, height);

سيكون عرض عنصر واجهة المستخدم وارتفاعه متناسبين مع حجم الشاشة إذا تم تشغيل أمر AutoScale() CSCS مسبقًا. أيضًا ، القيمة الأولية (في حالة وجود زر) هي النص المعروض عليها. يمكن تغيير هذا في أي وقت عن طريق استدعاء SetText(widgetName, newText) .

استخدام Visual Studio Code لتصحيح أخطاء CSCS

يمكننا أيضًا استخدام Visual Studio Code لتصحيح أخطاء نصوص CSCS. إذا كنت ترغب في تطوير تطبيقات لكل من Android و iOS ، فأنت بحاجة إلى استخدام جهاز Mac. بعد تثبيت Visual Studio Code ، قم بتثبيت ملحق CSCS Debugger و REPL.

من أجل استخدام الامتداد ، أضف هذا السطر من التعليمات البرمجية في أي مكان في البرنامج النصي الخاص start.cscs CSCS:

 StartDebugger();

توضح الصورة التالية أدناه كيف يمكنك استخدام Visual Studio Code لتصحيح وتغيير وظيفة "Hello، World!" التطبيق الذي قمنا بتطويره في القسم السابق. في المثال التالي ، سنضيف تسمية وزرًا سريعًا إلى التخطيط الحالي.

للقيام بذلك ، نختار فقط الكود الذي سيتم تنفيذه بواسطة المحلل اللغوي ثم نضغط على Ctrl + 8 . نتيجة لذلك ، ستتم إضافة تسمية وزر في منتصف الشاشة. نضيف أيضًا معالج زر من شأنه تحديث التسمية الجديدة بالوقت الحالي عند كل نقرة زر.

تغيير التخطيط أثناء التنقل باستخدام Visual Studio Code
تغيير التخطيط أثناء التنقل باستخدام Visual Studio Code (معاينة كبيرة)

استخدام سكليتي في CSCS

SQLite هو نوع حمض (Atomicity، Consistency، Isolation، Durability) لقاعدة بيانات علائقية ، وقد تم تطويره بواسطة Richard Hipp (تم إصدار الإصدار الأول في عام 2000). بخلاف قواعد البيانات العلائقية الأخرى ، مثل Microsoft SQL Server أو Oracle Database ، فهو مضمن. (مدمج ليس فقط في الجهاز ، ولكن أيضًا في البرنامج النهائي.) إنه مدرج في البرنامج كمكتبة مضغوطة جدًا ، يقل حجمها عن 500 كيلوبايت. لكن يمكن لتطبيقين (تم إصدارهما بواسطة نفس المطور) قراءة نفس قاعدة بيانات SQLite إذا كان مسار ملف قاعدة البيانات معروفًا لكلا التطبيقين.

تتمثل ميزة SQLite في أنه يمكن استخدامه دون تثبيت إضافي على جهاز iOS أو Android. العيب هو أنه من الواضح أنه لا يمكن أن يحتوي على الكثير من البيانات مثل قاعدة البيانات "العادية" وأيضًا أنه مكتوب بشكل ضعيف (على سبيل المثال ، يمكنك إدخال سلسلة بدلاً من عدد صحيح - سيتم تحويلها بعد ذلك إلى عدد صحيح أو 0 عند الفشل). من ناحية أخرى ، يمكن اعتبار الأخير ميزة أيضًا.

يمكن استخدام SQLite بسهولة من CSCS بدون عبارات استيراد إضافية. فيما يلي جدول سيساعدك في الحصول على نظرة عامة على وظائف SQLite الرئيسية المستخدمة في CSCS:

أمر وصف
SQLInit(DBName) يهيئ قاعدة بيانات أو يحدد قاعدة بيانات لاستخدامها مع عبارات قاعدة البيانات اللاحقة.
SQLDBExists(DBName) للتحقق مما إذا كانت قاعدة البيانات قد تمت تهيئتها. يعيّن أيضًا قاعدة البيانات لاستخدامها مع عبارات قاعدة البيانات اللاحقة.
SQLQuery(query) ينفذ استعلام SQL (جملة تحديد). إرجاع جدول بالسجلات.
SQLNonQuery(nonQuery) ينفذ استعلام SQL غير ، على سبيل المثال تحديث أو إنشاء أو حذف بيان. إرجاع عدد السجلات المتضررة.
SQLInsert(tableName, columnList, data) يُدرج جدول بيانات السجلات الذي تم تمريره إلى جدول قاعدة البيانات المحدد. تحتوي وسيطة columnList على البنية التالية: colName1,colName2,…,colNameN

الجدول 1: أوامر SQLite في CSCS

هذه هي الطريقة التي يتم بها استخدام SQLInit() و SQLDBExists() عادةً:

 DBName = "myDB.db1"; if (!SQLDBExists(DBName)) { create = "CREATE TABLE [Data] (Symbol ntext, Low real, High real, Close real, Volume real, Stamp text DEFAULT CURRENT_TIMESTAMP)"; SQLNonQuery(create); } SQLInit(DBName);

سنرى المزيد من الأمثلة حول كيفية تحديد وإدراج البيانات في قاعدة بيانات SQLite لاحقًا. سأريكم مثالاً على كيفية كتابة بيانات المخزون التي تم استخراجها من خدمة ويب إلى قاعدة بيانات SQLite محلية.

إضافة وظائف مخصصة إلى CSCS

في هذا القسم ، سنرى كيف يمكنك توسيع وظيفة CSCS. كمثال ، سنرى التنفيذ الحالي لوظيفة CSCS Sleep أدناه.

لإضافة وظيفة مخصصة ، كل ما عليك فعله هو إنشاء فئة جديدة عن طريق الاشتقاق من فئة ParserFunction ، وتجاوز طريقة Evaluate() الخاصة بها ، وتسجيل هذه الفئة مع المحلل اللغوي. إليك نسخة قصيرة (بدون تدقيق الأخطاء):

 class SleepFunction : ParserFunction { protected override Variable Evaluate(ParsingScript script) { List args = script.GetFunctionArgs(); int sleepms = Utils.GetSafeInt(args, 0); Thread.Sleep(sleepms); return Variable.EmptyInstance; } } class SleepFunction : ParserFunction { protected override Variable Evaluate(ParsingScript script) { List args = script.GetFunctionArgs(); int sleepms = Utils.GetSafeInt(args, 0); Thread.Sleep(sleepms); return Variable.EmptyInstance; } }

يمكن تسجيل فصل دراسي مع المحلل اللغوي في أي مكان في مرحلة التهيئة عن طريق الأمر التالي:

 ParserFunction.RegisterFunction("Sleep", new SleepFunction());

هذا هو! الآن سيتم استدعاء طريقة Evaluate() لفئة SleepFunction بمجرد استخراج رمز "Sleep" بواسطة المحلل اللغوي.

لاحظ أن CSCS غير حساس لحالة الأحرف (باستثناء عبارات تدفق التحكم الأساسية: if ، elif ، else ، for ، while ، function ، include ، new ، class ، return ، try ، throw ، catch ، break ، continue ). هذا يعني أنه يمكنك كتابة إما "سكون (100)" أو "سكون (100)" - كلا الاستدعائين سيوقفان سلسلة التنفيذ لمدة 100 مللي ثانية.

معالجة JSON في CSCS

JSON (JavaScript Object Notation) هو تنسيق خفيف لتبادل البيانات ، ويتألف من أزواج قيمة السمة وأزواج من نوع الصفيف. تم تطويره بواسطة Douglas Crockford في أوائل العقد الأول من القرن الحادي والعشرين (في نفس الوقت تقريبًا عندما ظهر SQLite أيضًا).

في هذا القسم ، سوف نتعلم كيفية تحليل JSON باستخدام CSCS.

دالة CSCS لتحليل سلسلة JSON هي GetVariableFromJSON(jsonText) . تقوم هذه الوظيفة بإرجاع جدول تجزئة تكون فيه المفاتيح هي السمات من سلسلة JSON.

ضع في اعتبارك المثال التالي لسلسلة JSON:

 jsonString = '{ "eins" : 1, "zwei" : "zweiString", "mehr" : { "uno": "dos" }, "arrayValue" : [ "une", "deux" ] }';

بعد الاحتجاج:

 a = GetVariableFromJSON();

سيكون المتغير a جدول تجزئة بالقيم التالية:

 a["eins"] = 1 a["zwei"] = "zweiString" a["mehr"]["uno"] = "dos" a["arrayValue"][0] = "une" a["arrayValue"][1] = "deux"

في القسم التالي ، سنرى مثالًا آخر لتحليل سلسلة JSON من خدمة ويب.

مثال على تطبيق به SQLite وطلبات الويب و JSON

بالنسبة إلى تطبيق يستخدم SQLite و Web Service و JSON ، سنستخدم Alpha Vantage Web Service. يمكنك الحصول على API Key مجانًا ولكن الإصدار المجاني لا يسمح بالوصول إلى خدمة الويب الخاصة بهم أكثر من 5 مرات في الدقيقة.

باستخدام Alpha Vantage ، يمكنك استخراج مجموعات بيانات مالية متنوعة - بما في ذلك أسعار الأسهم. هذا ما سنفعله في نموذج التطبيق الخاص بنا.

توضح الصورة أدناه كيف تبدو تطبيقات الأسهم على نظام iOS وعلى جهاز Android.

استخراج الأسهم من Alpha Vantage Web Service على iOS (يسار) وأندرويد (يمين)
استخراج الأسهم من Alpha Vantage Web Service على iOS (يسار) وأندرويد (يمين) (معاينة كبيرة)

كود CSCS لبناء واجهة المستخدم الرسومية هو كما يلي:

 locLabel = GetLocation("ROOT","CENTER", "ROOT","TOP", 0,30); AddLabel(locLabel, "labelRefresh", "", 480, 60); locSFWidget = GetLocation("ROOT","CENTER", labelRefresh,"BOTTOM"); AddSfDataGrid(locSFWidget, "DataGrid", "", graphWidth, graphHeight); listCols = {"Symbol","string", "Low","number", "High", "number", "Close","number", "Volume","number"}; AddWidgetData(DataGrid, listCols, "columns"); colWidth = {17, 19, 19, 19, 26}; AddWidgetData(DataGrid, colWidth, "columnWidth"); locButton = GetLocation("ROOT","CENTER",DataGrid,"BOTTOM"); AddButton(locButton, "buttonRefresh", "Refresh", 160, 80); locLabelError = GetLocation("ROOT","CENTER","ROOT","BOTTOM"); AddLabel(locLabelError, "labelError", "", 600, 160); SetFontColor(labelError, "red"); AlignText(labelError, "center"); getDataFromDB();

ستستخرج طريقة getDataFromDB() جميع البيانات من قاعدة بيانات SQLite. يستخدم استعلام SQL المحدد على النحو التالي:

 query = "SELECT Symbol, Low, High, Close, Volume, DATETIME(Stamp, 'localtime') as Stamp FROM Data ORDER BY Stamp DESC LIMIT 5;";

ألق نظرة على الكود أدناه لتطبيق getDataFromDB() .

 function getDataFromDB() { results = SQLQuery(query); for (i = 1; i < results.Size; i++) { vals = results[i]; stock = vals[0]; low = Round(vals[1], 2); high = Round(vals[2], 2); close = Round(vals[3], 2); volume = Round(vals[4], 2); refresh = vals[5]; stockData = {stock, low, high, close, volume}; AddWidgetData(DataGrid, stockData, "item"); } SetText(labelRefresh, "DB Last Refresh: " + refresh); lockGui(false); }

الآن دعنا نرى كيف نحصل على البيانات من Alpha Vantage Web Service. أولاً ، نقوم بتهيئة البيانات:

 baseURL = "https://www.alphavantage.co/query? " + "function=TIME_SERIES_DAILY&symbol="; apikey = "Y12T0TY5EUS6BC5F"; stocks = {"MSFT", "AAPL", "GOOG", "FB", "AMZN"}; totalStocks = stocks.Size;

بعد ذلك ، نقوم بتحميل الأسهم واحدًا تلو الآخر بمجرد أن ينقر المستخدم على الزر "تحديث":

 function buttonRefresh_click(object, arg) { lockGui(); SetText(labelRefresh, "Loading ..."); SetText(labelError, ""); ClearWidget(DataGrid); loadedStocks = 0; getData(stocks[loadedStocks]); } function getData(symbol) { stockUrl = baseURL + symbol + "&apikey=" + apikey; WebRequest("GET", stockUrl, "", symbol, "OnSuccess", "OnFailure"); }

فيما يلي وظيفة CSCS الرئيسية التي يجب استخدامها للحصول على البيانات من خدمة الويب:

 WebRequest("GET", stockUrl, "", symbol, "OnSuccess", "OnFailure");

المعلمتان الأخيرتان هما دالات يتم استدعاؤها عند إكمال طلب الويب. على سبيل المثال ، في حالة حدوث فشل ، سيتم استدعاء وظيفة CSCS التالية:

 function OnFailure(object, errorCode, text) { SetText(labelError, text); lockGui(false); }

نتيجة لذلك ، سيتلقى المستخدم رسالة خطأ كما هو موضح أدناه:

خطأ عند طلب بيانات الويب
حدث خطأ عند طلب بيانات الويب (معاينة كبيرة)

ولكن ، إذا كان كل شيء جيدًا ، فسنقوم بتحليل سلسلة JSON وإدخال محتوياتها في SQLite DB.

 function OnSuccess(object, errorCode, text) { jsonFromText = GetVariableFromJSON(text); metaData = jsonFromText[0]; result = jsonFromText[1]; symbol = metaData["2. Symbol"]; lastRefreshed = metaData["3. Last Refreshed"]; allDates = result.keys; dateData = result[allDates[0]]; high = Round(dateData["2. high"], 2); low = Round(dateData["3. low"], 2); close = Round(dateData["4. close"], 2); volume = dateData["5. volume"]; stockData = {symbol, low, high, close, volume}; SQLInsert("Data","Symbol,Low,High,Close,Volume",stockData); if (++loadedStocks >= totalStocks) { getDataFromDB(); } else { getData(stocks[loadedStocks]); } }

لفهم كيفية وصولنا إلى الحقول المختلفة في جدول التجزئة أعلاه ، دعنا نلقي نظرة على السلسلة الفعلية المستلمة من طلب ويب Alpha Vantage:

 { "Meta Data": { "1. Information": "Daily Prices (open, high, low, close) and Volumes", "2. Symbol": "MSFT", "3. Last Refreshed": "2019-10-02 14:23:20", "4. Output Size": "Compact", "5. Time Zone": "US/Eastern" }, "Time Series (Daily)": { "2019-10-02": { "1. open": "136.3400", "2. high": "136.3700", "3. low": "133.5799", "4. close": "134.4100", "5. volume": "11213086" }, … } }

كما ترى ، نحصل على أحدث تاريخ كعنصر أول في allDates جميع التواريخ الذي يتكون من جميع التواريخ المستخرجة.

خاتمة

من السهل إضافة CSCS إلى مشروعك. كل ما عليك فعله هو ببساطة تضمين الكود المصدري لـ CSCS كوحدة نمطية في مشروعك - تمامًا كما يتم في مشروع Xamarin عينة.

هل تستخدم لغة البرمجة النصية CSCS وتوسعها في مشاريعك؟ اترك تعليقًا أدناه - يسعدني أن أسمع منك!

قراءة متعمقة

إذا كنت ترغب في استكشاف لغة CSCS أكثر قليلاً ، فإليك بعض المقالات التي كتبتها حول هذا الموضوع:

  • "A Split-and-Merge Expression Parser in C #،" MSDN Magazine (أكتوبر 2015)
  • "برمجة نصية قابلة للتخصيص في C # ،" مجلة MSDN (فبراير 2016)
  • "كتابة تطبيقات الجوال الأصلية باستخدام لغة برمجة قابلة للتخصيص" ، مجلة MSDN (فبراير 2018)
  • “CSCS: برمجة مخصصة في C # ،” GitHub
  • "تطوير تطبيقات أصلية عبر الأنظمة الأساسية باستخدام لغة برمجة وظيفية ،" مجلة CODE
  • "تنفيذ لغة مخصصة بإيجاز" (كتاب إلكتروني)
  • "كتابة تطبيقات الجوال الأصلية بلغة وظيفية بإيجاز" (كتاب إلكتروني)

كمورد إضافي ، أوصي أيضًا بقراءة كيف يمكنك تحسين أداء CSCS من خلال تجميع وظائفها مسبقًا.