Zergatik Go txarra da programatzaile adimendunentzat

Artikulua aurretik argitaratutako baten erantzun gisa idatzi da antipodear artikulua.

Zergatik Go txarra da programatzaile adimendunentzat

Azken bi urteotan Goa erabili dut RADIUS zerbitzari espezializatu bat inplementatzeko fakturazio sistema garatu batekin. Bide horretan, hizkuntzaren beraren korapilatsuak ikasten ari naiz. Programak berez oso sinpleak dira eta ez dira artikulu honen helburua, baina Go erabiltzearen esperientziak berak merezi du hitz batzuk bere defentsan. Go gero eta hizkuntza arruntagoa bihurtzen ari da kode serio eta eskalagarrirako. Googlek sortu zuen hizkuntza, non aktiboki erabiltzen den. Azken finean, zintzotasunez uste dut Go hizkuntzaren diseinua txarra dela adimendun gabeko programatzaileentzat.

Programatzaile ahulentzat diseinatuta?

Ahulek arazoez hitz egiten dute. Ideiei eta ametsei buruzko eztabaida indartsua...

Go oso erraza da ikasteko, hain erraza da kodea irakur dezakezula ia prestakuntzarik gabe. Hizkuntzaren ezaugarri hau mundu mailako enpresa askotan erabiltzen da kodea ez diren espezialistekin batera irakurtzen denean (kudeatzaileak, bezeroak, etab.). Hau oso erosoa da Design Driven Development bezalako metodologietarako.
Programatzaile hasiberriak ere kode nahiko duina sortzen hasten dira aste bat edo biren buruan. Ikasi dudan liburua "Go Programming" da (Mark Summerfield-ena). Liburua oso ona da, hizkuntzaren Γ±abardura asko ukitzen ditu. Java, PHP bezalako alferrikako lengoaien ondoren, magia eza freskagarria da. Baina lehenago edo beranduago, programatzaile mugatu askok metodo zaharrak eremu berri batean erabiltzeko ideia dute. Benetan beharrezkoa al da?

Rob Pike (hizkuntzaren ideologo nagusia) Go hizkuntza sortu zuen ulerterraza eta erabiltzeko eraginkorra den hizkuntza industrial gisa. Hizkuntza talde handietan produktibitate handiena lortzeko diseinatuta dago eta ez dago zalantzarik. Programatzaile hasiberri asko kexatzen dira falta zaizkien funtzio asko daudela. Soiltasun-nahi hori hizkuntzaren diseinatzaileek erabaki kontziente bat izan zen, eta zergatik behar zen ondo ulertzeko, garatzaileen motibazioa eta Go-n lortzen saiatzen ari zirena ulertu behar dugu.

Orduan, zergatik egin zen hain sinplea? Hona hemen Rob Pikeren aipu pare bat:

Hemen gakoa da gure programatzaileak ez direla ikertzaileak. Oro har, nahiko gazteak dira, ikasi ondoren etortzen zaizkigu, agian Java, edo C/C++ edo Python ikasi zuten. Ezin dute hizkuntza handirik ulertu, baina, aldi berean, software ona sortzea nahi dugu. Horregatik, hizkuntzak ulertzeko eta ikasteko erraza izan behar du.

Ezaguna izan behar du, gutxi gorabehera C-ren antzera. Googlen lan egiten duten programatzaileek goiz hasten dute karrera eta gehienbat prozedurazko lengoaiak ezagutzen dituzte, bereziki C familia. Programazio-lengoaia berri batean produktibitate azkarra eskakizunak esan nahi du hizkuntzak ez duela erradikala izan behar.

Hitz jakintsuak, ezta?

Sinpletasunaren artefaktuak

Soiltasuna edertasunerako beharrezko baldintza da. Lev Tolstoi.

Sinplea mantentzea edozein diseinutan helburu garrantzitsuenetako bat da. Dakizuenez, proiektu perfektua ez da ezer gehitzeko ezer ez dagoen proiektua, baizik eta kentzeko ezer ez dagoena. Jende askok uste du arazo konplexuak konpontzeko (edo adierazteko) tresna konplexu bat behar dela. Hala ere, ez da. Har dezagun adibidez PERL hizkuntza. Hizkuntza-ideologoek uste zuten programatzaile batek gutxienez hiru modu ezberdin izan behar zituela arazo bat konpontzeko. Go hizkuntzaren ideologoek beste bide bat hartu zuten; bide bakarra, baina benetan ona, nahikoa zela erabaki zuten helburua lortzeko. Ikuspegi honek oinarri serioa du: modu bakarra errazagoa da ikastea eta zailagoa ahaztea.

Migratzaile asko kexatzen dira hizkuntzak ez duela abstrakzio dotorerik. Bai, egia da, baina hori da hizkuntzaren abantaila nagusietako bat. Hizkuntzak gutxieneko magia dauka; beraz, ez da ezagutza sakonik behar programa irakurtzeko. Kodearen verbositateari dagokionez, hau ez da batere arazorik. Ondo idatzitako Golang programa batek bertikalki irakurtzen du, egitura gutxirekin edo inolako egiturarik gabe. Gainera, programa bat irakurtzeko abiadura idazteko abiadura baino magnitude ordena bat handiagoa da gutxienez. Kode guztiak formatu uniformea ​​duela kontuan hartzen baduzu (gofmt komandoa erabiliz egina), orduan lerro gehigarri batzuk irakurtzea ez da batere arazorik.

Ez oso adierazgarria

Arteak ez du onartzen bere askatasuna mugatuta dagoenean. Zehaztasuna ez da bere ardura.

Soiltasun nahia dela eta, Go-k ez ditu beste hizkuntzetan ohituta dauden pertsonek naturaltzat hartzen dituzten eraikuntzak. Hasieran deseroso samarra izan daiteke, baina gero programa irakurtzen askoz errazagoa eta anbiguoagoa dela ohartzen zara.

Adibidez, stdin edo komando-lerroko argumentuetatik fitxategi bat irakurtzen duen kontsola-erabilgarritasun batek itxura hau izango luke:

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-ko problema beraren konponbidea, zertxobait laburragoa dirudien arren, ez da errazago irakurtzen

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);
    }
}

Kopiaren infernua

Gizakiak bere baitan darama infernua. Martin Lutero.

Hasiberriak etengabe kexatzen dira Go-rekin generikoen faltagatik. Arazo hau konpontzeko, gehienek zuzeneko kodea kopiatzea erabiltzen dute. Esaterako, zenbaki osoen zerrenda batutzeko funtzio bat, horrelako profesionalek uste dute funtzionalitatea ezin dela inplementatu datu mota bakoitzerako kopia-itsatsi soilarekin baino.

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))
}

Hizkuntzak baliabide nahikoak ditu horrelako eraikuntzak gauzatzeko. Adibidez, programazio generikoa ondo legoke.

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))
}

Eta, gure kodea aurreko kasua baino luzeagoa izan arren, orokortu egin da. Beraz, ez zaigu zaila izango eragiketa aritmetiko guztiak ezartzea.

Askok esango dute D-ko programa bat nabarmen laburragoa dela, eta arrazoia izango dute.

import std.stdio;
import std.algorithm;

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

Hala ere, laburragoa da, baina ez zuzenagoa, D inplementazioak erroreen kudeaketaren arazoa erabat baztertzen baitu.

Bizitza errealean, logikaren konplexutasuna handitzen doan heinean, tartea azkar murrizten da. Hutsunea are azkarrago ixten da hizkuntza-operadore estandarrak erabiliz egin ezin den ekintza bat egin behar duzunean.

Mantengarritasunari, hedagarritasunari eta irakurgarritasunari dagokionez, nire ustez, Go hizkuntzak irabazten du, nahiz eta hitzez galtzen duen.

Programazio orokortuak kasu batzuetan onura ukaezinak ematen dizkigu. Hori argi eta garbi erakusten du sort paketeak. Beraz, edozein zerrenda ordenatzeko, sort.Interface interfazea ezartzea besterik ez dugu behar.

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)
}

Kode irekiko edozein proiektu hartu eta grep "interface{}" -R komandoa exekutatzen baduzu, interfaze nahasiak zenbat aldiz erabiltzen diren ikusiko duzu. Gertuko lagunek berehala esango dute hori guztia generikoen faltagatik dela. Hala ere, ez da beti horrela gertatzen. Har dezagun DELPHI adibide gisa. Generiko hauek egon arren, datu-mota arbitrarioak dituzten eragiketetarako VARIANT mota berezi bat dauka. Go hizkuntzak gauza bera egiten du.

Kanoi batetik txolarreetara

Eta kamikazeak eromenaren neurrira egokitu behar du. Stanislav Lec.

Muturreko zale askok Gok generikoak sortzeko beste mekanismo bat duela esan dezakete: hausnarketa. Eta arrazoi izango dute... baina kasu bakanetan bakarrik.

Rob Pike-k ohartarazi digu:

Kontuz erabili beharreko tresna indartsua da hau. Beharrezkoa ez bada behintzat, saihestu egin behar da.

Wikipediak honako hau esaten digu:

Hausnarketa programa batek exekuzioan zehar bere egitura eta portaera kontrolatu eta alda dezakeen prozesuari egiten dio erreferentzia. Hausnarketaren azpian dagoen programazio paradigmari programazio islatzailea deitzen zaio. Hau metaprogramazio mota bat da.

Hala ere, dakizuenez, dena ordaindu behar duzu. Kasu honetan hau da:

  • programak idazteko zailtasuna
  • programaren exekuzio abiadura

Horregatik, gogoeta kontu handiz erabili behar da, kalibre handiko arma bat bezala. Hausnarketa pentsamendurik gabe erabiltzeak programa irakurgaitzak, etengabeko akatsak eta abiadura baxua dakar. Programatzaile snob batentzat bere kodea beste lankide pragmatiko eta xumeen aurrean erakusteko gai izatea.

Xi-ren kultur ekipajea? Ez, hainbat hizkuntzatatik!

Aberastasunarekin batera, zorrak ere oinordekoei uzten zaizkie.

Askok hizkuntza C ondarean guztiz oinarritzen dela uste duten arren, ez da horrela. Lengoaiak programazio-lengoaia onenen alderdi asko biltzen ditu.

sintaxia

Lehenik eta behin, egitura gramatikalen sintaxia C hizkuntzaren sintaxian oinarritzen da. Hala ere, DELPHI hizkuntzak ere eragin nabarmena izan zuen. Horrela, programaren irakurgarritasuna asko murrizten duten parentesi erredundanteak guztiz kendu direla ikusten dugu. Hizkuntzak DELPHI hizkuntzaren berezko β€œ:=” operadorea ere badu. Pakete kontzeptua ADA bezalako hizkuntzetatik hartzen da. Erabiltzen ez diren entitateen aitorpena PROLOG hizkuntzatik mailegatuta dago.

Semantika

Paketeak DELPHI hizkuntzaren semantikan oinarritzen ziren. Pakete bakoitzak datuak eta kodea biltzen ditu eta entitate pribatuak eta publikoak ditu. Horrek paketeen interfazea gutxienera murrizteko aukera ematen du.

Delegazioaren metodoaren ezarpen-eragiketa DELPHI hizkuntzatik hartu da.

konpilazio

Ez da arrazoirik gabe txantxa bat dagoela: Go C programa bat konpilatzen ari zen bitartean garatu zen. Hizkuntzaren indarguneetako bat konpilazio ultra-azkarra da. DELPHI hizkuntzatik hartu zuten ideia. Go pakete bakoitza DELPHI modulu bati dagokio. Pakete hauek benetan beharrezkoa denean bakarrik birkonpilatzen dira. Hori dela eta, hurrengo edizioaren ondoren, ez duzu programa osoa konpilatu behar, aldatutako pakete eta pakete horien araberakoak diren pakete aldatuak soilik birkonpilatu behar (eta orduan ere, paketeen interfazeak aldatu badira bakarrik).

Goi-mailako eraikuntzak

Lengoaiak C bezalako behe-mailako lengoaiekin zerikusirik ez duten goi-mailako hainbat eraikuntza ditu.

  • Kateak
  • Hash taulak
  • Xerrak
  • Duck idazketa RUBY bezalako hizkuntzetatik maileguan hartzen da (tamalez, askok ez dute ulertzen edo bere ahalmen guztian erabiltzen).

Memoriaren kudeaketa

Memoriaren kudeaketak, oro har, aparteko artikulu bat merezi du. C++ bezalako hizkuntzetan kontrola garatzailearen esku geratzen bada, gero DELPHI bezalako lengoaietan erreferentzia zenbaketa eredua erabili zen. Ikuspegi honekin, erreferentzia ziklikoak ez ziren onartzen, kluster umezurtzak sortu zirenez gero, Go-k kluster horien detekzioa barneratua du (C# bezalakoa). Gainera, zabor-biltzailea gaur egun ezagutzen diren inplementazio gehienak baino eraginkorragoa da eta denbora errealeko zeregin askotarako erabil daiteke jada. Hizkuntzak berak antzematen ditu aldagai bat gordetzeko balio bat pilara esleitu daitekeen egoerak. Horrek memoria-kudeatzailearen karga murrizten du eta programaren abiadura handitzen du.

Aldiberetasuna eta aldiberekotasuna

Hizkuntzaren paralelismoa eta lehiakortasuna laudorioz kanpo dago. Maila baxuko hizkuntzak ere ezin du Go-rekin urrunetik lehiatu. Zintzoa izateko, azpimarratzekoa da eredua ez dutela hizkuntzaren egileek asmatu, ADA hizkuntza zahar onetik hartu besterik ez dutela. Lengoaia gai da milioika konexio paralelo prozesatzeko PUZ guztiak erabiliz, hari anitzeko kodearentzat ohikoak diren blokeoekin eta lasterketa-baldintzekin arazo konplexuak ez diren neurrian.

Abantail gehigarriak

Errentagarria bada, denak desinteresatu egingo dira.

Hizkuntzak, gainera, zalantzarik gabeko onura ugari eskaintzen dizkigu:

  • Proiektua eraiki ondoren fitxategi exekutagarri bakar batek asko errazten du aplikazioen hedapena.
  • Idazketa estatikoak eta inferentzia motak nabarmen murrizten dute zure kodean akatsen kopurua, nahiz eta probak idatzi gabe. Ezagutzen ditut programatzaile batzuk probak idatzi gabe egiten dituztenak eta haien kodearen kalitateak ez du nabarmen sufritzen.
  • Konpilazio gurutzatu oso sinplea eta liburutegi estandarraren eramangarritasun bikaina, plataforma anitzeko aplikazioen garapena asko errazten duena.
  • RE2 adierazpen erregularrak hari seguruak dira eta aurreikus daitezkeen exekuzio-denborak dituzte.
  • Liburutegi estandar indartsua, proiektu gehienei hirugarrenen esparrurik gabe egitea ahalbidetzen diena.
  • Hizkuntza nahikoa indartsua da arazoa nola konpondu beharrean, baina maila baxua arazoa modu eraginkorrean konpondu ahal izateko.
  • Go eko sistemak dagoeneko tresna garatuak ditu kaxa guztietarako: probak, dokumentazioa, paketeen kudeaketa, linter indartsuak, kodea sortzea, lasterketa-baldintzen detektagailua, etab.
  • Go 1.11 bertsioak mendekotasun semantikoen kudeaketa integratua sartu zuen, VCS ostalaritza ezagunaren gainean eraikia. Go ekosistema osatzen duten tresna guztiek zerbitzu hauek erabiltzen dituzte haien kodea kolpe bakarrean deskargatzeko, eraikitzeko eta instalatzeko. Eta hori bikaina da. 1.11 bertsioa iristearekin batera, paketeen bertsioaren arazoa ere erabat konpondu zen.
  • Hizkuntzaren oinarrizko ideia magia murriztea denez, hizkuntzak garatzaileak bultzatzen ditu akatsak modu esplizituan kudeatzeko. Eta hau zuzena da, bestela, erroreen kudeaketaz guztiz ahaztuko baita. Beste gauza bat da garatzaile gehienek nahita alde batera uzten dutela erroreen kudeaketa, eta nahiago dute prozesatu beharrean errorea gorantz bidaltzea.
  • Hizkuntzak ez du OOP metodologia klasikoa ezartzen, bere forma hutsean ez baitago birtualitaterik Go-n. Hala ere, hau ez da arazoa interfazeak erabiltzean. OOP ezak nabarmen murrizten du hasiberrientzako sarrera-hesia.

Soiltasuna komunitatearen onurarako

Erraza da konplikatzea, zaila da erraztea.

Go sinplea izateko diseinatu zen eta helburu horretan lortzen du. Talde-lanaren onurak ulertzen dituzten eta Enpresa mailako lengoaien aldakortasun amaigabeaz nekatuta dauden programatzaile adimentsuentzat idatzi zen. Bere armategian egitura sintaktikoen multzo nahiko txikia izanik, ia ez du denboran zehar aldaketarik jasan, beraz, garatzaileek denbora asko libre dute garapenerako, eta ez hizkuntza-berrikuntzak etengabe aztertzeko.

Enpresek ere abantaila ugari jasotzen dituzte: sarrera-hesi baxuari esker, espezialista bat azkar aurki dezakete, eta hizkuntzaren aldaezintasunari esker kode bera erabiltzeko aukera ematen du 10 urte igaro ondoren ere.

Ondorioa

Garunaren tamaina handiak ez du inoiz elefanterik Nobel saridun bihurtu.

Bere ego pertsonalak talde-espirituaren gainetik lehenesten duten programatzaileentzat, baita erronka akademikoak eta amaigabeko "auto-hobekuntza" maite dituzten teorikoentzat ere, hizkuntza oso txarra da, helburu orokorreko artisau-hizkuntza bat baita, lortzen uzten ez dizuna. plazer estetikoa zure lanaren emaitzatik eta erakutsi zure burua profesionala lankideen aurrean (baldin eta irizpide horien arabera neurtzen badugu adimena, eta ez adimenaren arabera). Bizitzan dena bezala, lehentasun pertsonalen kontua da. Merezi duten berrikuntza guztiak bezala, hizkuntzak ukazio unibertsaletik masa onartzera bide luzea egin du jada. Hizkuntza asmatsua da bere soiltasunean, eta, dakizuenez, ingenioso guztia sinplea da!

Iturria: www.habr.com

Gehitu iruzkin berria