Perchè Go hè Bad for Unsmart Programmers

L'articulu hè statu scrittu cum'è una risposta à un precedente publicatu articulu antipode.

Perchè Go hè Bad for Unsmart Programmers

In l'ultimi dui anni, aghju utilizatu Go per implementà un servitore RADIUS specializatu cù un sistema di fattura sviluppatu. À a strada, imparu l'intricacies di a lingua stessa. I prugrammi stessi sò assai sèmplice è ùn sò micca u scopu di stu articulu, ma l'esperienza di usu Go stessu meriteghja uni pochi di parolle in a so difesa. Go hè diventatu una lingua sempre più mainstream per codice seriu è scalabile. A lingua hè stata creata da Google, induve hè attivamente utilizata. In fondu, pensu onestamente chì u disignu di a lingua Go hè male per i programatori UNintelligent.

Cuncepitu per i programatori debuli?

I debbuli parlanu di prublemi. I forti discorsu di idee è sogni...

Vai hè assai faciule d'amparà, cusì faciule chì pudete leghje u codice cù quasi nisuna furmazione à tutti. Sta funziunalità di a lingua hè aduprata in parechje cumpagnie glubale, quandu u codice hè lettu cù specialisti non core (manager, clienti, etc.). Questu hè assai convenientu per metodulugia cum'è Design Driven Development.
Ancu i programatori principianti cumincianu à pruduce un codice abbastanza decentu dopu una settimana o duie. U libru chì aghju studiatu hè "Go Programming" (di Mark Summerfield). U libru hè assai bonu, tocca à parechje sfumature di a lingua. Dopu à e lingue inutilmente complicate cum'è Java, PHP, a mancanza di magia hè rinfrescante. Ma prima o dopu, assai programatori limitati anu l'idea di utilizà metudi antichi in un novu campu. Hè veramente necessariu?

Rob Pike (l'ideologu principale di a lingua) hà criatu a lingua Go cum'è una lingua industriale chì hè faciule da capisce è efficace à aduprà. A lingua hè pensata per a produtividade massima in grandi squadre è ùn ci hè dubbitu. Parechji programatori principianti si lamentanu chì ci sò parechje funziunalità chì mancanu. Stu desideriu di simplicità era una decisione cuscente da i diseggiani di a lingua, è per capiscenu cumplettamente perchè era necessariu, duvemu capisce a motivazione di i sviluppatori è ciò chì anu pruvatu à ottene in Go.

Allora perchè era fattu cusì simplice? Eccu un paru di citazioni da Rob Pike:

U puntu chjave quì hè chì i nostri programatori ùn sò micca circadori. Sò, in regula, abbastanza ghjovani, venenu à noi dopu avè studiatu, forsi anu studiatu Java, o C/C++, o Python. Ùn ponu micca capisce una grande lingua, ma à u stessu tempu vulemu chì creanu un bonu software. Hè per quessa chì a lingua deve esse faciule da capisce è amparà.

Deve esse familiarizatu, à pocu pressu simile à C. I programatori chì travaglianu in Google cumincianu a so carriera prima è sò soprattuttu familiarizati cù e lingue procedurali, in particulare a famiglia C. U requisitu per a produtividade rapida in una nova lingua di prugrammazione significa chì a lingua ùn deve esse troppu radicali.

Parolle sapienti, ùn sò micca ?

Artifatti di a simplicità

A simplicità hè una cundizione necessaria per a bellezza. Lev Tolstoj.

Mantene a simplicità hè unu di i scopi più impurtanti in ogni disignu. Comu sapete, un prughjettu perfettu ùn hè micca un prughjettu induve ùn ci hè nunda di aghjunghje, ma quellu da quale ùn ci hè nunda di sguassà. Parechje persone crede chì per risolve (o ancu spressione) prublemi cumplessi, hè necessariu un strumentu cumplessu. Tuttavia, ùn hè micca. Pigliemu a lingua PERL per esempiu. L'ideologi di a lingua cridianu chì un programatore deve avè almenu trè modi diffirenti per risolve un prublema. L'ideologi di a lingua Go hà pigliatu una strada diversa, decisu chì un modu, ma veramente bonu, era abbastanza per ghjunghje u scopu. Stu approcciu hà un fundamentu seriu: l'unicu modu hè più faciule d'amparà è più difficiuli di scurdà.

Parechji migranti si lamentanu chì a lingua ùn cuntene astrazioni eleganti. Iè, questu hè veru, ma questu hè unu di i vantaghji principali di a lingua. A lingua cuntene un minimu di magia - cusì ùn hè micca necessariu una cunniscenza prufonda per leghje u prugramma. In quantu à a verbosità di u codice, questu ùn hè micca un prublema in tuttu. Un prugramma Golang bè scrittu leghje verticalmente, cù struttura pocu o micca. Inoltre, a vitezza di leghje un prugramma hè almenu un ordine di grandezza più grande di a velocità di scrittura. Se cunsiderà chì tuttu u codice hà furmatu uniformi (fattu cù u cumandamentu gofmt integratu), allora leghje uni pochi di linee extra ùn hè micca un prublema.

Ùn hè micca assai espressivu

L'arti ùn tollerà micca quandu a so libertà hè limitata. A precisione ùn hè micca a so rispunsabilità.

A causa di u desideriu di simplicità, Go manca di custruzzioni chì in altre lingue sò percepiti cum'è qualcosa di naturali da e persone abituati à elli. À u principiu, pò esse un pocu inconveniente, ma poi avete nutatu chì u prugramma hè assai più faciule è più senza ambiguità di leghje.

Per esempiu, una utilità di cunsola chì leghje stdin o un schedariu da l'argumenti di a linea di cumanda parerebbe cusì:

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

A suluzione à u listessu prublema in D, anche si pare un pocu più corta, ùn hè micca più faciule da leghje

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

L'infernu di copia

L'omu porta l'infernu in sè stessu. Martin Luther.

I principianti si lamentanu constantemente Go in quantu à a mancanza di generici. Per risolve stu prublema, a maiò parte di elli usanu a copia diretta di codice. Per esempiu, una funzione per summing una lista di numeri interi, tali prufessiunali prufessiunali credi chì a funziunalità ùn pò esse implementata in alcunu altru modu ch'è da semplice copia-incolla per ogni tipu di dati.

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

A lingua hà abbastanza mezi per implementà tali custruzzioni. Per esempiu, a prugrammazione generica seria bè.

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

E, ancu s'è u nostru codice hè diventatu un pocu più longu di u casu precedente, hè diventatu generalizatu. Dunque, ùn serà micca difficiule per noi di implementà tutte e operazioni aritmetiche.

Parechje diceranu chì un prugramma in D pare significativamente più brevi, è seranu ghjustu.

import std.stdio;
import std.algorithm;

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

In ogni casu, hè solu più corta, ma micca più curretta, postu chì l'implementazione D ignora completamente u prublema di a gestione di l'errore.

In a vita reale, cum'è a cumplessità di a logica aumenta, u distaccu si riduce rapidamente. U gap si chjude ancu più rapidamente quandu avete bisognu di fà una azzione chì ùn pò micca esse realizatu cù l'operatori di lingua standard.

In quantu à a manutenibilità, l'estensibilità è a leggibilità, in my opinion, a lingua Go vince, anche si perde in verbosità.

A prugrammazione generalizata in certi casi ci dà benefici innegabili. Questu hè chjaramente illustratu da u pacchettu di sorte. Allora, per sorte ogni lista, avemu solu bisognu di implementà l'interfaccia sort.Interface.

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

Se pigliate qualsiasi prughjettu open source è eseguite u grep "interface{}" -R cumanda, vi vede quantu spessu si usanu interfacce confuse. I camaradi chjusi dichjaranu immediatamente chì tuttu questu hè dovutu à a mancanza di generici. Tuttavia, questu ùn hè micca sempre u casu. Pighemu DELPHI per esempiu. Malgradu a prisenza di sti stessi generici, cuntene un tipu VARIANT speciale per l'operazioni cù tipi di dati arbitrarii. A lingua Go faci u listessu.

Da un cannone à i passeri

È u straitjacket deve esse adattatu à a dimensione di a follia. Stanislav Lec.

Parechji fans estremi ponu pretendenu chì Go hà un altru mecanismu per creà generici - riflessione. È seranu ghjustu ... ma solu in casi rari.

Rob Pike ci avvisa:

Questu hè un strumentu putente chì deve esse usatu cun prudenza. Hè da esse evitata, salvu micca strettamente necessariu.

Wikipedia ci dice ciò chì segue:

A riflessione si riferisce à u prucessu durante u quale un prugramma pò monitorà è mudificà a so propria struttura è u cumpurtamentu durante l'esecuzione. U paradigma di prugrammazione sottu à a riflessione hè chjamatu prugrammazione riflessiva. Questu hè un tipu di metaprogrammazione.

Tuttavia, cum'è sapete, avete da pagà per tuttu. In questu casu hè:

  • difficultà à scrive prugrammi
  • rapidità di esecuzione di u prugramma

Dunque, a riflessione deve esse usata cun prudenza, cum'è un'arma di grande calibre. L'usu senza penseru di a riflessione porta à prugrammi illegibili, errori custanti è bassa velocità. Solu a cosa per un programatore snob per pudè mostrà u so codice davanti à altri culleghi più pragmatici è modesti.

U bagagliu culturale di Xi ? Innò, da parechje lingue !

Inseme à a furtuna, i debiti sò ancu lasciati à l'eredi.

Malgradu chì parechji credi chì a lingua hè tutta basata nantu à u patrimoniu C, ùn hè micca cusì. A lingua incorpora parechji aspetti di i migliori linguaggi di prugrammazione.

fuori

Prima di tuttu, a sintassi di e strutture grammaticali hè basatu annantu à a sintassi di a lingua C. Tuttavia, a lingua DELPHI hà avutu ancu una influenza significativa. Cusì, vedemu chì i parentesi redundanti, chì riducenu assai a leghjibilità di u prugramma, sò stati completamente eliminati. A lingua cuntene ancu l'operatore ":=" inherente à a lingua DELPHI. U cuncettu di pacchetti hè prestu da lingue cum'è ADA. A dichjarazione di e entità inutilizate hè presa in prestu da a lingua PROLOG.

Semantica

I pacchetti sò stati basati nantu à a semantica di a lingua DELPHI. Ogni pacchettu incapsula dati è codice è cuntene entità private è pubbliche. Questu permette di riduce l'interfaccia di u pacchettu à u minimu.

L'operazione di implementazione per metudu di delegazione hè stata presa da a lingua DELPHI.

Cumpilation

Ùn hè senza ragiuni chì ci hè un scherzu: Go hè statu sviluppatu mentre un prugramma C era cumpilatu. Unu di i punti di forza di a lingua hè a so compilazione ultra-rapida. L'idea hè stata presa in prestito da a lingua DELPHI. Ogni pacchettu Go currisponde à un modulu DELPHI. Questi pacchetti sò ricompilati solu quandu hè veramente necessariu. Per quessa, dopu à u prossimu editu, ùn avete micca bisognu di cumpilà u prugramma sanu, ma piuttostu recompilà solu i pacchetti cambiati è i pacchetti chì dependenu di sti pacchetti cambiati (è ancu allora, solu se l'interfaccia di i pacchetti anu cambiatu).

Custruzzioni di altu livellu

A lingua cuntene parechje diverse custruzzioni di altu livellu chì ùn sò in alcun modu ligati à e lingue di livellu bassu cum'è C.

  • Corde
  • Tavulini Hash
  • Fette
  • Duck typing hè prestitu da lingue cum'è RUBY (chì, sfurtunatamenti, assai ùn capiscenu micca o usanu à u so pienu potenziale).

Gestione di memoria

A gestione di a memoria in generale meriteghja un articulu separatu. Se in lingue cum'è C ++, u cuntrollu hè completamente lasciatu à u sviluppatore, allora in lingue più tardi cum'è DELPHI, un mudellu di cunti di riferimentu hè statu utilizatu. Cù questu approcciu, i riferimenti ciclichi ùn sò micca permessi, postu chì i clusters orfani sò stati furmati, allora Go hà integratu a rilevazione di tali clusters (cum'è C#). Inoltre, u cullettivu di basura hè più efficau cà a maiò parte di l'implementazioni cunnisciute attualmente è pò esse digià utilizatu per parechje attività in tempu reale. A lingua stessa ricunnosce situazioni quandu un valore per almacenà una variàbile pò esse attribuita nantu à a pila. Questu reduce a carica nantu à u gestore di memoria è aumenta a velocità di u prugramma.

Cuncurrenza è cuncurrenza

U parallelismu è a cumpetitività di a lingua ùn hè più di elogi. Nisuna lingua di livellu bassu pò ancu cumpete remotamente cù Go. Per esse ghjustu, vale a pena nutà chì u mudellu ùn hè micca inventatu da l'autori di a lingua, ma hè statu solu prestu prestu da a bona lingua antica ADA. A lingua hè capace di processà milioni di cunnessione parallele cù tutti i CPU, mentre avè un ordine di grandezza menu cumplessu di prublemi cù i blocchi è e cundizioni di razza chì sò tipici per u codice multi-threaded.

Beneficii supplementari

S'ellu hè prufittu, ognunu diventerà altruista.

A lingua ci furnisce ancu una quantità di vantaghji indubbi:

  • Un unicu schedariu eseguibile dopu a custruzzione di u prugettu simplificà assai l'implementazione di l'applicazioni.
  • A tipografia statica è l'inferenza di tipu pò riduce significativamente u numeru di errori in u vostru codice, ancu senza testi di scrittura. Cunnoscu certi programatori chì facenu senza scrive testi in tuttu è a qualità di u so codice ùn soffre micca significativamente.
  • Compilazione croce assai simplice è portabilità eccellente di a biblioteca standard, chì simplifica assai u sviluppu di l'applicazioni multipiattaforma.
  • L'espressioni regulari RE2 sò thread-safe è anu tempi di esecuzione prevedibili.
  • Una libreria standard putente chì permette à a maiò parte di i prughjetti di fà senza quadri di terzu.
  • A lingua hè abbastanza putente per fucalizza nantu à u prublema piuttostu chè cumu per risolve, ma abbastanza bassu chì u prublema pò esse risoltu in modu efficace.
  • L'ecosistema Go cuntene digià arnesi sviluppati fora di a scatula per tutte l'occasioni: teste, documentazione, gestione di pacchetti, linters putenti, generazione di codice, rilevatore di cundizioni di razza, etc.
  • Go a versione 1.11 hà introduttu a gestione di a dependenza semantica integrata, custruita nantu à u popular hosting VCS. Tutti l'arnesi chì custituiscenu l'ecosistema Go utilizanu questi servizii per scaricà, custruisce è installà u codice da elli in un colpu. È questu hè grande. Cù l'arrivu di a versione 1.11, u prublema cù a versione di u pacchettu era ancu risolta cumplettamente.
  • Perchè l'idea core di a lingua hè di riduce a magia, a lingua incentiva i sviluppatori à fà a gestione di l'errore esplicitamente. È questu hè currettu, perchè altrimenti, si scurderà solu di a gestione di l'errore. Un'altra cosa hè chì a maiò parte di i sviluppatori ignoranu deliberatamente a manipulazione di l'errore, preferendu invece di trasfurmà solu per invià l'errore in cima.
  • A lingua ùn implementa micca a metodulugia OOP classica, postu chì in a so forma pura ùn ci hè micca virtualità in Go. Tuttavia, questu ùn hè micca un prublema quandu si usa l'interfaccia. L'assenza di OOP riduce significativamente a barriera à l'ingressu per i principianti.

Simplicità per u benefiziu di a cumunità

Hè facilitu di cumplicà, difficiule di simplificà.

Go hè statu cuncepitu per esse simplice è riesce à quellu scopu. Hè statu scrittu per i programatori intelligenti chì capiscenu i benefizii di u travagliu in squadra è sò stanchi di a variabilità infinita di e lingue à livellu Enterprise. Avè un inseme relativamente chjucu di strutture sintattiche in u so arsenale, ùn hè praticamente micca sottumessu à cambiamenti cù u tempu, cusì i sviluppatori anu assai tempu liberatu per u sviluppu, è micca per studià senza fine l'innuvazioni di lingua.

L'imprese ricevenu ancu una quantità di vantaghji: una barriera d'entrata bassa li permette di truvà rapidamente un specialista, è l'immutabilità di a lingua li permette di utilizà u listessu codice ancu dopu à 10 anni.

cunchiusioni

A grande dimensione di u cervellu ùn hà mai fattu un elefante vincitore di u Premiu Nobel.

Per quelli programatori chì u so ego persunale prima di u spiritu di squadra, è ancu i teorichi chì amanu i sfidi accademichi è l'infinitu "automigliuramentu", a lingua hè veramente male, postu chì hè una lingua artisgianale generale chì ùn vi permette micca di ottene. piacè esteticu da u risultatu di u vostru travagliu è mustrà voi prufessiunale davanti à i culleghi (furnitu chì noi misurà intelligenza da sti criteri, è micca da IQ). Cum'è tuttu in a vita, hè una questione di priorità persunale. Cum'è tutte l'innuvazioni chì valenu a pena, a lingua hà digià fattu una longa strada da a negazione universale à l'accettazione di massa. A lingua hè ingegnosa in a so simplicità, è, cum'è sapete, tuttu l'ingegnu hè simplice !

Source: www.habr.com

Add a comment