Մոտ մեկ տարի առաջ ինձ հանձնարարվեց փոփոխել կլանող խողովակաշարը: Այն, ինչ ես հայտնաբերեցի, այն էր, որ բավականին դժվար էր պատճառաբանել: Դա նշանակում էր, որ, իհարկե, դժվար էր փորձարկել, բայց, որ ավելի կարևոր է, դժվար էր որևէ մեկի համար վստահորեն հասկանալ և փոխել:
Այն վերցրեց իրերը Wordpress-ից, «հարստացրեց» և ուղարկեց Elasticsearch-ին (չեմ պատրաստվում մանրամասնել մուտքերի և ելքերի մասին):
Այն գրված էր ES6-ով SQS աշխատողի համար, ուստի մի տեսակ ֆունկցիոնալ տեսք ուներ: Համենայն դեպս, շատ =>
ներ էին կախված, և շատ Promise
ներ: Պարզապես իրականացման մանրամասները, բայց հուսով եմ, որ դա կօգնի մի փոքր ավելի կոնկրետ համատեքստ տալ:
Ես հիմա նման դիրքում եմ հայտնվել։ Ես աշխատում եմ ֆունկցիոնալ խողովակաշարի վրա, այս անգամ Սկալայում: Այն, անշուշտ, պետք է լինի ավելի զուտ գործառական, պարզապես լեզվի բնույթով: . . և, այնուամենայնիվ, դա դեռ դժվար է կարդալ և պատճառաբանել:
Այսպիսով (վերջապես հասնելով կետին) ես ուզում եմ կիսվել, թե ինչ եմ արել ES6 տարբերակի հետ, որպեսզի հեշտացնեմ պատճառաբանելը և, հետևաբար, փորձարկելը:
Վերադարձ դեպի հիմունքներ
Եկեք նախ հիշեցնենք մեզ ծրագրավորման որոշ հիմունքների մասին:
Անփոփոխելիություն
Իմպերատիվ ծրագրավորումը հիմնականում կազմված է փոփոխականությունից: Դուք ունեք որոշ փոփոխականներ: Դու նրանց մուտացիա ես անում: Կազմողը չի կարող շատ օպտիմիզացնել դրանց օգտագործումը:
Անփոփոխությունը հակառակն է (duh), և կարևոր է բանականության համար: Դա C/C++ կոմպիլյատորների մի ամբողջ դասի հիմքն է տասնամյակների ընթացքում: Այդ համատեքստում const
բանալի բառն է: Դուք կարող եք հասնել այս Scala-ին և Kotlin-ին, օգտագործելով val
-ը var
-ի փոխարեն: Դուք նույնիսկ կարող եք դա անել 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 անգամ: Բայց ես արեցի վիճակի դիագրամ՝ ցույց տալով բոլոր խոստումնալից վիճակները ճանապարհի ամեն քայլափոխի (լուծել, մերժել և այլն): Դա շատ ավելի խոսուն է և հիանալի է վրիպազերծման համար:
(Դիագրամների մասին ավելի շատ՝ հետագա գրառման մեջ):
Միավոր փորձարկում
Այժմ, երբ ամեն ինչ խելամիտ է անվանվել (ճիշտ?), միավորի թեստերը պետք է լինեն հեշտ և ակնհայտ: Բերման բիթերը կարող են հաղթահարել ուրախ և տխուր դեպքեր: Շենքի բիթերը չեն հետաքրքրում, թե ինչ տվյալներ են ստանում, քանի դեռ դրանք ճիշտ վիճակում են:
Այլ թեստեր
Այս փոփոխություններն ակնկալում են, որ սև տուփի մուտքերն ու ելքերը նույնն են, ուստի ես չեմ անդրադարձել որևէ այլ տեսակի թեստերի: Ակնհայտ է, որ միայն միավորի թեստերը չեն կարող ձեզ լիարժեք վստահություն տալ:
Վերակազմավորում
Երբ դուք չեք ստանում մեծ, հիմնականում անտեղի տվյալների կառուցվածք, դուք չպետք է իմանաք դրա ձևը և փոփոխեք կամ վերակառուցեք այն: Գործառույթներին տալով ամենանվազագույն պարամետրերի հավաքածուն, որն անհրաժեշտ է, նվազեցնում է միացումը:
Ուրեմն հիմա ի՞նչ։
Հիմնականում սա այն բաների մասին է, որոնք մարդիկ պետք է սովորեին համալսարանում: Երբ դուք զբաղված եք զբաղված գործերով, հավանաբար ժամանակ չեք գտնում ամեն ինչ ճիշտ անելու համար: Ես գիտեմ, որ միշտ չէ:
Այն, ինչ ես անում եմ, սակայն, այն է, որ տեսնեմ, թե ինչ օրինաչափություններ և մոդելներ են առաջարկում այլ մարդիկ, որպեսզի կարողանամ փորձել դրանք առանց վերլուծության վրա այդքան ժամանակ ծախսելու:
Սա այն է, ինչ ես արել եմ ձեզ համար այսօր: Հուսով եմ կստացվի~*
Տեղեկացրե՛ք ինձ, եթե ունեք ավելի լավ գաղափարներ կամ փոփոխություններ, որոնք աշխատել են ձեզ համար: