<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Moori Heidari</title>
        <link>https://virgool.io/feed/@mohamad_mahdi_heidar</link>
        <description>اندک دولوپر گیک و از جمله مریدان جامعه گنو لینوکس</description>
        <language>fa</language>
        <pubDate>2026-06-16 13:43:16</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/41460/avatar/7SZQT2.jpeg?height=120&amp;width=120</url>
            <title>Moori Heidari</title>
            <link>https://virgool.io/@mohamad_mahdi_heidar</link>
        </image>

                    <item>
                <title>فریلنسینگ یا بلای جان توسعه دهنده</title>
                <link>https://virgool.io/@mohamad_mahdi_heidar/%D9%81%D8%B1%DB%8C%D9%84%D9%86%D8%B3%DB%8C%D9%86%DA%AF-%DB%8C%D8%A7-%D8%A8%D9%84%D8%A7%DB%8C-%D8%AC%D8%A7%D9%86-%D8%AA%D9%88%D8%B3%D8%B9%D9%87-%D8%AF%D9%87%D9%86%D8%AF%D9%87-cx37mtvufucw</link>
                <description>سلام من محمد مهدی ام و امروز یهو به سرم زد که در مورد تجربه ام از فریلنسیگ یا به عبارت بهتر  بلای جان یک توسعه دهنده بگم .خب چرا من اسشمو گذاشتم &quot;بلای جان یک توسعه دهنده&quot; یعنی فریلنسینگ اینقدر بده ؟ اره دقیقا میگم براتونمن با شروع دانشگاه  و زیاد شدن مخارج زندگی تصمیم گرفتم که شروع به کار کردن کنم تا بتونم از عهده مخارجی که دارم بر بیام و خب از اونجایی که عاشق برنامه نویسی بودم گفتم خب همین برنامه نویسی عالیه و از همین میتونم پول در بیارم کارمو از یک سایت فریلنسینگ شروع کردم و یک بسته ی به قول خودشون برنزی خریدم با اون بسته میتونستم حدودا روی ۳۰ تا پروژه در طول یک ماه بید کنم خب مشکل از همینجا شروع شد : این سایت به من بی تجربه حق داده بود ماهیانه روی ۳۰ تا پروژه  نظر بدم خب منم شروع کردم به بید کردن برنامه نویسی موبایل رو کار کرده بودم یکم فتوشاپ بلد بودم و یکم متریال دیزاین میفهمیدم و یه چیزایی در مورد ui/ux میدونستمتنوع پروژه ها زیاد بود و من هم به اندازه کافی خام و بی تجربه ، بعد از چند تا بید اولین پروژه رو گرفتم پروژه طراحی لوگو :) خب منم یه چیز چرت برای کارفرما طراحی کردم و اونم خوشش اومد و اون پروژه تموم شد و پولشو هم گرفتم .کلا کارم همین شده بود روی هر چیزی که میدیدم بید میکردم هر چیزی  ! از پروژه ساخت اپلیکیشین موبایل و برنامه نویسی بک اند بگیر تا طراحی پوستر و بنر تبلیغاتی هر پروژه رو هم که میگرفتم همزمان آموزشش رو میدیم و انجام میدادم مثلا یک پروژه برنامه نویسی موبایل گرفتم و همزمان شب ها بیدار میموندم تا هم پروژه موبایل رو انجام بدم هم برنامه نویسی بکند یاد بگیرم که بتونم بکندش رو هم خودم بزنم .یکم که گذشت شده بودم فریلسنر برتر چند تا سایت و راستی راستی باورم شده بود که آچاره فرانسه ام ، تو دنیای بسته ی من همه چیز خوب پیش میرفت. خدابیامرز استیون هاوکینگ میگه &quot; بزرگترین دشمن انسان ناآگاهی و جهل نیست، بلکه توهم دانستن است&quot; من دچار این توهم شده بودم  تو دنیایی برنامه نویسی دنبال از هر دری سخنی بودم یک روز برنامه نویس موبایل بودم یک روز طراح وب سایت و یک روز دیگه طراح مدل های  3d برای ساخت پروژه های AR و VR  !  تا یک روز رسید که یک پروژه مهم و سنگین رو قبول کردم  و به قول معروف لقمه خیلی گنده تر  از دهنم برداشتم  باید  با چند تا تیم مختلف همکاری میکردم برای اپ موبایل  و قسمتی از بک اند پروژه هم دست من بود .این بار من تنها نبودم و در کنار کسایی بودم که با من همکار من بودن و تخصصشون به ظاهر با من یکی بود روز هام هر روز تیره و تار میشد تازه داشتم میفهمیدم چقدر اشتباه کردم من توی هیچی عمیق نشده بودم از عهده اون کارا بر نمیومدم خلا عمیق دانش داشتم ولی اینبار تو زمان پروژه قابل یادگیری نبود سرتون رو درد نیارم من آدم اون کار نبودم پروژه رو کنسل کردم کنار کشیدم و اون روز بود که یاد گرفتم به جای این که آچار فرانسه تخیلی بشم باید وقت بزارم و روی یک مهارت خاص متخصص بشم .از اون روز حدودا ۳ سال میگذره اگه بخوام نمودارش رو بکشم اینطوری میشه درسته خودمم مقصر بودم ولی مسیر هم مشکل داشت مسیر فریلنسینگ آدم رو به سمت آچار فرانسه تخیلی شدن و از هر دری سخن گفتن میبره .</description>
                <category>Moori Heidari</category>
                <author>Moori Heidari</author>
                <pubDate>Sun, 12 Sep 2021 13:25:57 +0430</pubDate>
            </item>
                    <item>
                <title>بهترین روش برای طراحی REST API</title>
                <link>https://virgool.io/@mohamad_mahdi_heidar/%D8%A8%D9%87%D8%AA%D8%B1%DB%8C%D9%86-%D8%B1%D9%88%D8%B4-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%B7%D8%B1%D8%A7%D8%AD%DB%8C-rest-api-udsligaimtom</link>
                <description>میخوام براتون در مورد بهترین روش طراحی API توضیح بدم و راهکار هایی رو بنویسم که باعث میشه استفاده از API که طراحی میکنی برای بقیه خیلی ساده باشه .خب همون طور که میدونید REST API خیلی جاها استفاده میشه و خب من همیشه یکی از دغدغه هام این بوده که REST API رو یه طوری طراحی کنم که  استفاده ازش خیلی خیلی ساده باشه و همزمان  عملکرش تحت تاثیر قرار نگیره .از JSON استفاده کنید باور کنید دیگه زمان استفاه از  soap و امثالهم سر اومده و واقعا استفاده از XML  نفرت انگیزه و نهایتا منجر به سردرد و اعصاب خوردی ( و شایدم دعوا ) با فرانت دولوپر میشه پس به عنوان قدم اول از JSON استفاده کنید .یک مورد مهم دیگه Form data برای انتقال دیتا خوبه به خوصوص برای فایل ولی بهتره که برای ارسال متن  از form data استفاده نکنید و همون از JSON استفاده کنید.از اسم (nouns) به جای فعل (verb) در endpoint هاتون استفاده کنید اجازه بدید واضح تر توضیح بدم ما نباید از یک فعل داخل endpoint هایی که داریم استفاده کنیم مثلا ننویسیم getArticleList حالا چرا ؟ خب چون داخل method HTTP ی که داریم  فعل استفاه شده و استفاه مجدد از یک فعل فقط باعث طولانی شدن اون اند پوینت میشه و هیچ کمکی دیگه ای نمیکنه .پس عملی که اون ریکوئست انجام میده رو نباید داخل اندپوینتش ذکر کنیم و باید با HTTP method هایی که معموله مثل GET, POST, PUT, DELETE عملکر اون ریکوئست رو نشون بدیم.خب پس فعلا با ۲ تا قانونی که بالا توضیح دادم اگه بخوایم route هایی برای یک سری مقاله درست کنیم اینطوری میشه : برای گرفتن لیست مقاله ها :app.get(&#039;/articles&#039;, (req, res) =&gt; {
  const articles = [];
  // code to retrieve an article...
  res.json(articles);
});برای ایجاد مقاله جدید :‌app.post(&#039;/articles&#039;, (req, res) =&gt; {
  // code to add a new article...
  res.json(req.body);
});برای ادیت کردن یه مقاله : app.put(&#039;/articles/:id&#039;, (req, res) =&gt; {
  const { id } = req.params;
  // code to update an article...
  res.json(req.body);
});و در آخر برای حذف یک مقاله :app.delete(&#039;/articles/:id&#039;, (req, res) =&gt; {
  const { id } = req.params;
  // code to delete an article...
  res.json({ deleted: id });
});خب دیدید ما از هیچ فعلی برای تعریف مسیر هامون استفاه نکردیم برای کالکشن ها از اسم جمع استفاده کنیدتو همین مثال قبلی /articles/   قسمتی از endpoint ما بود که خب به صورت جمع نوشته شده و دیگه نیازی نیست برای گرفتن لیست مقاله ها یه چیز مضخرفی مثل getArticleListForAllUser اضافه کنیم :)داخل ساختار های تودرتو (nested) سلسله مراتب رو رعایت کنیمها این که وگفتی یعنی‌ چه ! مثلا فرض کنید داخل مثال قبلی مون هر مقاله یک لیستی از کامنت ها داره و ما میخوایم این کامنت هارو به یوزر نشون بدیم خب برای انجام این کار باید /comments رو به آخر articles/ اضافه کنیم که اگه بخوام با کد نشون بدم اینطوری میشه :app.get(&#039;/articles/:articleId/comments&#039;, (req, res) =&gt; {
  const { articleId } = req.params;
  const comments = [];
  // code to get comments by articleId
  res.json(comments);
});ما اگه این کارو انجام بدیم بقیه خیلی راحت متوجه میشن که کامنت های ما زیر مجموعه ساختار مقاله هامون قرار داره و دیگه نیست کلی توضیح بدید این موضوع رو .به کاربر اجازه صفحه بندی (pagination) ، مرتب سازی (sorting) و فیلتر کردن بدیم خیلی از مواقع دیتابیس ما خیلی بزرگ میشه و ما نباید همه دیتا رو یکباره برای کاربر بفرستیم برای همین ما باید به کاربر اجازه فیلتر کردن دیتا رو بدیم صفحه بندی و فیلتر کردن پرفورمنس رو خیلی بالا میبره و خب زمانی که مقادیر دیتا زیاد میشه اهمیت این موضوع خیلی برجسته تر میشه اگه بخوام فیلتر کردن رو با یک مثال نشون بدم اینطوری میشه : // employees data in a database
const employees = [
  { firstName: &#039;Jane&#039;, lastName: &#039;Smith&#039;, age: 20 },
  //...
  { firstName: &#039;John&#039;, lastName: &#039;Smith&#039;, age: 30 },
  { firstName: &#039;Mary&#039;, lastName: &#039;Green&#039;, age: 50 },
]

app.use(bodyParser.json());

app.get(&#039;/employees&#039;, (req, res) =&gt; {
  const { firstName, lastName, age } = req.query;
  let results = [...employees];
  if (firstName) {
    results = results.filter(r =&gt; r.firstName === firstName);
  }

  if (lastName) {
    results = results.filter(r =&gt; r.lastName === lastName);
  }

  if (age) {
    results = results.filter(r =&gt; +r.age === +age);
  }
  res.json(results);
});برای افزایش پرفورمنس حتما دیتا رو کش کنید ما میتونیم با کش کردن دیتا روی memory کاری کنیم که هر بار برای ارسال دیتا به یوزر نیاز به query زدن نباشه . راه حل های زیادی برای انجام این کار وجود داره مثلا استفاده از Redis و امثالهم ولی خب اگه حوصله انجام این کارا رو ندارید حداقل میتونید با apicache middleware خیلی راحت و بدون نیاز به کانفیگ خاصی این کارو انجام بدید :const express = require(&#039;express&#039;);
const bodyParser = require(&#039;body-parser&#039;);
const apicache = require(&#039;apicache&#039;);
const app = express();
let cache = apicache.middleware;
app.use(cache(&#039;5 minutes&#039;));
// employees data in a database
const employees = [
  { firstName: &#039;Jane&#039;, lastName: &#039;Smith&#039;, age: 20 },
  //...
  { firstName: &#039;John&#039;, lastName: &#039;Smith&#039;, age: 30 },
  { firstName: &#039;Mary&#039;, lastName: &#039;Green&#039;, age: 50 },
]
app.use(bodyParser.json());
app.get(&#039;/employees&#039;, (req, res) =&gt; {
  res.json(employees);
});
app.listen(3000, () =&gt; console.log(&#039;server started&#039;));ورژن بندی API ها برای این که کلاینت های مختلف ما به مشکل نخورن باید api های ما ورژن بندی مناسبی دارشته باشه مثلا میتونیم از روش semantic version که خیلی این روزا استفاده میشه استفاه کنیم.با این روش اون قدیمی ها کم کم خارج میشن و دیگه نیازی نیست همه رو مجبور به استفاه از یک api واحد کنیم و مثلا api v1 ما برای کسایی میشه که نمیخوان تغییر کنن ولی  به v2 هامون فیچر های جدید ارائه میدیم و البته اهمیت این موضوع زمانی آشکار میشه که api های ما public باشه و همه بتونن ازش استفاده کنند.راستی این اولین نوشته من داخل ویرگول بود خوشحال میشم نظرتون رو بگید :)</description>
                <category>Moori Heidari</category>
                <author>Moori Heidari</author>
                <pubDate>Tue, 26 Jan 2021 19:58:28 +0330</pubDate>
            </item>
            </channel>
</rss>