Memilih bahasa pemrograman: 3 tips dari seorang programmer dari Apple

gambar

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 abstraksi

Jika sangat digeneralisasikan, kita dapat mengatakan bahwa bahasa pemrograman modern dibagi menjadi tiga jenis:

  1. "Fast", yang digunakan untuk membuat aplikasi atau prototipe dengan cepat.
  2. "Infrastruktur", yang membantu mengoptimalkan atau memodifikasi bagian-bagian dari aplikasi yang sudah ditulis untuk meningkatkan produktivitasnya.
  3. 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.

Fungsionalitas

Seperti 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) -- Filters Twitter tweets that are written only in English filterEnglishTweets :: StreamingAPI -> Bool filterEnglishTweets tweet = let langIsEnglish (Status {statusLang=language}) = case language of Just "en" -> True _ -> False in case tweet of SStatus statusObj -> langIsEnglish statusObj SRetweetedStatus (RetweetedStatus {rsRetweetedStatus=statusObj}) -> langIsEnglish statusObj _ -> False -- Filters Twitter tweets that are original posts tweetParser :: StreamingAPI -> Maybe String tweetParser tweet = case tweet of SStatus (Status {statusText=status}) -> Just $ unpack status SRetweetedStatus (RetweetedStatus {rsRetweetedStatus=rstatus}) -> Just $ unpack $ statusText rstatus _ -> Nothing main :: IO () main = do -- a bunch of connection setup details to Twitter {- Imagine a stream/production line of continually incoming Twitter tweets out of this stream, non-English tweets are removed each remaining tweet then gets packaged into one of two forms - one for original tweets - one for non-original tweets (retweets and whatnot) We then only grab packaged forms of original tweets and display them! -} in runResourceT $ do stream <- stream twitterInfo connectionManager apiRequest stream $=+ Data.Conduit.List.filter filterEnglishTweets $=+ Data.Conduit.List.map tweetParser $=+ Data.Conduit.List.catMaybes $$+- Data.Conduit.List.mapM_ (liftIO . putStrLn) 

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 sampah

Pengumpulan 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 atas

PHP (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 paket

Kenali 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 sinkron

Ini 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); }); }); }); } // One way we can proceed with execution // Make one Promise out of a list of Promises Promise.all(urlList.map(getSiteContents)) .then(function (siteContents) { console.log("Promise based execution --->"); console.log(siteContents); }); // Another way we can proceed with execution // "async" is an ES7 feature that makes our Promise/async I/O code look // more synchronous async function main () { const siteContents = await Promise.all(urlList.map(getSiteContents)) console.log("Main() based execution --->"); console.log(siteContents); } main(); // As Promises will happen in some future time, this will happen first console.log("This console.log will most likely happen first"); 

Menerapkan Asynchronous I / O Menggunakan Javascript

Pemrograman fungsional

Pemrograman 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 // Accumulator gets passed around for reuse - function as a value $accumulator = function ( string $accumulated_string, string $mapped_list_element ) { return $accumulated_string . $mapped_list_element . "\n"; }; // Notice how array_map, array_filter and array_reduce // accept functions as parameters - they are higher order functions $mapped_array = array_reduce( array_map( function (int $list_element): string { return "A list element: " . $list_element; }, [1, 2, 3, 4] ), $accumulator, "" ); echo "Mapped Array: \n"; echo $mapped_array; $filtered_array = array_reduce( array_filter( [1, 2, 3, 4], function (int $list_element): bool { return $list_element > 2; } ), $accumulator, "" ); echo "Filtered Array: \n"; echo $filtered_array; // Closures "enclose" over their surrounding state // The $closure_incrementer function here returns a function // making it a higher order function. echo "Closure Incrementer: \n"; $closure_incrementer = function () { $internal_variable = 0; return function () use (&$internal_variable) { return $internal_variable += 1; }; }; $instance = $closure_incrementer(); echo $instance() . " is equal to 1\n"; echo $instance() . " is equal to 2\n"; 

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 kerjanya

Tahap 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:

Source: https://habr.com/ru/post/id421533/


All Articles