Чаро тарроҳии Go барои барномасозони оқил бад аст

Дар тӯли моҳҳои охир ман Go-ро барои татбиқ истифода мекардам. Исботи консепсия (тақрибан.: код барои санчидани фаъолияти идея) дар вакти холии худ, кисман барои омухтани худи забони барномасозй. Худи барномаҳо хеле соддаанд ва ҳадафи ин мақола нестанд, аммо таҷрибаи истифодаи Go худи сазовори чанд сухан дар бораи он аст. Рафта ваъда медиҳад, ки (тақрибан.: мақолае, ки соли 2015 навишта шудааст) забони маъмул барои коди ҷиддии миқёспазир. Забон аз ҷониби Google сохта шудааст, ки дар он фаъолона истифода мешавад. Дар поён, ман ростқавлона фикр мекунам, ки тарҳи забони Go барои барномасозони оқил бад аст.

Барои барномасозони заиф тарҳрезӣ шудааст?

Гузаштанро омӯхтан хеле осон аст, он қадар осон аст, ки муқаддима маро як бегоҳ гирифт, ки пас аз он ман аллакай самаранок рамзгузорӣ карда метавонистам. Китобе, ки ман Go омӯхтам, ном дорад Муқаддима ба барномасозӣ дар Go (тарҷума), он дар интернет дастрас аст. Китоб, ба монанди худи коди сарчашмаи Go, хондан осон аст, намунаҳои хуби рамзӣ дорад ва тақрибан 150 саҳифаро дар бар мегирад, ки онҳоро дар як нишаст хондан мумкин аст. Ин соддагӣ дар аввал тароватбахш аст, махсусан дар ҷаҳони барномасозӣ пур аз технологияи аз ҳад мураккаб. Аммо дар охир дер ё зуд чунин фикр ба миён меояд: «Оё дар хакикат хамин тавр аст?».

Google иддао дорад, ки соддагии Go нуқтаи фурӯши он аст ва забон барои ҳосилнокии ҳадди аксар дар дастаҳои калон тарҳрезӣ шудааст, аммо ман ба ин шубҳа дорам. Хусусиятҳое ҳастанд, ки ё гум шудаанд ё аз ҳад зиёд муфассал. Ва ҳама аз сабаби набудани эътимод ба таҳиягарон, бо гумони он, ки онҳо ҳеҷ кореро дуруст карда наметавонанд. Ин хоҳиши соддагӣ тасмими бошуурона аз ҷониби тарроҳони забон буд ва барои пурра фаҳмидани он, ки чаро он зарур аст, мо бояд ангезаи таҳиягарон ва он чизеро, ки онҳо дар Go ноил шудан мехостанд, бифаҳмем.

Пас чаро ин қадар содда карда шуд? Дар ин ҷо якчанд иқтибосҳо ҳастанд Роб Пайк (тақрибан.: яке аз созандагони забони Go):

Нуктаи асосии ин ҷо он аст, ки барномасозони мо (тақрибан.: Googlers) тадкикотчиён нестанд. Онҳо, чун қоида, хеле ҷавонанд, пас аз таҳсил ба мо меоянд, шояд онҳо Java, ё C/C++ ё Python-ро омӯхтаанд. Онҳо забони олиро фаҳмида наметавонанд, аммо дар айни замон мо мехоҳем, ки онҳо нармафзори хуб эҷод кунанд. Аз ин рӯ, забони онҳо бояд барои фаҳмидан ва омӯхтан осон бошад.
 
Ӯ бояд шинос бошад, тақрибан ба C монанд бошад. Барномасозоне, ки дар Google кор мекунанд, карераи худро барвақт оғоз мекунанд ва асосан бо забонҳои мурофиавӣ, бахусус оилаи C, ошно ҳастанд. Талабот барои ҳосилнокии зуд дар забони нави барномасозӣ маънои онро дорад, ки забон набояд аз ҳад радикалӣ бошад.

Чӣ? Ҳамин тавр, Роб Пайк аслан мегӯяд, ки таҳиягарон дар Google он қадар хуб нестанд, аз ин рӯ онҳо забонеро барои аблаҳон сохтаанд (тақрибан.: гунг) то тавонанд коре кунанд. Ба хамкасбони худатон чй гуна нигохи магрурй? Ман ҳамеша боварӣ доштам, ки таҳиягарони Google аз беҳтарин ва беҳтарин дар рӯи замин интихоб карда мешаванд. Албатта, онҳо метавонанд чизи душвортарро ҳал кунанд?

Артефактҳои соддагии аз ҳад зиёд

Содда будан дар ҳама гуна тарҳ ҳадафи арзанда аст ва кӯшиши содда кардани чизе душвор аст. Бо вуҷуди ин, ҳангоми кӯшиши ҳалли (ё ҳатто ифода кардани) мушкилоти мураккаб баъзан асбоби мураккаб лозим аст. Мушкилӣ ва печидаӣ беҳтарин хусусиятҳои забони барномасозӣ нест, аммо як заминаи миёна вуҷуд дорад, ки дар он забон абстраксияҳои шево эҷод кунад, ки барои фаҳмидан ва истифода осон аст.

На он қадар ифоданок

Аз сабаби ӯҳдадории худ ба соддагӣ, Go конструксияҳое надорад, ки дар забонҳои дигар ҳамчун табиӣ қабул карда мешаванд. Ин метавонад дар аввал як идеяи хуб ба назар расад, аммо дар амал он ба рамзи муфассал оварда мерасонад. Сабаби ин бояд равшан бошад - барои таҳиягарон хондани рамзи одамони дигар бояд осон бошад, аммо дар асл ин соддакунӣ танҳо ба хондан зарар мерасонад. Дар Go ягон ихтисорот вуҷуд надорад: ё бисёр ё ҳеҷ чиз.

Масалан, утилитаи консоле, ки stdin ё файлро аз аргументҳои сатри фармон мехонад, чунин хоҳад буд:

package main

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

func main() {

    flag.Parse()
    flags := flag.Args()

    var text string
    var scanner *bufio.Scanner
    var err error

    if len(flags) > 0 {

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

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

        scanner = bufio.NewScanner(file)

    } else {
        scanner = bufio.NewScanner(os.Stdin)
    }

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

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

    fmt.Println(text)
}

Ҳарчанд ин код низ кӯшиш мекунад, ки то ҳадди имкон умумӣ бошад, ифшои маҷбурии Go монеа мешавад ва дар натиҷа, ҳалли як масъалаи оддӣ боиси миқдори зиёди код мегардад.

Дар ин ҷо, масалан, як роҳи ҳалли ҳамон мушкилот дар D:

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

Ва кӣ ҳоло хондантар аст? Ман овози худро ба Д медиҳам. Рамзи ӯ бештар хондан аст, зеро вай амалҳоро равшантар тасвир мекунад. D мафҳумҳои хеле мураккабтарро истифода мебарад (тақрибан.: даъвати функсияи алтернативӣ и қолибҳо) назар ба мисоли Go, аммо дар фаҳмидани онҳо ҳеҷ чизи мушкиле вуҷуд надорад.

Ҷаҳаннам нусхабардорӣ

Пешниҳоди маъмул барои беҳтар кардани Go умумӣ аст. Ин ҳадди аққал аз нусхабардории нолозими код барои дастгирии ҳама намуди додаҳо кӯмак мекунад. Масалан, функсияи ҷамъбасти рӯйхати ададҳоро ба ҷуз аз нусхабардорӣ кардани вазифаи асосии он барои ҳар як намуди бутун ба ҳеҷ ваҷҳ амалӣ кардан мумкин нест; роҳи дигар вуҷуд надорад:

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 int16Sum(list []int16) (uint64) {
    var result int16 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

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

func main() {

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

    fmt.Println(int8Sum(list8))
    fmt.Println(int16Sum(list16))
    fmt.Println(int32Sum(list32))
    fmt.Println(int64Sum(list64))
}

Ва ин мисол ҳатто барои намудҳои имзошуда кор намекунад. Ин равиш принсипи такрор накардани худро комилан вайрон мекунад (хушк), яке аз маъмултарин ва равшантарин принсипҳост, ки нодида гирифтани он манбаи хатогиҳои зиёд аст. Чаро Go ин корро мекунад? Ин як ҷанбаи даҳшатноки забон аст.

Ҳамон мисол дар D:

import std.stdio;
import std.algorithm;

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

Содда, шево ва рост ба нукта. Функсияи дар ин ҷо истифодашаванда аст reduce барои навъи шаблон ва предикат. Бале, ин боз ҳам мураккабтар аз версияи Go аст, аммо фаҳмидани барномасозони оқил он қадар душвор нест. Кадом мисол барои нигоҳдорӣ ва хондан осонтар аст?

Бозгашти системаи навъи оддӣ

Ман тасаввур мекунам, ки барномасозони Go, ки инро мехонанд, аз даҳон кафк мебароянд ва фарёд мезананд: "Шумо ин корро нодуруст мекунед!" Хуб, роҳи дигари сохтани функсия ва намудҳои умумӣ вуҷуд дорад, аммо он системаи типро комилан вайрон мекунад!

Барои ҳалли мушкилот ба ин мисоли ислоҳи забони аблаҳ назар кунед:

package main

import "fmt"
import "reflect"

func Reduce(in interface{}, memo interface{}, fn func(interface{}, interface{}) interface{}) interface{} {
    val := reflect.ValueOf(in)

    for i := 0; i < val.Len(); i++ {
        memo = fn(val.Index(i).Interface(), memo)
    }

    return memo
}

func main() {

    list := []int{1, 2, 3, 4, 5}

    result := Reduce(list, 0, func(val interface{}, memo interface{}) interface{} {
        return memo.(int) + val.(int)
    })

    fmt.Println(result)
}

Ин амалй Reduce аз мақола гирифта шудааст Генерикҳои идиоматикӣ дар Go (тақрибан.: Ман тарҷумаро ёфта натавонистам, агар шумо дар ин кор кӯмак кунед, ман шод хоҳам шуд). Хуб, агар ин идиоматикӣ бошад, ман аз дидани як мисоли ғайриоддӣ нафрат дорам. Истифода interface{} - фарс аст ва дар забон он танҳо барои гузаштан аз чоп кардан лозим аст. Ин интерфейси холӣ аст ва ҳама намудҳо онро амалӣ мекунанд, ки барои ҳама озодии комил фароҳам меорад. Ин услуби барномасозӣ бениҳоят зишти аст ва ин ҳама нест. Чунин корнамоиҳои акробатикӣ истифодаи инъикоси вақти корро талаб мекунанд. Ҳатто Роб Пайк шахсонеро, ки аз ин суиистифода мекунанд, дӯст намедорад, тавре ки ӯ дар яке аз гузоришҳои худ қайд кардааст.

Ин як воситаи пурқувватест, ки бояд бо эҳтиёт истифода шавад. Аз он бояд канорагирӣ кард, агар қатъӣ зарур бошад.

Ман ба ҷои ин сафсата D қолибҳои гирифта. Чӣ тавр касе метавонад инро бигӯяд interface{} хондан бештар ё ҳатто навъи бехатар?

Мушкилоти идоракунии вобастагӣ

Go дорои системаи вобастагии дарунсохт, ки дар болои провайдерҳои маъмули хостинг сохта шудааст SCV. Асбобҳое, ки бо Go меояд, дар бораи ин хидматҳо медонанд ва метавонанд дар як лаҳза кодро аз онҳо зеркашӣ, созанд ва насб кунанд. Гарчанде ки ин олиҷаноб аст, як камбудии калон дар версия вуҷуд дорад! Бале, воқеан, шумо метавонед рамзи сарчашмаро аз хидматҳо ба монанди github ё bitbucket бо истифода аз абзорҳои Go гиред, аммо шумо версияро муайян карда наметавонед. Ва боз соддагӣ аз ҳисоби фоидаовар. Ман мантиқи чунин тасмимро фаҳмида наметавонам.

Пас аз пурсидани саволҳо дар бораи ҳалли ин мушкилот, дастаи таҳияи Go таъсис дод риштаи форум, ки дар он нишон дода шудааст, ки чӣ гуна онҳо ин масъаларо ҳал кардан мехоҳанд. Тавсияи онҳо ин буд, ки як рӯз тамоми анборро ба лоиҳаи худ нусхабардорӣ кунед ва онро "чун ҳаст" гузоред. Онҳо чӣ фикр мекунанд? Мо системаҳои аҷиби идоракунии версия дорем, ки дорои барчасп ва дастгирии версияи олӣ ҳастанд, ки эҷодкорони Go нодида мегиранд ва танҳо рамзи сарчашмаро нусхабардорӣ мекунанд.

Бағоҷи фарҳангӣ аз Си

Ба андешаи ман, Go аз ҷониби одамоне таҳия шудааст, ки тамоми умри худро C-ро истифода бурдаанд ва аз ҷониби онҳое, ки намехоҳанд чизи навро санҷанд. Забонро ҳамчун C бо чархҳои иловагӣ тавсиф кардан мумкин аст (ориг.: чархҳои таълимӣ). Дар он гайр аз дастгирй кардани параллелизм (ки, дар омади гап, ачоиб аст) ягон идеяи нав нест ва ин шармандагист. Шумо дар забони базӯр истифодашаванда ва ланг параллелизми аъло доред.

Мушкилоти дигари ҷиддие дар он аст, ки Go забони мурофиавӣ аст (ба мисли даҳшати хомӯшонаи C). Шумо ба навиштани код бо услуби мурофиавӣ хотима медиҳед, ки худро архаикӣ ва кӯҳна ҳис мекунад. Ман медонам, ки барномасозии ба объект нигаронидашуда як тири нуқра нест, аммо хуб мебуд, ки тавонистани тафсилотро ба намудҳо абстракт кардан ва инкапсуляцияро таъмин кардан мумкин аст.

Содда ба манфиати худ

Go барои содда тарҳрезӣ шудааст ва он дар ин ҳадаф муваффақ мешавад. Он барои барномасозони заиф бо истифода аз забони кӯҳна ҳамчун қолаб навишта шудааст. Он бо асбобҳои оддӣ барои иҷрои корҳои оддӣ пурра меояд. Хондан ва истифодааш осон аст.

Ин барои барномасозони оқил бениҳоят муфассал, бетаъсир ва бад аст.

Спасибо мерсинвалд барои таҳрир

Манбаъ: will.com

Илова Эзоҳ