Մոտ մեկ տարի առաջ ինձ հանձնարարվեց փոփոխել կլանող խողովակաշարը: Այն, ինչ ես հայտնաբերեցի, այն էր, որ բավականին դժվար էր պատճառաբանել: Դա նշանակում էր, որ, իհարկե, դժվար էր փորձարկել, բայց, որ ավելի կարևոր է, դժվար էր որևէ մեկի համար վստահորեն հասկանալ և փոխել:

Այն վերցրեց իրերը Wordpress-ից, «հարստացրեց» և ուղարկեց Elasticsearch-ին (չեմ պատրաստվում մանրամասնել մուտքերի և ելքերի մասին):

Այն գրված էր ES6-ով SQS աշխատողի համար, ուստի մի տեսակ ֆունկցիոնալ տեսք ուներ: Համենայն դեպս, շատ =>ներ էին կախված, և շատ Promiseներ: Պարզապես իրականացման մանրամասները, բայց հուսով եմ, որ դա կօգնի մի փոքր ավելի կոնկրետ համատեքստ տալ:

Ես հիմա նման դիրքում եմ հայտնվել։ Ես աշխատում եմ ֆունկցիոնալ խողովակաշարի վրա, այս անգամ Սկալայում: Այն, անշուշտ, պետք է լինի ավելի զուտ գործառական, պարզապես լեզվի բնույթով: . . և, այնուամենայնիվ, դա դեռ դժվար է կարդալ և պատճառաբանել:

Այսպիսով (վերջապես հասնելով կետին) ես ուզում եմ կիսվել, թե ինչ եմ արել ES6 տարբերակի հետ, որպեսզի հեշտացնեմ պատճառաբանելը և, հետևաբար, փորձարկելը:

Վերադարձ դեպի հիմունքներ

Եկեք նախ հիշեցնենք մեզ ծրագրավորման որոշ հիմունքների մասին:

Անփոփոխելիություն

Իմպերատիվ ծրագրավորումը հիմնականում կազմված է փոփոխականությունից: Դուք ունեք որոշ փոփոխականներ: Դու նրանց մուտացիա ես անում: Կազմողը չի կարող շատ օպտիմիզացնել դրանց օգտագործումը:

Անփոփոխությունը հակառակն է (duh), և կարևոր է բանականության համար: Դա C/C++ կոմպիլյատորների մի ամբողջ դասի հիմքն է տասնամյակների ընթացքում: Այդ համատեքստում const բանալի բառն է: Դուք կարող եք հասնել այս Scala-ին և Kotlin-ին, օգտագործելով valvar-ի փոխարեն: Դուք նույնիսկ կարող եք դա անել ES6-ից առաջ անփոփոխելի հետ, ի թիվս այլոց:

Բանն այն է, որ տվյալները չեն փոխվում այն ​​սահմանելուց հետո (և գործառույթները չպետք է ունենան կողմնակի ազդեցություններ): Եթե ​​այն չփոխվի, այժմ կարող եք դրա մասին շատ ավելի լավ պատճառաբանել: Նախ պետք է գնահատել նրա բոլոր կախվածությունները: Այն ամենը, ինչ կախված է դրանից, պետք է ավելի ուշ գա: Ցանկացած անկապ բան կարող է տեղի ունենալ զուգահեռաբար, կամ ցանկացած այլ ժամանակ, ցանկացած հերթականությամբ:

Դա նաև ենթադրում է, որ եթե ինչ-որ բան փոխանցեք գործառույթին, այն չի փոփոխվի: Որոշ լեզուներով դա ավելի դժվար է կիրառել, բայց եթե դուք միշտ աշխատում եք տվյալների պատճեններով, ձեզ այլևս պետք չէ հոգ տանել: Դուք պարզապես գնացեք «Ահա ձեր տվյալները, արեք այն, ինչ ուզում եք, քանի որ ես այլևս սեփականատերը չեմ»:

Միայն պատասխանատվություն

Այս մեկն այնքան հիմնական է, բայց հազվադեպ է պահպանվում:

Քանի՞ միավորի թեստ պետք է գրեք իդեալական ֆունկցիայի համար՝ առանց ճյուղավորումների: Սա հնարք հարց չէ: Կախված մուտքերի և ելքերի տեսակներից: . . գուցե 5, մաքս. Երկուսը յուրաքանչյուր սահմանի համար, և մեկը նորմալ արժեքի համար:

Ի՞նչ կասեք մեկ ճյուղավորվող պայմանի մասին, այսինքն՝ մեկ պարզ if/else: Ամենավատ դեպքում վերջին թիվը բազմապատկեք 2-ով:

Եթե ​​ֆունկցիան կատարում է մեկից ավելի բան, ապա այս թվերն արագորեն պայթում են ամբողջական (կոպիտ ուժի համակցություններ) ծածկույթի համար:

Բայց մոռացեք թեստավորման մասին, նույնիսկ: Ինչպե՞ս կարելի է անվանել մի ֆունկցիա, որն անում է մեկից ավելի բան: Գրազ կգամ, որ ավելի վերացական անուն կտաս: Այն դառնում է անորոշ, և մարդկանց համար հեշտ է բիթեր ավելացնել: Միգուցե բայ-անվան փոխարեն նրան տալիս եք գոյական-անուն: Այժմ դա գործողություն է, գործողության փոխարեն:

Ավելի ուշ կվերադառնամ բաներ անվանելուն: . .

Քայքայումը

Սա մեծ բաները փոքր մասերի բաժանելու մասին է, ոչ թե քայքայվելու;)

Այն, ինչով ես սկսել եմ (այժմ երկու անգամ) խողովակաշար է, որտեղ կոդի գրեթե յուրաքանչյուր միավոր կատարում է մի քանի բան: Որոշ բիթեր վերցնում են տվյալներ, կազմում տվյալներ, անշուշտ փոխում են տվյալները և նույնիսկ ընտրովի փոփոխում են տվյալները:

Շատերը վերցնում են մեծ կառույցներ և փոխում արժեքները դրանց խորքում: Սա նշանակում է, որ ծածկագիրը ավելի շատ պարտականություններ ունի. այն պետք է իմանա, թե կառուցվածքում որտեղ գտնի իր համապատասխան տվյալները:

Այսպիսով, եկեք փորձենք քանդել այս բաները:

Բիթեր, որոնք կատարում են իրեր, բիթեր, որոնք կազմում են նյութեր

Իմ հին օրինակում կային բազմաթիվ որոնումներ (mysql) տվյալների բազայում: Մուտքային և ելքային ձևերը հեշտ է պատճառաբանել: Եվ մենք միավորի թեստեր չենք գրում SQL-ի համար:

Սրանք այն բիթերն են, որոնք կատարում են իրեր: Յուրաքանչյուրն ապրում է որպես մեկ ֆունկցիա .js ֆայլում: Բառացիորեն մեկ գործառույթ, որը կատարում է տվյալների բազայի հարցում: Այն ունի հստակ պարամետրեր և հայտնի ձև: Այժմ դուք կարող եք գրել միավորի թեստեր դրա համար՝ կոճղված պատասխաններով (հավանաբար իրական աշխարհի պատասխանները պատճենված են հարմարանքների մեջ):

Երբ ես դուրս բերեցի յուրաքանչյուր հարցում իր սեփական մոդուլի մեջ, շատ ավելի ակնհայտ էր, որ մնացած ամեն ինչ պարզապես կոմպոզիցիա էր: Եթե ​​խողովակաշարի քայլը նախկինում մեծ կառույց էր պահանջում, բայց հարցումը դրա կարիքը չուներ, դա կոմպոզիտորի պատասխանատվությունն է:

Այնտեղ, որտեղ կախվածություն կա, մենք սերիական խողովակաշարեր ենք կառուցում: Որտեղ տարանջատումներ կան, զուգահեռ խողովակաշարեր ենք կառուցում։

Ասեք, որ ես ունեմ փաստաթուղթ (հարցման արդյունք), որն ունի 5 մանրապատկեր: Ես կարող եմ անջատել 5 զուգահեռ փոքր նույնական հարցումներ, որոնք պարամետրացված են մանրապատկերի ID-ի վրա (կամ ինչ էլ որ լինի): Միգուցե ոչ օպտիմալ տվյալների բազայի կատարման համար, բայց հեշտ է պատճառաբանել: Մենք կարող ենք ավելի ուշ օպտիմալացնել, եթե պարզվի, որ դա խոչընդոտ է:

Երբ այդ հարցումները վերադառնում են, կոմպոզիտորը, որը ճյուղավորվել է մինչև 5, կարող է միաձուլվել 1-ին: Ես հենց նոր նկարագրեցի (ապ)կազմության 2 տեսակ։ Այսպիսով, դա անելու համար ինձ կպահանջվի առնվազն 2 խողովակաշարի բիթ.

ա) առաջինը վերցնում է փաստաթուղթը և գտնում դրա մանրապատկերների ցանկը,
բ) երկրորդը վերցնում է մանրապատկերների ID-ների ցուցակը և այն վերածում զուգահեռ հարցումների,
x) հարցման ֆունկցիան (արդեն քննարկվել է), և վերադառնալ
ա) ճյուղավորողին, որը պետք է ճիշտ կերպով միաձուլի արդյունքները տվյալների կառուցվածքի մեջ:

Գուցե դուք կարող եք դրանք պահել որպես առանձին գործառույթներ նույն ֆայլում, քանի որ դրանք բավականին լավ զուգակցված են թվում: Բայց գուցե սա սովորական ֆունկցիոնալություն է, այնպես որ կարող եք դրանք բաժանել: Ես չունեմ բոլոր պատասխանները, բայց դա որոշում է, որի մասին գոնե պետք է մտածել: Եթե ​​գտնում եք, որ այն մի քանի վայրերում դառնում է copypasta, դուք պետք է իմանաք, որ այն կարող է ավելի լավ վերացարկվել:

Իրերի անուններ տալը

Առայժմ մենք ունենք միանգամյա կոդի միավորների կույտ: Քանի որ նրանք միայն մեկ բան են անում, դրանք պետք է հեշտ լինի անվանել:

Իմ դեպքում, բոլոր նրանք, ովքեր խոսում էին տվյալների բազայի հետ, նախածանցով fetch էին: Մնացած ամեն ինչ նախածանցով էր build: Այսպիսով, buildAttachmentsը զանգահարել է fetchAttachmentThumbին 5 անգամ: Եվ buildAndIndexArticleը կանչեց buildAttachments, և մի քանի այլ բաներ:

Գրաֆիկի բոլոր տերևները fetch* են: Բոլոր մյուս հանգույցները build* են:

Սա հեշտացնում է ամեն ինչ պատճառաբանել և բացահայտել, բացառությամբ խողովակաշարի գրաֆիկի ընդհանուր ձևի: Կարծում եմ՝ կարո՞ղ եք այն դնել readme-ում: Ես պարզապես կասեմ, որ խողովակաշարի ձևը նախկինում նույնպես անթափանց էր, և այս գործընթացը չի շտկում այն, պարզապես մեղմացնում է այլ բծերը:

Նշում գրաֆիկների մասին

Ես սա ինձ համար ներկայացրեցի որպես գրաֆիկ, բայց շատ անգամ սխալ կարդացի.

Մարդկանց մեծամասնությունը դժվարանում է կարդալ գրաֆիկները, քանի որ դրանք այնքան պարզ են ներկայացնում լուծման տարածքը: Այն, ինչ նրանք ցույց չեն տալիս, ալգորիթմական մանրամասներ են, բայց դա միշտ չէ, որ ակնհայտ է: Կարևոր բանը, որ պետք է հիշել, այն է, որ յուրաքանչյուր հանգույց ունի որոշակի բովանդակություն և երեխաներ և կանոններ, թե ինչ հերթականությամբ պետք է անել բաները:

Սա, բնորոշ է, ուղղորդված ացիկլիկ գրաֆիկ է: Այս տեսակի գծապատկերները շատ օգտակար մաթեմատիկական հատկություններ ունեն, հատկապես դեդուկցիայի շուրջ, հետևաբար վերը նշված անփոփոխության և հիմնավորման մասին պարզաբանումը:

Այս գրաֆիկից դուք չեք կարող ասել, որ այն առաջինն է խորության վրա, կամ որ fetchAttachments-ը տեղի է ունենում մինչև fetchAttachmentThumb_ը, կամ որ վերջինս օգտագործվում է 5 անգամ: Բայց ես արեցի վիճակի դիագրամ՝ ցույց տալով բոլոր խոստումնալից վիճակները ճանապարհի ամեն քայլափոխի (լուծել, մերժել և այլն): Դա շատ ավելի խոսուն է և հիանալի է վրիպազերծման համար:

(Դիագրամների մասին ավելի շատ՝ հետագա գրառման մեջ):

Միավոր փորձարկում

Այժմ, երբ ամեն ինչ խելամիտ է անվանվել (ճիշտ?), միավորի թեստերը պետք է լինեն հեշտ և ակնհայտ: Բերման բիթերը կարող են հաղթահարել ուրախ և տխուր դեպքեր: Շենքի բիթերը չեն հետաքրքրում, թե ինչ տվյալներ են ստանում, քանի դեռ դրանք ճիշտ վիճակում են:

Այլ թեստեր

Այս փոփոխություններն ակնկալում են, որ սև տուփի մուտքերն ու ելքերը նույնն են, ուստի ես չեմ անդրադարձել որևէ այլ տեսակի թեստերի: Ակնհայտ է, որ միայն միավորի թեստերը չեն կարող ձեզ լիարժեք վստահություն տալ:

Վերակազմավորում

Երբ դուք չեք ստանում մեծ, հիմնականում անտեղի տվյալների կառուցվածք, դուք չպետք է իմանաք դրա ձևը և փոփոխեք կամ վերակառուցեք այն: Գործառույթներին տալով ամենանվազագույն պարամետրերի հավաքածուն, որն անհրաժեշտ է, նվազեցնում է միացումը:

Ուրեմն հիմա ի՞նչ։

Հիմնականում սա այն բաների մասին է, որոնք մարդիկ պետք է սովորեին համալսարանում: Երբ դուք զբաղված եք զբաղված գործերով, հավանաբար ժամանակ չեք գտնում ամեն ինչ ճիշտ անելու համար: Ես գիտեմ, որ միշտ չէ:

Այն, ինչ ես անում եմ, սակայն, այն է, որ տեսնեմ, թե ինչ օրինաչափություններ և մոդելներ են առաջարկում այլ մարդիկ, որպեսզի կարողանամ փորձել դրանք առանց վերլուծության վրա այդքան ժամանակ ծախսելու:

Սա այն է, ինչ ես արել եմ ձեզ համար այսօր: Հուսով եմ կստացվի~*

Տեղեկացրե՛ք ինձ, եթե ունեք ավելի լավ գաղափարներ կամ փոփոխություններ, որոնք աշխատել են ձեզ համար: