Iman Hosseini Pour
syscall-nodemaster.png
یه فکت درمورد لینوکس هست که میگه:
"همه چیز در لینوکس File هست"
همین یک جمله کافی هست که متوجه بشیم تقریبا وقتی میخوایم با هرچیزی کار کنیم به نوعی با File Denoscriptor ها سرکار داریم. داخل پست قبل داخل عکس بالا یک نکته ای اشاره کرده بودم که File Denoscriptor عدد 1 چی هست؟ باهم جوابش رو اینجا برسی میکنیم.
وقتی یک Process جدید در سیستم عامل ساخته میشه File Denoscriptor های 1,2,3 به صورت رزرو شده هستن و به به Process اختصاص داده میشوند.
0 = stdin
1 = stdout
2 = stderr
داخل عکس پست قبل هرجا از
استفاده کرده بودیم در حقیقت داشتیم روی FD 1 مینوشتیم. به صورت خلاصه هروقت console.log میزنیم داریم روی FD 1 مینویسیم. یعنی کنسول هم یک فایل هست. این موضوع منطقی هم هست چون وقتی یک ترمینال باز میکنید اگر
بزنید بهتون آدرس terminal باز شده رو بهتون میده که وقتی Process روش باز میکنید از طریق FD 1 و 2 شما به برنامتون input و output میفرستید و میبینید.
با این تفاسیر وقتی Terminal ما یک file هست پس میتونیم با node:fs داخلش بنویسیم.
"همه چیز در لینوکس File هست"
همین یک جمله کافی هست که متوجه بشیم تقریبا وقتی میخوایم با هرچیزی کار کنیم به نوعی با File Denoscriptor ها سرکار داریم. داخل پست قبل داخل عکس بالا یک نکته ای اشاره کرده بودم که File Denoscriptor عدد 1 چی هست؟ باهم جوابش رو اینجا برسی میکنیم.
وقتی یک Process جدید در سیستم عامل ساخته میشه File Denoscriptor های 1,2,3 به صورت رزرو شده هستن و به به Process اختصاص داده میشوند.
0 = stdin
1 = stdout
2 = stderr
داخل عکس پست قبل هرجا از
fmt.Println()
استفاده کرده بودیم در حقیقت داشتیم روی FD 1 مینوشتیم. به صورت خلاصه هروقت console.log میزنیم داریم روی FD 1 مینویسیم. یعنی کنسول هم یک فایل هست. این موضوع منطقی هم هست چون وقتی یک ترمینال باز میکنید اگر
tty
بزنید بهتون آدرس terminal باز شده رو بهتون میده که وقتی Process روش باز میکنید از طریق FD 1 و 2 شما به برنامتون input و output میفرستید و میبینید.
با این تفاسیر وقتی Terminal ما یک file هست پس میتونیم با node:fs داخلش بنویسیم.
import fs from "node:fs";
fs.writeSync(1, Buffer.from("Hello NodeMaster\n"));
👍14
Iman Hosseini Pour
یه فکت درمورد لینوکس هست که میگه: "همه چیز در لینوکس File هست" همین یک جمله کافی هست که متوجه بشیم تقریبا وقتی میخوایم با هرچیزی کار کنیم به نوعی با File Denoscriptor ها سرکار داریم. داخل پست قبل داخل عکس بالا یک نکته ای اشاره کرده بودم که File Denoscriptor عدد…
داشتم داکیومنت مربوط به #Docker میخوندم یک چیزی نظرم رو خیلی جلب کرد و توضیح مربوط به "-i" بود.
https://docs.docker.com/reference/compose-file/services/#stdin_open
من همیشه فکر میکردم برای این که دوتا Process بتونن باهم از طریق چنل های stdin و stdout ارتباط بگیرن نیاز دارن که رابطه Parrent and Child باهم داشته باشند که خب اشتباه میکردم. اشتباه به این بزرگی که اصلا دقت نمیکردم که pipe ها در #Linux اصلا ارتباط Parrent و Child ندارند ولی روی stdin و stdout دارن با هم ارتباط میگیرن.
بزارید این موضوع رو با مثال ببینیم یک کنجکاوی جدید هم برای آینده ایجاد کنیم.
یک ترمینال باز کنید و "ps" رو بزنید که PID مربوط بهش رو دریافت کنید. همونطور که میدونید هر Process هم 3 تا FD به صورت استاندارد برای stdout, stdin, stderr داره. حالا اگر ما یطوری PID مربوط به terminal رو داشته باشیم باید بتونیم روی چنل stdin اون Process دیتا ارسال کنیم و روی ترمینال ببینیمش.
اینجا هست که در لینوکس "/proc" میاد وسط
در این دایرکتوری میتونیم اطلاعات زیادی درمورد وضعیت کرنل بگیریم و یکی از کاراش این هست که میتونیم اطلاعات درمورد Process ها درموردش ببینیم با استفاده از فرمت زیر.
قبل تر باهم PID مربوط به ترمینالی که باز داریم رو گرفتیم حالا اگر بخوایم میتونیم از اینجا به stdin اون Process دسترسی داشته باشیم باتوجه به این که fd استاندارد stdin برای تمام proccess ها 0 هست.
خب حالا به عنوان مثال اگر برنامه زیر رو اجرا کنید میبینید که داخل stdin ترمینال شما بدون ارتباط Child and parrent از طریق stdin channel تونستید دیتا ارسال کنید.
نکته این هست که Sky is the limit. به عنوان مثال میتونید کار سم کنید که http request از طریق stdin بفرستید و response رو از stdout بخونید.
البته رابطه child and parrent همونطوری که تقریبا داخل docker هم میبینیم میتونه بهمون دسترسی بده که این چنل ها رو در دسترس بزاریم یا نه همونطوری که اگر "-i" استفاده نکنیم این چنل در دسترس نیست از طریق داکر. یک طوری مثل عوارضی بزرگ راه در نظر بگیرد.
این کار همینطور که میدونید به نوعی IPC هست اما اینجا یک سوال پیش میاد.
- وقتی نیاز نیست که دوتا Process رابطه Child and parrent داشته باشند تا روی stdin و stdout باهم ارتباط بگیرن. پس کجا محدودیت ایجاد میشه که این دوتا Process نتونن با هم روی این چنل ها ارتباط برقرار کنند؟
اینجا هست که یک ویژگی در کرنل لینوکس به اسم Namespace به ما کمک میکنه که مجموعه های مختلف از Process های ایزوله داشته باشیم و Process که در یک Namespace وجود دارند، نمیتواند با یک Process دیگر که در Namespace دیگر وجود دارد ارتباط روی stdout , stdin چنل بگیرد ( مگر socket )
منطقی هم هست چون namespace رو میشه دوتا machine مختلف در نظر گرفت تقریبا.( این موضوع درست مطلق نیست و بیشتر برای تصویر سازی هست )
حالا میخوام برگردم به مثال بالا اگر دقت کنید من مثل یک فایل رفتار کردم با fd/0. حالا با وجود این فکت که تمام IO device ها به نوعی فایل هستن میتونیم "lsusb" بزنیم فایل مربوط به کیبورد خودمون رو پیدا کنیم و براش درایور بنویسیم. که یک Process دیتا رو از روی کیبورد وقتی تایپ میکنیم بگیره و از طریق stdin مربوط به ترمینال تایپ کردن ما رو بفرسته برای TTY. این یکی رو واقعا دقیق نمیدونم چطور کار میکنه. حتی شاید این جمله یکم اشتباهات هم داشته باشه. ولی در کلیات حس میکنم اون پشت همچین اتفاقی داره میافته. که قطعا یک روز باهم دقیق برسیش میکنیم.
https://docs.docker.com/reference/compose-file/services/#stdin_open
من همیشه فکر میکردم برای این که دوتا Process بتونن باهم از طریق چنل های stdin و stdout ارتباط بگیرن نیاز دارن که رابطه Parrent and Child باهم داشته باشند که خب اشتباه میکردم. اشتباه به این بزرگی که اصلا دقت نمیکردم که pipe ها در #Linux اصلا ارتباط Parrent و Child ندارند ولی روی stdin و stdout دارن با هم ارتباط میگیرن.
بزارید این موضوع رو با مثال ببینیم یک کنجکاوی جدید هم برای آینده ایجاد کنیم.
یک ترمینال باز کنید و "ps" رو بزنید که PID مربوط بهش رو دریافت کنید. همونطور که میدونید هر Process هم 3 تا FD به صورت استاندارد برای stdout, stdin, stderr داره. حالا اگر ما یطوری PID مربوط به terminal رو داشته باشیم باید بتونیم روی چنل stdin اون Process دیتا ارسال کنیم و روی ترمینال ببینیمش.
اینجا هست که در لینوکس "/proc" میاد وسط
در این دایرکتوری میتونیم اطلاعات زیادی درمورد وضعیت کرنل بگیریم و یکی از کاراش این هست که میتونیم اطلاعات درمورد Process ها درموردش ببینیم با استفاده از فرمت زیر.
/proc/PID
قبل تر باهم PID مربوط به ترمینالی که باز داریم رو گرفتیم حالا اگر بخوایم میتونیم از اینجا به stdin اون Process دسترسی داشته باشیم باتوجه به این که fd استاندارد stdin برای تمام proccess ها 0 هست.
/proc/4561/fd/0"
خب حالا به عنوان مثال اگر برنامه زیر رو اجرا کنید میبینید که داخل stdin ترمینال شما بدون ارتباط Child and parrent از طریق stdin channel تونستید دیتا ارسال کنید.
import fs from "node:fs";
const stdinFd = fs.openSync("/proc/4561/fd/0", fs.constants.O_WRONLY);
fs.writeSync(stdinFd, Buffer.from("echo Write To stdin - NodeMaster"));
fs.closeSync(stdinFd);
نکته این هست که Sky is the limit. به عنوان مثال میتونید کار سم کنید که http request از طریق stdin بفرستید و response رو از stdout بخونید.
البته رابطه child and parrent همونطوری که تقریبا داخل docker هم میبینیم میتونه بهمون دسترسی بده که این چنل ها رو در دسترس بزاریم یا نه همونطوری که اگر "-i" استفاده نکنیم این چنل در دسترس نیست از طریق داکر. یک طوری مثل عوارضی بزرگ راه در نظر بگیرد.
این کار همینطور که میدونید به نوعی IPC هست اما اینجا یک سوال پیش میاد.
- وقتی نیاز نیست که دوتا Process رابطه Child and parrent داشته باشند تا روی stdin و stdout باهم ارتباط بگیرن. پس کجا محدودیت ایجاد میشه که این دوتا Process نتونن با هم روی این چنل ها ارتباط برقرار کنند؟
اینجا هست که یک ویژگی در کرنل لینوکس به اسم Namespace به ما کمک میکنه که مجموعه های مختلف از Process های ایزوله داشته باشیم و Process که در یک Namespace وجود دارند، نمیتواند با یک Process دیگر که در Namespace دیگر وجود دارد ارتباط روی stdout , stdin چنل بگیرد ( مگر socket )
منطقی هم هست چون namespace رو میشه دوتا machine مختلف در نظر گرفت تقریبا.( این موضوع درست مطلق نیست و بیشتر برای تصویر سازی هست )
حالا میخوام برگردم به مثال بالا اگر دقت کنید من مثل یک فایل رفتار کردم با fd/0. حالا با وجود این فکت که تمام IO device ها به نوعی فایل هستن میتونیم "lsusb" بزنیم فایل مربوط به کیبورد خودمون رو پیدا کنیم و براش درایور بنویسیم. که یک Process دیتا رو از روی کیبورد وقتی تایپ میکنیم بگیره و از طریق stdin مربوط به ترمینال تایپ کردن ما رو بفرسته برای TTY. این یکی رو واقعا دقیق نمیدونم چطور کار میکنه. حتی شاید این جمله یکم اشتباهات هم داشته باشه. ولی در کلیات حس میکنم اون پشت همچین اتفاقی داره میافته. که قطعا یک روز باهم دقیق برسیش میکنیم.
Docker Documentation
Services
Explore all the attributes the services top-level element can have.
👍20
درود به همگی دوستان.
براتون سال خوش و پر از موفقیتی رو آرزو میکنم.
امیدوارم موفق باشید.🔥
براتون سال خوش و پر از موفقیتی رو آرزو میکنم.
امیدوارم موفق باشید.🔥
👍30
یک مفهمومی در یادگیری مفاهیم عمیق وجود داره به اسم First principles thinking. خیلی خالصه میشه شکستن یک مسئله پیچیده به مسائل کوچک تر و برسی اون ها از طریق مفاهیم Fundamental. روز به روز که جلوتر میریم این موضوع کم رنگ تر و کم رنگ تر شده تا الان که باتوجه به پیشرفت LLM ها خیلی ها دیگه علاقه ای به داشتن کسب دانش عمیق درمورد یک موضوعی ندارند.
جدا از این موضوع خیلی ها از قدرتی که دانش Fundamental در هر موردی بهشون میده ( در اینجا برنامه نویسی ) خبر ندارن یا علاقه ای بهش ندارن و همین باعث میشه گاهی اوقات در یک Loop ناقص از LLM های مختلف درخواست فیکس کردن باگشون رو کنن یا در فورم های مختلف به دنبال چرایی مشکلشون بگردن و هیچ وقت ممکنه به این موضوع دقت نکنن که چقدر Fundamental میتونه راه گشا باشه براشون و اگر در این مورد خوب بودن خیلی موفق تر بودن.
به عنوان مثال در این سال ها کلی دوره آموزشی، مقاله، بلاگ پست، ویدیو یوتیوب، درمورد Event loop تهیه شده و همه دیدم ولی هیچکس نیومد تو این ویدیو ها به ما بگه که کل Event loop رو به صورت خیلی ساده میتونیم در همین چند خط کد #Clang ببینیم.
حجم چیز هایی که میشه از این man page و این تکه کد یاد گرفت درمورد مفاهیم AsyncIO و کلا IO واقعا مثال زدنی نیست و البته همین موضوع میتونه اهمیت یادگیری مفاهیم سیستم عامل رو دوباره به ما نشون بده.
گاهی اوقات بهتره وقتی یک مسئله ای داریم یک قدم عقب تر بریم و از یک زاویه دیگه بهش نگاه کنیم.
حالا سوال پیش میاد خب ایمان من میخوام Fundamental قوی بشم از کجا شروع کنم؟
فرقی نداره که Frontend dev هستین یا Backend.
سیستم عامل، شبکه، الگوریتم و البته برای FrontDev ها Web Api هم میشه در نظر گرفت.
https://man7.org/linux/man-pages/man7/epoll.7.html
جدا از این موضوع خیلی ها از قدرتی که دانش Fundamental در هر موردی بهشون میده ( در اینجا برنامه نویسی ) خبر ندارن یا علاقه ای بهش ندارن و همین باعث میشه گاهی اوقات در یک Loop ناقص از LLM های مختلف درخواست فیکس کردن باگشون رو کنن یا در فورم های مختلف به دنبال چرایی مشکلشون بگردن و هیچ وقت ممکنه به این موضوع دقت نکنن که چقدر Fundamental میتونه راه گشا باشه براشون و اگر در این مورد خوب بودن خیلی موفق تر بودن.
به عنوان مثال در این سال ها کلی دوره آموزشی، مقاله، بلاگ پست، ویدیو یوتیوب، درمورد Event loop تهیه شده و همه دیدم ولی هیچکس نیومد تو این ویدیو ها به ما بگه که کل Event loop رو به صورت خیلی ساده میتونیم در همین چند خط کد #Clang ببینیم.
حجم چیز هایی که میشه از این man page و این تکه کد یاد گرفت درمورد مفاهیم AsyncIO و کلا IO واقعا مثال زدنی نیست و البته همین موضوع میتونه اهمیت یادگیری مفاهیم سیستم عامل رو دوباره به ما نشون بده.
گاهی اوقات بهتره وقتی یک مسئله ای داریم یک قدم عقب تر بریم و از یک زاویه دیگه بهش نگاه کنیم.
حالا سوال پیش میاد خب ایمان من میخوام Fundamental قوی بشم از کجا شروع کنم؟
فرقی نداره که Frontend dev هستین یا Backend.
سیستم عامل، شبکه، الگوریتم و البته برای FrontDev ها Web Api هم میشه در نظر گرفت.
https://man7.org/linux/man-pages/man7/epoll.7.html
👍20👎1
درود و وقت بخیر دوستان. امیدوارم حالتون خوب باشه.
اخیر یک ویدیو دیدم درمورد این که چطور در Netflix از #Java استفاده میکنن. سوال پیش میاد چرا این ویدیو باید برای ما جالب باشه و اهمیت بدیم؟
باتوجه به این که این روزا به شدت تکنولوژی در حال پیشرفت هست و هر روز ابزارها و فریمورک های جدید رو شاهد هستیم. این حس رو به ما القا میکنه که باید سریع باشیم و این تکنولوژی های جدید رو یاد بگیریم و اگر یاد نگیریم عقب میافتیم و در بازار کار جایی نخواهیم داشت!
منطقی هست باتوجه به این سرعت پیشرفت و AI این حس FOMO خیلی بیشتر شده به خصوص برای دوستانی که تازه کارتر هستن و هنوز وارد بازار کار نشدند. این دسته افراد خیلی بیشتر آسیب میبینن چون تا حالا حقیقت ماجرا که اکثر شرکت ها به شدت نسبت به تغییر این دسته از تکنولوژی ها گارد دارن رو لمس نکردن و همین موضوع باعث ناراحتی و ترس خیلی زیادی میشه.
نکته جالبی که در این ویدیو میبینیم جدا از زاویه دید فنی. زاویه دید بیزینسی هم رو میبینیم که چطور تیم فنی #Netflix رو تحت تاثیر خودش گذاشته که به عنوان مثال درمورد مهاجرت کدبیس ها از #Java 8 به #Java 17 صحبت میکنه که در چندسال پیش انجام شده و این رو به عنوان یک نکته مهم بیان میکنه و درموردش و تاثیراتش صحبت میکنه. دوباره با این حال بعد از این همه تلاشی که کردن روی ورژن های مثل 21 یا 24 که جدیدتر هستن نیومدن و قطعا تا سال چند سال آینده روی همین java 17 خواهند موند.
نکته بعدی خود #Java هست؟ چرا باوجود چیزایی مثل #Golang #Rust از زبانی که برای boomer ها بوده استفاده میکنن؟
خب جواب این هست چرا اصلا استفاده نکنن؟ اکوسیستم خوبی داره سرعت بالایی داره و از همه مهم تر خیلی خیلی Stable هست و از نظر هزینه براشون به صرفه نیست که مهاجرت کنن روی تکنولوژی های دیگه.
این صحبت ها به این معنی نیست که #Java خوب هست یا #Golang یا بقیه زبان ها بد یا خوب هستند. هدف صحبت امروز بیشتر این هست که لزوما برای موفق بودن همیشه نیازی نیست آخرین فریمورک آخرین تکنولوژی Backend خفن رو بلد باشیم. هنوز هم کدبیس های #COBOL هست و #CLang و #C++ به این زودی ها جایی نمیرن و البته چقدر شرکت هایی وجود داره که روی Java 8 و .NET 3.5 هستن و البته #PHP هم هنوز نمرده و نشانه هایی از مردن هم نداره جز در ویدیو های Tech influencer ها.
https://www.youtube.com/watch?v=XpunFFS-n8I
اخیر یک ویدیو دیدم درمورد این که چطور در Netflix از #Java استفاده میکنن. سوال پیش میاد چرا این ویدیو باید برای ما جالب باشه و اهمیت بدیم؟
باتوجه به این که این روزا به شدت تکنولوژی در حال پیشرفت هست و هر روز ابزارها و فریمورک های جدید رو شاهد هستیم. این حس رو به ما القا میکنه که باید سریع باشیم و این تکنولوژی های جدید رو یاد بگیریم و اگر یاد نگیریم عقب میافتیم و در بازار کار جایی نخواهیم داشت!
منطقی هست باتوجه به این سرعت پیشرفت و AI این حس FOMO خیلی بیشتر شده به خصوص برای دوستانی که تازه کارتر هستن و هنوز وارد بازار کار نشدند. این دسته افراد خیلی بیشتر آسیب میبینن چون تا حالا حقیقت ماجرا که اکثر شرکت ها به شدت نسبت به تغییر این دسته از تکنولوژی ها گارد دارن رو لمس نکردن و همین موضوع باعث ناراحتی و ترس خیلی زیادی میشه.
نکته جالبی که در این ویدیو میبینیم جدا از زاویه دید فنی. زاویه دید بیزینسی هم رو میبینیم که چطور تیم فنی #Netflix رو تحت تاثیر خودش گذاشته که به عنوان مثال درمورد مهاجرت کدبیس ها از #Java 8 به #Java 17 صحبت میکنه که در چندسال پیش انجام شده و این رو به عنوان یک نکته مهم بیان میکنه و درموردش و تاثیراتش صحبت میکنه. دوباره با این حال بعد از این همه تلاشی که کردن روی ورژن های مثل 21 یا 24 که جدیدتر هستن نیومدن و قطعا تا سال چند سال آینده روی همین java 17 خواهند موند.
نکته بعدی خود #Java هست؟ چرا باوجود چیزایی مثل #Golang #Rust از زبانی که برای boomer ها بوده استفاده میکنن؟
خب جواب این هست چرا اصلا استفاده نکنن؟ اکوسیستم خوبی داره سرعت بالایی داره و از همه مهم تر خیلی خیلی Stable هست و از نظر هزینه براشون به صرفه نیست که مهاجرت کنن روی تکنولوژی های دیگه.
این صحبت ها به این معنی نیست که #Java خوب هست یا #Golang یا بقیه زبان ها بد یا خوب هستند. هدف صحبت امروز بیشتر این هست که لزوما برای موفق بودن همیشه نیازی نیست آخرین فریمورک آخرین تکنولوژی Backend خفن رو بلد باشیم. هنوز هم کدبیس های #COBOL هست و #CLang و #C++ به این زودی ها جایی نمیرن و البته چقدر شرکت هایی وجود داره که روی Java 8 و .NET 3.5 هستن و البته #PHP هم هنوز نمرده و نشانه هایی از مردن هم نداره جز در ویدیو های Tech influencer ها.
https://www.youtube.com/watch?v=XpunFFS-n8I
YouTube
How Netflix Uses Java - 2025 Edition
👉 Join us for JavaOne 2026. Sign up now to get ongoing updates https://go.oracle.com/LP=149517
The Netflix architecture and the way we use Java is ever-changing. On top of that, Java itself and the OSS ecosystem is changing faster than ever.
In this talk…
The Netflix architecture and the way we use Java is ever-changing. On top of that, Java itself and the OSS ecosystem is changing faster than ever.
In this talk…
👍18
یکی از ابزار هایی که وقتی با #Postgres کار میکنید و کمتر استفاده میشه ولی خیلی کاربردی هست Window function ها هستن.
به صورت کلی Window function ها این قابلیت رو میدن که دسترسی داشته باشین به مجموعه row های قبل یا بعد از record که در حال حاظر در حال برسی هست.
به عنوان مثال سناریویی رو در نظر بگیرد که نیاز دارید یک سطر X رو با سطر های X+N یا X-N برسی کنید ( row های قبل یا بعد ). یکی از کاربرد هایی که ممکنه براتون داشته باشه داخل کار کردن سناریو هایی است که با Timeseries دیتا ها سرکار دارید.
سینتکس مربوط به استفاده از window function ها به صورت کلی به این صورت هستن.
- منظور از window_function در اینجا اون فانکشنی هست که میخوایم استفاده کنیم به عنوان مثال LAG function
- قسمت PARTITION BY به صورت کلی شباهت هایی به Group by دارد ولی در حال حاظر کاری بهشون نداریم.
- قسمت Order by هم ترتیب مقایسه Row ها رو با سطر بعد یا قبلش مشخص میکنه. دقیقا مثل Order by در حالت معمولی کار میکنه.
به صورت کلی window function های مختلفی داریم ولی برای درک بهتر و این که یک مثال ساده داشته باشیم LAG function هم کاربردی هست هم ساده.
فرض کنید یک table دارید که تعداد فروش محصولات رو برای هر سال دارد.
حالا سناریویی رو تصور کنید که میخواید در هر سطر برسی کنید که نسبت به سال قبل چقدر محصول بیشتر فروش داشتین؟ اینجا LAG function به داد شما میرسه
در اینجا ما نیاز داریم که مقدار sales_amount سطر جاری رو از sales_amount سطر قبل که مربوط به سال قبل هست کم کنیم که تفاوت این دو رو بتونیم به دست بیاریم.
حالا Lag 3 تا arg میگیره که به این ترتیب هستن
- نام فیلدی که دیتا مربوط به سطر قبل یا بعدش رو لازم داریم.
- مقدار offset که میتوان عدد منفی به عنوان مثل -1 هم داشت. به صورت پیش فرض عدد 1 هست
- مقدار سوم که در اینجا نداریم default value هست که به صورت پیش فرض Null هست وقتی معمولا پیش میاد که در سطر اول یا اخر در هرکدوم از این سناریو ها ممکنه سطر بعدی یا قبلی وجود نداشته باشه پس در نتیجه یک مقداری باید قرار بگیره که پیش فرض Null هست
حالا وقتی Query رو اجرا کنید همچین نتیجه ای میبینید.
جمع بندی:
کلا Window function ها ابزار های قدرتمندی هستن که بهمون خیلی کمک میکنن Query های پیچیده ای بزنیم که ممکنه در بیزینس لاجیک های خاص مخصوصا وقتی با timeseries دیتا کار داریم انجام بدیم.
موضوع بعدی این که ترکیبشون با Subquery یک ترکیب قدرتمند هست که رسما میشه Query هایی رو نوشت که در حالت عادی باتوجه به Data model که داریم ممکنه بدست آوردن اون دیتا غیرممکن باشه و قبل از هرچیزی برای رسیدن به نتیجه وقتی نیاز داریم که دیتا رو یک تغییرات بدیم و بعد از روی اون به اطلاعات برسیم; سناریو خوبی هست برای استفاده از این دو مفهوم.
به صورت کلی Window function ها این قابلیت رو میدن که دسترسی داشته باشین به مجموعه row های قبل یا بعد از record که در حال حاظر در حال برسی هست.
به عنوان مثال سناریویی رو در نظر بگیرد که نیاز دارید یک سطر X رو با سطر های X+N یا X-N برسی کنید ( row های قبل یا بعد ). یکی از کاربرد هایی که ممکنه براتون داشته باشه داخل کار کردن سناریو هایی است که با Timeseries دیتا ها سرکار دارید.
سینتکس مربوط به استفاده از window function ها به صورت کلی به این صورت هستن.
window_function(arg1, arg2,..) OVER (
[PARTITION BY partition_expression]
[ORDER BY sort_expression [ASC | DESC] [NULLS {FIRST | LAST }])
- منظور از window_function در اینجا اون فانکشنی هست که میخوایم استفاده کنیم به عنوان مثال LAG function
- قسمت PARTITION BY به صورت کلی شباهت هایی به Group by دارد ولی در حال حاظر کاری بهشون نداریم.
- قسمت Order by هم ترتیب مقایسه Row ها رو با سطر بعد یا قبلش مشخص میکنه. دقیقا مثل Order by در حالت معمولی کار میکنه.
به صورت کلی window function های مختلفی داریم ولی برای درک بهتر و این که یک مثال ساده داشته باشیم LAG function هم کاربردی هست هم ساده.
فرض کنید یک table دارید که تعداد فروش محصولات رو برای هر سال دارد.
"year","sales_amount"
"2018","100"
"2019","120"
"2020","150"
"2021","180"
حالا سناریویی رو تصور کنید که میخواید در هر سطر برسی کنید که نسبت به سال قبل چقدر محصول بیشتر فروش داشتین؟ اینجا LAG function به داد شما میرسه
SELECT
year,
sales_amount,
sales_amount - LAG(sales_amount , 1) OVER (ORDER BY year) AS sales_diff
FROM
sales;
در اینجا ما نیاز داریم که مقدار sales_amount سطر جاری رو از sales_amount سطر قبل که مربوط به سال قبل هست کم کنیم که تفاوت این دو رو بتونیم به دست بیاریم.
حالا Lag 3 تا arg میگیره که به این ترتیب هستن
- نام فیلدی که دیتا مربوط به سطر قبل یا بعدش رو لازم داریم.
- مقدار offset که میتوان عدد منفی به عنوان مثل -1 هم داشت. به صورت پیش فرض عدد 1 هست
- مقدار سوم که در اینجا نداریم default value هست که به صورت پیش فرض Null هست وقتی معمولا پیش میاد که در سطر اول یا اخر در هرکدوم از این سناریو ها ممکنه سطر بعدی یا قبلی وجود نداشته باشه پس در نتیجه یک مقداری باید قرار بگیره که پیش فرض Null هست
حالا وقتی Query رو اجرا کنید همچین نتیجه ای میبینید.
year,sales_amount,sales_diff
2018,100,
2019,120,20
2020,150,30
2021,180,30
جمع بندی:
کلا Window function ها ابزار های قدرتمندی هستن که بهمون خیلی کمک میکنن Query های پیچیده ای بزنیم که ممکنه در بیزینس لاجیک های خاص مخصوصا وقتی با timeseries دیتا کار داریم انجام بدیم.
موضوع بعدی این که ترکیبشون با Subquery یک ترکیب قدرتمند هست که رسما میشه Query هایی رو نوشت که در حالت عادی باتوجه به Data model که داریم ممکنه بدست آوردن اون دیتا غیرممکن باشه و قبل از هرچیزی برای رسیدن به نتیجه وقتی نیاز داریم که دیتا رو یک تغییرات بدیم و بعد از روی اون به اطلاعات برسیم; سناریو خوبی هست برای استفاده از این دو مفهوم.
👍19
Node Master
قرار بر این بود که درمورد تمام موضوعات BackEnd صحبت کنیم. ولی خب تا به امروز فقط درمورد Runtime های مربوط به js بیشتر NodeJS صحبت کردیم. امروز نگاهی به یکی از ویژگی های بسیار خوب #postgres اشاره میکنیم. شما میتونید یک فیلد با تایپ JSON تعریف کنید و دیتا رو…
قبلا در مورد استفاده از jsonb در #postgres صحبت کردیم و به صورت خلاصه اشاره کردیم چرا میتونه خوب باشه. امروز دوباره قراره یک نکته دیگ که خیلی خیلی میتونه مفید باشه یاد بگیرم. این که چطور اطلاعات یک جدول رو تبدیل کنیم به json ؟
حالا سوالی که برامون پیش میاد اصلا چرا باید همچین کاری کنیم؟ به صورت کلی گاهی اوقات نیاز دارید در هنگام Query زدن اطلاعات مربوط به polymorphic table ها رو همه و همه با جزیات در یک Query ببینید. در #MySQL ظاهرا راه حل های Native برای این گونه مسائل وجود داره که در آینده باهم یاد خواهیم گرفت ولی در Postgres با کمک Json ها که آزادی عمل زیادی بهتون میده میتونید هر کاری کنید از جمله حل کردن این گونه مسائل.
فرض کنید یک users table داریم با column های id, name , email. حالا میخواهیم تمام اطلاعات مربوط به هر row رو داخل یک column به اسم user_data داشته باشیم
خب در اینجا ما از فانکشن کمکی to_json کمک گرفتیم که هر row در جدول users رو به json تبدیل کنیم که سطون های جدول users به عنوان key و مقادیر هر row به عنوان value در نظر گرفته میشود. این فانکشن کمکی به صورت کلی یکم محدود هست به این که کل سطون ها رو تبدیل به json میکنه. حالا اگر بخوایم قبل از json شدن روی دیتا مربوط به اون column های خاص یک کاری انجام بدیم مثلا type cast انجام بدیم چکار باید کنیم؟
اینجا json_build_object به نجات ما میاد.
اینجا رسما دیتا مربوط هر row رو میگیرم و دستی به شکلی که میخوایم در Result set نهایی داشته باشیم شکل میدیم. فانکشن json_build_object تعداد زوج از param ها رو میگیره که param های فرد به عنوان Key و param های زوج به عنوان Value نهایی ما در json هستن. فانکشن split_part هم مثل اینجا صرفا برای split کردن یک string هست مثل متد split در #JavaScript عمل میکنه.
به صورت کلی فانکشن های کمکی خیلی زیادی برای کار کردن با json ها در #Postgres هستن ولی این دوتا بین اون ها خیلی کاربردی تر هستن. بقیه خیلی خیلی خاص تر هستن. کلا استفاده از همین ها هم خیلی نمیبینیم چون به صورت روزمره کاربردی نیستن ولی داخل سناریو های خاصی که بالا به یکیش اشاره کردم این ها کمک خیلی بزرگی میکنند. یا حتی در استفاده از Union برای ایجاد یک interface یکسان برای Table های مربوط در Query.
نکته بعدی این که هردو فانکشن بالا ورژن jsonb هم دارند.
درمورد Performance اطلاعات دقیق ندارم و بیشتر نظر شخصی خودم هست.
- قطعا تاثیر منفی در Performance دارن ولی اونقدر کمک بزرگی میکنند که به هیچ عنوان این تاثیر منفی به چشم نمیاد برای مشکلاتی که از این روش ها استفاده میکنید.
- معمولا مشکلاتی که بالا اشاره کردم شخصا در کدبیس ها دیدم که به هردلیلی سناریو های مختلف که از این طریق میشه رفت جلو رو، در سطح application هندل کردن که خب اونجا قطعا هم دردسر خیلی بیشتری داره برای توسعه هم نگهداری و هم البته وب سرور رو درگیر کاری میکنه که لزوما براش ساخته و بهینه نشده. در نتیجه اینجا اگر تمام این موضوعات در نظر بگیری فدا کردن یک کوچولو Performance دیتابیس خیلی منطقی به نظر میاد.
حالا سوالی که برامون پیش میاد اصلا چرا باید همچین کاری کنیم؟ به صورت کلی گاهی اوقات نیاز دارید در هنگام Query زدن اطلاعات مربوط به polymorphic table ها رو همه و همه با جزیات در یک Query ببینید. در #MySQL ظاهرا راه حل های Native برای این گونه مسائل وجود داره که در آینده باهم یاد خواهیم گرفت ولی در Postgres با کمک Json ها که آزادی عمل زیادی بهتون میده میتونید هر کاری کنید از جمله حل کردن این گونه مسائل.
فرض کنید یک users table داریم با column های id, name , email. حالا میخواهیم تمام اطلاعات مربوط به هر row رو داخل یک column به اسم user_data داشته باشیم
SELECT to_json(users) AS user_data FROM users;
خب در اینجا ما از فانکشن کمکی to_json کمک گرفتیم که هر row در جدول users رو به json تبدیل کنیم که سطون های جدول users به عنوان key و مقادیر هر row به عنوان value در نظر گرفته میشود. این فانکشن کمکی به صورت کلی یکم محدود هست به این که کل سطون ها رو تبدیل به json میکنه. حالا اگر بخوایم قبل از json شدن روی دیتا مربوط به اون column های خاص یک کاری انجام بدیم مثلا type cast انجام بدیم چکار باید کنیم؟
اینجا json_build_object به نجات ما میاد.
SELECT
json_build_object(
'id',
u.id :: TEXT,
'base_mail_name',
split_part(u.email, '@', 1),
'fqdn',
split_part(u.email, '@', 2)
) AS users_data
FROM
users AS u;
اینجا رسما دیتا مربوط هر row رو میگیرم و دستی به شکلی که میخوایم در Result set نهایی داشته باشیم شکل میدیم. فانکشن json_build_object تعداد زوج از param ها رو میگیره که param های فرد به عنوان Key و param های زوج به عنوان Value نهایی ما در json هستن. فانکشن split_part هم مثل اینجا صرفا برای split کردن یک string هست مثل متد split در #JavaScript عمل میکنه.
به صورت کلی فانکشن های کمکی خیلی زیادی برای کار کردن با json ها در #Postgres هستن ولی این دوتا بین اون ها خیلی کاربردی تر هستن. بقیه خیلی خیلی خاص تر هستن. کلا استفاده از همین ها هم خیلی نمیبینیم چون به صورت روزمره کاربردی نیستن ولی داخل سناریو های خاصی که بالا به یکیش اشاره کردم این ها کمک خیلی بزرگی میکنند. یا حتی در استفاده از Union برای ایجاد یک interface یکسان برای Table های مربوط در Query.
نکته بعدی این که هردو فانکشن بالا ورژن jsonb هم دارند.
to_jsonb
jsonb_build_object
درمورد Performance اطلاعات دقیق ندارم و بیشتر نظر شخصی خودم هست.
- قطعا تاثیر منفی در Performance دارن ولی اونقدر کمک بزرگی میکنند که به هیچ عنوان این تاثیر منفی به چشم نمیاد برای مشکلاتی که از این روش ها استفاده میکنید.
- معمولا مشکلاتی که بالا اشاره کردم شخصا در کدبیس ها دیدم که به هردلیلی سناریو های مختلف که از این طریق میشه رفت جلو رو، در سطح application هندل کردن که خب اونجا قطعا هم دردسر خیلی بیشتری داره برای توسعه هم نگهداری و هم البته وب سرور رو درگیر کاری میکنه که لزوما براش ساخته و بهینه نشده. در نتیجه اینجا اگر تمام این موضوعات در نظر بگیری فدا کردن یک کوچولو Performance دیتابیس خیلی منطقی به نظر میاد.
👍10👎2
Iman Hosseini Pour
قبلا در مورد استفاده از jsonb در #postgres صحبت کردیم و به صورت خلاصه اشاره کردیم چرا میتونه خوب باشه. امروز دوباره قراره یک نکته دیگ که خیلی خیلی میتونه مفید باشه یاد بگیرم. این که چطور اطلاعات یک جدول رو تبدیل کنیم به json ؟ حالا سوالی که برامون پیش میاد…
to_json.pdf
117.7 KB
این هم یک مثال با دیتا هست که میتونه برای درک بهتر بهتون کمک کنه
درود و وقت همگی بخیر امیدوارم حالتون خوب باشه.
بچه هایی که تازه کار هستن و #Backend رو مدت کمی هست کار میکنن ممکنه یکم براشون سوال باشه که به صورت کلی یک سیستم چه چیزهایی رو دارد و چطور این ها باهم کار میکنند. به جواب رسیدن برای هرکدوم از این سوال ها زمان زیادی ممکنه از ادم بگیره اگر راهنما خوبی هم وجود نداشته باشه.
پیشنهاد میکنم این دوره رو حتما ببینید.
https://downloadly.ir/elearning/video-tutorials/system-design-for-beginners/
بهتون دید خیلی خوبی میده که چه چیزایی رو حداقل باید بدونید و میتونه به عنوان یک Roadmap هم بهش نگاه کنید که در آینده در هرکدوم از بخش های مختلف این آموزش عمیق تر بشید.
اگر باتجربه تر هم هستید و سیستم دیزاین نیاز به refresher دارید یا کلا تا حالا کار نکردین شروع خوبی میتونه باشه.
بچه هایی که تازه کار هستن و #Backend رو مدت کمی هست کار میکنن ممکنه یکم براشون سوال باشه که به صورت کلی یک سیستم چه چیزهایی رو دارد و چطور این ها باهم کار میکنند. به جواب رسیدن برای هرکدوم از این سوال ها زمان زیادی ممکنه از ادم بگیره اگر راهنما خوبی هم وجود نداشته باشه.
پیشنهاد میکنم این دوره رو حتما ببینید.
https://downloadly.ir/elearning/video-tutorials/system-design-for-beginners/
بهتون دید خیلی خوبی میده که چه چیزایی رو حداقل باید بدونید و میتونه به عنوان یک Roadmap هم بهش نگاه کنید که در آینده در هرکدوم از بخش های مختلف این آموزش عمیق تر بشید.
اگر باتجربه تر هم هستید و سیستم دیزاین نیاز به refresher دارید یا کلا تا حالا کار نکردین شروع خوبی میتونه باشه.
دانلود رایگان نرم افزار
دانلود System Design for Beginners
دانلود NeetCode.io - System Design for Beginners 2024-2 - دوره آموزشی طراحی سیستم ها، مبانی مصاحبه های طراحی سیستم را یاد بگیرید
👍22
درود و خسته نباشید دوستان امیدوارم حالتون خوب باشه.
اگر با lib هایی مثل #jest و #vitest برای پروژه هاتون تست نوشته باشید و البته بعد تلاش کرده باشین که سوییچ کنید روی std test runner خود #NodeJS که خیلی هم از Stable شدنش نمیگذره.
یکی از بزرگترین مشکلاتی که این Test runner داشت و تست نوشتن رو در یک سناریو واقعا آزار دهنده میکرد در آپدیت 22.17 LTS فیکس شده.
گاهی اوقات پیش میاد که میخواید یک subset از یک object رو assert کنید و نمیخواید کل اون attr های اون object رو assert کنید. تا قبل از این آپدیت این سناریو در STD test runner غیرممکن بود. شخصا واقعا خوشحالم که این رو خیلی سریع متوجه شدن و اضاف کردن چون همه چیزش خیلی خوب شده و فقط همین یدونه کم بود.
اگر با lib هایی مثل #jest و #vitest برای پروژه هاتون تست نوشته باشید و البته بعد تلاش کرده باشین که سوییچ کنید روی std test runner خود #NodeJS که خیلی هم از Stable شدنش نمیگذره.
یکی از بزرگترین مشکلاتی که این Test runner داشت و تست نوشتن رو در یک سناریو واقعا آزار دهنده میکرد در آپدیت 22.17 LTS فیکس شده.
assert.partialDeepStrictEqual()
گاهی اوقات پیش میاد که میخواید یک subset از یک object رو assert کنید و نمیخواید کل اون attr های اون object رو assert کنید. تا قبل از این آپدیت این سناریو در STD test runner غیرممکن بود. شخصا واقعا خوشحالم که این رو خیلی سریع متوجه شدن و اضاف کردن چون همه چیزش خیلی خوب شده و فقط همین یدونه کم بود.
👍11
امیدوارم حالتون خوب باشه دوستان.
داخل آپدیت ES2025 یک static method جدید برای به اسم Promise.try اضافه شده و در این پست باهم برسیش میکنیم.
https://telegra.ph/%D9%85%D8%AA%D8%AF-%D8%AC%D8%AF%DB%8C%D8%AF-Promisetry-%D8%AF%D8%B1-ES2025-07-21
البته به صورت تستی با استفاده از telegra.ph شاید بهتر باشه
داخل آپدیت ES2025 یک static method جدید برای به اسم Promise.try اضافه شده و در این پست باهم برسیش میکنیم.
https://telegra.ph/%D9%85%D8%AA%D8%AF-%D8%AC%D8%AF%DB%8C%D8%AF-Promisetry-%D8%AF%D8%B1-ES2025-07-21
البته به صورت تستی با استفاده از telegra.ph شاید بهتر باشه
Telegraph
متد جدید Promise.try در ES2025
NodeMaster درود امیدوارم حالتون باشه. داشتم آپدیت مربوط به ES2025 رو نگاهی یک چیز جالب دیدم. تصور کنید همچین کدی دارید function error() { throw new Error("MY ERROR") } function promiseAdaptor(callback) { return Promise.resolve(callback()) } promi…
👍13
درود دوستان.
قبلا که #python کد میزدم یک پکیج داشت به اسم isort که import ها رو خیلی تر تمیز sort میکرد. همیشه دنبال یک پکیج خوب بودم برای #typenoscript که همچین کاری رو انجام بده تا بلاخره دیروز یک پکیح خوب پیدا کردم که میتونید به عنوان config prettier استفاده کنید.
البته package های دیگ هم هستن ولی این خیلی برای من راحت تر بود. فکر کنم eslint هم همچین چیزی داشته باشه ولی فرصت نشده تست کنم.
https://www.npmjs.com/package/prettier-plugin-organize-imports
قبلا که #python کد میزدم یک پکیج داشت به اسم isort که import ها رو خیلی تر تمیز sort میکرد. همیشه دنبال یک پکیج خوب بودم برای #typenoscript که همچین کاری رو انجام بده تا بلاخره دیروز یک پکیح خوب پیدا کردم که میتونید به عنوان config prettier استفاده کنید.
البته package های دیگ هم هستن ولی این خیلی برای من راحت تر بود. فکر کنم eslint هم همچین چیزی داشته باشه ولی فرصت نشده تست کنم.
https://www.npmjs.com/package/prettier-plugin-organize-imports
👍7
Forwarded from amir jahan
Node.js Backend Developer
📍 مکان: تهران – با امکان دورکاری کامل یا هیبریدی
👨💻 نوع همکاری: تماموقت یا پارهوقت (ساعت کاری منعطف، مبتنی بر خروجی)
درباره ما
ما یک تیم تحقیق و توسعهی پویا هستیم که روی ساخت محصولات دیجیتال نوآورانه با محوریت هوش مصنوعی، دادهکاوی و سرویسهای کاربردی وب کار میکنیم. تمرکز ما روی طراحی و پیادهسازی معماریهای تمیز، مقیاسپذیر و انعطافپذیر برای پروژههاییست که کاربران واقعی و چالشهای فنی جدی دارند.
در حال حاضر به دنبال یک توسعهدهندهی بکاند با Node.js هستیم که عاشق حل مسئله و طراحی سیستمهای پایدار باشه و بتونه در ساخت سرویسهای مقیاسپذیر و حرفهای نقش کلیدی ایفا کنه.
مسئولیتها
طراحی و توسعهی سرویسهای بکاند با استفاده از Node.js (ترجیحاً با Nest.js یا Express.js)
طراحی و پیادهسازی APIها (RESTful / GraphQL) با رعایت اصول امنیتی و بهینهسازی
اتصال به دیتابیسهای MongoDB و PostgreSQL و طراحی مدل دادهی کارآمد
پیادهسازی صفهای پردازش با Kafka یا RabbitMQ
استفاده از Redis برای کشینگ و بهبود عملکرد سیستم
مشارکت در طراحی معماری سیستمها بر اساس Clean Architecture و Design Patterns
همکاری در Code Review و بهبود کیفیت کد تیم
مستندسازی مؤثر برای ماژولها و سرویسها
مهارتها و تجربهها
تسلط بالا به Node.js و یکی از فریمورکهای محبوب (Nest.js یا Express.js)
تجربه کار عملی با MongoDB و PostgreSQL
آشنایی با ابزارهای Messaging Queue مثل Kafka یا RabbitMQ
تجربهی استفاده از Redis برای کش و مدیریت Session
آشنایی با مفاهیم Microservices و معماریهای رویدادمحور (Event-driven)
تسلط به Git و آشنایی با ابزارهای مدیریت پروژه (Jira یا مشابه)
توانایی تستنویسی (Unit/Integration)
درک مفاهیم امنیتی وب و استانداردهای OWASP
آشنایی با CI/CD و مفاهیم DevOps امتیاز محسوب میشود
چرا اینجا جذابه؟
تیم حرفهای ولی صمیمی داریم
محیط کاری آزمایشی + تحقیقاتی، مناسب عاشقان یادگیری
امکان دورکاری کامل یا حضور در دفتر (اگر تهران باشی)
ساعت کاری شناور؛ تمرکز ما روی نتیجهست، نه زمان
درگیر پروژهای میشی که کاربر واقعی، مقیاسپذیری و چالشهای معماری جدی داره
اگر این موقعیت برات جالبه، لطفاً برامون بفرست:
رزومه (حتی اگر خیلی رسمی نیست)
لینک گیتهاب یا چندتا از پروژههای قبلیت
حقوق پیشنهادی (اختیاری)
مدت زمانی که میتونی در هفته همکاری داشته باشی
@amirjaha_n
y2311769@gmail.com
📍 مکان: تهران – با امکان دورکاری کامل یا هیبریدی
👨💻 نوع همکاری: تماموقت یا پارهوقت (ساعت کاری منعطف، مبتنی بر خروجی)
درباره ما
ما یک تیم تحقیق و توسعهی پویا هستیم که روی ساخت محصولات دیجیتال نوآورانه با محوریت هوش مصنوعی، دادهکاوی و سرویسهای کاربردی وب کار میکنیم. تمرکز ما روی طراحی و پیادهسازی معماریهای تمیز، مقیاسپذیر و انعطافپذیر برای پروژههاییست که کاربران واقعی و چالشهای فنی جدی دارند.
در حال حاضر به دنبال یک توسعهدهندهی بکاند با Node.js هستیم که عاشق حل مسئله و طراحی سیستمهای پایدار باشه و بتونه در ساخت سرویسهای مقیاسپذیر و حرفهای نقش کلیدی ایفا کنه.
مسئولیتها
طراحی و توسعهی سرویسهای بکاند با استفاده از Node.js (ترجیحاً با Nest.js یا Express.js)
طراحی و پیادهسازی APIها (RESTful / GraphQL) با رعایت اصول امنیتی و بهینهسازی
اتصال به دیتابیسهای MongoDB و PostgreSQL و طراحی مدل دادهی کارآمد
پیادهسازی صفهای پردازش با Kafka یا RabbitMQ
استفاده از Redis برای کشینگ و بهبود عملکرد سیستم
مشارکت در طراحی معماری سیستمها بر اساس Clean Architecture و Design Patterns
همکاری در Code Review و بهبود کیفیت کد تیم
مستندسازی مؤثر برای ماژولها و سرویسها
مهارتها و تجربهها
تسلط بالا به Node.js و یکی از فریمورکهای محبوب (Nest.js یا Express.js)
تجربه کار عملی با MongoDB و PostgreSQL
آشنایی با ابزارهای Messaging Queue مثل Kafka یا RabbitMQ
تجربهی استفاده از Redis برای کش و مدیریت Session
آشنایی با مفاهیم Microservices و معماریهای رویدادمحور (Event-driven)
تسلط به Git و آشنایی با ابزارهای مدیریت پروژه (Jira یا مشابه)
توانایی تستنویسی (Unit/Integration)
درک مفاهیم امنیتی وب و استانداردهای OWASP
آشنایی با CI/CD و مفاهیم DevOps امتیاز محسوب میشود
چرا اینجا جذابه؟
تیم حرفهای ولی صمیمی داریم
محیط کاری آزمایشی + تحقیقاتی، مناسب عاشقان یادگیری
امکان دورکاری کامل یا حضور در دفتر (اگر تهران باشی)
ساعت کاری شناور؛ تمرکز ما روی نتیجهست، نه زمان
درگیر پروژهای میشی که کاربر واقعی، مقیاسپذیری و چالشهای معماری جدی داره
اگر این موقعیت برات جالبه، لطفاً برامون بفرست:
رزومه (حتی اگر خیلی رسمی نیست)
لینک گیتهاب یا چندتا از پروژههای قبلیت
حقوق پیشنهادی (اختیاری)
مدت زمانی که میتونی در هفته همکاری داشته باشی
@amirjaha_n
y2311769@gmail.com
سلام و درود دوستان امیدوارم حالتون خوب باشه.
یک نکته ای که همیشه در پروژه ها میبینم چه در پروژه های Front و چه در پروژه های Backend وقتی با یک HTTP Request کار میکنیم اکثرا URL ها رو به صورت Hardcode میبینیم و اگر پارامتری هم نیاز داشته باشه در نهایت با استفاده از #JavaScript Template Literal کارمون رو پیش میبریم.
به صورت کلی استفاده کردن از Template Literal هیچ مشکلی نداره و کارمون راه میندازه ولی گاهی اوقات ممکنه کمی برامون دردسر ایجاد کنه. برای درک این موضوع به مثال زیر توجه کنید.
در اینجا همه چی اوکی کار میکنه مشکلی نیست ولی یک نکته که باید توجه کنیم این هست که حتما BASE_URL ما "/" اضافه نداشته باشد.
به صورت کلی مسئله خیلی بزرگی نیست ولی همین نکته کوچیک داخل code base که بهش آشنایی ندارید ممکنه ساعت ها ازتون زمان بگیره تا پیداش کنیم. خب حالا سوال پیش میاد که راه حل برای این موضوع چی هست؟
برای حل این موضوع میتونید از URL Web API استفاده کنید. به عنوان مثال اگر کد بالا را بخواهیم Refactor کنیم به این صورت خیلی کارمون تمیز تر و راحت تر میشه و دیگه همچین چیزی رو نمیبینیم.
باتوجه به این که داریم از Web API استفاده میکنیم داخل تمامی Runtime ها به راحتی میتونیم از این API استفاده کنیم و همشون هم به همین شکل کار میکنن.
حالا گاهی اوقات میخوایم querystring مثل زیر داشته باشیم
دوباره استفاده از Template literal هیچ ایرادی نداره کارمون راه میندازه ولی اگر بخواهیم این رو هم تمیز تر کنیم که در آینده کارمون راحت تر باشه و کد تمیز تری داشته باشیم چطور؟
برای این کار هم میتونیم از سه روش کارمون رو پیش ببریم
1. استفاده از node:querystring که این module فقط استاندارد #NodeJS هست.
2. استفاده از URLSearchParams Web API که باتوجه به این که Web API هست قطعا همه جا پشتیبانی میشه.
3. استفاده از راه حل دوم به صورت غیر مستقیم با استفاده از searchParams property مربوط به URL.
حالا اگر بخواهیم مثال بالا رو Refactor کنیم و همچین چیزی رو اضاف کنیم به این صورت عمل میکنیم.
در نگاه اول ممکنه خیلی نکته بزرگی به نظر نیاد ولی داخل code base های بزرگ که با کلی API 3rd party کار میکنید میتونه فرشته نجات باشه.
یک نکته ای که همیشه در پروژه ها میبینم چه در پروژه های Front و چه در پروژه های Backend وقتی با یک HTTP Request کار میکنیم اکثرا URL ها رو به صورت Hardcode میبینیم و اگر پارامتری هم نیاز داشته باشه در نهایت با استفاده از #JavaScript Template Literal کارمون رو پیش میبریم.
به صورت کلی استفاده کردن از Template Literal هیچ مشکلی نداره و کارمون راه میندازه ولی گاهی اوقات ممکنه کمی برامون دردسر ایجاد کنه. برای درک این موضوع به مثال زیر توجه کنید.
import process from "node:process";
const BASE_URL = process.env.BASE_URL;
const url = `${BASE_URL}/posts/1`;
fetch(url);
در اینجا همه چی اوکی کار میکنه مشکلی نیست ولی یک نکته که باید توجه کنیم این هست که حتما BASE_URL ما "/" اضافه نداشته باشد.
https://jsonplaceholder.typicode.com/ ❌
https://jsonplaceholder.typicode.com ✅
به صورت کلی مسئله خیلی بزرگی نیست ولی همین نکته کوچیک داخل code base که بهش آشنایی ندارید ممکنه ساعت ها ازتون زمان بگیره تا پیداش کنیم. خب حالا سوال پیش میاد که راه حل برای این موضوع چی هست؟
برای حل این موضوع میتونید از URL Web API استفاده کنید. به عنوان مثال اگر کد بالا را بخواهیم Refactor کنیم به این صورت خیلی کارمون تمیز تر و راحت تر میشه و دیگه همچین چیزی رو نمیبینیم.
import process from "node:process";
import { URL } from "node:url";
const url = new URL(process.env.BASE_URL);
const path = "/posts/1";
url.pathname = path;
fetch(url.href);
باتوجه به این که داریم از Web API استفاده میکنیم داخل تمامی Runtime ها به راحتی میتونیم از این API استفاده کنیم و همشون هم به همین شکل کار میکنن.
حالا گاهی اوقات میخوایم querystring مثل زیر داشته باشیم
/post?userId=1&tag=nodejs
دوباره استفاده از Template literal هیچ ایرادی نداره کارمون راه میندازه ولی اگر بخواهیم این رو هم تمیز تر کنیم که در آینده کارمون راحت تر باشه و کد تمیز تری داشته باشیم چطور؟
برای این کار هم میتونیم از سه روش کارمون رو پیش ببریم
1. استفاده از node:querystring که این module فقط استاندارد #NodeJS هست.
2. استفاده از URLSearchParams Web API که باتوجه به این که Web API هست قطعا همه جا پشتیبانی میشه.
3. استفاده از راه حل دوم به صورت غیر مستقیم با استفاده از searchParams property مربوط به URL.
حالا اگر بخواهیم مثال بالا رو Refactor کنیم و همچین چیزی رو اضاف کنیم به این صورت عمل میکنیم.
import process from "node:process";
import { URL } from "node:url";
import querystring from "node:querystring";
const url = new URL(process.env.BASE_URL);
const query = { userId: 1, tag: "NodeMaster" };
// #1 Using querystring module from NodeJS
const path = "/posts";
url.pathname = path;
url.search = querystring.stringify(query);
// #2 Using URLSearchParams
url.pathname = "/posts";
url.search = new URLSearchParams(query).toString();
// #3 Using searchParams property of URL instance
url.pathname = "/posts";
url.searchParams.append("userId", "1");
url.searchParams.append("tag", "NodeMaster");
//
fetch(url.href);
در نگاه اول ممکنه خیلی نکته بزرگی به نظر نیاد ولی داخل code base های بزرگ که با کلی API 3rd party کار میکنید میتونه فرشته نجات باشه.
👍17
درود دوستان امیدوارم حالتون خوب باشه. یک ویژگی خیلی کوچیک #Python داشت که من همیشه دلم میخواد داخل #NodeJS ببینم. این ویژگی خیلی وقته روی #Deno هست ( فکر کنم #BunJS هم داره ). واقعا جای خالیش رو من حس میکردم. و بلاخره این ویژگی رو به صورت Experimental در آپدیت 22.18 دیدیم که اضافه شد. برا این که وارد بحث بشیم دوست دارم با این کد پایتون شروع کنم.
توضیح کد خیلی ساده هست که با استفاده از این پترن میشه تشخیص داد آیا این بخش از code که داره اجرا میشه آیا import شده توسط یک ماژول دیگه یا ماژول اصلی هست که باهاش برنامه رو اجرا کردن؟ اگر ماژول اصلی باشه که برنامه رو run کردن فانکشن main رو اجرا میکنه برنامه وارد main routine خودش میشه. شاید فکر کنید داخل زبانی مثل #Python و #JavaScript اینکار احمقانه باشه باتوجه به این که هر expressionـی رو میتونیم داخل top level خودمون اجرا کنیم. پس مزیت این کار چیه؟ جواب این هست که باتوجه به این که ما برنامه رو مینویسیم خب ما میدونیم کجا main routine رو اجرا کنیم ولی تصور کنید روی یک code base بزرگ رفتین و دنبال entrypoint میگردید. در این سناریو میتونه به عنوان داکیومنتیشن مناسب باشه. یا زمانی بخواید کدی رو اجرا کنید که فقط و فقط اگر کسی اون ماژول رو import کرده باشه و ... . همین الان هم وقتی پروژه #NestJS دارید bootstrap function دقیقا داره نقش main routine رو بازی میکنه و شما حتما باید اون رو اجرا کنید که برنامتون اجرا بشه. معمولا داخل #NestJS همچین چیزی میبینیم
سناریویی رو در نظر بگیرد به هر دلیلی میخواید از این main.js یک چیزی رو import کنید( هرچند اگر همچین چیزی نیاز داشتید بهتره سعی کنید راه دیگه ای پیدا کنید ) و اگر شما این فایل رو import کنید داخل یک ماژول دیگه خب bootstrap اجرا میشه و ما این رو نمیخوایم. پس چیکار میتونیم کنیم؟
اینجا هست import.meta.main به کمک ما میاد حالا اگر شما مستقیما node main.js بزنید فانکشن bootstrap اجرا میشه ولی اگر از یک فایل دیگ مثل server.js داشته باشید و این فایل رو import کنید بخش else اجرا میشه و bootstrap هیچ وقت call نمیشه.
def main():
print("Hello From Main Function")
if __name__ == "__main__":
main()
توضیح کد خیلی ساده هست که با استفاده از این پترن میشه تشخیص داد آیا این بخش از code که داره اجرا میشه آیا import شده توسط یک ماژول دیگه یا ماژول اصلی هست که باهاش برنامه رو اجرا کردن؟ اگر ماژول اصلی باشه که برنامه رو run کردن فانکشن main رو اجرا میکنه برنامه وارد main routine خودش میشه. شاید فکر کنید داخل زبانی مثل #Python و #JavaScript اینکار احمقانه باشه باتوجه به این که هر expressionـی رو میتونیم داخل top level خودمون اجرا کنیم. پس مزیت این کار چیه؟ جواب این هست که باتوجه به این که ما برنامه رو مینویسیم خب ما میدونیم کجا main routine رو اجرا کنیم ولی تصور کنید روی یک code base بزرگ رفتین و دنبال entrypoint میگردید. در این سناریو میتونه به عنوان داکیومنتیشن مناسب باشه. یا زمانی بخواید کدی رو اجرا کنید که فقط و فقط اگر کسی اون ماژول رو import کرده باشه و ... . همین الان هم وقتی پروژه #NestJS دارید bootstrap function دقیقا داره نقش main routine رو بازی میکنه و شما حتما باید اون رو اجرا کنید که برنامتون اجرا بشه. معمولا داخل #NestJS همچین چیزی میبینیم
function bootstrap() {
// init app
}
bootstrap();سناریویی رو در نظر بگیرد به هر دلیلی میخواید از این main.js یک چیزی رو import کنید( هرچند اگر همچین چیزی نیاز داشتید بهتره سعی کنید راه دیگه ای پیدا کنید ) و اگر شما این فایل رو import کنید داخل یک ماژول دیگه خب bootstrap اجرا میشه و ما این رو نمیخوایم. پس چیکار میتونیم کنیم؟
function bootstrap() {
console.log("hello");
}
if (import.meta.main) {
bootstrap();
} else {
console.log("imported");
}اینجا هست import.meta.main به کمک ما میاد حالا اگر شما مستقیما node main.js بزنید فانکشن bootstrap اجرا میشه ولی اگر از یک فایل دیگ مثل server.js داشته باشید و این فایل رو import کنید بخش else اجرا میشه و bootstrap هیچ وقت call نمیشه.
👍14
همیشه ما همه تلاش داریم کد با Performance خوب توسعه بدیم بدون این که این موضوع رو تصور کنیم که داخل کدبیس های #JavaScript معمولا Performance شوخیه.
ولی امروز قراره درمورد یک ویژگی جدید که در آپدیت ES2025 به #JavaScript اضافه شده صحبت کنیم که بهمون کمک میکنه که Performance بهتری داشته باشیم. سمت #NodeJS در بیزینس لاجیک های پیچیده میتونه معجزه کنه. برای #FrontEnd هم کاربردی هست ولی باتوجه به این که مرورگر های قدیمی ساپورت نمیکنن خب قطعا به این زودی استفاده ازش رو نمیبینیم.
ویژگی جدید ما اضاف شدن یک static method جدید به Iterator هست.
حالا سوال پیش میاد که چطور این به ما کمک میکنه. فرض کنید یک array بزرگ دارید و میخواید data رو map کنید به یک شکل دیگه و برای این کار یک pipeline از map ها رو ایجاد کردید:
در نگاه اول مشکلی نداره ولی اگر با عینک Performance ببینیم دوتا مشکل میبینیم.
1. برای هر map مجبوریم یکبار کامل loop بزنیم خب 3 بار loop میزنیم پس داریم O(3n)
2. هربار که یک loop کامل میزنیم هربار داریم یک Array جدید بعد از map ایجاد میکنیم. به صورت خلاصه هر .map برابر هست با یک Array allocation جدید. خب اینجا یک array اورجینال داریم و 3 تا map پس 4 تا array allocation داریم.
ممکنه برای تازه کارترها سوال های زیر پیش بیاد:
1. خب چرا اصلا این استایل کد میزنیم؟
2. چرا همه رو داخل یک map انجام نمیدیم؟
پاسخ سوال اول:
- میتونیم با for ... of کار رو بهتر با یک loop در بیاریم ولی مسئله این هست که معمولا برنامه نویس های #JavaScript در اینجور مواقع حتی بدون این که خودشون بدونن دیدگاه Functional Programming دارن و خب از اونجایی که به صورت فلسفی FP ذات Declarative داره و به صورت فلسفی کار کردن با API ها Declarative خیلی راحت تر و لذت بخش تر از Imperative هست همچین چیزی رو میبینیم.
- اگر هم خیلی کنجکاوید بیشتر بدونید وقتش هست نگاهی به #Elixir #Scala یا حتی Lambda ها در #Java اونجا قشنگ متوجه میشید. یا اصلا مسیر رو برعکس برید و نگاهی به رویکرد #Golang کنید و فرق زمین تا آسمونی رو ببینید.
پاسخ سوال دوم:
- در بزینس لاجیک های پیچیده برای خوانایی کد داشتن map های بیشتر خیلی بهتر از این هست که یک map بزرگ داشته باشیم. منطقی هم هست چون خیلی بهمون God Object ها رو یادآوری میکنه.
خب حالا سوال پیش میاد چیکار کنیم؟ خیلی ساده هست کافیه فقط خط اول رو به این شکل عوض کنیم و array رو تبدیل کنیم به Iterator.
خب دوباره الان سوال پیش میاد که WTF الان چی شد؟ سادس.
ما دیتا رو تبدیل کردیم به یک Iterator که ذات Iterator ها به صورت Lazy هست یعنی تا وقتی که نیاز به consume شدن data نباشه هیچ پردازشی انجام نمیشه و اگر هم نیاز به map کردن باشه دقیقا در runtime به صورت on-demand برای هر index تبدیل انجام میشه و ما نیازی به alloc کردن حافظه اضافه برای Array نداریم و هیچ loop اضافه ای هم درکار نیست.
حالا به این نکات توجه کنید:
- هر iterator رو فقط یکبار میشه consume کرد و اگر نیاز باشه باید دوباره ازش بسازی. در حقیقت با .toArray داریم consume کردن رو شبیه سازی میکنیم و دومی مقدار خالی به ما میده به خاطر iterator بودن.
- در این قسمت به map ها باید توجه کرد که با هر بار call شدن یک Array جدید نمیسازن بلکه یک Iterator جدید که روی Iterator قبلی سوار هست رو به ما میده! پس در نتیجه با توجه به تعریف Iterator که بالاتر گفتم نه loop اضافه ای داریم و نه alloc اضافه.
حالا اگر یکم بیشتر دقت کنی میبینیم خیلی شبیه به stream ها هست. اصلا این دوتا api به شدت باهم سازگار هستن. در این حد که استریم ها رو میشه تبدیل کرد به iterator و برعکس. بقیه کد هم دقیقا به صورت مشابهه کار میکنه.
دل نوشته:
حقیقتا دیگ نمیشه تفاوت بین stream, iterator, generator, rxjs, web stream, رو تشخیص داد😂. همشون رو میتونی جایگزین هم استفاده کنی. ( دلایل مختلفی برای وجود این همه api برای یک کار هست )
ولی امروز قراره درمورد یک ویژگی جدید که در آپدیت ES2025 به #JavaScript اضافه شده صحبت کنیم که بهمون کمک میکنه که Performance بهتری داشته باشیم. سمت #NodeJS در بیزینس لاجیک های پیچیده میتونه معجزه کنه. برای #FrontEnd هم کاربردی هست ولی باتوجه به این که مرورگر های قدیمی ساپورت نمیکنن خب قطعا به این زودی استفاده ازش رو نمیبینیم.
ویژگی جدید ما اضاف شدن یک static method جدید به Iterator هست.
Iterator.from()
حالا سوال پیش میاد که چطور این به ما کمک میکنه. فرض کنید یک array بزرگ دارید و میخواید data رو map کنید به یک شکل دیگه و برای این کار یک pipeline از map ها رو ایجاد کردید:
const data = [1, 2, 3, 4, 5];
const final = data
.map((item) => item.toString())
.map((item) => `- ${item} -`)
.map((item) => `${item} ${new Date()}`);
در نگاه اول مشکلی نداره ولی اگر با عینک Performance ببینیم دوتا مشکل میبینیم.
1. برای هر map مجبوریم یکبار کامل loop بزنیم خب 3 بار loop میزنیم پس داریم O(3n)
2. هربار که یک loop کامل میزنیم هربار داریم یک Array جدید بعد از map ایجاد میکنیم. به صورت خلاصه هر .map برابر هست با یک Array allocation جدید. خب اینجا یک array اورجینال داریم و 3 تا map پس 4 تا array allocation داریم.
ممکنه برای تازه کارترها سوال های زیر پیش بیاد:
1. خب چرا اصلا این استایل کد میزنیم؟
2. چرا همه رو داخل یک map انجام نمیدیم؟
پاسخ سوال اول:
- میتونیم با for ... of کار رو بهتر با یک loop در بیاریم ولی مسئله این هست که معمولا برنامه نویس های #JavaScript در اینجور مواقع حتی بدون این که خودشون بدونن دیدگاه Functional Programming دارن و خب از اونجایی که به صورت فلسفی FP ذات Declarative داره و به صورت فلسفی کار کردن با API ها Declarative خیلی راحت تر و لذت بخش تر از Imperative هست همچین چیزی رو میبینیم.
- اگر هم خیلی کنجکاوید بیشتر بدونید وقتش هست نگاهی به #Elixir #Scala یا حتی Lambda ها در #Java اونجا قشنگ متوجه میشید. یا اصلا مسیر رو برعکس برید و نگاهی به رویکرد #Golang کنید و فرق زمین تا آسمونی رو ببینید.
پاسخ سوال دوم:
- در بزینس لاجیک های پیچیده برای خوانایی کد داشتن map های بیشتر خیلی بهتر از این هست که یک map بزرگ داشته باشیم. منطقی هم هست چون خیلی بهمون God Object ها رو یادآوری میکنه.
خب حالا سوال پیش میاد چیکار کنیم؟ خیلی ساده هست کافیه فقط خط اول رو به این شکل عوض کنیم و array رو تبدیل کنیم به Iterator.
const data = [1, 2, 3, 4, 5, 6]; ❌
const data = Iterator.from([1, 2, 3, 4, 5, 6]); ✅
خب دوباره الان سوال پیش میاد که WTF الان چی شد؟ سادس.
ما دیتا رو تبدیل کردیم به یک Iterator که ذات Iterator ها به صورت Lazy هست یعنی تا وقتی که نیاز به consume شدن data نباشه هیچ پردازشی انجام نمیشه و اگر هم نیاز به map کردن باشه دقیقا در runtime به صورت on-demand برای هر index تبدیل انجام میشه و ما نیازی به alloc کردن حافظه اضافه برای Array نداریم و هیچ loop اضافه ای هم درکار نیست.
حالا به این نکات توجه کنید:
- هر iterator رو فقط یکبار میشه consume کرد و اگر نیاز باشه باید دوباره ازش بسازی. در حقیقت با .toArray داریم consume کردن رو شبیه سازی میکنیم و دومی مقدار خالی به ما میده به خاطر iterator بودن.
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
data.toArray()
data.toArray()
- در این قسمت به map ها باید توجه کرد که با هر بار call شدن یک Array جدید نمیسازن بلکه یک Iterator جدید که روی Iterator قبلی سوار هست رو به ما میده! پس در نتیجه با توجه به تعریف Iterator که بالاتر گفتم نه loop اضافه ای داریم و نه alloc اضافه.
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
const final = data
.map((item) => item.toString())
.map((item) => `- ${item} -`)
.map((item) => `${item} ${new Date()}`);
حالا اگر یکم بیشتر دقت کنی میبینیم خیلی شبیه به stream ها هست. اصلا این دوتا api به شدت باهم سازگار هستن. در این حد که استریم ها رو میشه تبدیل کرد به iterator و برعکس. بقیه کد هم دقیقا به صورت مشابهه کار میکنه.
import { Readable } from "node:stream";
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
const streamData = Readable.from(data);دل نوشته:
حقیقتا دیگ نمیشه تفاوت بین stream, iterator, generator, rxjs, web stream, رو تشخیص داد😂. همشون رو میتونی جایگزین هم استفاده کنی. ( دلایل مختلفی برای وجود این همه api برای یک کار هست )
👍16
درود رفقا امیدوارم حالتون خوب باشه.
بلاخره تلسم رو شکوندم بعد از چند ماه این ویدیو رو گرفتم.
در این ویدیو باهم یاد میگیرم که چطور از AsyncLocalStorage استفاده کنیم در #NodeJS البته قبل از هرچیزی میریم نگاهی به react context در #React میکنیم که از بچه های #FrontEnd یاد بگیرم چطور همچین مسائلی رو که AsyncLocalStorage به ما کمک میکنه حل کنیم رو با react context حل میکنن.
https://youtu.be/B_s401HuZAU
بلاخره تلسم رو شکوندم بعد از چند ماه این ویدیو رو گرفتم.
در این ویدیو باهم یاد میگیرم که چطور از AsyncLocalStorage استفاده کنیم در #NodeJS البته قبل از هرچیزی میریم نگاهی به react context در #React میکنیم که از بچه های #FrontEnd یاد بگیرم چطور همچین مسائلی رو که AsyncLocalStorage به ما کمک میکنه حل کنیم رو با react context حل میکنن.
https://youtu.be/B_s401HuZAU
YouTube
برسی AsyncLocalStorage در #nodejs با کمک #react context
درود دوستان امیدوارم حالتون خوب باشه.
امروز در این ویدیو با هم دیگه یاد میگیریم که AsyncLocalStorage چی هست البته قبل از هرچیزی نگاهی به React و React context میکنیم چون برای درک بهتر AsyncLocalStorage خیلی به ما کمک میکنند.
کدهای مربوط به این ویدیو:
ht…
امروز در این ویدیو با هم دیگه یاد میگیریم که AsyncLocalStorage چی هست البته قبل از هرچیزی نگاهی به React و React context میکنیم چون برای درک بهتر AsyncLocalStorage خیلی به ما کمک میکنند.
کدهای مربوط به این ویدیو:
ht…
👍18
Node Master
در حال حاظر NodeJs برای هرکاری 3 API گاهی هم 2 API در دسترس شما قرار میده تا کارتون رو انجام بدید. به مثال زیر دقت کنید. import { readFile as readFileCps, readFileSync } from "node:fs"; import { readFile as readFilePromise } from "node:fs/promises"; // Sync…
یکی از معجزه های #JavaScript ویژگی Closure هست. البته هر زبانی که این ویژگی رو داشته باشه خیلی دست بازی برای پیاده سازی پترن هایی داره که بدون Closure ها شاید ممکن نباشه. خیلی وقت پیش درمورد Async Cps Style صحبت کردیم میتونید برید نگاهی بندازید. نکته ای که میخوایم امروز درموردش صحبت کنیم این که چه جادویی در این تکه کد ساده که به صورت روزانه مینویسیم و کار میکنیم وجود داره ولی خیلی ساده ازش رد میشیم چون کار میکنه! ولی داستان از فقط کار کردن پیچیده تره!
در این کد یک localScope داریم که مستقیما اشاره داره که این variable در localScope مربوط به asyncCPSTask تعریف شده و در حالت عادی وقتی به پایان فانکشن مربوطه میرسیم و از call stack خارج میشیم، localScope هم باید خارج بشه و رسما دیگه نداریمش. ( اگر هم refrence type باشه که GC زحمتش رو باید بکشه )
اگر نکته بالا رو در نظر داشته باشیم باید انتظار داشته باشیم که console.log به ما مقداری رو نشون نده چون به کمک setTimeout یک delay داریم برای اجرا کردن innerFn که قطعا در iteration های بعدی Event-loop اتفاق میافته و صدرصد مطمئن هستیم که تا اون موقع asyncCPSTask از call stack خارج شده. با وجود این موضوع که ما رسما از call stack خارج شدیم و runtime برای ما innerFN رو داخل iteration های بعدی Event-loop اجرا میکنه باز هم مقدار localScope رو میبینیم. دلیل این اتفاق و این رفتار Closure هست.
حالا برای درک بهتر این موضوع دوست دارم دقیقا متن کتاب JavaScript The Definitive Guide - David Flanagan (صفحه 204 بخش 8.6) بیارم:
جمله دوم دقیقا ساده ترین و قشنگ ترین تعریف برای این رفتار هست. به دلیل این که innerFn در زمان تعریف در local scope مربوط به asyncCPSTask قرار داشته میتونه از اون scope استفاده کنه و ما چون در innerFn یک refrence به متغییر localScope داریم رسما asyncCPSTask رو تبدیل کردیم به یک Closure برای innerFn و باتوجه به این که در این حالت مهم نیست فانکشن از کجا call میشه و فقط نکته مهم این هست که کجا تعریف شده فانکشن. حالا چه event-loop برای ما فانکشن رو کال کنه چه خودمون در هر صورت دسترسی به localScope داریم.
خیلی وقت پیش یک نگاهی به این ویژگی تقریبا داشتیم و باهاش decorator pattern رو به صورت کاربردی پیاده سازی کردیم و دیدیم.
https://news.1rj.ru/str/NodeMaster/115
function asyncCPSTask(cb) {
const localScope = "localScope";
function innrerFn() {
cb(localScope);
}
setTimeout(innrerFn, 1000);
}
asyncCPSTask((data) => console.log(data));در این کد یک localScope داریم که مستقیما اشاره داره که این variable در localScope مربوط به asyncCPSTask تعریف شده و در حالت عادی وقتی به پایان فانکشن مربوطه میرسیم و از call stack خارج میشیم، localScope هم باید خارج بشه و رسما دیگه نداریمش. ( اگر هم refrence type باشه که GC زحمتش رو باید بکشه )
اگر نکته بالا رو در نظر داشته باشیم باید انتظار داشته باشیم که console.log به ما مقداری رو نشون نده چون به کمک setTimeout یک delay داریم برای اجرا کردن innerFn که قطعا در iteration های بعدی Event-loop اتفاق میافته و صدرصد مطمئن هستیم که تا اون موقع asyncCPSTask از call stack خارج شده. با وجود این موضوع که ما رسما از call stack خارج شدیم و runtime برای ما innerFN رو داخل iteration های بعدی Event-loop اجرا میکنه باز هم مقدار localScope رو میبینیم. دلیل این اتفاق و این رفتار Closure هست.
حالا برای درک بهتر این موضوع دوست دارم دقیقا متن کتاب JavaScript The Definitive Guide - David Flanagan (صفحه 204 بخش 8.6) بیارم:
Like most modern programming languages, JavaScript uses lexical scoping. This
means that functions are executed using the variable scope that was in effect when
they were defined, not the variable scope that is in effect when they are invoked
جمله دوم دقیقا ساده ترین و قشنگ ترین تعریف برای این رفتار هست. به دلیل این که innerFn در زمان تعریف در local scope مربوط به asyncCPSTask قرار داشته میتونه از اون scope استفاده کنه و ما چون در innerFn یک refrence به متغییر localScope داریم رسما asyncCPSTask رو تبدیل کردیم به یک Closure برای innerFn و باتوجه به این که در این حالت مهم نیست فانکشن از کجا call میشه و فقط نکته مهم این هست که کجا تعریف شده فانکشن. حالا چه event-loop برای ما فانکشن رو کال کنه چه خودمون در هر صورت دسترسی به localScope داریم.
خیلی وقت پیش یک نگاهی به این ویژگی تقریبا داشتیم و باهاش decorator pattern رو به صورت کاربردی پیاده سازی کردیم و دیدیم.
https://news.1rj.ru/str/NodeMaster/115
👍10
این اولین بلاگ پست یکی از نزدیک ترین دوستان من هست که داخل AMD منتشر شده و درمورد استفاده از #k8s برای نیاز های AI برای کارت گرافیک ها AMD هست.
دوست داشتید نگاهی بندازید مخصوصا اگر #K8S آشنایی دارید.
https://rocm.blogs.amd.com/software-tools-optimization/gpu-operator-partitioning/README.html
دوست داشتید نگاهی بندازید مخصوصا اگر #K8S آشنایی دارید.
https://rocm.blogs.amd.com/software-tools-optimization/gpu-operator-partitioning/README.html
ROCm Blogs
GPU Partitioning Made Easy: Pack More AI Workloads Using AMD GPU Operator
What’s New in AMD GPU Operator: Learn About GPU Partitioning and New Kubernetes Features
👍11
ما Developer ها به Magic عادت داریم. بیشتر وقت ها کدی که مینویسیم فقط میخوایم کار کنه. اما چطور کار کردن اون کد خیلی اهمیتی نداره تا وقتی که کدمون کار میکنه. حالا چه به صورت جادویی کار کنه چه با جزئیات کامل بدونیم پشت پرده چخبر هست. گاها بعضی از این جادو ها اینقدر پیچیده و ترسناک به نظر میان که اصلا بهشون نزدیک نمیشیم. یکی از این Magic ها Promise ها در #JavaScript هست. اکثرا فکر میکنیم یک چیزی هست که داخل گوشت و وجود #JavaScript فرو رفته و به هیچ عنوان نمیشه تغییرش داد یا اگر هم بشه خیلی سخت هست. کاری به پیاده سازی اصلیش امروز نداریم. امروز بعد از این مقدمه طولانی میخواهیم باهم یاد بگیرم چطور یک Object بسازیم که شبیه به Promise عمل میکنه. یعنی میتونیم await کنیم اون رو با وجود این که اصلا اون Promise نیست و یک Object ساده هست. به این کد پایین دقت کنید.
معمولا اولین واکنش افراد به این تکه کد "WTF" هست. داستان از این قرار هست که خیلی قبل تر از این که Promise ها به صورت استاندارد وارد #JavaScript بشن پیاده سازی های مختلف ازش وجود داشته و هرکدوم implemention detail خاص خودشون رو داشتن ولی طی گذر زمان بلاخره رسیدن به این interface که الان داریم هر روز باهاش کار میکنیم ( تقریبا شبیه به وضعیت decorator ها و پروپزوال مربوط بهش ). بزارید یکم بیشتر وارد داستان بشیم.
برای این که بتونیم یک object رو await کنیم لزوما نیازی نداره حتما یک instance از Promise باشد. بلکه هر object که Promise-like باشد میتواند await بشود. این تعریف دقیقا تعریف Duck-typing هست که قبلا مفصل درموردش حرف زدیم. حالا سوال پیش میاد که Promise-like یعنی چی؟
- هر class که thanable interface را implement کند میتوان آن را await کرد.
پس میتونیم نتیجه بگیریم که همه Promise ها thenable هستند ولی همه thenable ها Promise نیستند.
حالا میرسیم که thanable interface چیست؟ در ساده ترین حالت دقیقا مثال بالا رو در نظر بگیرد. یک object یا class که then method رو که با دوتا argument که هردو callback هستن یکی برای وقتی که reject شده و یکی برای وقتی resolve میشه invoke میشود و ما میتونیم با اون دوتا رفتاری که Promise-like هست رو از خودمون نشون بدیم.
حالا این ویژگی به ما اجازه داده که پکیج های معروفی مثل promise-retry ببینیم یا حتی یکم تلاش کنیم به کمک Promise-like ها در ES5 بتونیم چیزی شبیه بهش رو داشته باشیم که البته این موضوع خودش یک بحث دیگس اگر دوست دارید نگاهی به promise-polyfill یا babel-polyfill بندازید.
این هم پست مربوط به duck typing به نظرم نگاهی بندازید:
https://news.1rj.ru/str/NodeMaster/128
const thenable = {
then(resolve, reject) {
setTimeout(() => resolve("Hello from thenable!"), 1000)
},
}
const txt = await thenable
console.log(txt)معمولا اولین واکنش افراد به این تکه کد "WTF" هست. داستان از این قرار هست که خیلی قبل تر از این که Promise ها به صورت استاندارد وارد #JavaScript بشن پیاده سازی های مختلف ازش وجود داشته و هرکدوم implemention detail خاص خودشون رو داشتن ولی طی گذر زمان بلاخره رسیدن به این interface که الان داریم هر روز باهاش کار میکنیم ( تقریبا شبیه به وضعیت decorator ها و پروپزوال مربوط بهش ). بزارید یکم بیشتر وارد داستان بشیم.
برای این که بتونیم یک object رو await کنیم لزوما نیازی نداره حتما یک instance از Promise باشد. بلکه هر object که Promise-like باشد میتواند await بشود. این تعریف دقیقا تعریف Duck-typing هست که قبلا مفصل درموردش حرف زدیم. حالا سوال پیش میاد که Promise-like یعنی چی؟
- هر class که thanable interface را implement کند میتوان آن را await کرد.
پس میتونیم نتیجه بگیریم که همه Promise ها thenable هستند ولی همه thenable ها Promise نیستند.
حالا میرسیم که thanable interface چیست؟ در ساده ترین حالت دقیقا مثال بالا رو در نظر بگیرد. یک object یا class که then method رو که با دوتا argument که هردو callback هستن یکی برای وقتی که reject شده و یکی برای وقتی resolve میشه invoke میشود و ما میتونیم با اون دوتا رفتاری که Promise-like هست رو از خودمون نشون بدیم.
حالا این ویژگی به ما اجازه داده که پکیج های معروفی مثل promise-retry ببینیم یا حتی یکم تلاش کنیم به کمک Promise-like ها در ES5 بتونیم چیزی شبیه بهش رو داشته باشیم که البته این موضوع خودش یک بحث دیگس اگر دوست دارید نگاهی به promise-polyfill یا babel-polyfill بندازید.
این هم پست مربوط به duck typing به نظرم نگاهی بندازید:
https://news.1rj.ru/str/NodeMaster/128
Telegram
Node Master
امروز درمورد Duck Typing صحبت میکنیم. این موضوع مربوط به رفتار زبان های dynamic type میباشد. البته این تکنیک در زبان هایی static type هم در حالت های خاصی استفاده میشود. برای درک این موضوع با مثال در #Python شروع میکنیم.
class Duck:
def fly(self):
…
class Duck:
def fly(self):
…
👍11
درود دوستان امیدوارم حالتون خوب باشه. ورژن #NodeJS جدید 24.11 به صورت LTS منتشر شد.
https://nodejs.org/en/blog/release/v24.11.0
https://nodejs.org/en/blog/release/v24.11.0
nodejs.org
Node.js — Node.js v24.11.0 (LTS)
Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and noscripts.
👍19