Dari penerjemah: Artikel ini adalah terjemahan dari
bahan yang ditulis oleh programmer
Alastair Paragas dari Apple dan telah bekerja dengan bahasa pemrograman seperti Javascript, Python, PHP, Jawa, Scala, Haskell, Swift, dan Rust. Alastair berbagi pemikirannya tentang topik memilih dan mempelajari bahasa "nya", karena masalah ini relevan untuk pemula dan profesional yang ingin memilih toolkit baru.
Apakah Anda belajar bahasa pemrograman demi pekerjaan atau pelatihan lanjutan, atau apakah itu hobi murni, cepat atau lambat Anda harus memilih di antara mereka. Bagaimana cara melakukannya? Pertanyaannya tidak sederhana, tetapi jawabannya adalah: ribuan programmer melakukannya setiap hari. Untuk memudahkan tugas Anda, ada baiknya mengikuti beberapa prinsip.
Skillbox merekomendasikan: Kursus praktis "Pengembang Web Profesi" .
Kami mengingatkan Anda: untuk semua pembaca Habr - diskon 10.000 rubel saat mendaftar untuk kursus Skillbox apa pun sesuai dengan kode promosi Habr
.
Indikator komparatif
Tingkat abstraksiJika sangat digeneralisasikan, kita dapat mengatakan bahwa bahasa pemrograman modern dibagi menjadi tiga jenis:
- "Fast", yang digunakan untuk membuat aplikasi atau prototipe dengan cepat.
- "Infrastruktur", yang membantu mengoptimalkan atau memodifikasi bagian-bagian dari aplikasi yang sudah ditulis untuk meningkatkan produktivitasnya.
- Apa yang disebut bahasa pemrograman sistem, yang penggunaannya memungkinkan Anda untuk mendapatkan kontrol penuh atas memori perangkat.
Tentu saja, pemisahan jenis yang nyata di antara bahasa pemrograman kurang ketat: ada varian menengah, hibrida dari berbagai jenis.
Jika kita berbicara tentang belajar bahasa, maka pertama-tama Anda harus mencoba jenis pertama - "cepat" bahasa: mereka memungkinkan Anda untuk segera melihat hasil kerja dan belajar dari kesalahan Anda sendiri. Ini terutama PHP, Javascript, Ruby, dan Python. Ambang entri di sini minimal, dan Anda dapat mempelajari dasar-dasarnya dalam waktu singkat. Bahasa-bahasa ini memiliki perpustakaan standar yang memungkinkan Anda untuk menambahkan sejumlah besar fungsi ke aplikasi, dan jangkauan kemampuannya cukup besar.
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)
Menerapkan permintaan HTTP multi-utas dalam Python dengan pengetikan statis. Multithreading menyediakan kemungkinan untuk berganti-ganti tiga tugas (sebut saja tugas-tugas A, B dan C). Sementara satu tugas (katakanlah, tugas A) melakukan beberapa operasi yang terkait dengan I / O (dan, karena itu, tidak melakukan pekerjaan perhitungan), tugas-tugas lain dilakukan bersamaan dengan itu.Adapun bahasa "infrastruktur", ini adalah Jawa, Kotlin, Scala, Clojure, serta GoLang, Swift dan Haskell. Anda dapat menyebutnya nyaman dengan peregangan, tetapi memungkinkan Anda membuat aplikasi yang produktif. Kompleksitas mencakup lebih sedikit elemen out-of-the-box, sintaksis yang tepat, dll. Bahasa-bahasa ini baik karena mereka memungkinkan Anda untuk menyempurnakan aplikasi. Jika Anda membutuhkan kecepatan, cobalah menulis aplikasi pada salah satunya.
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()
Masalah serupa telah diselesaikan di atas menggunakan Python. Sekarang dalam bisnis - Swift.Bahasa pemrograman sistem - C, C ++, Rust. Mereka memberikan kontrol maksimum atas aplikasi, termasuk manajemen memori. Juga, bahasa ini sangat bagus untuk pemrograman mikrokontroler, komputer dengan arsitektur prosesor kustom dan sistem lainnya. Bahasa tingkat rendah masih penting dan kemungkinan besar akan tetap relevan dalam waktu dekat.
FungsionalitasSeperti yang Anda ketahui, bahasa berfungsi sebagai sarana "komunikasi" antara komputer dan programmer. Agar komunikasi ini berjalan dengan lancar, ada baiknya mempelajari sintaks bahasa secara rinci. Secara khusus, seorang spesialis harus mengetahui struktur data yang paling umum digunakan dan memahami cara memodifikasi elemen tertentu dari aplikasinya.
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)
Haskell adalah bahasa pemrograman fungsional yang ketat. Dia dapat memeriksa struktur data yang masuk dan bekerja dengannya jika memenuhi persyaratan tertentu.
Runtime - Anda perlu tahu bagaimana aplikasi Anda akan bekerja pada berbagai sistem. Apakah diperlukan juru bahasa (mis. Python, NodeJS, PHP)? Apakah biner yang tergantung pada sistem dihasilkan (mis. Swift dan GoLang)? Apakah bahasa yang dipilih menggunakan kombinasi opsi pertama dan kedua, misalnya, aplikasi dikompilasi dan diluncurkan pada beberapa mesin virtual (Java, Scala, Clojure)?
Ngomong-ngomong, di jalan menuju keunggulan, sangat dianjurkan untuk belajar dan mulai menggunakan Docker plus untuk memastikan untuk memahami prinsip-prinsip administrasi Linux.
Perpustakaan - setiap bahasa sangat cocok untuk situasi tertentu. Sebagai contoh, Java memenuhi banyak persyaratan orkestrasi dan logistik jaringan, termasuk dukungan basis data melalui standarisasi antarmuka JDBC dan proyek-proyek seperti yang berada di bawah dukungan Yayasan Apache. Hal yang sama berlaku untuk Python - ini sangat ideal untuk analisis data dan perhitungan statistik - serta Haskell dengan tata bahasa, ekspresi reguler, dan kompilernya. Popularitas bahasa dan ukuran komunitasnya adalah dua argumen lagi yang mendukung penggunaan alat pemrograman tertentu dalam proyek Anda. Jika komunitasnya kecil, maka Anda tidak harus mengandalkan bantuan ambulans dari para pesertanya. Dan sebaliknya, semakin besar komunitas dan semakin populer bahasa pemrogramannya, semakin cepat Anda dapat menyelesaikan tugas yang sulit atau mendapatkan saran dari rekan kerja.
Pengumpulan sampahPengumpulan sampah adalah bentuk manajemen memori otomatis. Proses khusus yang disebut pengumpul sampah secara berkala membebaskan memori dengan menghapus objek yang tidak lagi dibutuhkan oleh aplikasi. Setiap bahasa pemrograman melakukan ini dengan caranya sendiri.
Python mengimplementasikan penghitungan referensi melalui algoritma stop-the-world. Ini menjeda eksekusi program, memulai dan mengeksekusi pengumpulan sampah, kemudian melanjutkan proses utama. Selama "pembersihan" 3 "generasi" yang terpisah muncul - satu set "tumpukan sampah". Nol berisi objek "paling segar", kemudian diikuti oleh generasi 1 dan 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
Implementasi pengumpul sampah python
Hasil kode program di atasPHP (dimulai dengan versi PHP5.3) menggunakan opsi pengumpulan sampah lain bersama dengan penghitungan referensi. Di sini, proses ini, jika perlu, dilakukan bersama dengan program. Subgraf yang tidak dapat dijangkau dari root dihilangkan.
Swift juga menggunakan penghitungan referensi, tidak ada cara lain untuk mengumpulkan sampah. Kasing ditunjukkan di bawah ini ketika penghitung "kuat" objek sepenuhnya mencapai 0 dan membersihkan Orang (karena berkorelasi lemah dengan Apartemen).
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") }

Ada banyak contoh mekanisme pengumpulan sampah yang diterapkan dalam bahasa lain. Mereka dapat memengaruhi kinerja aplikasi secara keseluruhan atau bekerja tanpa mempengaruhi pelaksanaan tugas utama.
Konsep rangkap
Membuat dan mengelola paketKenali mekanisme untuk menyimpan dan melacak dependensi, serta cara untuk mempertahankan informasi tentang "perakitan" (deskripsi paket, cara menjalankan tes unit, mengkonfigurasi dan mempersiapkan lingkungan, dll.).
Python menggunakan
pip bersama-sama dengan file requirement.txt untuk mengelola dependensi dan
setup.py untuk mengelola pengaturan lingkungan , Haskell bekerja dengan
Cabal untuk menyelesaikan kedua masalah, Java memiliki
Maven dan
Gradle , dalam kasus karya Scala
SBT , PHP menggunakan
Komposer , NodeJS -
npm , dll.
Pastikan untuk memutuskan lokalisasi lingkungan pengembangan - Anda mungkin ingin menjalankan berbagai versi bahasa pemrograman tergantung pada proyek. Phpbrew untuk PHP, pyenv untuk Python, dan nvm untuk NodeJS memungkinkan ini.
Menggunakan pyenv, Anda dapat bekerja dengan berbagai versi Python.Dalam kasus khusus, itu terjadi bahwa perpustakaan yang digunakan dalam satu proyek secara otomatis diinstal pada yang lain. Ini benar, khususnya, untuk bahasa seperti Python dan Haskell. Untuk menghindari masalah ini, Anda harus menggunakan
virtualenv / venv untuk Python,
virtphp untuk PHP, dan
Cabal Sandboxes untuk Haskell.
Input / output tidak sinkronIni adalah peluang untuk meningkatkan kinerja data aplikasi I / O. Pada saat yang sama, setiap utas bekerja dengan set register dan informasi tumpukan.

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); }); }); }); }
Menerapkan Asynchronous I / O Menggunakan JavascriptPemrograman fungsionalPemrograman fungsional memungkinkan Anda untuk "memberi tahu" komputer pada tingkat tinggi apa yang benar-benar Anda inginkan darinya. Sebagian besar bahasa saat ini memiliki kemampuan paling mendasar untuk mengimplementasikan ini: melalui
peta ,
filter ,
perkecil untuk daftar , dll. Tapi masih layak digunakan. Di bawah ini adalah contoh pemrograman fungsional dalam bahasa yang tampaknya tidak menyiratkan kemungkinan seperti itu.
<?php
Pelatihan
Tahap pertama adalah pencarian informasi yang diperlukan tentang sumber daya khusus dan pembuatan proyek kecil setelah pelatihan dasar selesai. Dalam kebanyakan kasus, Anda dapat menggunakan artikel seperti "Pelajari X dalam Y Hari," banyak di antaranya sangat bagus. Dalam banyak kasus, ada contoh pelatihan interaktif:
Tur GoLang dan
GoLang dengan contoh (untuk GoLang),
latihan NodeSchool Command Line (untuk Javascript, yaitu NodeJS),
Latihan Scala (untuk Scala),
Koal Python (untuk Python), dan sebagainya. .p.
Memulai dengan sesuatu yang rumit tidak sepadan. Membuat aplikasi kecil dan skrip adalah apa yang dibutuhkan pemula. Jumlah baris kode dalam percobaan tersebut tidak melebihi 300-400. Hal utama yang diperlukan pada tahap ini adalah untuk mendapatkan informasi dasar, belajar memprogram pada kecepatan normal dan yang paling penting adalah memahami apa yang Anda lakukan.
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") } }
Contoh skrip awal yang memberikan ide kepada programmer pemula tentang cara kerjanyaTahap kedua adalah studi yang lebih mendalam tentang bahasa, penciptaan proyek penuh, yang tidak lagi bisa disebut "kekanak-kanakan". Dalam banyak kasus, Anda perlu membiasakan diri dengan dokumentasi resmi. Untuk Javascript, ini
Mozilla Developer Documents , untuk Swift,
Swift Official Documents , untuk Java,
Java Learning Trails , untuk Python,
Python Official Docs t. Perhatian khusus harus diberikan pada kursus online dengan guru yang baik.
Ada baiknya
juga mengeksplorasi proyek sumber terbuka lainnya. Sumber daya seperti
sumber jQuery Beranotasi atau
sumber BackboneJS Beranotasi memberikan gambaran tentang bagaimana bahasa pemrograman tertentu dan pustaka tambahan digunakan dalam proyek profesional.
Semua ini akan membantu untuk membuat proyek serius Anda sendiri, misalnya, aplikasi desktop, aplikasi web, program seluler. Cobalah menggunakan perpustakaan eksternal ketika Anda membutuhkan alat dan fungsi tambahan.

Jangan lupa tentang kinerja aplikasi Anda, selalu berusaha menggambar informasi dari sumber terbaru. Peluang belajar tidak terbatas, Anda dapat meningkatkan selamanya. Tetapi pada akhirnya, Anda bisa merasa seperti telah menjadi seorang profesional dari seorang pemula - dan sama sekali tidak ada perasaan yang lebih baik di dunia.
Skillbox merekomendasikan: