<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمد امین</title>
        <link>https://virgool.io/feed/@aminvafaei13</link>
        <description>طراح و برنامه نویس وب ،عاشق یادگرفتن راهکارای جدید و چالش برانگیز</description>
        <language>fa</language>
        <pubDate>2026-06-07 12:53:29</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/12532/avatar/hXjieD.png?height=120&amp;width=120</url>
            <title>محمد امین</title>
            <link>https://virgool.io/@aminvafaei13</link>
        </image>

                    <item>
                <title>استفاده از فیلدهای Unique در دیتابیس با Soft Delete</title>
                <link>https://virgool.io/@aminvafaei13/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D9%81%DB%8C%D9%84%D8%AF%D9%87%D8%A7%DB%8C-unique-%D8%AF%D8%B1-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-%D8%A8%D8%A7-soft-delete-ckfmlbhf3wa5</link>
                <description>اگر تا الان می‌خواستید که از ویژگی soft delete به همراه unique fields استفاده کنید، احتمالا متوجه شدید که خیلی با هم هماهنگ نیستن. ممکنه یک رکورد رو پاک کنید و انتظار داشته باشید که بتونین رکورد جدیدی با همون دیتا ثبت کنید، اما به مشکل خورده. بیاین با هم بررسی کنیم چقدر این مسئله مهمه و چجوری میتونیم حلش کنیم.برای طراحی یک سیستم نرم افزاری validation دیتا عنصر مهمیه، validation میتونه تو لایه های مختلفی انجام بشه. از دیتابیس تا بکند و فرانت اند. اما validation سطح دیتابیس باید آخرین نقطه اون باشه و نباید به عنوان اعتبار سنجی اصلی بهش نگاه کرد. برای من اعتبارسنجی در سطح دیتابیس مثل اعتبار سنجی فرانت اند میمونه. درسته که از لحاظ تجربه کاربری چک کردن فرمت ایمیل کاربر در فرم های فرانت اند حس خوبی میده اما اگر کاربری چک های فرانت رو حذف کنه به راحت میتونه تو روال کد خطا ایجاد کنه.از طرفی تا ۹۹ درصد سیستم هایی که طراحی میشه نیاز به ایجاد فیلد unique  در سطح دیتابیس داره.مثلا باید ایمیل، نام کاربری یا تلفن کاربر unique باشه. حالا اگر کاربری بخواد اکانتشو پاک کنه و ما بهش اجازه soft delete دادیم. آیا دیگ اون فرد اجازه نداره با اون شماره، ایمیل یا نام کاربری تو سیستم ما اکانت داشته باشه؟ یا اینکه به صورت سیستمی تو کد بکند چک میکنیم که اکانت با این اطلاعات موجوده یا نه؟خوب اوکی حالا مسئله رو متوجه شدیم و فهمیدیم که فیلد unique مهمه و باید استفاده بشه، اما استفاده همزمان اون با soft delete غیر عملیه!!!فرض کنید یک سیستم فروشگاهی طراحی کردید و به خاطر فروش های گذشته نمی‌خواید تا محصولات ناموجود رو از دیتابیس پاک کنید.پس تصمیم میگیرید با اضافه کردن یک ستون (مثلا deleted_at ) چک کنید که اون پاک شده یا نه. حالا اگر محصولی soft delete بشه ،باید کاربر بتونه محصولی رو دقیقا با همون مشخصات وارد دیتابیس کنه. اما از اون اونجایی که مثلا نام کالا به عنوان یک فیلد unique تو دیتابیس بوده عملا نمیتونه دیتا رو وارد کنه.راه حل چیه؟ ما مقدار فیلد deleted_at رو  به صورت پیش فرض null میزاریم.راه حلی که برای این مشکل هست اینه که به جای unique کردن یک فیلد ، ترکیبی از فیلدها رو unique کنیم. ALTER TABLE products ADD UNIQUE KEY name_deleted_at_unique_key (name, deleted_at);اینجوری ترکیب دو تا فیلد name  و deleted_at رو unique میکنیم و دیگ اگر رکوردی soft delete شده بود برای ما مشکلی پیش نمیاره.باز هم یک مشکل کوچیک؟ من تو دیتابیس postgres تست کردم و تونستم ترکیب یک فیلد با مقدار null  و یک فیلد دیگ رو unique کنم. اما دیدم تو mysql نمیشه فیلدی با مقدار null رو به عنوان unique اضافه کرد. اینجا هم یه تریک کوچیکی میشه زد.فیلد deleted_at از نوع timestamp هستش و مقدار پیش فرضش هم null هست.میتونیم به جای این کار از مقدار 0 به عنوان پیش فرض استفاده کنیم.deleted_at int(11) NOT NULL DEFAULT 0البته اینجا ممکنه یکم مبهم باشه چون مقدار صفر در فیلد از نوع timestamp برابر میشه با اول ژانویه 1970 . ولی خوب از اونجایی که اپ شما اون موقع وجود نداشته و به اون تاریخ هم خیلی کار نداره مقدار صفر با درصد زیادی میتونه یک مقدار مطمئن برای این فیلد باشه تا بفهمیم که مقدار deleted_at خالیه.من این موضوع رو برای یک پروژه با دیتابیس postgres انجام دادم و جواب داد ، اما روی سایر دیتابیس ها کار نکردم و از جوابش مطمئن نیستم.اگر کسی تجربه این کارو داشت به منم یاد بده.</description>
                <category>محمد امین</category>
                <author>محمد امین</author>
                <pubDate>Mon, 17 Feb 2020 17:51:50 +0330</pubDate>
            </item>
                    <item>
                <title>ساخت API  با استفاده از gRPC در Node js</title>
                <link>https://virgool.io/apieco/%D8%B3%D8%A7%D8%AE%D8%AA-api-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-grpc-%D8%AF%D8%B1-node-js-e6lxzowp02cc</link>
                <description>در حال گشت و گذار تو ویرگول بودم که مقاله جالبی از عرفان توجهم رو جلب کرد. تو این مقاله در مورد  gRPC و تفاوت اون با REST توضیح داده بود. توضیحات قبل و بعدش هم کامل بود و اینجا هر زمانی که نیاز بشه بهش استناد می‌کنم. بعد خوندنش تصمیم گرفتم gRPC رو روی Node js هم پیاده سازی کنم و ساختار API پایه بنویسم. http://vrgl.ir/Le84W ‏gRPC چیه؟‏ gRPC یک فریم ورک که گوگل اون رو توسعه داده و مزیت اصلیش امنیت و سرعت فوق العادش نسبت به معماری REST هستش. این مزیت ها به خاطر دلایل پایینه:با استاندارد HTTP/2 ساخته شده. تو این استاندارد دیگ برای هر درخواست یک tcp جداگونه باز نمیشه و برای انتقال دیتا از باینری استفاده می‌کنه که نسبت به استاندارد HTTP/1 خیلی سریع‌تر و چابک‌تره. برای اینکه بیشتر در مورد HTTP/2 بدونید اینجا رو بخونید.از پروتکل بافر استفاده می‌کنه. پروتکل بافر در واقع یک ساختار دیتا هستش که از قواعد خاصی پیروی  میکنه.دیتا رو کمپرس می‌کنه و تقریبا  ۷ برابر از json سریعتره. اطلاعات کاملتر رو اینجا بخونید.از message به جای verb ها در REST استفاده می‌کنه. وقتی که تو معماری REST توسعه می‌دیم عملاً متدها یا GET هستن یا POST . (متدهای PUT,PATCH, DELETE هم به نوعی POST محسوب میشن) این امکان دست توسعه دهنده رو باز میزاره تا متدهای دلخواه خودش رو هم بدون محدودیت ایجاد کنه.برای مقایسه کامل‌تر REST و gRPC می‌تونید این مقاله رو بخونید.راه اندازی پروژهیک دایرکتوری جدید برای پروژه می‌سازیم.$ mkdir NODE-GRPC
$ cd NODE-GRPCو این ساختار رو ایجاد می‌کنیم.├── client
│   ├── app.js
│   └── package.json
├── protos
└── server
    ├── index.js
    └── package.jsonمن برای این پروژه از PostgreSQL استفاده کردم ، ولی شما می‌تونید از هر دیتابیسی استفاده کنید.یک دیتابیس به نام  grpc_products می‌سازیم.سرویس های gRPCکاری که امروز میخوایم انجام بدیم ساخت API با استفاده از gRPC برای انجام عملیات CRUD هستش.در  gRPC مشابه Socket ما یک سرور و یک کلاینت داریم. اول از همه سرور رو شروع می‌کنیم. تو فولدر protos یک فایل با عنوان product.proto  می‌سازیم که تو اون سرویس‌ها و مسیج‌های gRPC  رو می‌نویسیم.syntax = &quot;proto3&quot;;
package product;

// service definition

service ProductService {
  rpc listProducts(Empty) returns (ProductList) {}
  rpc readProduct(ProductId) returns (Product) {}
  rpc createProduct(newProduct) returns (result) {}
  rpc updateProduct(Product) returns (result) {}
  rpc deleteProduct(ProductId) returns (result) {}
}

// message type definitions

message Empty {}

message ProductList {
  repeated Product products = 1;
}

message ProductId {
  int32 id = 1;
}

message Product {
  int32 id = 1;
  string name = 2;
  string price = 3;
}

message newProduct {
  string name = 1;
  string price = 2;
}

message result {
  string status = 1;
}تو این قسمت اول ورژن پروتوبافر رو مشخص کردیم و بعد هم براش یک package ساختیم. ساخت پکیج برای فایل پروتو الزامی نیست ولی ایده خوبیه تا تو پروژه های بزرگ گیج نشیم.بعد از اون متدهای gRPC رو که معادل عملیات پایه ای CRUD هست رو نوشتیم.CRUD gRPC methodIndex                                                                             listProductsStore                                                                             createProductUpdate                                                                          updateProductGet                                                                                readProductDelete                                                                           deleteProduct متد listProducts یک مسیج Empty  رو به عنوان ورودی دریافت و ProductList رو برمی‌گردونه.حالا فایل &#x60;package.json&#x60;   اپدیت می‌کنیم.{
  &quot;name&quot;: &quot;node-grpc-server&quot;,
  &quot;dependencies&quot;: {
    &quot;@grpc/proto-loader&quot;: &quot;^0.4.0&quot;,
    &quot;google-protobuf&quot;: &quot;^3.6.1&quot;,
    &quot;grpc&quot;: &quot;^1.18.0&quot;,
    &quot;knex&quot;: &quot;^0.16.3&quot;,
    &quot;pg&quot;: &quot;^7.8.0&quot;
  },
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node index.js&quot;
  }
}کاربرد هرکدوم از این ماژول ها تو شکل پایینه.@grpc/proto-loader: loads .proto files
google-protobuf: JavaScript version of the Protocol Buffers runtime library
grpc: Node gRPC Library
knex: SQL query builder for Node
pg: PostgreSQL client for Nodeقبل از نصب پکیج ها باید protoc رو روی ماشین‌مون نصب کرده باشیم.از این لینک می‌تونید استفاده کنید.بعد نصب protoc باید پیکج های سرور رو نصب کنیم.$ cd server
$ npm installبعد فایل knexfile.js رو در فولدر server که برای ست کردن کانفیگ دیتابیس و میگریشن ها هست رو ایجاد می‌کنیم.const path = require(&#039;path&#039;);

module.exports = {
  development: {
    client: &#039;postgresql&#039;,
    connection: {
      host: &#039;127.0.0.1&#039;,
      user: &#039;&#039;,
      password: &#039;&#039;,
      port: &#039;5432&#039;,
      database: &#039;grpc_products&#039;,
    },
    pool: {
      min: 2,
      max: 10,
    },
    migrations: {
      directory: path.join(__dirname, &#039;db&#039;, &#039;migrations&#039;),
    },
    seeds: {
      directory: path.join(__dirname, &#039;db&#039;, &#039;seeds&#039;),
    },
  },
};بعد از وارد کردن اطلاعات دیتابیس باید فولدری برای میگرشن ها و سیدرها بسازیم. ساختار پروژه بعد ساخت این فولدرها به شکل زیره.├── client
│   ├── app.js
│   └── package.json
├── protos
│   └── product.proto
└── server
    ├── db
    │   ├── migrations
    │   └── seeds
    ├── index.js
    ├── knexfile.js
    ├── package-lock.json
    └── package.jsonیک میگرشن جدید می‌سازیم.$ ./node_modules/.bin/knex migrate:make productsو کدهای زیر رو داخلش قرار می‌دیم.exports.up = function (knex, Promise) {
  return knex.schema.createTable(&#039;products&#039;, function (table) {
    table.increments();
    table.string(&#039;name&#039;).notNullable();
    table.string(&#039;price&#039;).notNullable();
  });
};

exports.down = function (knex, Promise) {
  return knex.schema.dropTable(&#039;products&#039;);
};حالا یک سیدر می‌سازیم.$ ./node_modules/.bin/knex seed:make productو تعدای دیتای فیک می‌سازیم.exports.seed = function (knex, Promise) {
  // Deletes ALL existing entries
  return knex(&#039;products&#039;).del()
    .then(function () {
      // Inserts seed entries
      return knex(&#039;products&#039;).insert([
        { name: &#039;pencil&#039;, price: &#039;100&#039; },
        { name: &#039;pen&#039;, price: &#039;550&#039; },
                { name: &#039;book&#039;, price: &#039;98&#039; },
      ]);
    });
};و سیدر رو ران می‌کنیم تا دیتابیس پر شه.$ ./node_modules/.bin/knex seed:runحالا فایل index.js رو آپدیت می‌کنیم.// requirements
const path = require(&#039;path&#039;);
const protoLoader = require(&#039;@grpc/proto-loader&#039;);
const grpc = require(&#039;grpc&#039;);

// knex
const environment = process.env.ENVIRONMENT || &#039;development&#039;;
const config = require(&#039;./knexfile.js&#039;)[environment];
const knex = require(&#039;knex&#039;)(config);

// grpc service definition
const productProtoPath = path.join(__dirname, &#039;..&#039;, &#039;protos&#039;, &#039;product.proto&#039;);
const productProtoDefinition = protoLoader.loadSync(productProtoPath);
const productPackageDefinition = grpc.loadPackageDefinition(productProtoDefinition).product;
/*
Using an older version of gRPC?
(1) You won&#039;t need the @grpc/proto-loader package
(2) const productPackageDefinition = grpc.load(productProtoPath).product;
*/

// knex queries
function listProducts(call, callback) {}
function readProduct(call, callback) {}
function createProduct(call, callback) {}
function updateProduct(call, callback) {}
function deleteProduct(call, callback) {}

// main
function main() {
  const server = new grpc.Server();
  // gRPC service
  server.addService(productPackageDefinition.ProductService.service, {
    listProducts: listProducts,
    readProduct: readProduct,
    createProduct: createProduct,
    updateProduct: updateProduct,
    deleteProduct: deleteProduct,
  });
  // gRPC server
  server.bind(&#039;localhost:50051&#039;, grpc.ServerCredentials.createInsecure());
  server.start();
  console.log(&#039;gRPC server running at http://127.0.0.1:50051&#039;);
}

main();برای تبدیل فایل پروتو به js از پیکج زیر استفاده می‌کنیم.$ npm install -g grpc-toolsبعد از نصب پکیج تو روت پروژه کامند زیر رو ران می‌کنیم تا پروتو به js تبدیل شه.$ protoc -I=. ./protos/product.proto \
  --js_out=import_style=commonjs,binary:./server \
  --grpc_out=./server \
  --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin`بعد ران شدن کامند دو تا فایل در پوشه server/protos ساخته میشه. فعلا کار ما با سرور تمومه می‌تونیم با دستور npm start ن رو ران کنیم و اگر مشکلی نباشه باید پیام زیر رو ببینید.gRPC server running at http://127.0.0.1:50051حالا قبل از اینکه کویری بزنیم و اطلاعات رو فتچ کنیم بیاید کلاینت رو بسازیم.مثل سرور از فایل package.json شروع می‌کنیم.{
  &quot;name&quot;: &quot;node-grpc-client&quot;,
  &quot;dependencies&quot;: {
    &quot;@grpc/proto-loader&quot;: &quot;^0.4.0&quot;,
    &quot;body-parser&quot;: &quot;^1.18.3&quot;,
    &quot;express&quot;: &quot;^4.16.4&quot;,
    &quot;google-protobuf&quot;: &quot;^3.6.1&quot;,
    &quot;grpc&quot;: &quot;^1.18.0&quot;
  },
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node app.js&quot;
  }
}پکیج ها رو نصب می‌کنیم و فایل app.js و آپدیت می‌کنیم.// requirements
const express = require(&#039;express&#039;);
const bodyParser = require(&#039;body-parser&#039;);
const productRoutes = require(&#039;./routes/productRoutes&#039;);

// express
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// routes
app.use(&#039;/api&#039;, productRoutes);

// run server
app.listen(3000, () =&gt; {
  console.log(&#039;Server listing on port 3000&#039;);
});در اینجا یک سرور با اکسپرس به همراه روت‌ها تعریف کردیم.هم چنین در فایل client/routes/grpcRoutes.js کدهای زیر رو اضافه می‌کنیم.// requirements
const path = require(&#039;path&#039;);
const protoLoader = require(&#039;@grpc/proto-loader&#039;);
const grpc = require(&#039;grpc&#039;);

// gRPC client
const productProtoPath = path.join(__dirname, &#039;..&#039;, &#039;..&#039;, &#039;protos&#039;, &#039;product.proto&#039;);
const productProtoDefinition = protoLoader.loadSync(productProtoPath);
const productPackageDefinition = grpc.loadPackageDefinition(productProtoDefinition).product;
const client = new productPackageDefinition.ProductService(
  &#039;localhost:50051&#039;, grpc.credentials.createInsecure());
/*
Using an older version of gRPC?
(1) You won&#039;t need the @grpc/proto-loader package
(2) const productPackageDefinition = grpc.load(productProtoPath).product;
(3) const client = new productPackageDefinition.ProductService(
  &#039;localhost:50051&#039;, grpc.credentials.createInsecure());
*/

// handlers
const listProducts = (req, res) =&gt; {};
const readProduct = (req, res) =&gt; {};
const createProduct = (req, res) =&gt; {};
const updateProduct = (req, res) =&gt; {};
const deleteProduct = (req, res) =&gt; {};

module.exports = {
  listProducts,
  readProduct,
  createProduct,
  updateProduct,
  deleteProduct,
};حالا با ران کردن کامند npm start  باید پیام زیر رو ببینیم.Server listing on port 3000بعد از هر تغییری سرور و کلاینت رو ریستارت کنید.حاال به سرور برگردیم و مثلا عملیات خوندن لیست کامل همه محصولات رو بنویسیم.Server : function listProducts(call, callback) {
  /*
  Using &#039;grpc.load&#039;? Send back an array: &#039;callback(null, { data });&#039;
  */
  knex(&#039;products&#039;)
    .then((data) =&gt; { callback(null, { products: data }); });
}Client : const listProducts = (req, res) =&gt; {
  /*
  gRPC method for reference:
  listProducts(Empty) returns (ProductList)
  */
  client.listProducts({}, (err, result) =&gt; {
    res.json(result);
  });
};حالا اگر این اندپوینت رو تست کنیم باید دیتای محصولات که با سیدر ران کرده بویم ببینیم.$ curl http://127.0.0.1:3000/api/productsخروجی باید به صورت زیر باشه.{
  &quot;products&quot;: [
    {
      &quot;id&quot;: 1,
      &quot;name&quot;: &quot;pencil&quot;,
      &quot;price&quot;: &quot;100&quot;
    },
    {
      &quot;id&quot;: 2,
      &quot;name&quot;: &quot;pen&quot;,
      &quot;price&quot;: &quot;550&quot;
    },
       {      
        &quot;id&quot;: 3,  
         &quot;name&quot;: &quot;book&quot;, 
          &quot;price&quot;: &quot;98&quot;  
           }
  ]
}بقیه اندپوینت‌ها هم مشابه این ساخته میشه و میشه هر کنترلر دلخواهی روش نوشت.اگر مشتاقید مقاله کامل این موضوع رو بخونید میتونید از لینک زیر پیداش کنید. https://mherman.org/blog/node-grpc-postgres/ </description>
                <category>محمد امین</category>
                <author>محمد امین</author>
                <pubDate>Mon, 29 Jul 2019 19:34:35 +0430</pubDate>
            </item>
                    <item>
                <title>راه‌اندازی Swagger UI با Docker</title>
                <link>https://virgool.io/apieco/%D8%B1%D8%A7%D9%87%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C-swagger-ui-%D8%A8%D8%A7-docker-xdikurnzevs1</link>
                <description>اغلب برنامه‌نویس‌ها برای تست APIهایی که می‌نویسن از ابزار Postman استفاده می‌کنن. به شخصه اعتقاد دارم ابزار کامل و مناسبیه مخصوصاً برای تست نویسی، اما مشکلی که داره اینه که نمیشه محیط‌های ایجاد شده رو در حالت رایگان با بقیه دولوپرها به اشتراک گذاشت و به محض کوچکترین تغییر باید همه دوباره ایمپورتش بکنن.به خاطر این موضوع از سواگر(swagger)  استفاده میکنیم. راه اندازی swagger UI نیاز به نصب اون روی سیستم عامل داره و داستان‌های مخصوص به خودش رو داره . داکر (که خدا خیرش بده) خیلی کار رو راحت کرده و با چند تا کامنت ساده میشه ایمیج مورد نظر رو دانلود و استفاده کرد.اما در مورد swagger UI یه نکته خیلی ریز  و کاربردی داره. فرض کنید با کامند زیر ایمیج swagger UI رو ران میکنیم.$ docker run -p 81:8080 --name=my_swagger_name -d swaggerapi/swagger-uiدستور بالا swagger UI رو از پورت پیش فرض ۸۰۸۰ روی پورت ۸۱ ما با نام دلخواه my_swagger_name اجرا میکنه و میشه تو مرورگر دیدش.نتیجه اجرای دستور بالانکته ای که گفتم اینجاست، بعد از اجرای داکر محیط پیش فرض swagger UI لود میشه و Json پیش فرض خودش رو نمایش میده ، چیزی که ما بهش نیازی نداریم.در واقع ما میخوایم Json خودمون رو لود کنیم. برای این کار از این دستور استفاده میکنیم.docker run -p 81:8080 --name=my_swagger_name -e SWAGGER_JSON=/mnt/api-docs.json -d -v `pwd`:/mnt swaggerapi/swagger-uiاین دستور باید در محل قرار گیری فایل json (در اینجا api-docs.json )ران بشه .همونطور که معلومه دو تا آپشن جدید داریم:e :  Set environment variables v : Volumeآپشن v یا volume یک کپی از فایل ها و فولدرهای آدرس فعلی (pwd) رو در فولدر mnt داکر ما کپی میکنه، آپشن e یا enviroment variable هم آدرس داکری فایلی که باید لود بشه رو دریافت میکنه و به محض هر تغییری در فایل در آدرس لوکالی اون همون تغییر رو روی داکر هم اعمال میکنه.همونطور که تو عکس معلومه بعد اجرای کامند آدرس  swagger UI به آدرس جدید آپدیت میشه و دیتا رو هم لود میکنه.</description>
                <category>محمد امین</category>
                <author>محمد امین</author>
                <pubDate>Tue, 25 Jun 2019 17:35:47 +0430</pubDate>
            </item>
                    <item>
                <title>واقعا «Node.js» رو یاد داریم؟ - قسمت دوم - معماری نودجی‌اس</title>
                <link>https://virgool.io/JavaScript8/%D9%88%D8%A7%D9%82%D8%B9%D8%A7-nodejs-%D8%B1%D9%88-%DB%8C%D8%A7%D8%AF-%D8%AF%D8%A7%D8%B1%DB%8C%D9%85-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D9%86%D9%88%D8%AF%D8%AC%DB%8C%D8%A7%D8%B3-ysnkcxh1qgqp</link>
                <description>قسمت دوم - معماری نودجی‌اس در قسمت قبل در مورد اینکه نودجی‌اس چی هست، چی کار می‌کنه و چه تاثیری روی دنیای وب داشته صحبت کردیم.تو این قسمت می‌خوام برم سراغ معماری اون و اینکه واقعا چطوری کار می‌کنه؟قبل از اینکه نودجی‌اس به دنیای برنامه‌نویسی وارد بشه تمامی کدهای جاوااسکریپت فقط درون مرورگرها قابل اجرا بود.یعنی هر مرورگر موتور اجرایی مربوط به خودش رو داشت و کدهای جاوااسکریپت رو به کد ماشین قابل فهم دستگاه تبدیل می‌کرد.تبدیل کدهای جاوااسکریپت به کدقابل فهم ماشین توسط موتورهای جستجوی مرورگرهادر این بین هر مرورگر از موتور اجرایی مخصوص به خودش استفاده می‌کرد مثلا بین مرورگرهای معروف ie از  chakra، کروم از v8 و فایرفاکس از SpiderMonkey که این موضوع باعث می‌شه گاهی اوقات کدهای جاوااسکریپت تفسیر جداگانه‌ای داشته باشه و نتیجه در مرورگرهای مختلف یکسان نباشه.برای حل این مشکلات در سال 2009 ، یکی از دولوپرهای شرکت گوگل به نام Ryan Dahl سریع‌ترین موتور تحلیل‌گر جاوااسکریپت یعنی موتور v8 گوگل رو با یک پروژه c++ ادغام کرد و اسم اون پروژه رو Node.exe گذاشت.بنابراین نودجی‌اس به یک محیط اجرایی برای کدهای جاوااسکریپت خارج از محیط مرورگرها تبدیل شد.مساله‌ای که خیلی بین دولوپرها شایع هست اینه که ما هیچ‌وقت نمی‌تونیم برای پروژه‌هامون یک زبان برنامه‌نویسی رو انتخاب کنیم و همیشه درگیر مقایسه فیچرهای اونها با هم هستیم.ولی مقایسه نودجی‌اس با زبان‌های برنامه نویسی مثل PHP یا فریم‌ورک‌های مختلف مثل Django یا ASP.NET یک کار کاملا اشتباهه، چون نودجی‌اس نه یک زبان برنامه‌نویسی و نه یک فریم‌ورکه.بلکه نودجی‌اس تنها یک محیط اجرایی برای اجرای کدهای جاوااسکریپت خارج از محیط مرورگره.میدونم این جمله رو خیلی تکرار کردم، ولی حس می‌کنم واقعا همین‌قدر به تکرارش نیاز بود. ببخشید??تو قسمت بعدی در مورد Globalها در نودجی‌اس صحبت می‌کنیم.</description>
                <category>محمد امین</category>
                <author>محمد امین</author>
                <pubDate>Sat, 04 Aug 2018 19:09:36 +0430</pubDate>
            </item>
                    <item>
                <title>کافرمای خوب، کارفرمای بد</title>
                <link>https://virgool.io/digitalmarketing/%DA%A9%D8%A7%D9%81%D8%B1%D9%85%D8%A7%DB%8C-%D8%AE%D9%88%D8%A8-%DA%A9%D8%A7%D8%B1%D9%81%D8%B1%D9%85%D8%A7%DB%8C-%D8%A8%D8%AF-p79kgphc3ubx</link>
                <description>مدتی پیش یکی از رفقای زمان دانشگاه صحبت می‌کردم و می‌گفت که می‌خواد برای پدرش تو تالش موتور برق بخره.قرار شد با هم بریم بازار و قیمت بگیریم و اگر شد بخریم. پنج‌شنبه بود و اکثر مغازه‌ها هنوز باز نکرده بودن.اولین مغازه‌ای که دیدیم رو رفتیم داخل و سوال کردیم.شاگرد مغازه تازه اومده بود و داشت آب‌وجارو می‌کرد و کامپیوترشم تازه روشن کرده بود. تا ما اومدیم چونه بزنیم سر قیمت سریع سایتشونو باز کرد و گفت که آقا ما مرجع بازاریم و به همکار به این قیمت میدیم و از این حرفای بازاری که ربطی هم به اینجا نداره.سرعت بالا اومدن سایتش خیلی پایین بود منم فضولیم گل کرد و گفتم میشه ببینم سایتتون رو. اجازه داد و من دیدم خیلی بد نوشته شده و حتا از CMSهای هم استفاده نکرده بودن.خلاصه گفتم برای شما که مرجع بازارین این خوب نیست و بدین سایتتون رو بازنویسی کنن. تو همین حین صاحب مغازه اومد و بحث موتور‌برق رفت کنار و درباره سایت صحبت کردیم.خلاصه قرار شد من با وردپرس سایتشون رو بیارم بالا و فروشگاه‌شونم راه بندازم و خلاصه یک کار تکمیل بکنیم.صاحب‌مغازه می‌گفت نفر قبلی سر ما کلاه گذاشته و پول الکی گرفته منم گفتم اشکالی نداره من کل پول رو (که خیلی برای اون کار کم بود) بعد از اجرای پروژه می‌گیرم.یکی دو جلسه رفتم مغازه برای تحلیل کار و اینکه چی می‌خوان. دیدم خیلی بین فکرامون فاصله است.حتی حاضر نبودن برای کارشون vps بگیرن و اصرار که روی هاست اشتراکی کار کنیم. از اون ورم  می‌گفتن چرا اینقد سرعتش پایینه.من چون صبح تا عصر شرکت مشغول به کار بودم عصرا روی پروژه ایشون کار می‌کردم و انصافا خیلی سایت جذاب و خوبی شده بود. روزی که سایت آماده تزریق دیتا بود من بهش وویس دادم که آقا سایت آماده اس، ببینیم هم‌دیگه رو تا من سایت رو تحویل بدم،این تماس من زمانی بود که تازه دلار گرون شده بود(!) و بازاری‌ها اعتصاب کرده بودن.من پیش خودم فکر کردم شاید اوضاع خرابه و اینا سایت رو نمی‌خوان.چند بار دیگه هم تماس گرفتم ولی تا یک ماه هیچ جوابی نیومد.بعد از یک ماه شاگرد مغازه تماس گرفت با من و خیلی شاکی که آقا کجایی،ما رو گیر آوردی مگه یه سایت چقد طول میکشه؟. گفتم برادر من من اگر نیاز مالی نداشتم هیچ‌وقت همچین پروژه‌ای قبول نمی‌کردم و به خاطر اوضاع اقتصادی پیگیری نکردم وگرنه حق با من بود.بعد کلی بحث قرار شد یک روز برم سایت رو تحویل بدم.تیتر رو به خاطر این قسمت روایت زدم. من گفتم به احترام حرف شما و برای اینکه اعتماد کنید من کل مبلغ رو بعد پروژه می‌گیرم پس لطفا چک رو آماده کنید تا بعد تحویل پروژه بگیرم. تا یکسال هم پشتیبانی رو رایگان انجام میدم.اما جوابی که شنیدم خیلی جالب بود.ما سایت رو از شما تحویل می‌گیریم و دیتا رو تزریق می‌کنیم اگر سایت شما خوب بود و ما اومدیم صفحه اول گوگل اون‌وقت با شما تسویه می‌کنیم!!!!!واقعا نمی‌دونستم چی کار کنم.به هیچ وجه زیر بار نمی‌رفتم.در اصل بیشتر به خودم برخورد چون هنوز اینجوری در مورد برداشت می‌شد که منم هدفم کلاهبرداریه و می‌خوام یک کاری رو سمبل کنم و بعدش بزنم به چاک.بهشون گفتم حتی اگر شما همین الان دو برابر مبلغ قرارداد رو هم به من نقدی بدین هیچ وقت سایت رو تحویل نمی‌دم درسته زمان زیادی برای این پروژه گذاشتم و انرژی خیلی زیادی از من گرفت ولی چون خودم میدونم چقد برای این کار زحمت کشیدم و الان با این طرز رفتاری بازاری شما روبرو می‌شم از خیر پولش می‌گذرم اما رو عزت خودم پا نمی‌ذارم.شما عملا داری منو به کم‌کاری،کلاهبرداری و دزدی از کار متهم می‌کنی.من اونقدر به کارم اعتماد دارم که می‌گم تا یکسال حاضرم رایگان پشتیبانی کنم.ولی شما اونقد به من اعتماد نداری که اون مبلغ که حق انجام پروژه است (حتی درصدی از اون) رو بپردازی.این اتفاق و داستان برای من خیلی تاثیر‌گذار بود و بعید میدونم دیگ زمانی برسه که من با امثال این‌جور کارفرماها کار کنم.متاسفانه اوضاع به نحوی داره جلو میره که همه افراد به هم‌دیگه به چشم آدمای کلاهبردار نگاه می‌کنن و تو حتی باوجدان هم باشی بازم زیر بار این اتهامات می‌مونی.امیدوارم یک روزی این تابو و فرهنگ غلط از بین بره.</description>
                <category>محمد امین</category>
                <author>محمد امین</author>
                <pubDate>Sat, 04 Aug 2018 14:08:23 +0430</pubDate>
            </item>
                    <item>
                <title>واقعا «Node.js» رو یاد داریم؟ - قسمت اول - نودجی‌اس چیست؟</title>
                <link>https://virgool.io/JavaScript8/%D9%88%D8%A7%D9%82%D8%B9%D8%A7-nodejs-%D8%B1%D9%88-%DB%8C%D8%A7%D8%AF-%D8%AF%D8%A7%D8%B1%DB%8C%D9%85-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-%D9%86%D9%88%D8%AF%D8%AC%DB%8C%D8%A7%D8%B3-%DA%86%DB%8C%D8%B3%D8%AA-pmdyholwdcor</link>
                <description>قسمت اول - نودجی‌اس چیست؟همونطور که تو مقدمه گفته بودم تو این قسمت می‌خوام در مورد اینکه نودجی‌اس چیه و چی کار می‌کنه صحبت کنیم.به نظر من بهترین و کاملترین تعریف از نود تعریف خود سایتشه:Node.js is an open-source, cross-platform JavaScript run-time environment that executes JavaScript code طبق تعریف خودش نودجی‌اس نه فریم ورکه نه یک زبان برنامه نویسی بلکه تنها یک محیط اجرایی برای اجرای کدهای جاوااسکریپت خارج از محیط مرورگره.بیشترین موارد استفاده از نودجی‌اس مربوط به نوشتن API که باعث میشه توسعه دهنده های سمت کلاینت بتونن به اطلاعات دسترسی داشته باشن و از اون‌ها استفاده کنن.استفاده از نودجی‌اس به عنوان سرویس بکند حالا ممکنه این سوال پیش بیاد که خوب زبان‌های برنامه نویسی یا فریم ورک های زیادی مث Django,Ruby on Rails,ASP.NET,PHP و ... هستش که همین قابلیت رو داره، پس چرا باید برم سراغ نودجی‌اس و از اون استفاده کنم؟؟ من بهتون میگم چراشروع کار با نودجی‌اس خیلی راحته و برای prototyping و همینطور برای تیم‌هایی که به صورت agile کار توسعه رو انجام میدن خیلی مناسبه.سرعت اجرای بالایی داره و برای پروژه‌های با scale بالا یکی از بهترین انتخاب‌ها میتونه باشه.همونطور که Paypal,Uber,Nexflix و خیلی تیم‌های بزرگ دیگه از اون دارن استفاده میکنن.برای نمونه Paypal یکی از سیستم‌های قدیمیش که با ASP.NET نوشته شده بود رو با نودجی‌اس بازنویسی کرد و نتایج خوبی هم گرفت.نتایج ریفکتور کردن PayPal با نودجی‌اساونا تونستن با تعداد نیروی کمتر و سرعت بیشتری سیستم رو توسعه بدن.33 درصد از خط‌های کد و 40 درصد از فایل‌های روی سرور رو کم کنن.و از همه مهم‌تر در زمان مشابه دوبار درخواست‌هایی که به سیستم وارد میشه رو پاسخ بدن و زمان پاسخگویی به APIها رو تا 35 درصد کاهش بدن.مزیت بعدی نودجی‌اس استفاده کامل از زبان جاوااسکریپت هست.شما اگر یه توسعه دهنده فرانت‌اند باشید مسلما خیلی خوب با جاوااسکریپت آشنا هستین و می‌تونید با نودجی‌اس از تخصص خودتون در بکند هم استفاده کنید.دیگه نیازی نیست زبان برنامه نویسی جدیدی رو یاد بگیرید.علاوه بر‌این چون همه جا از جاوااسکریپت استفاده میشه کد شما تمیزتر،خواناتر و قابلیت دیباگ سریع‌تری داره.دلیل آخر استفاده از نودجی‌اس جامعه بزرگ برنامه نویس‌های اون و وجود کتابخانه‌های اوپن سورس زیاده.هرچیزی که شما به ذهنتون برسه و بخواید به پروژتون اضافه کنید حتما یه کتابخونه براش وجود داره.بنابراین نیاز نیست برای خیلی از اصول اولیه و مفاهیم پایه‌ای خودتون کد بزنید و می‌تونید تمرکزتون رو بذارید روی هسته اصلی business plan خودتون.خوب فکر میکنم تا حدی درباره اینکه نودجی‌اس چیه و مزیت‌هاش نسبت به بقیه زبان‌ها چیه صحبت کردیم.تو قسمت بعدی (لینک) درباره معماری نودجی‌اس صحبت می‌کنیم.</description>
                <category>محمد امین</category>
                <author>محمد امین</author>
                <pubDate>Wed, 25 Jul 2018 09:58:40 +0430</pubDate>
            </item>
                    <item>
                <title>واقعا «Node.js» رو یاد داریم؟ - مقدمه</title>
                <link>https://virgool.io/@aminvafaei13/%D9%88%D8%A7%D9%82%D8%B9%D8%A7-nodejs-%D8%B1%D9%88-%DB%8C%D8%A7%D8%AF-%D8%AF%D8%A7%D8%B1%DB%8C%D9%85-%D9%85%D9%82%D8%AF%D9%85%D9%87-uytrxw1xkdn3</link>
                <description>از nodejs.org مدت زیادی هست که با نودجی‌اس و فریم‌ورک های اون کار می‌کنم تا اینکه مدتی قبل یک مقاله با عنوان You don’t know Node (منبع) خوندم و برام خیلی جالب بود که برای شروع هر فریم‌ورک میرم سراغ Hello World و بزن که بریم...برای همین تصمیم گرفتم فارغ از فریم‌ورک و نوشتن کد به اصل مطلب و اینکه واقعا نودجی‌اس چطوری کار می‌کنه بپردازم.خودم دربارش خیلی خوندم و ویدیوهای زیادی هم دیدم و تا حدی مطلب دستم اومد و دوست داشتم تو سرچ‌های فارسی زبان هم ازش اثری باشه به همین خاطر شروع به نوشتن این رشته مطلب کردم.قبل از شروع  سر یک سری تعریف با هم به توافق برسیم : ممکنه توضیحات من دارای اشتباه و ایراد باشه.لطفا اگر به مورد اشتباهی رسیدین کامنت بذارید.یک سری تعاریف و کلمات کلیدی مثل Event Loop و ... هستش که (به نظر من) نباید ترجمه بشه چون هم باعث گیج شدن افراد میشه و هم ما رو از اصل مطلب دور می‌کنه.بنابراین من اون‌ها رو ترجمه نمی‌کنم.توی قسمت بعدی (لینک) درباره اینکه Node js چیه و چطور کار می‌کنه صحبت می‌کنیم.</description>
                <category>محمد امین</category>
                <author>محمد امین</author>
                <pubDate>Tue, 24 Jul 2018 13:26:35 +0430</pubDate>
            </item>
            </channel>
</rss>