Nima uchun Go aqlsiz dasturchilar uchun yomon

Maqola avval chop etilgan maqolaga javob sifatida yozilgan antipodean maqola.

Nima uchun Go aqlsiz dasturchilar uchun yomon

Oxirgi ikki yildan ortiq vaqt mobaynida men Go-dan billing tizimi rivojlangan ixtisoslashtirilgan RADIUS serverini joriy qilish uchun foydalandim. Yo'lda men tilning o'zi nozik tomonlarini o'rganyapman. Dasturlarning o'zi juda oddiy va bu maqolaning maqsadi emas, lekin Go'dan foydalanish tajribasi uning himoyasida bir necha so'zlarga loyiqdir. Go jiddiy, kengaytiriladigan kod uchun tobora asosiy tilga aylanib bormoqda. Til Google tomonidan yaratilgan bo'lib, u erda faol foydalaniladi. Xulosa qilib aytganda, men Go tilining dizayni UNintelligent dasturchilari uchun yomon deb o'ylayman.

Zaif dasturchilar uchun mo'ljallanganmi?

Zaiflar muammolar haqida gapiradi. G'oyalar va orzular haqida kuchli gapirish ...

Go o'rganish juda oson, shuning uchun siz kodni deyarli hech qanday mashg'ulotsiz o'qishingiz mumkin. Tilning bu xususiyati ko'plab global kompaniyalarda kod asosiy bo'lmagan mutaxassislar (menejerlar, mijozlar va boshqalar) bilan birgalikda o'qilganda qo'llaniladi. Bu dizaynga asoslangan rivojlanish kabi metodologiyalar uchun juda qulay.
Hatto tajribasiz dasturchilar ham bir yoki ikki haftadan so'ng juda yaxshi kod ishlab chiqarishni boshlaydilar. Men o'qigan kitob "Go Programming" (Mark Summerfild tomonidan). Kitob juda zo'r, u tilning ko'plab nuanslarini qamrab oladi. Java, PHP kabi keraksiz murakkab tillardan so'ng, sehrning etishmasligi yangilanadi. Ammo ertami-kechmi ko'plab cheklangan dasturchilar yangi sohada eski usullardan foydalanish g'oyasiga ega. Bu haqiqatan ham kerakmi?

Rob Pike (tilning asosiy mafkurachisi) Go tilini tushunish oson va foydalanishda samarali bo'lgan sanoat tili sifatida yaratdi. Til katta jamoalarda maksimal mahsuldorlikka mo'ljallangan va bunga hech qanday shubha yo'q. Ko'pgina tajribasiz dasturchilar, ular etishmayotgan ko'plab xususiyatlar mavjudligidan shikoyat qiladilar. Ushbu soddalikka intilish til dizaynerlarining ongli qarori edi va bu nima uchun kerakligini to'liq tushunish uchun biz dasturchilarning motivatsiyasini va ular Go'da nimaga erishmoqchi bo'lganini tushunishimiz kerak.

Xo'sh, nega bu juda oddiy qilingan? Rob Pikedan bir nechta iqtiboslar:

Bu erda asosiy nuqta shundaki, bizning dasturchilarimiz tadqiqotchilar emas. Ular, qoida tariqasida, juda yosh, bizga o'qishdan keyin kelishadi, ehtimol ular Java, C/C++ yoki Python tillarini o'rgangandirlar. Ular ajoyib tilni tushuna olmaydilar, lekin shu bilan birga biz ulardan yaxshi dasturiy ta'minot yaratishlarini xohlaymiz. Shuning uchun til tushunish va o'rganish uchun qulay bo'lishi kerak.

U tanish bo'lishi kerak, taxminan C ga o'xshash. Googleda ishlaydigan dasturchilar o'z kareralarini erta boshlaydilar va asosan protsessual tillarni, xususan, C oilasini yaxshi bilishadi. Yangi dasturlash tilida tez mahsuldorlikka bo'lgan talab bu til juda radikal bo'lmasligi kerakligini anglatadi.

Dono so'zlar, shunday emasmi?

Oddiylik artefaktlari

Oddiylik go'zallikning zaruriy shartidir. Lev Tolstoy.

Uni sodda saqlash har qanday dizayndagi eng muhim maqsadlardan biridir. Ma'lumki, mukammal loyiha qo'shadigan hech narsa bo'lmagan loyiha emas, balki olib tashlash uchun hech narsa bo'lmagan loyihadir. Ko'p odamlar murakkab muammolarni hal qilish (yoki hatto ifodalash) uchun murakkab vosita kerakligiga ishonishadi. Biroq, unday emas. Masalan, PERL tilini olaylik. Til mafkurachilari dasturchi bitta muammoni hal qilish uchun kamida uch xil usulga ega bo'lishi kerak, deb hisoblashgan. Go tilining mafkurachilari boshqacha yo'l tutishdi; ular maqsadga erishish uchun bitta yo'l, lekin haqiqatan ham yaxshi yo'l etarli deb qaror qilishdi. Bu yondashuv jiddiy asosga ega: yagona yo'lni o'rganish osonroq va unutish qiyinroq.

Ko'pgina muhojirlar tilda nafis abstraktsiyalar yo'qligidan shikoyat qiladilar. Ha, bu haqiqat, lekin bu tilning asosiy afzalliklaridan biridir. Til minimal sehrni o'z ichiga oladi - shuning uchun dasturni o'qish uchun chuqur bilim talab qilinmaydi. Kodning aniqligiga kelsak, bu umuman muammo emas. Yaxshi yozilgan Golang dasturi vertikal ravishda o'qiydi, tuzilishi kam yoki umuman yo'q. Bundan tashqari, dasturni o'qish tezligi hech bo'lmaganda uni yozish tezligidan kattaroq tartibdir. Agar siz barcha kodlar bir xil formatga ega deb hisoblasangiz (o'rnatilgan gofmt buyrug'i yordamida amalga oshiriladi), unda bir nechta qo'shimcha qatorlarni o'qish umuman muammo emas.

Juda ifodali emas

San'at erkinligi cheklangan bo'lsa, toqat qilmaydi. Aniqlik uning javobgarligi emas.

Oddiylik istagi tufayli Go boshqa tillarda ularga o'rganib qolgan odamlar tomonidan tabiiy narsa sifatida qabul qilinadigan konstruktsiyalarga ega emas. Avvaliga bu biroz noqulay bo'lishi mumkin, ammo keyin dasturni o'qish ancha oson va aniqroq ekanligini sezasiz.

Misol uchun, stdin yoki buyruq qatori argumentlaridan faylni o'qiydigan konsol yordam dasturi quyidagicha ko'rinadi:

package main

import (
    "bufio"
    "flag"
    "fmt"
    "log"
    "os"
)

func main() {

    flag.Parse()

    scanner := newScanner(flag.Args())

    var text string
    for scanner.Scan() {
        text += scanner.Text()
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }

    fmt.Println(text)
}

func newScanner(flags []string) *bufio.Scanner {
    if len(flags) == 0 {
        return bufio.NewScanner(os.Stdin)
    }

    file, err := os.Open(flags[0])

    if err != nil {
        log.Fatal(err)
    }

    return bufio.NewScanner(file)
}

D dagi bir xil muammoning yechimi, garchi u biroz qisqaroq ko'rinsa ham, o'qish oson emas

import std.stdio, std.array, std.conv;

void main(string[] args)
{
    try
    {
        auto source = args.length > 1 ? File(args[1], "r") : stdin;
        auto text   = source.byLine.join.to!(string);

        writeln(text);
    }
    catch (Exception ex)
    {
        writeln(ex.msg);
    }
}

Nusxa ko'chirish jahannami

Inson o'z ichida do'zaxni olib yuradi. Martin Lyuter.

Yangi boshlanuvchilar doimiy ravishda Go haqida generiklarning etishmasligidan shikoyat qiladilar. Ushbu muammoni hal qilish uchun ularning aksariyati to'g'ridan-to'g'ri kodni nusxalashdan foydalanadi. Masalan, butun sonlar ro'yxatini yig'ish funktsiyasi, bunday bo'lajak mutaxassislar ushbu funktsiyani har bir ma'lumot turi uchun oddiy nusxa ko'chirishdan boshqa yo'l bilan amalga oshirish mumkin emas deb hisoblashadi.

package main

import "fmt"

func int64Sum(list []int64) (uint64) {
    var result int64 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

func int32Sum(list []int32) (uint64) {
    var result int32 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

func main() {

    list32 := []int32{1, 2, 3, 4, 5}
    list64 := []int64{1, 2, 3, 4, 5}

    fmt.Println(int32Sum(list32))
    fmt.Println(int64Sum(list64))
}

Bunday konstruksiyalarni amalga oshirish uchun til yetarli vositalarga ega. Misol uchun, umumiy dasturlash yaxshi bo'ladi.

package main

import "fmt"

func Eval32(list []int32, fn func(a, b int32)int32) int32 {
    var res int32
    for _, val := range list {
        res = fn(res, val)
    }
    return res
}

func int32Add(a, b int32) int32 {
    return a + b
}

func int32Sub(a, b int32) int32 {
    return a + b
}

func Eval64(list []int64, fn func(a, b int64)int64) int64 {
    var res int64
    for _, val := range list {
        res = fn(res, val)
    }
    return res
}

func int64Add(a, b int64) int64 {
    return a + b
}

func int64Sub(a, b int64) int64 {
    return a - b
}

func main() {

    list32 := []int32{1, 2, 3, 4, 5}
    list64 := []int64{1, 2, 3, 4, 5}

    fmt.Println(Eval32(list32, int32Add))
    fmt.Println(Eval64(list64, int64Add))
    fmt.Println(Eval64(list64, int64Sub))
}

Va bizning kodimiz avvalgi holatdan bir oz uzunroq bo'lsa ham, u umumlashtirildi. Shuning uchun barcha arifmetik amallarni amalga oshirish biz uchun qiyin bo'lmaydi.

Ko'pchilik D dagi dastur sezilarli darajada qisqaroq ko'rinishini aytadi va ular to'g'ri bo'ladi.

import std.stdio;
import std.algorithm;

void main(string[] args)
{
    [1, 2, 3, 4, 5].reduce!((a, b) => a + b).writeln;
}

Biroq, bu qisqaroq, ammo to'g'ri emas, chunki D ilovasi xatolarni qayta ishlash muammosini butunlay e'tiborsiz qoldiradi.

Haqiqiy hayotda, mantiqning murakkabligi oshgani sayin, bo'shliq tez qisqaradi. Standart til operatorlari yordamida bajarib bo'lmaydigan amalni bajarish kerak bo'lganda bo'shliq yanada tezroq yopiladi.

Ishonchlilik, kengaytirilish va o'qilishi nuqtai nazaridan, mening fikrimcha, Go tili g'alaba qozonadi, garchi u batafsil ma'lumotni yo'qotsa ham.

Umumlashtirilgan dasturlash ba'zi hollarda bizga shubhasiz foyda keltiradi. Bu tartiblash paketida aniq ko'rsatilgan. Shunday qilib, har qanday ro'yxatni saralash uchun biz faqat sort.Interface interfeysini amalga oshirishimiz kerak.

import "sort"

type Names []string

func (ns Names) Len() int {
    return len(ns)
}

func (ns Names) Less(i, j int) bool {
    return ns[i] < ns[j]
}

func (ns Names) Swap(i, j int) {
    ns[i], ns[j] = ns[j], ns[i]
}

func main() {
    names := Names{"London", "Berlin", "Rim"}
    sort.Sort(names)
}

Agar biron bir ochiq kodli loyihani olsangiz va grep β€œinterface{}” -R buyrug'ini ishga tushirsangiz, chalkash interfeyslar qanchalik tez-tez ishlatilishini ko'rasiz. Yaqin fikrli o'rtoqlar bularning barchasi generiklarning yo'qligi bilan bog'liqligini darhol aytishadi. Biroq, bu har doim ham shunday emas. Misol tariqasida DELPHI ni olaylik. Xuddi shu generiklarning mavjudligiga qaramay, u o'zboshimchalik bilan ma'lumotlar turlari bilan operatsiyalar uchun maxsus VARIANT turini o'z ichiga oladi. Go tili ham xuddi shunday qiladi.

To'pdan chumchuqlargacha

Bog'li ko'ylagi esa jinnilikning o'lchamiga mos kelishi kerak. Stanislav Lec.

Ko'pgina ekstremal muxlislar Go'da generiklarni yaratish uchun yana bir mexanizm - aks ettirish mavjudligini da'vo qilishlari mumkin. Va ular to'g'ri bo'ladi ... lekin kamdan-kam hollarda.

Rob Pike bizni ogohlantiradi:

Bu ehtiyotkorlik bilan ishlatilishi kerak bo'lgan kuchli vositadir. Qattiq zarurat bo'lmasa, undan qochish kerak.

Vikipediya bizga quyidagilarni aytadi:

Reflektsiya deganda dastur bajarilish vaqtida o'z tuzilishi va xatti-harakatlarini kuzatishi va o'zgartirishi mumkin bo'lgan jarayonni anglatadi. Ko'zguga asoslangan dasturlash paradigmasi aks ettiruvchi dasturlash deb ataladi. Bu metadasturlashning bir turi.

Biroq, siz bilganingizdek, siz hamma narsa uchun to'lashingiz kerak. Bu holda u:

  • dasturlarni yozishda qiyinchilik
  • dasturni bajarish tezligi

Shuning uchun, aks ettirishni katta kalibrli qurol kabi ehtiyotkorlik bilan ishlatish kerak. Ko'zgudan o'ylamasdan foydalanish o'qilmaydigan dasturlarga, doimiy xatolarga va past tezlikka olib keladi. Shunchaki, snob dasturchi boshqa, yanada pragmatik va kamtarin hamkasblari oldida o'z kodini namoyish eta olishi kerak.

Si dan madaniy yuk? Yo'q, bir qancha tillardan!

Boylik bilan birga qarzlar ham merosxo'rlarga qoldiriladi.

Ko'pchilik bu til butunlay C merosiga asoslangan deb hisoblashiga qaramay, bu unday emas. Til eng yaxshi dasturlash tillarining ko'p jihatlarini o'z ichiga oladi.

sintaktik

Avvalo, grammatik tuzilmalar sintaksisi C tili sintaksisiga asoslanadi. Biroq, DELPHI tili ham sezilarli ta'sir ko'rsatdi. Shunday qilib, dasturning o'qish qobiliyatini sezilarli darajada kamaytiradigan ortiqcha qavslar butunlay olib tashlanganligini ko'ramiz. Bu tilda DELPHI tiliga xos boβ€˜lgan β€œ:=” operatori ham mavjud. Paket tushunchasi ADA kabi tillardan olingan. Foydalanilmayotgan ob'ektlar deklaratsiyasi PROLOG tilidan olingan.

Semantik

Paketlar DELPHI tilining semantikasiga asoslangan edi. Har bir paket ma'lumotlar va kodlarni qamrab oladi va xususiy va jamoat tashkilotlarini o'z ichiga oladi. Bu sizga paket interfeysini minimal darajaga kamaytirish imkonini beradi.

Delegatsiya usuli bilan amalga oshirish operatsiyasi DELPHI tilidan olingan.

Jamlama

Bu yerda hazil boβ€˜lishi bejiz emas: Go C dasturi tuzilayotganda ishlab chiqilgan. Tilning kuchli tomonlaridan biri uning o'ta tezkor kompilyatsiyasidir. G'oya DELPHI tilidan olingan. Har bir Go paketi DELPHI moduliga mos keladi. Ushbu paketlar faqat zarur bo'lganda qayta kompilyatsiya qilinadi. Shuning uchun, keyingi tahrirdan so'ng, siz butun dasturni kompilyatsiya qilishingiz shart emas, balki faqat ushbu o'zgartirilgan paketlarga bog'liq bo'lgan o'zgartirilgan paketlar va paketlarni qayta kompilyatsiya qiling (va hatto paket interfeyslari o'zgargan bo'lsa ham).

Yuqori darajadagi konstruktsiyalar

Til C kabi past darajadagi tillarga hech qanday aloqasi bo'lmagan juda ko'p turli xil yuqori darajadagi konstruktsiyalarni o'z ichiga oladi.

  • Strings
  • Xesh jadvallari
  • Dilimlar
  • O'rdak terish RUBY kabi tillardan olingan (afsuski, ko'pchilik buni tushunmaydi yoki to'liq imkoniyatlaridan foydalanmaydi).

Xotirani boshqarish

Xotirani boshqarish odatda alohida maqolaga loyiqdir. Agar C++ kabi tillarda boshqaruv butunlay ishlab chiquvchiga topshirilgan boβ€˜lsa, keyingi DELPHI kabi tillarda havolalarni hisoblash modeli ishlatilgan. Ushbu yondashuv bilan tsiklik havolalarga ruxsat berilmagan, chunki etim klasterlar shakllangan, keyin Go'da bunday klasterlarni aniqlash o'rnatilgan (masalan, C#). Bundan tashqari, axlat yig'uvchi hozirda ma'lum bo'lgan ilovalarga qaraganda samaraliroq va ko'plab real vaqtda vazifalar uchun ishlatilishi mumkin. Tilning o'zi o'zgaruvchini saqlash uchun qiymat stekda ajratilishi mumkin bo'lgan vaziyatlarni tan oladi. Bu xotira menejeriga yukni kamaytiradi va dastur tezligini oshiradi.

Muvofiqlik va parallellik

Tilning parallelligi va raqobatbardoshligi maqtovga sazovor emas. Hech qanday past darajadagi til Go bilan masofadan ham raqobatlasha olmaydi. Adolat uchun, shuni ta'kidlash kerakki, model til mualliflari tomonidan ixtiro qilinmagan, balki eski yaxshi ADA tilidan olingan. Til barcha protsessorlar yordamida millionlab parallel ulanishlarni qayta ishlashga qodir, shu bilan birga ko'p tarmoqli kod uchun xos bo'lgan o'lik bloklar va poyga sharoitlari bilan bog'liq kamroq murakkab muammolarga ega.

Qo'shimcha imtiyozlar

Agar u foydali bo'lsa, hamma fidoyi bo'ladi.

Til bizga bir qator shubhasiz afzalliklarni ham beradi:

  • Loyihani yaratgandan so'ng bitta bajariladigan fayl ilovalarni joylashtirishni sezilarli darajada osonlashtiradi.
  • Statik yozish va turdagi xulosalar, hatto testlarni yozmasdan ham kodingizdagi xatolar sonini sezilarli darajada kamaytirishi mumkin. Men testlarni umuman yozmasdan bajaradigan ba'zi dasturchilarni bilaman va ularning kodlari sifati sezilarli darajada yomonlashmaydi.
  • Juda oddiy o'zaro kompilyatsiya va standart kutubxonaning ajoyib portativligi, bu o'zaro platforma ilovalarini ishlab chiqishni sezilarli darajada osonlashtiradi.
  • RE2 muntazam iboralari ish zarrachalari uchun xavfsizdir va bashorat qilinadigan bajarilish vaqtlariga ega.
  • Ko'pgina loyihalarni uchinchi tomon ramkalarisiz bajarishga imkon beruvchi kuchli standart kutubxona.
  • Til muammoni qanday hal qilishdan ko'ra muammoga e'tibor qaratish uchun etarlicha kuchli, ammo muammoni samarali hal qilish uchun etarlicha past darajada.
  • Go eko tizimi allaqachon barcha holatlar uchun ishlab chiqilgan vositalarni o'z ichiga oladi: testlar, hujjatlar, paketlarni boshqarish, kuchli linterlar, kod ishlab chiqarish, poyga sharoitlari detektori va boshqalar.
  • Go versiyasi 1.11 mashhur VCS xostingi ustiga qurilgan o'rnatilgan semantik qaramlikni boshqarishni taqdim etdi. Go ekotizimini tashkil etuvchi barcha vositalar ushbu xizmatlardan kodni bir zarbada yuklab olish, yaratish va oβ€˜rnatish uchun foydalanadi. Va bu ajoyib. 1.11 versiyasi kelishi bilan paket versiyalari bilan bog'liq muammo ham to'liq hal qilindi.
  • Tilning asosiy g'oyasi sehrni kamaytirish bo'lganligi sababli, til ishlab chiquvchilarni xatolarni aniq tuzatishga undaydi. Va bu to'g'ri, chunki aks holda, u xatolarni qayta ishlashni butunlay unutadi. Yana bir narsa shundaki, ko'pchilik ishlab chiquvchilar xatolarni qayta ishlashni ataylab e'tiborsiz qoldiradilar va ularni qayta ishlash o'rniga xatoni yuqoriga yo'naltirishni afzal ko'radilar.
  • Til klassik OOP metodologiyasini amalga oshirmaydi, chunki uning sof shaklida Go-da virtuallik yo'q. Biroq, interfeyslarni ishlatishda bu muammo emas. OOPning yo'qligi yangi boshlanuvchilar uchun kirish uchun to'siqni sezilarli darajada kamaytiradi.

Jamiyat manfaati uchun soddalik

Buni murakkablashtirish oson, soddalashtirish qiyin.

Go oddiy bo'lishi uchun yaratilgan va bu maqsadga erishadi. U jamoaviy ishning afzalliklarini tushunadigan va Enterprise darajadagi tillarning cheksiz o'zgaruvchanligidan charchagan aqlli dasturchilar uchun yozilgan. O'z arsenalida nisbatan kichik sintaktik tuzilmalarga ega bo'lib, u vaqt o'tishi bilan deyarli o'zgarmaydi, shuning uchun ishlab chiquvchilar til innovatsiyalarini cheksiz o'rganish uchun emas, balki rivojlanish uchun ko'p vaqt ajratadilar.

Kompaniyalar bir qator afzalliklarga ham ega bo'ladilar: past kirish to'sig'i ularga tezda mutaxassis topish imkonini beradi, tilning o'zgarmasligi esa 10 yildan keyin ham bir xil koddan foydalanish imkonini beradi.

xulosa

Katta miya hajmi hech qachon filni Nobel mukofoti sovrindoriga aylantirmagan.

Shaxsiy egoi jamoaviy ruhdan ustun turadigan dasturchilar, shuningdek, akademik qiyinchiliklarni va cheksiz "o'zini-o'zi takomillashtirishni" yaxshi ko'radigan nazariyotchilar uchun til haqiqatan ham yomon, chunki bu umumiy maqsadli hunarmandchilik tili bo'lib, uni olishga imkon bermaydi. ishingiz natijasidan estetik zavq oling va hamkasblar oldida o'zingizni professional ko'rsating (agar biz aqlni IQ bilan emas, balki ushbu mezonlar bo'yicha o'lchasak). Hayotdagi hamma narsa kabi, bu shaxsiy ustuvorliklar masalasidir. Barcha arzigulik innovatsiyalar singari, til ham umuminsoniy inkor etishdan ommaviy qabul qilishgacha bo'lgan uzoq yo'lni bosib o'tdi. Til o'zining soddaligi bilan mohir va siz bilganingizdek, hamma narsa sodda!

Manba: www.habr.com

a Izoh qo'shish