من مترجم: هذه المقالة عبارة عن ترجمة
لمواد كتبها المبرمج
Alastair Paragas من Apple ، وقد عملت مع لغات برمجة مثل Javascript و Python و PHP و Java و Scala و Haskell و Swift و Rust. يشارك Alastair أفكاره حول موضوع اختيار وتعلم لغته ، لأن هذه المسألة ذات صلة بالمبتدئين والمحترفين الذين يرغبون في اختيار مجموعة أدوات جديدة.
سواء كنت تتعلم لغة برمجة من أجل التوظيف أو التدريب المتقدم ، أم أنها هواية خالصة ، سيتعين عليك الاختيار عاجلاً أم آجلاً. كيف تفعل ذلك؟ السؤال ليس بسيطًا ، لكن الجواب: آلاف المبرمجين يقومون به يوميًا. لتسهيل مهمتك ، يجدر اتباع بعض المبادئ.
توصي Skillbox بما يلي: دورة تدريبية عملية "Web Developer Web Developer" .
نذكركم: لجميع قراء هبر - خصم 10000 روبل عند التسجيل في أي دورة من سكيل بوكس وفقًا لرمز هبر الترويجي
.
المؤشرات المقارنة
مستويات التجريدإذا تم تعميمها بشدة ، يمكننا القول أن لغات البرمجة الحديثة مقسمة إلى ثلاثة أنواع:
- "سريع" ، الذي يستخدم لإنشاء تطبيقات أو نماذج أولية بسرعة.
- "البنية الأساسية" ، التي تساعد على تحسين أو تعديل أجزاء من تطبيق مكتوب بالفعل من أجل زيادة إنتاجيته.
- ما يسمى لغات برمجة النظام ، والتي يتيح لك استخدامها التحكم الكامل في ذاكرة الجهاز.
بطبيعة الحال ، فإن الفصل الحقيقي للأنواع بين لغات البرمجة أقل صرامة: هناك متغيرات وسيطة مختلطة من أنواع مختلفة.
إذا كنا نتحدث عن تعلم اللغات ، فعليك أولاً تجربة النوع الأول - اللغات "السريعة": فهي تسمح لك برؤية نتيجة العمل على الفور والتعلم من أخطائك. هؤلاء هم بشكل أساسي PHP و Javascript و Ruby و Python. حد الدخول هنا هو الحد الأدنى ، ويمكنك تعلم الأساسيات في وقت قصير. تحتوي هذه اللغات على مكتبات قياسية تسمح لك بإضافة عدد كبير من الوظائف إلى التطبيق ، ونطاق قدراتها كبير جدًا.
from concurrent.futures import ThreadPoolExecutor from http.client import HTTPException from urllib import request from typing import Union, Dict, Any, List def get_request_task(url: str) -> Union[List[Dict[str, Any]], None]: try: contents = None with request.urlopen(url) as response: contents = response.read() return contents except HTTPException: return None with ThreadPoolExecutor() as executor: for result in executor.map(get_request_task, [ "https://jsonplaceholder.typicode.com/posts", "https://jsonplaceholder.typicode.com/comments", "https://jsonplaceholder.typicode.com/albums" ]): if result is None: print("Something terrible has happened!") else: print(result)
تنفيذ طلبات HTTP متعددة الخيوط في Python بكتابة ثابتة. يوفر تعدد مؤشرات الترابط إمكانية تبديل ثلاث مهام (دعنا نسميها المهام A و B و C). بينما تقوم إحدى المهام (على سبيل المثال ، المهمة أ) ببعض العمليات المتعلقة بالإدخال / الإخراج (وبالتالي ، لا تقوم بأي عمل حسابي) ، يتم تنفيذ المهام الأخرى في وقت واحد معها.أما لغات "البنية التحتية" فهي لغات Java و Kotlin و Scala و Clojure بالإضافة إلى GoLang و Swift و Haskell. يمكنك الاتصال بهم بشكل مريح مع الامتداد ، لكنهم يسمحون لك بإنشاء تطبيقات منتجة. تتضمن التعقيدات عددًا أقل من العناصر الجاهزة ، والبنية الدقيقة ، وما إلى ذلك. هذه اللغات جيدة لأنها تسمح لك بضبط التطبيق. إذا كنت بحاجة إلى السرعة ، فحاول كتابة تطبيق على أحدها.
import Foundation import Dispatch func getRequestTask(url: String, dispatchGroup: DispatchGroup) { dispatchGroup.enter() let request = URLRequest(url: URL(string: url)!) let task = URLSession(configuration: URLSessionConfiguration.default).dataTask( with: request, completionHandler: { (data, response, error) in if let data = data { if let dataAsString = String(data: data, encoding: .utf8) { print(dataAsString) dispatchGroup.leave() return } } print("Something terrible has happened!") dispatchGroup.leave() } ) task.resume() } let requestDispatchGroup = DispatchGroup() for url in [ "https://jsonplaceholder.typicode.com/posts", "https://jsonplaceholder.typicode.com/comments", "https://jsonplaceholder.typicode.com/albums" ] { getRequestTask(url: url, dispatchGroup: requestDispatchGroup) } requestDispatchGroup.wait()
تم بالفعل حل مشكلة مشابهة أعلاه باستخدام Python. الآن في العمل - Swift.لغات برمجة النظام - C ، C ++ ، Rust. أنها توفر أقصى قدر من التحكم في التطبيق ، بما في ذلك إدارة الذاكرة. كما أن هذه اللغات رائعة لبرمجة وحدات التحكم الدقيقة وأجهزة الكمبيوتر ذات بنية المعالج المخصصة وأنظمة أخرى. لا تزال اللغات منخفضة المستوى مهمة ومن المرجح أن تظل ذات صلة في المستقبل القريب.
وظائفكما تعلم ، تعمل اللغات كوسيلة "للتواصل" بين الكمبيوتر والمبرمج. لكي يسير هذا التواصل بسلاسة ، يجدر دراسة بناء الجملة في اللغة بالتفصيل. على وجه الخصوص ، يجب على الاختصاصي معرفة هياكل البيانات الأكثر استخدامًا وفهم كيفية تعديل عناصر معينة من تطبيقه.
module Main where import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Resource (runResourceT) import Data.Conduit (($$+-), ($=+), runConduit) import Data.Conduit.List (mapM_, map, filter, catMaybes) import Data.Text (unpack) import Data.Maybe (fromJust) import Web.Twitter.Types (StreamingAPI(SStatus, SRetweetedStatus) , Status(Status), statusText, statusLang , RetweetedStatus(RetweetedStatus), rsRetweetedStatus ) import Web.Twitter.Conduit.Stream (stream)
هاسكل هي لغة برمجة وظيفية صارمة. يمكنه التحقق من هياكل البيانات الواردة والعمل معها إذا كانت تلبي متطلبات معينة.
وقت التشغيل - تحتاج إلى معرفة كيفية عمل تطبيقك على أنظمة مختلفة. هل هناك حاجة إلى مترجم لغة (مثل Python ، NodeJS ، PHP)؟ هل يتم إنشاء نظام ثنائي يعتمد على النظام (مثل Swift و GoLang)؟ هل تستخدم اللغة المحددة مزيجًا من الخيارين الأول والثاني ، على سبيل المثال ، يتم تجميع التطبيق وتشغيله على بعض الأجهزة الافتراضية (Java ، Scala ، Clojure)؟
بالمناسبة ، على طريق التميز ، يوصى بشدة بدراسة وبدء استخدام Docker plus للتأكد من فهم مبادئ إدارة Linux.
المكتبات - كل لغة مناسبة تمامًا في مواقف معينة. على سبيل المثال ، تلبي Java العديد من متطلبات التنسيق واللوجستيات الشبكية ، بما في ذلك دعم قاعدة البيانات من خلال توحيد واجهة JDBC ومشاريع مثل تلك التي تقع تحت دعم مؤسسة Apache. وينطبق الشيء نفسه على Python - فهو مثالي لتحليل البيانات والحسابات الإحصائية - بالإضافة إلى Haskell بقواعدها وتعبيراتها العادية ومجمعيها. تعد شعبية اللغة وحجم مجتمعها حجتين أخريين تتحدثان لصالح استخدام أداة برمجة معينة في مشروعك. إذا كان المجتمع صغيرًا ، فلا يجب الاعتماد على مساعدة سيارات الإسعاف من المشاركين فيه. والعكس صحيح ، فكلما زاد حجم المجتمع وزادت شعبية لغة البرمجة ، زادت سرعة حل المهمة الصعبة أو الحصول على المشورة من الزملاء.
جمع القمامةجمع القمامة هو شكل من أشكال إدارة الذاكرة التلقائية. تقوم عملية خاصة تسمى أداة تجميع البيانات المهملة بتحرير الذاكرة بشكل دوري عن طريق حذف الكائنات التي لم تعد هناك حاجة إليها بواسطة التطبيقات. تقوم كل لغة برمجة بذلك بطريقتها الخاصة.
تقوم بايثون بتنفيذ العد المرجعي من خلال خوارزمية إيقاف العالم. يوقف تنفيذ البرنامج مؤقتًا ، ويبدأ وينفذ جمع القمامة ، ثم يستأنف العملية الرئيسية. أثناء "التنظيف" تظهر 3 "أجيال" منفصلة - مجموعة من "أكوام القمامة". يحتوي الصفر على الكائنات "الأحدث" ، ثم يتبعها الأجيال 1 و 2.
import gc import ctypes gc.set_debug(gc.DEBUG_SAVEALL) class PyObject(ctypes.Structure): _fields_ = [("refcnt", ctypes.c_long)] object1 = {} object2 = {} object3 = {} object1['reference_to_2'] = object2 object2['reference_to_1'] = object1 object3['some_key'] = 1 object1_memory_address = id(object1) object2_memory_address = id(object2) object3_memory_address = id(object3) print "Before garbage collection --->" print "Refcount for object1: {count}".format( count=PyObject.from_address(object1_memory_address).refcnt ) print "Refcount for object2: {count}".format( count=PyObject.from_address(object2_memory_address).refcnt ) print "Refcount for object3: {count}".format( count=PyObject.from_address(object3_memory_address).refcnt ) del object1, object2, object3 gc.collect() print "After garbage collection --->" print "Refcount for object1: {count}".format( count=PyObject.from_address(object1_memory_address).refcnt ) print "Refcount for object2: {count}".format( count=PyObject.from_address(object2_memory_address).refcnt ) print "Refcount for object3: {count}".format( count=PyObject.from_address(object3_memory_address).refcnt ) print "Objects that cannot be cleaned up by reference counting: --->" for x in gc.garbage: print x
تنفيذ جامع القمامة بايثون
نتائج كود البرنامج أعلاهيستخدم PHP (بدءًا من الإصدار PHP5.3) خيارًا آخر لجمع القمامة جنبًا إلى جنب مع العد المرجعي. هنا ، يتم تنفيذ هذه العملية ، إذا لزم الأمر ، مع البرنامج. يتم حذف الرسومات الفرعية التي لا يمكن الوصول إليها من الجذر.
يستخدم Swift أيضًا العد المرجعي ؛ لا توجد طرق أخرى لجمع القمامة. تظهر الحالة أدناه عندما يصل العداد "القوي" للكائن تمامًا إلى 0 ويزيل الشخص (نظرًا لارتباطه الضعيف بالشقة).
class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print("\(name) is being deinitialized") } } class Apartment { let unit: String init(unit: String) { self.unit = unit } weak var tenant: Person? deinit { print("Apartment \(unit) is being deinitialized") }

هناك العديد من الأمثلة على آليات جمع القمامة التي تم تنفيذها بلغات أخرى. يمكن أن تؤثر على الأداء العام للتطبيق أو العمل دون التأثير على تنفيذ المهمة الرئيسية.
مفاهيم مكررة
إنشاء وإدارة الحزمتعرف على آليات تخزين التبعيات وتتبعها ، بالإضافة إلى طرق الحفاظ على المعلومات حول "التجميع" (وصف الحزمة ، وكيفية إجراء اختبارات الوحدة ، وتكوين وإعداد البيئة ، وما إلى ذلك).
تستخدم Python
النقاط جنبًا إلى جنب مع ملف sources.txt لإدارة التبعيات و
setup.py لإدارة إعدادات البيئة ، ويعمل Haskell مع
Cabal لحل كلتا المشكلتين ، ولدى Java
Maven و
Gradle ، وفي حالة عمل Scala
SBT ، يستخدم PHP
Composer و NodeJS -
نبم ، إلخ.
تأكد من تحديد توطين بيئة التطوير - قد ترغب في تشغيل إصدارات مختلفة من لغات البرمجة اعتمادًا على المشروع. Phpbrew لـ PHP و pyenv لـ Python و nvm لـ NodeJS تجعل هذا ممكنًا.
باستخدام pyenv ، يمكنك العمل مع إصدارات مختلفة من Python.في حالات خاصة ، يحدث أن يتم تثبيت المكتبة المستخدمة في مشروع واحد تلقائيًا في مشاريع أخرى. هذا صحيح ، على وجه الخصوص ، للغات مثل Python و Haskell. لتجنب هذه المشكلة ، يجب عليك استخدام
virtualenv / venv لـ Python و
Virtphp لـ PHP و
Cabal Sandboxes for Haskell.
الإدخال / الإخراج غير المتزامنهذه فرصة لزيادة أداء I / O لبيانات التطبيق. في نفس الوقت ، يعمل كل مؤشر ترابط مع مجموعته الخاصة من السجلات ومعلومات المكدس.

const https = require("https"); const urlList = [ "https://reqres.in/api/users?page=1", "https://reqres.in/api/users?page=2", "https://reqres.in/api/users?page=3" ]; function getSiteContents(url) { return new Promise(function (resolve, reject) { https.get(url, function (res) { var bodyData = ""; res.on("data", function (chunk) { bodyData += chunk; }); res.on("end", function () { resolve(bodyData); }); res.on("error", function (error) { reject(error.message); }); }); }); }
تنفيذ الإدخال / الإخراج غير المتزامن باستخدام جافا سكريبتالبرمجة الوظيفيةتتيح لك البرمجة الوظيفية "إخبار" الكمبيوتر بمستوى عالٍ عما تريده حقًا منه. تتمتع معظم اللغات اليوم بالقدرات الأساسية لتنفيذ ذلك: من خلال
الخريطة والفلترة والتقليل للقوائم وما إلى ذلك. ولكن لا يزال الأمر يستحق الاستخدام. فيما يلي مثال على البرمجة الوظيفية بلغة لا يبدو أنها تنطوي على مثل هذا الاحتمال.
<?php
تدريب
المرحلة الأولى هي البحث عن المعلومات اللازمة عن الموارد المتخصصة وإنشاء مشروع صغير بعد الانتهاء من التدريب الأساسي. في معظم الحالات ، يمكنك استخدام مقالات مثل "Learn X in Y Days" ، والعديد منها جيد جدًا. في كثير من الحالات ، هناك أمثلة تدريبية تفاعلية:
جولة GoLang و
GoLang على سبيل المثال (لـ GoLang) ،
وتمارين سطر الأوامر NodeSchool (لـ Javascript ، وبالتحديد NodeJS) ،
وتمارين Scala (لـ Scala) ، و
Python Koans (لـ Python) ، وما إلى ذلك. .p.
البدء بشيء معقد لا يستحق ذلك. إن إنشاء تطبيقات ونصوص صغيرة هو ما يحتاجه المبتدئ. العدد الإجمالي لخطوط الشفرة في مثل هذه التجارب لا يتجاوز 300-400. الشيء الرئيسي الضروري في هذه المرحلة هو الحصول على المعلومات الأساسية ، وتعلم البرمجة بأي سرعة عادية والأهم هو فهم ما تفعله.
func containedClosureIncrementer() -> (() -> Int) { var anInt = 0 func incrementer() -> Int { anInt = anInt + 1 return anInt } return incrementer } func containedClosureIncrementer2() -> () -> Int { var anInt = 0 return { anInt = anInt + 1 return anInt } } let closureIncrementer = containedClosureIncrementer() print("containedClosureIncrementer call - should be 1: \(closureIncrementer() == 1)") print("containedClosureIncrementer call - should be 2: \(closureIncrementer() == 2)") var someOptionalValue: Optional<String> = nil; print("Optional - someOptionalValue is null: \(someOptionalValue == nil)") someOptionalValue = "real value" print("Optional - someOptionalValue is 'real value' \(someOptionalValue == "real value")") (["real value", nil] as Array<Optional<String>>).forEach({ someOptionalValue in if let someValue = someOptionalValue { if someValue.hasPrefix("real") { print("someValue: has real") } else { print("someValue: doesn't have real") } } else { print("someValue: has nil") } }) if (someOptionalValue ?? "").hasPrefix("real") { print("Has real 2") } else { print("Doesn't have real") } let numbersList: [Int] = Array(1...10) print("List of numbers 1 to 10: \(numbersList)") let numbersListTimes2 = numbersList.map({ (someNumber: Int) -> Int in let multiplicand = 2 return someNumber * multiplicand }) let numbersListTimes2V2 = numbersList.map({ number in number * 2 }) let numbersListTimes2V3 = numbersList.map { $0 * 2 } print("List of numbers * 2: \(numbersListTimes2)") print("V1, V2 Map operations do the same thing: \(numbersListTimes2 == numbersListTimes2V2)") print("V1, V3 Map operations do the same thing: \(numbersListTimes2 == numbersListTimes2V3)") func testGuard() { let someOptionalValue: Optional<String> = nil; guard let someOptionalValueUnwrapped = someOptionalValue else { print("testGuard: Thrown exception - nil value") return } print("testGuard: no exception - non-nil value: \(someOptionalValueUnwrapped)") } testGuard() class RuntimeError: Error {} [{throw RuntimeError()}, {1} as () throws -> Int].forEach { let returnValue = try? $0() if let returnValueUnwrapped = returnValue { print("List of closures: A normal value was returned \(returnValueUnwrapped)") } else { print("List of closures: An error was thrown") } }
مثال على نص أولي يعطي فكرة لمبرمج مبتدئ حول كيفية عمل شفرتهالمرحلة الثانية هي دراسة أعمق للغة ، وإنشاء مشروع كامل ، والذي لم يعد من الممكن تسميته "بالأطفال". في كثير من الحالات ، تحتاج إلى التعرف على الوثائق الرسمية. بالنسبة إلى Javascript ، إنه
محرر مستندات Mozilla ، لـ Swift ،
Swift Official Docs ، لـ Java ،
Java Learning Trails ، لـ Python ،
Python Official Docs t. يجب إيلاء اهتمام خاص للدورات عبر الإنترنت مع المعلمين الجيدين.
من الجدير
أيضًا استكشاف مشاريع أخرى مفتوحة المصدر. تعطي مصادر مثل
مصدر jQuery Annotated أو
مصدر BackboneJS المفصل فكرة عن كيفية استخدام لغة برمجة معينة ومكتبات إضافية في المشاريع المهنية.
كل هذا سيساعد على إنشاء مشروعك الجاد ، على سبيل المثال ، تطبيق سطح مكتب ، تطبيق ويب ، برنامج محمول. حاول استخدام مكتبات خارجية عندما تحتاج إلى أدوات ووظائف إضافية.

لا تنسى أداء تطبيقك ، حاول دائمًا استخلاص المعلومات من أحدث المصادر. فرص التعلم لا حصر لها ، يمكنك تحسين إلى الأبد. ولكن في النهاية ، يمكنك أن تشعر وكأنك أصبحت محترفًا من مبتدئ - وليس هناك ببساطة شعور أفضل في العالم.
توصي Skillbox بما يلي: