Facade pattern
Bugungi postda ko’pchilik (asosan boshlang’ich) dasturchilar funksiyalarni ishlatishda yo’l qo’yadigan xatolardan birini ko’rib chiqamiz. Bu xato funksiyani faqat bir holatga to’g’irlashdir. Ya’ni funksiya aynan bir holatga ishlaydi, lekin keyinchalik dasturga o’zgartirishlar kiritilganda funksiyani qaytadan yozib chiqish kerak. Bugun esa qanday qilib funksiyalarimizni facade pattern orqali moslashuvchan qilishni ko’rib chiqamiz.
API bilan ishlash
Hozir esa javascriptda qandaydir API dan ma’lumot olishda deyarli barcha yozishi ehtimoli katta bo’lgan kodni tahlil qilamiz. Bu kod 2ta API dan ma’lumotni olib keladi va console ga chiqaradi.
function getPosts(){
fetch("https://jsonplaceholder.typicode.com/posts?userId=1").then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err));
}
function getTodos(){
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => console.log(json))
}
getPosts();
getTodos();Katta ehtimol bilan barchangizga tanish kod :-)
Get Hayitbek Yusupov’s stories in your inbox
Join Medium for free to get updates from this writer.
Ko’rinishidan bu kod yaxshi, alohida funksiyaga olingan, refactoring qilingan. Lekin kodni funksiyani ichiga olib qo’yish bilangina ish bitmaydi. Bu kodda muammolar bor. Keling bu muammoni ko’rish uchun kodni biroz ko’paytiramiz.
function getPosts(){
fetch("https://jsonplaceholder.typicode.com/posts?userId=1").then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err));
}
function getTodos(){
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => console.log(json))
.catch(err => console.log(err));
}
function getPhotos(){
fetch('https://jsonplaceholder.typicode.com/photos')
.then(response => response.json())
.then(json => console.log(json))
.catch(err => console.log(err));
}
function getUsers(){
fetch("https://jsonplaceholder.typicode.com/users")
.then(response => response.json())
.then(users => console.log(users))
.catch(err => console.log(err));
}
getPosts();
getTodos();
getPhotos();
getUsers();Bu gal endi biz 4 xil API dan ma’lumot olyapmiz. Lekin baribir kodga qarasangiz muammolarni ko’rasiz. Siz balkim async/await ishlatish orqali muammoga yechim topsa bo’lar deb o’ylayotgandursiz. Mayli, keling endi .then() va .catch() lar o’rniga try/catch va async/await ni ishlatib ko’ramiz.
async function getPosts() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts?userId=1");
const posts = await response.json();
console.log(posts);
} catch (error) {
console.log(error);
}
}
async function getTodos() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const todos = await response.json();
console.log(todos);
} catch (error) {
console.log(error);
}
}
async function getPhotos() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/photos');
const photos = await response.json();
console.log(photos);
} catch (error) {
console.log(error);
}
}
async function getUsers() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await response.json();
console.log(users);
} catch (error) {
console.log(error);
}
}
getPosts();
getTodos();
getPhotos();
getUsers();Biz endi funksiyalarimizda async/await va try catch ishlatdik. Lekin bu ham muammoni hal qilmaydi. Chunki kodga qarasangiz bir xil kod takror takror kelgan. Bir xil kod qayta qayta kelishi esa albatta yaxshi emas. Biz endi bu muammoni hal qilish uchun facade patterndan foydalanamiz.
Facade pattern
Keling endi bir funksiya yaratamiz. Bu funksiya biz takror-takror yozgan kodni bitta qilib beradi.
async function getFetch(url) {
try {
const res = await fetch(`${url}`);
return await res.json();
} catch (error) {
console.log("Xatolik chiqdi", error);
}
}Ko’rib turganingizdek bizda funksiya o’ziga url degan argument oladi. Keyin esa o’sha url ga so’rov yuboradi va kelgan ma’lumotni return qiladi. Biror xatolik yuz bersa, console ga chiqaradi. Endi funksiyalardagi barcha fetch ishlatilingan joylarni o’zgartirib chiqamiz. fetch() ning o’rniga o’zimizning getFetch() funksiyasini ishlatamiz.
async function getFetch(url) {
try {
const res = await fetch(`${url}`);
return await res.json();
} catch (error) {
console.log("Xatolik chiqdi", error);
}
}
async function getPosts() {
const posts = await getFetch("https://jsonplaceholder.typicode.com/posts?userId=1");
console.log(posts);
}
async function getTodos() {
const todos = await getFetch('https://jsonplaceholder.typicode.com/todos/1');
console.log(todos);
}
async function getPhotos() {
const photos = await getFetch("https://jsonplaceholder.typicode.com/photos");
console.log(photos);
}
async function getUsers() {
const users = await getFetch("https://jsonplaceholder.typicode.com/users");
console.log(users);
}
getPosts();
getTodos();
getPhotos();
getUsers();Kodimiz qancha qisqarganiga bir qara Karl! Shuncha qatorlik kodni bitta oddiy funksiyada yozish orqali kodni ancha kamaytirdik. Lekin bu hammasi emas. Keling endi yanayam chuqurroq kirishamiz. Biz API dan qandaydir ma’lumotni GET qilmoqchi bo’lsak API linkni oxiriga parametrlar berib o’tirishimiz kerak. Masalan posts?userId=1 va hokazo. Buni qo’lda yozib o’tirish biroz muammoroq. Keling endi shu muammochani ham hal qilamiz. Biz barcha parametrlarni getFetch() funksiyamizga object ko’rinishida berib yuboramiz va getFetch() funksiyada shu parametrlar bilan ishlaymiz.
async function getFetch(url,params = {}) {
const queryString = Object.entries(params).map(param => {
return `${param[0]}=${param[1]}`;
}).join("&");
try {
const res = await fetch(`${url}?${queryString}`);
return await res.json();
} catch (error) {
console.log("Xatolik chiqdi", error);
}
}
async function getPosts() {
const posts = await getFetch("https://jsonplaceholder.typicode.com/posts",{
userId:1
});
console.log(posts);
}Funksiyamiz o’ziga params nomli objectni oladi. U object esa quyidagi ko’rinishda bo’ladi {userId:1} . Lekin biz parametrni sql command sifatida berib yuborishimiz kerak. Shuning uchun ham queryString degan o’zgaruvchiga har bitta parametrni ichidagi property (key:value) larni sql commandga o’giradi. Masalan funksiyaning params argumentiga {userId:1, userName:”john”,userAge:18} qiymatini bersak, bizga userId=1&userName=John&userAge=18 ko’rinishidagi sql command hosil bo’ladi. Keyin shu queryString nomli stringni fetch qilayotganimizda url ni yoniga qo’shib qo’yamiz.
const posts = await getFetch("https://jsonplaceholder.typicode.com/posts",{
userId:1
});
Bu holatda getFetch() funksiyasida bizning url quyidagi ko'rinishni oladi -> https://jsonplaceholder.typicode.com/posts?userId=1
Ko’rganimizdek, facade pattern orqali kodimizni ancha tozaladik va qisqartirdik. Endi facade pattern orqali getFetch() funksiyada fetch() dan emas axios kutubxonasidan foydalanamiz. Axios ni ishlatganimizda funksiyamiz deyarli o’zgarmaydi. Axios ni ishlatish uchun CDN orqali ulab olsangiz yetadi. Axios bilan ishlaganimizda getFetch() funksiyasi o’zgaradi, lekin o’zgarishi juda ham oson bo’ladi.
async function getFetch(link,params = {}) {
return axios({
url:link,
method:"GET",
params:params
}).then(res => res.data).catch(err => console.log("Xatolik",err));
}Ko’rganingizdek, unchalik ham ko’p o’zgarish yo’q. O’qishga juda ham sodda. Endi ushbu funksiyamizni qolgan joylarda ishlata olamiz.
async function getFetch(url,params = {}) {
return axios({
url:url,
method:"GET",
params:params
}).then(res => res.data).catch(err => console.log("Xatolik",err));
}
async function getPosts() {
const posts = await getFetch("https://jsonplaceholder.typicode.com/posts",{
userId:1
});
console.log(posts);
}
async function getTodos() {
const todos = await getFetch('https://jsonplaceholder.typicode.com/todos/1');
console.log(todos);
}
async function getPhotos() {
const photos = await getFetch("https://jsonplaceholder.typicode.com/photos");
console.log(photos);
}
async function getUsers() {
const users = await getFetch("https://jsonplaceholder.typicode.com/users");
console.log(users);
}
getPosts();
getTodos();
getPhotos();
getUsers();Ko’rganingizdek, facade pattern orqali yozgan kodimiz eng boshidagi koddan ancha saviyaliroq. O’qishga ham tushunishga ham va eng asosiysi o’zgartirishga ham oson. Haqiqiy flexible (moslashuvchan) funksiya. Agar biz axios ishlatganimizdayu facade pattern ni ishlatmasak, har bir joyda fetch ning o’rniga axios yozib chiqishimiz kerak. Eng boshidagi kodga qayting. O’sha kodda fetchni o’rniga axios ishlatish kerak bo’lib qolganda tamom edi. Har bitta fetch ishlatilgan joyni axios ga o’zgartirish kerak edi. Lekin biz bittagina funksiyani ichida o’zgartirdik. Lekin dasturimiz ishlashdan to’xtamadi.
Xulosa
Facade pattern ning maqsadi ishlatishga noqulay bo’lgan API ni ishlatish qulay bo’lgan API ga aylantirishdir. Bir marta yaxshilab qulay qilib funksiya yozib olasiz va uni ishlataverasiz. Mabodo axios ishlatishingiz kerak bo’lib qolsa kodingizni faqat bir joyda o’zgartirasiz. Xato qilish ehtimolingiz kamroq bo’ladi.




