Zamonaviy JavaScript-da oqlangan naqshlar: RORO

Wu yi surati Unsplash-da

Men birinchi JavaScript satrlarimni til ixtiro qilinganidan ko'p o'tmay yozdim. Agar siz o'sha paytda menga JavaScript-da oqlangan naqshlar haqida bir qator maqolalar yozaman, deb aytsangiz, men xonadan kulib yuborgan bo'lar edim. Men JavaScript-ni hatto "haqiqiy dasturlash" deb ataladigan juda g'alati bir til deb o'yladim.

O'shandan beri 20 yil ichida juda ko'p narsa o'zgardi. Men endi JavaScriptda Duglas Krokfordning JavaScript-ni yozganida ko'rgan narsalarini ko'rdim: Yaxshi qismlar: "Ajoyib, ifodali kuchga ega ajoyib, dinamik dasturlash tili."

Shunday qilib, keyingi ogohlantirishsiz, bu mening so'nggi paytlarda o'zimning kichkina ajoyib naqshim. Umid qilamanki, siz undan ko'p bahramand bo'lishingiz uchun kelasiz.

Iltimos, diqqat qiling: men bu narsalardan birini ixtiro qilmaganimga aminman. Men buni boshqalarning kodlarida uchratib, oxir-oqibat o'zim qabul qilgan bo'lishim mumkin.

Ob'ektni oling, ob'ektni qaytaring (RORO).

Hozirda mening ko'pgina funktsiyalarim bitta turdagi ob'yektning bitta parametrini qabul qilishadi va ularning aksariyati tip ob'ekti qiymatiga qaytadi yoki qaror qiladi.

ES2015-da taqdim etilgan buzuvchi xususiyat tufayli, men buni kuchli namuna deb bildim. Men hatto unga ahmoqona nom berdim, chunki "RORO", chunki ... markalash? ¯ \ _ (ツ) _ / ¯

Izoh: Vayron qilish zamonaviy JavaScript-ning eng yaxshi ko'rgan xususiyatlaridan biridir. Ushbu maqolada biz undan bir oz ko'proq foydalanmoqchimiz, shuning uchun agar siz u bilan tanish bo'lmasangiz, tezlashtirish uchun tezkor video mana bu erda.

Ushbu naqshni yoqtirishingizning ba'zi sabablari:

  • Nomlangan parametrlar
  • Tozalovchi standart parametrlar
  • Boylik qiymatlari
  • Funktsiyaning oson tuzilishi

Keling, ularning har birini ko'rib chiqaylik.

Nomlangan parametrlar

Aytaylik, bizda ma'lum bir Rolda foydalanuvchilar ro'yxatini qaytaradigan va biz har bir foydalanuvchining Aloqa ma'lumotlarini, shuningdek, faol bo'lmagan foydalanuvchilarni qo'shish uchun boshqa variantni taqdim etishimiz kerak deb taxmin qilamiz.

funktsiya findUsersByRole (
  rol,
  bilanContactInfo,
  includeInactive
) {...}

Keyin ushbu funktsiyaga qo'ng'iroq quyidagicha ko'rinishi mumkin:

findUsersByRole (
  'admin',
  rost,
  rost
)

So'nggi ikkita parametrlar bir-biridan farq qiladi. "Haqiqiy, haqiqat" nimani anglatadi?

Bizning ilovamiz deyarli hech qachon Kontakt ma'lumotiga muhtoj emas, lekin deyarli har doim ham Faol bo'lmagan foydalanuvchilarga ehtiyoj sezsa nima bo'ladi? Biz doimo ushbu o'rta parametr bilan kurashishimiz kerak, garchi u unchalik ahamiyatli bo'lmasa ham (keyinchalik bu haqda ko'proq).

Muxtasar qilib aytganda, ushbu an'anaviy yondashuv bizni noaniq, shovqinli kodni qoldiradi, tushunish qiyin va yozishni qiyinlashtiradi.

Keling, bitta ob'ektni qabul qilganda nima bo'lishini ko'rib chiqaylik:

funktsiya findUsersByRole ({
  rol,
  bilanContactInfo,
  includeInactive
}) {...}

E'tibor bergan bo'lsangiz, bizning funktsiyalarimiz deyarli bir xil ko'rinishga ega, ammo biz parametrlarimiz atrofida qavslarni o'rnatganimizdan tashqari. Bu shuni anglatadiki, uchta alohida parametrlarni olishning o'rniga, bizning vazifamiz hozirda nomli xususiyatlarga ega ob'ekt bilan, ob'ektniContactInfo va includeInactive bilan kutmoqda.

Bu ES2015-da Destructuring deb nomlangan JavaScript xususiyati tufayli ishlaydi.

Endi biz o'z funktsiyamizni quyidagicha chaqirishimiz mumkin:

findUsersByRole ({
  rol: 'admin',
  bilanContactInfo: rost,
  includeInactive: haqiqiy
})

Bu ancha noaniq va o'qish va tushunish osonroq. Bundan tashqari, bizning parametrlarni o'tkazib yuborish yoki qayta tartiblash endi muammo emas, chunki ular endi ob'ektning nomlangan xususiyatlari.

Masalan, bu ishlaydi:

findUsersByRole ({
  bilanContactInfo: rost,
  rol: 'admin',
  includeInactive: haqiqiy
})

Va shunday qiladi:

findUsersByRole ({
  rol: 'admin',
  includeInactive: haqiqiy
})

Bu eski kodni buzmasdan yangi parametrlarni qo'shish imkonini beradi.

Bu erda bitta muhim eslatma shundaki, agar biz barcha parametrlarning ixtiyoriy bo'lishini xohlasak, boshqacha qilib aytganda, agar quyidagi raqamlar to'g'ri qo'ng'iroq bo'lsa ...

findUsersByRole ()

... biz parametr ob'ekti uchun standart qiymatni o'rnatishimiz kerak, masalan:

funktsiya findUsersByRole ({
  rol,
  bilanContactInfo,
  includeInactive
} = {}) {...}

Parametr ob'ekti uchun buzilishdan foydalanishning qo'shimcha afzalligi shundaki, u o'zgarmaslikka yordam beradi. Ob'ektni o'z funktsiyamizga buzganimizda, biz ob'ektning xususiyatlarini yangi o'zgaruvchiga tayinlaymiz. Ushbu parametrlarning qiymatini o'zgartirish asl ob'ektni o'zgartirmaydi.

Quyidagilarni ko'rib chiqing:

const parametrlari = {
  rol: 'Administrator',
  includeInactive: haqiqiy
}
findUsersByRole (variantlar)
funktsiya findUsersByRole ({
  rol,
  bilanContactInfo,
  includeInactive
} = {}) {
  rol = role.toLowerCase ()
  console.log (rol) // 'admin'
  ...
}
console.log (options.role) // 'Administrator'

Rolning qiymatini o'zgartirsak ham, options.role qiymati o'zgarishsiz qoladi.

Tahrirlash: Shuni ta'kidlash kerakki, buzish jarayoni sayoz nusxani yaratadi, agar biron bir parametr ob'ekti xususiyatlari (masalan, massiv yoki ob'ekt) ularni o'zgartirsa, asliga ta'sir qilishi mumkin.
(Buni ta'kidlash uchun Yuriy Xomyakovga shapka).

Hozirgacha juda yaxshi, ha?

Tozalovchi standart parametrlar

ES2015 JavaScript funktsiyalari yordamida standart parametrlarni aniqlash imkoniyati paydo bo'ldi. Aslida, yaqinda yuqoridagi findUsersByRole funktsiyamizdagi parametr ob'ektiga = {} qo'shganda standart parametrdan foydalandik.

An'anaviy standart parametrlarda bizning findUsersByRole funktsiyasi quyidagicha ko'rinishi mumkin.

funktsiya findUsersByRole (
  rol,
  withContactInfo = true,
  includeInactive
) {...}

Agar biz "Innaktiv" ni "true" ga o'rnatmoqchi bo'lsak, u holda standartni saqlab qolish uchun withContactInfo uchun aniqlik kiritilmagan tarzda o'tishimiz kerak:

findUsersByRole (
  'Administrator',
  aniqlanmagan,
  rost
)

Bu qanchalar bema'ni?

Buni parametr ob'ekti yordamida quyidagicha taqqoslang:

funktsiya findUsersByRole ({
  rol,
  withContactInfo = true,
  includeInactive
} = {}) {...}

Endi biz yoza olamiz ...

findUsersByRole ({
  rol: 'Administrator',
  includeInactive: haqiqiy
})

... vaContactInfo uchun bizning standart qiymatimiz saqlanib qoladi.

BONUS: Kerakli parametrlar

Siz shunga o'xshash narsalarni qanchadan-qancha yozgansiz?

funktsiya findUsersByRole ({
  rol,
  bilanContactInfo,
  includeInactive
} = {}) {
  if (rol == null) {
    otish xatosi (...)
  }
  ...
}
Eslatma: yuqorida == (ikki baravar teng) dan foydalanib, ikkala nol ham, aniqlanmagan ham bitta bayonot bilan tekshiriladi.

Agar men sizga kerakli parametrlarni tekshirish uchun standart parametrlardan foydalanishingiz mumkinligini aytsam nima bo'ladi?

Birinchidan, biz Xato qo'yadigan kerakliParam () funktsiyasini aniqlashimiz kerak.

Shunga o'xshash:

funktsiya zarurParam (parametr) {
  const requiredParamError = yangi xato (
   "Kerakli parametr," $ {param} "mavjud emas. '
  )
  // asl suyak izini saqlab qolish
  if (Error.captureStackTrace === 'funktsiya' turi)) {
    Error.captureStackTrace (
      zarurParamError,
      zarurParam
    )
  }
  tashlash zarurParamError
}
Bilaman, bilaman. zarurParam RORO qilmaydi. Shuning uchun men ko'p funktsiyalarimni aytdim - barchasi ham emas.

Endi biz rolni standart qiymati sifatida requiredParam so'rovini o'rnatamiz, masalan:

funktsiya findUsersByRole ({
  rol = zarurParam ('rol'),
  bilanContactInfo,
  includeInactive
} = {}) {...}

Yuqoridagi kod bilan, kimdir biron bir rolni taklif qilmasdan findUsersByRole-ga qo'ng'iroq qilsa, "Kerakli parametr", "rol" yo'q degan xato paydo bo'ladi.

Texnik jihatdan biz ushbu texnikadan odatiy standart parametrlar bilan ham foydalanishimiz mumkin; biz har doim ob'ektga muhtoj emasmiz. Ammo bu hiyla-nayrangni eslashning keragi yo'q edi.

Boylik qiymatlari

JavaScript funktsiyalari faqat bitta qiymatni qaytarishi mumkin. Agar bu qiymat ob'ekt bo'lsa, unda ko'proq ma'lumot bo'lishi mumkin.

A'zoni ma'lumotlar bazasida saqlaydigan funktsiyani ko'rib chiqing. Ushbu funktsiya ob'ektni qaytarganda, u qo'ng'iroq qiluvchiga juda ko'p ma'lumot berishi mumkin.

Masalan, saqlash funktsiyasidagi ma'lumotlarni "ko'tarish" yoki "birlashtirish" odatiy holdir. Bu degani, biz ma'lumotlar bazasi jadvaliga satrlar qo'shamiz (agar ular mavjud bo'lmasa) yoki ularni yangilaymiz (agar ular mavjud bo'lsa).

Bunday holatlarda, bizning Saqlash funktsiyamiz tomonidan amalga oshirilgan operatsiya INSERT yoki YANGILASH ekanligini bilish oson bo'ladi. Ma'lumotlar bazasida saqlangan narsalar to'g'risida aniq ma'lumot olish yaxshi bo'lar edi va operatsiya holatini bilish yaxshi bo'lar edi; u muvaffaqiyatli bo'ldimi, kattaroq bitimning bir qismi sifatida kutilmoqda, kutish vaqti keldimi?

Ob'ektni qaytarayotganda, ushbu ma'lumotlarning barchasini birdaniga etkazish oson.

Shunga o'xshash narsa:

async saveUser ({
  upsert = rost,
  bitim,
  ... userInfo
}) {
  // ma'lumotlar bazasiga saqlash
  return {
    operatsiya, // e.g 'INSERT'
    status, // masalan 'Muvaffaqiyat'
    saqlandi: userInfo
  }
}

Texnik jihatdan yuqoridagi narsa ob'ektni hal qiladigan va'da beradi, ammo siz g'oyani olasiz.

Funktsiyaning oson tarkibi

"Funktsiya tarkibi - bu yangi funktsiyani ishlab chiqarish uchun ikki yoki undan ko'p funktsiyani birlashtirish jarayoni. Funktsiyalarni bir-biriga bog'lab qo'yish, ma'lumot uzatilishi uchun bir qator quvurlarni birlashtirishga o'xshaydi ". Erik Elliot

Biz shunga o'xshash ko'rinadigan quvur funktsiyasidan foydalanib funktsiyalarni birgalikda tuzishimiz mumkin:

funktsiya trubkasi (... fns) {
  return param => fns.reduce (
    (natija, fn) => fn (natija),
    parametr
  )
}

Yuqoridagi funktsiya funktsiyalar ro'yxatini oladi va berilgan parametrdan boshlab ro'yxatni chapdan o'ngga qo'llashi mumkin bo'lgan funktsiyani qaytaradi va ro'yxatdagi har bir funktsiyaning natijasini ro'yxatdagi keyingi funktsiyaga o'tkazadi.

Agar chalkash bo'lsangiz, tashvishlanmang, quyidagi narsani tozalash kerak bo'lgan bir misol mavjud.

Ushbu yondashuvning bitta cheklanishi shundaki, ro'yxatdagi har bir funktsiya faqat bitta parametrni olishi kerak. Yaxshiyamki, biz RORO bo'lganimizda, bu muammo bo'lmaydi!

Mana bizda userUnfo ob'ekti orqali foydalanuvchi ma'lumotlarini ketma-ketligini tasdiqlaydigan, normallashtiradigan va saqlaydigan 3 alohida funktsiyalar orqali o'tkazadigan saveUser funktsiyasi bor.

saveUser (userInfo) funktsiyasi {
  qaytish trubkasi (
    tasdiqlash,
    normal holatga keltirmoq,
    turmoq
  ) (userInfo)
}

Biz tasdiqlash, normalizatsiya qilish va turg'un funktsiyalarda dam olish parametridan foydalanishimiz mumkin, faqat har bir funktsiya kerak bo'lgan qiymatlarni yo'q qilish uchun va baribir qo'ng'iroq qiluvchiga qaytarib berish.

Buning mohiyatini ochib berish uchun biroz kod berilgan.

funktsiya validate ({
  id,
  ism,
  familiya,
  elektron pochta = talab qilinganParam (),
  foydalanuvchi nomi = zarurParam (),
  o'tish = zarurParam (),
  manzili,
  ... dam oling
}) {
  // ba'zi tekshiruvlarni amalga oshiring
  return {
    id,
    ism,
    familiya,
    elektron pochta,
    foydalanuvchi nomi,
    o'tish,
    manzili,
    ... dam oling
  }
}
funktsiya normalizatsiya qilinadi ({
  elektron pochta,
  foydalanuvchi nomi,
  ... dam oling
}) {
  // normallashtirish
  return {
    elektron pochta,
    foydalanuvchi nomi,
    ... dam oling
  }
}
asinx funktsiyasi saqlanib qoladi ({
  upsert = rost,
  ... ma'lumot
}) {
  // userInfo-ni MBga saqlash
  return {
    operatsiya,
    holat,
    saqlandi: ma'lumot
  }
}

ROga yoki ROga kirmaslik - bu savol.

Boshida aytgan edim, ko'p funktsiyalarim ob'ektni oladi va ularning ko'plari ob'ektni qaytarib beradi.

Har qanday naqsh singari, RORO-ni bizning asboblar qutisidagi boshqa vosita sifatida ko'rish kerak. Biz undan parametrlar ro'yxatini yanada aniq va moslashuvchan qilib, va qaytish qiymatini yanada ifodali qilib, qiymat qo'shadigan joylarda foydalanamiz.

Agar siz har doim bitta parametrni olish kerak bo'lgan funktsiyani yozayotgan bo'lsangiz, ob'ektni qabul qilish haddan tashqari talabga javob beradi. Shunga o'xshab, agar siz qo'ng'iroq qiluvchiga oddiy qiymatni qaytarib aniq va intuitiv javob bera oladigan funktsiyani yozsangiz, ob'ektni qaytarib berishning hojati yo'q.

Men deyarli hech qachon RORO emas, bu tasdiqlash funktsiyalari. Aytaylik, bizda mavjud bo'lgan yoki yo'qligini tekshiradigan isPositiveInteger funktsiyasi musbat butun son bo'lsa, ROROdan umuman foyda bo'lmaydi.

Agar sizga ushbu maqola yoqsa, iltimos, qarsaklar ikonkasini bir necha marta silkiting va so'zni tarqatishga yordam bering. Va agar siz shunga o'xshash narsalarni o'qishni istasangiz, quyida "Dev Mastery" byulleteniga yoziling.