<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های حامد پارسا</title>
        <link>https://virgool.io/feed/@parsahmd</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-15 23:34:30</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/4862704/avatar/xYgrlH.jpg?height=120&amp;width=120</url>
            <title>حامد پارسا</title>
            <link>https://virgool.io/@parsahmd</link>
        </image>

                    <item>
                <title>فرهنگ اجایل و اسکواد؛ وقتی مشکل ساختار نیست</title>
                <link>https://virgool.io/@parsahmd/agile-culture-yltdrmem64ad</link>
                <description>در سه مقاله قبل درباره تیم‌های تخصصی، اسکوادها و چپترها صحبت کردم.از تیم‌های تخصصی تا Squadها؛ آیا واقعاً بهتر شدیم؟اسکواد، چه اسم شیکی!رئیس من کیه؟تیم‌های تخصصی برای حل یک مسئله به وجود آمدند؛ اینکه هر حوزه توسط افرادی اداره شود که دانش و تجربه بیشتری در آن دارند. بعد از مدتی مشخص شد که همین تخصص‌گرایی می‌تواند وابستگی‌های زیادی ایجاد کند و سرعت تصمیم‌گیری را کاهش دهد.اسکوادها تلاش کردند این مشکل را حل کنند. تیم‌های کوچک‌تر و مستقل‌تری شکل گرفتند که بتوانند بدون وابستگی دائمی به بخش‌های دیگر، مسئولیت یک بخش از محصول را بر عهده بگیرند.بعد از آن، چپترها وارد شدند تا از پراکنده شدن دانش و تجربه در بین اسکوادهای مختلف جلوگیری کنند.همه این تغییرات منطقی به نظر می‌رسند. هر کدام برای حل یک مسئله واقعی به وجود آمده‌اند و در بسیاری از شرکت‌ها هم نتایج خوبی داشته‌اند.اما یک سؤال همچنان باقی می‌ماند.اگر ساختار این‌قدر مهم است، چرا بعضی تیم‌ها با همین مدل‌ها عملکرد فوق‌العاده‌ای دارند و بعضی دیگر نه؟چرا بعضی اسکوادها واقعاً مستقل هستند و بعضی فقط نام اسکواد را یدک می‌کشند؟هرچه بیشتر به تجربه‌های مختلف نگاه می‌کنم، کمتر می‌توانم پاسخ این سؤال‌ها را در چارت سازمانی پیدا کنم.به نظر می‌رسد جایی زیر همه این ساختارها، عامل دیگری وجود دارد که تأثیرش از خود ساختار بیشتر است:فرهنگ.از مجموعه‌ای از متخصصان تا یک تیمیکی از تفاوت‌های مهم بین یک تیم و مجموعه‌ای از افراد متخصص، نگاه آن‌ها به مسئولیت است.در بسیاری از سازمان‌ها، مسئولیت‌ها به‌خوبی تعریف شده‌اند. هر بخش صاحب مشخصی دارد، هر فرد حوزه اختیارات خودش را می‌شناسد و همه می‌دانند برای چه چیزی باید پاسخگو باشند. این شفافیت ضروری است، اما گاهی نتیجه ناخواسته‌ای هم دارد؛ مرزهایی شکل می‌گیرند که همکاری را دشوار می‌کنند.در چنین شرایطی، وقتی مشکلی پیش می‌آید، اولین واکنش معمولاً پیدا کردن صاحب مسئله است. اگر خطایی در زیرساخت وجود داشته باشد، باید تیم زیرساخت آن را بررسی کند. اگر مشکلی در طراحی مشاهده شود، باید به طراح ارجاع داده شود. اگر موضوعی به محصول مربوط باشد، تصمیم‌گیری نهایی بر عهده مدیر محصول خواهد بود.هرکدام از این تصمیم‌ها به‌تنهایی منطقی هستند، اما در عمل ممکن است باعث شوند که مسئله بین افراد و تیم‌های مختلف جابه‌جا شود، بدون آنکه کسی واقعاً احساس مالکیت نسبت به حل آن داشته باشد.در مقابل، تیم‌هایی وجود دارند که مسئولیت را به شکل دیگری تعریف می‌کنند. در این تیم‌ها همچنان تخصص‌ها و نقش‌ها وجود دارند، اما افراد مشکل را صرفاً متعلق به صاحب آن بخش نمی‌دانند. آن‌ها پیش از آنکه بپرسند «مسئول این قسمت چه کسی است؟» سعی می‌کنند بفهمند «چطور می‌توان این مسئله را حل کرد؟».شاید به همین دلیل است که بعضی تیم‌ها با وجود منابع کمتر، سریع‌تر از تیم‌های بزرگ‌تر حرکت می‌کنند. تفاوت اصلی معمولاً در سطح دانش فنی یا تجربه نیست؛ تفاوت در این است که افراد خود را در قبال نتیجه نهایی مسئول می‌دانند.وقتی اشتباه کردن ممنوع می‌شوداگر قرار باشد افراد مسئولیت بیشتری بپذیرند، باید بتوانند تصمیم بگیرند. و اگر قرار باشد تصمیم بگیرند، گاهی هم اشتباه خواهند کرد.با این حال، بسیاری از تیم‌ها هم‌زمان که از افرادشان انتظار استقلال دارند، فضایی ایجاد می‌کنند که در آن اشتباه کردن هزینه زیادی دارد. نتیجه معمولاً قابل پیش‌بینی است؛ افراد محافظه‌کار می‌شوند، کمتر ریسک می‌کنند و ترجیح می‌دهند در محدوده‌ای حرکت کنند که کمترین احتمال خطا را داشته باشد.این موضوع به‌خصوص در مورد نیروهای تازه‌وارد بیشتر دیده می‌شود. بخش زیادی از استرس آن‌ها نه از پیچیدگی فنی، بلکه از ترس اشتباه کردن ناشی می‌شود.در یکی از تیم‌هایی که با آن کار می‌کردم، یکی از توسعه‌دهندگان تازه‌وارد سال‌ها بعد خاطره‌ای را تعریف می‌کرد که برایم جالب بود. چیزی که در ذهنش مانده بود یک تصمیم مهم فنی یا یک پروژه موفق نبود. موضوع به یک تغییر نسبتاً ساده برمی‌گشت که از انجام آن واهمه داشت. چیزی که به خاطر سپرده بود، خودِ کار نبود؛ بلکه این اطمینان بود که اگر اشتباهی رخ دهد، قرار نیست به تنهایی با پیامدهای آن روبه‌رو شود.شاید به همین دلیل باشد که در بسیاری از تیم‌های موفق، اشتباه به‌عنوان بخشی از فرایند یادگیری پذیرفته می‌شود. نه به این معنا که کیفیت اهمیت ندارد یا خطاها نادیده گرفته می‌شوند، بلکه به این معنا که اشتباه فرصتی برای یادگیری است، نه بهانه‌ای برای سرزنش.شاید هیچ‌جا به اندازه جلسه Retrospective نتوان این تفاوت را مشاهده کرد. در بعضی تیم‌ها، رترو به جلسه‌ای برای پیدا کردن مقصر تبدیل می‌شود. افراد تلاش می‌کنند توضیح دهند چرا مشکل از سمت آن‌ها نبوده یا چه کسی باعث به وجود آمدن یک تصمیم اشتباه شده است.اما هدف اصلی رترو چیز دیگری است. قرار نیست مشخص کند چه کسی اشتباه کرده است؛ قرار است مشخص کند تیم چه چیزی یاد گرفته است.شاید بتوان کیفیت فرهنگ یک تیم را از روی یک سؤال ساده سنجید:وقتی در جلسه رترو درباره یک اشتباه صحبت می‌شود، افراد بیشتر به دنبال پیدا کردن دلیل هستند یا پیدا کردن مقصر؟رشد فردی یا رشد تیمی؟در بسیاری از محیط‌های کاری، رشد معمولاً به‌عنوان یک موضوع فردی دیده می‌شود. هرکس تلاش می‌کند مهارت‌های خودش را افزایش دهد، فناوری‌های جدید یاد بگیرد و موقعیت حرفه‌ای بهتری برای خودش بسازد.اما در تیم‌های موفق، رشد فقط یک اتفاق فردی نیست.وقتی افراد برای حل یک مشکل کنار هم می‌نشینند، چیزی فراتر از همان مشکل حل می‌شود. دانش بین افراد منتقل می‌شود. تجربه‌ها به اشتراک گذاشته می‌شوند و تیم به‌مرور توانمندتر می‌شود.به همین دلیل، تیم‌هایی که یادگیری را جدی می‌گیرند معمولاً وابستگی کمتری به افراد خاص دارند. دانش در ذهن چند نفر محدود نمی‌شود و خروج یا جابه‌جایی افراد، کل تیم را با بحران مواجه نمی‌کند.این نگاه حتی روی نحوه تشویق افراد نیز تأثیر می‌گذارد.سال‌ها پیش در یکی از تیم‌ها، پیشنهادی مطرح شد که در پایان هر اسپرینت یک «قهرمان» انتخاب شود؛ فردی که بیشترین تأثیر را در موفقیت آن دوره داشته است.در نگاه اول ایده جذابی به نظر می‌رسید. اما توسعه نرم‌افزار، به‌خصوص در تیم‌های محصولی، به‌ندرت یک فعالیت فردی است. خروجی نهایی حاصل همکاری افرادی است که هرکدام بخشی از مسیر را هموار کرده‌اند. گاهی مهم‌ترین نقش را کسی ایفا می‌کند که اصلاً در گزارش‌های عملکرد دیده نمی‌شود.به همین دلیل، انتخاب یک قهرمان در پایان هر دوره می‌تواند ناخواسته این پیام را منتقل کند که موفقیت یک دستاورد فردی است. رقابتی که قرار بود انگیزه ایجاد کند، کم‌کم می‌تواند زمینه‌ساز مقایسه، حس نابرابری و حتی حسادت شود.شاید به همین دلیل باشد که بسیاری از تیم‌های موفق به‌جای ساختن قهرمان‌های فردی، تلاش می‌کنند احساس موفقیت مشترک ایجاد کنند. مهم‌ترین سؤال در پایان یک اسپرینت این نیست که چه کسی بیشترین نقش را داشته است؛ بلکه این است که تیم چه چیزی را با هم به دست آورده است.وقتی ساختار کافی نیستبخش زیادی از بحث‌هایی که درباره اجایل، اسکواد و چپتر وجود دارد، حول ساختار می‌چرخد. اینکه تیم‌ها چگونه سازماندهی شوند، مسئولیت‌ها چطور تقسیم شوند و چه فرایندهایی برای هماهنگی بهتر وجود داشته باشد.اما تجربه بسیاری از تیم‌ها نشان می‌دهد که ساختار به‌تنهایی تضمین‌کننده موفقیت نیست.می‌توان اسکواد داشت اما مالکیت مشترک نداشت.می‌توان رترو برگزار کرد اما چیزی از اشتباهات یاد نگرفت.می‌توان افراد بااستعداد را کنار هم قرار داد اما هرگز به یک تیم واقعی تبدیل نشد.شاید اسکواد، چپتر و بسیاری از مفاهیم مشابه را بیشتر از آنکه بتوان به‌عنوان یک ساختار سازمانی دید، باید تلاشی برای حمایت از نوعی فرهنگ دانست؛ فرهنگی که در آن مسئولیت مشترک است، اشتباه بخشی از یادگیری محسوب می‌شود و موفقیت به‌عنوان یک دستاورد جمعی دیده می‌شود.اما حتی اگر چنین فرهنگی شکل بگیرد، یک سؤال مهم باقی می‌ماند.تا وقتی یک تیم کوچک است، انتقال دانش معمولاً به شکل طبیعی اتفاق می‌افتد. افراد کنار هم می‌نشینند، از هم یاد می‌گیرند و تجربه‌ها به‌مرور در کل تیم پخش می‌شود.اما وقتی تعداد اسکوادها بیشتر می‌شود، این فرایند دیگر آن‌قدر ساده نیست. هر تیم تجربه‌های خودش را تولید می‌کند، ابزارهای خودش را انتخاب می‌کند و راه‌حل‌های خودش را می‌سازد.سؤال اینجاست که چطور می‌توان بدون از بین بردن استقلال اسکوادها، از پراکنده شدن دانش و تجربه در سطح سازمان جلوگیری کرد؟یکی از پاسخ‌هایی که برای این مسئله شکل گرفت، Chapter بود.</description>
                <category>حامد پارسا</category>
                <author>حامد پارسا</author>
                <pubDate>Sun, 31 May 2026 13:20:14 +0330</pubDate>
            </item>
                    <item>
                <title>معماری ارتباط</title>
                <link>https://virgool.io/@parsahmd/communication-architecture-hrtjqupwctk9</link>
                <description>قبل از اینکه درباره HTTP، WebSocket یا هر تکنولوژی دیگری صحبت کنیم، بهتر است اول خود «معماری ارتباط» را بشناسیم.چون تفاوت اصلی سیستم‌ها معمولاً نه در زبان برنامه‌نویسی است، نه در Framework؛ بلکه در مدلی است که برای ارتباط بین Client و Server انتخاب می‌کنند.وقتی یک اپلیکیشن با سرور ارتباط برقرار می‌کند، چند سؤال بنیادی پشت صحنه وجود دارد:چه کسی ارتباط را شروع می‌کند؟ارتباط کوتاه‌مدت است یا دائمی؟Server وضعیت Client را نگه می‌دارد یا نه؟داده فقط هنگام درخواست ارسال می‌شود یا به‌صورت لحظه‌ای Push می‌شود؟سیستم synchronous است یا asynchronous؟پاسخ به همین سؤال‌هاست که معماری ارتباط را شکل می‌دهد.Push در مقابل Pull اولین تفاوت مهم بین معماری‌های ارتباطی این است که چه کسی شروع‌کننده ارتباط باشد.معماری Pullدر مدل Pull، این Client است که درخواست ارسال می‌کند و Server فقط در پاسخ به همان درخواست داده برمی‌گرداند.Client ---&gt; Request ---&gt; Server
Client &lt;--- Response --- Serverاین همان مدلی است که سال‌ها پایه اصلی Web بوده است.مثال‌ها:HTTPREST APIsPollingمزیت اصلی این مدل، سادگی و مقیاس‌پذیری بالاست.اما یک محدودیت مهم دارد:Server نمی‌تواند خودش داده‌ای ارسال کند مگر اینکه Client درخواست جدیدی بفرستد.به همین دلیل realtime کردن سیستم‌هایی مثل Chat یا Live Dashboard روی معماری Pull سخت‌تر می‌شود.معماری Push در مدل Push، Server می‌تواند بدون درخواست جدید از سمت Client، داده را ارسال کند.Server ---&gt; Event/Data ---&gt; Clientاین مدل برای سیستم‌های realtime طراحی شده است.مثال‌ها:WebSocketSSEFirestore Realtime Listenersدر این معماری، Client معمولاً یک connection باز نگه می‌دارد و Server هر زمان event جدیدی رخ دهد، داده را Push می‌کند.مزیت اصلی:تاخیر (latency ) پایینrealtime واقعیکاهش درخواست‌های غیرضروریاما در عوض:مدیریت connection پیچیده‌تر می‌شودscaling سخت‌تر می‌شودServer باید state بیشتری نگه داردStateless  در مقابل Statefulیکی از مهم‌ترین تفاوت‌های معماری‌های ارتباطی، نحوه مدیریت state است.معماری Stateless در معماری Stateless، هر request مستقل از request قبلی است.Server هیچ اطلاعاتی درباره ارتباط قبلی نگه نمی‌دارد.Request #1 -&gt; مستقل
Request #2 -&gt; مستقل
Request #3 -&gt; مستقلمثال کلاسیک:HTTPREST APIsمزیت بزرگ Stateless بودن:Horizontal Scaling ساده‌ترLoad Balancing راحت‌ترFault tolerance بهترچون هر request می‌تواند توسط هر سروری پردازش شود.به همین دلیل HTTP هنوز هم backbone بسیاری از سیستم‌های اینترنتی است.Stateful Architectureدر معماری Stateful، Server وضعیت connection یا session را نگه می‌دارد.Client &lt;==== Persistent Connection ====&gt; Serverمثال‌ها:WebSocketRealtime Sync EnginesMultiplayer Game Serversدر این مدل، ارتباط فقط یک request ساده نیست؛بلکه یک session دائمی بین Client و Server شکل می‌گیرد.مزایا:realtime communicationsynchronizationbidirectional messagingاما هزینه‌هایی هم دارد:memory usage بیشترscaling پیچیده‌ترمدیریت connection lifecycleنیاز به distributed coordinationSync در مقابل Asyncتمام ارتباط‌ها قرار نیست فوری و هم‌زمان باشند.ارتباط Synchronousدر این مدل Client درخواست ارسال می‌کند و تا دریافت پاسخ منتظر می‌ماند.Request ---&gt; Wait ---&gt; Responseاین مدل ساده و قابل‌فهم است، اما برای عملیات سنگین یا طولانی مناسب نیست.ارتباط Asynchronousدر معماری asynchronous، درخواست ثبت می‌شود اما پاسخ ممکن است بعداً پردازش شود.Client -&gt; Queue -&gt; Worker -&gt; Resultمثال‌ها:Message QueuesKafkaRabbitMQEvent Bus Architecturesاین مدل در سیستم‌های توزیع‌شده و scalable بسیار رایج است.Persistent  در مقابل Non-Persistent Connectionsیکی دیگر از تفاوت‌های مهم، طول عمر connection است.اتصال Non-Persistent ارتباط فقط برای یک request ایجاد می‌شود و بعد بسته می‌شود.Connect -&gt; Request -&gt; Response -&gt; Closeمثل HTTP سنتی.Persistent اتصالارتباط باز باقی می‌ماند و چندین پیام روی همان connection ردوبدل می‌شود.Connect ======================= Activeمثل:WebSocketSSEHTTP/2 Streamsاین مدل latency را کاهش می‌دهد و برای realtime communication مناسب‌تر است، اما مدیریت آن پیچیده‌تر است.در ادامه مقاله، تمام تکنولوژی‌های ارتباطی را با همین مدل ذهنی بررسی می‌کنیم؛چون بدون درک این مفاهیم، HTTP فقط یک request است و WebSocket فقط یک socket.اما وقتی این تفاوت‌های معماری روشن شوند، می‌توان فهمید که هر روش دقیقاً چه مسئله‌ای را حل می‌کند و چه trade-off هایی به همراه دارد.اولین معماری غالب وب: HTTP Request/Responseقبل از اینکه Web تبدیل به چیزی شبیه اپلیکیشن‌های امروزی شود، اینترنت بر پایه یک مدل بسیار ساده ساخته شده بود:Client ---&gt; Request ---&gt; Server
Client &lt;--- Response --- ServerClient درخواستی ارسال می‌کرد، Server پاسخ می‌داد و ارتباط تمام می‌شد. همین.امروز این مدل آن‌قدر بدیهی به‌نظر می‌رسد که شاید ساده و ابتدایی دیده شود، اما واقعیت این است که بخش بزرگی از موفقیت و رشد اینترنت، نتیجه همین سادگی بود.مدل معماری HTTPHTTP بر پایه معماری Request/Response ساخته شده است.یعنی:Client همیشه شروع‌کننده ارتباط استServer فقط در پاسخ به request عمل می‌کندارتباط معمولاً کوتاه‌مدت استهر request مستقل از request قبلی استمثلاً:GET /productsیا:POST /loginServer درخواست را پردازش می‌کند، response را برمی‌گرداند و connection بسته می‌شود.Stateless بودن؛ مهم‌ترین ویژگی HTTPیکی از مهم‌ترین ویژگی‌های معماری HTTP، Stateless بودن آن است.یعنی Server به‌صورت پیش‌فرض چیزی از request قبلی به خاطر نمی‌سپارد.Request #1 -&gt; مستقل
Request #2 -&gt; مستقل
Request #3 -&gt; مستقلهر request باید تمام اطلاعات لازم برای پردازش را همراه خودش داشته باشد.مثلاً:authentication tokensession idheadersrequest dataهمه باید در همان request ارسال شوند.چرا Stateless بودن مهم بود؟این تصمیم معماری، یکی از دلایل اصلی scalability اینترنت شد.وقتی Server نیازی به نگه‌داری state نداشته باشد:هر request می‌تواند توسط هر server پردازش شودload balancing ساده‌تر می‌شودhorizontal scaling راحت‌تر می‌شودfailure recovery بهتر انجام می‌شودمثلاً اگر ۱۰ server داشته باشیم:Client Request
      ↓
Load Balancer
   ↙  ↓  ↘
 S1  S2  S3هر request می‌تواند به هر node ارسال شود بدون اینکه server قبلی مهم باشد.و این دقیقاً همان چیزی بود که Web برای رشد massive خودش نیاز داشت.معماری Pull-BasedHTTP یک معماری Pull-based است.یعنی همیشه Client باید درخواست جدیدی ارسال کند تا داده دریافت کند.Client ---&gt; Request ---&gt; ServerServer نمی‌تواند خودش ارتباط را شروع کند یا داده‌ای ارسال کند.این موضوع در سال‌های اولیه Web کاملاً منطقی بود، چون بیشتر صفحات فقط document بودند:HTML pageimageform submissionاما بعدها همین ویژگی تبدیل به محدودیت شد.مزایای معماری HTTPسادگی HTTP یکی از بزرگ‌ترین نقاط قوت آن است.سادگی توسعهتقریباً تمام زبان‌ها و platformها از HTTP پشتیبانی می‌کنند.مقیاس‌پذیری بالابه دلیل Stateless بودن، scaling ساده‌تر است.امکان CacheHTTP برای caching طراحی بسیار خوبی دارد:Cache-Control
ETag
Expiresو همین موضوع فشار روی server را کاهش می‌دهد.سازگاری عالی با Infrastructureتقریباً تمام زیرساخت اینترنت برای HTTP optimized شده است:CDNReverse ProxyLoad BalancerBrowserFirewallمحدودیت‌های معماری HTTPبا رشد Web، محدودیت‌های این معماری کم‌کم مشخص شد.عدم پشتیبانی واقعی از Realtimeبزرگ‌ترین مشکل HTTP این بود:Server بدون request جدید از سمت Client نمی‌تواند داده‌ای ارسال کند.مثلاً اگر پیام جدیدی در Chat برسد، Server راه مستقیمی برای اطلاع دادن به Client ندارد.Connection کوتاه‌مدتدر مدل سنتی HTTP:Connect -&gt; Request -&gt; Response -&gt; Closeبعد از هر response ارتباط بسته می‌شود.برای ارتباط‌های مکرر، این موضوع overhead ایجاد می‌کند.Latency بیشتر در ارتباط‌های تعاملیبرای هر interaction جدید:connectionrequestresponseدوباره تکرار می‌شود.نتیجه چه شد؟وقتی Web از «صفحه‌های ساده» به سمت «اپلیکیشن‌های realtime» حرکت کرد، HTTP دیگر به‌تنهایی کافی نبود.نیازهای جدیدی به وجود آمد:ChatNotificationLive DashboardMultiplayer SystemsStreaming Dataاما معماری HTTP برای این نوع ارتباط طراحی نشده بود.در نتیجه توسعه‌دهنده‌ها شروع کردند به ساخت workaround هایی برای realtime communication.اولین راه‌حل رایج: Polling بود؛روشی ساده اما پرهزینه که تلاش می‌کرد محدودیت Pull-based بودن HTTP را دور بزند.اولین تلاش برای Realtime کردن وب:‌ Pollingدر Polling، کلاینت به‌صورت مداوم و در بازه‌های زمانی مشخص، درخواست جدید ارسال می‌کند تا بررسی کند آیا داده جدیدی وجود دارد یا نه.مثلاً:Every 5 seconds:
GET /notificationsیا:Every 2 seconds:
GET /messagesمعماری کلی:Client ---&gt; Request ---&gt; Server
Client &lt;--- Response --- Server

(wait)

Client ---&gt; Request ---&gt; Server
Client &lt;--- Response --- Serverدر واقع Client دائماً می‌پرسد:«چیزی تغییر کرده؟»Polling هنوز هم Pull-Based استبا اینکه هدف Polling ایجاد حس realtime است، اما از نظر معماری هنوز همان مدل Pull-based HTTP باقی می‌ماند.یعنی:ارتباط همیشه توسط Client شروع می‌شودServer همچنان passive استconnection کوتاه‌مدت باقی می‌ماندفقط تعداد requestها بیشتر شده است.مزیت اصلی Pollingدلیل محبوب شدن Polling خیلی ساده بود:پیاده‌سازی آن بسیار آسان بود.بدون نیاز به:protocol جدیدconnection دائمیinfrastructure پیچیدهفقط کافی بود Client هر چند ثانیه یک request بفرستد.به همین دلیل سال‌ها در بسیاری از سیستم‌ها استفاده می‌شد.Use Case های رایجPolling هنوز هم در بعضی سناریوها منطقی است.مثلاً:بررسی وضعیت Jobهاسیستم‌های ساده NotificationAdmin PanelsMonitoring با حساسیت پایینSynchronizationهای غیر realtimeاگر latency چندثانیه‌ای قابل‌قبول باشد، Polling می‌تواند انتخاب ساده و مناسبی باشد.مشکل معماری Pollingمشکل اصلی Polling از جایی شروع می‌شود که scale بالا می‌رود.فرض کنیم ۱۰۰ هزار Client داشته باشیم و هر Client هر ۵ ثانیه یک request ارسال کند.100,000 clients
      ×
Request every 5sحتی اگر هیچ داده جدیدی وجود نداشته باشد، Server همچنان باید requestها را پردازش کند.یعنی بخش بزرگی از traffic کاملاً useless است.مشکل شماره ۱: Requestهای غیرضروریدر بسیاری از مواقع response چیزی شبیه این است:{
  &quot;updates&quot;: []
}یعنی:request ارسال شدهconnection باز شدهserver پردازش انجام دادهولی هیچ اتفاقی نیفتادهاین یعنی:مصرف CPUمصرف bandwidthفشار روی infrastructureبدون value واقعی.مشکل شماره ۲: Trade-off بین Latency و Costهرچه interval کوتاه‌تر باشد:Polling every 1 secondRealtime بهتر می‌شود، اما:تعداد requestها افزایش پیدا می‌کندهزینه infrastructure بالا می‌رودفشار روی backend بیشتر می‌شودو اگر interval را زیاد کنیم:Polling every 30 secondsهزینه کمتر می‌شود، اما realtime بودن تقریباً از بین می‌رود.پس Polling همیشه بین این دو گیر می‌کند:Lower Latency        Higher CostHigher Latency       Lower Costمشکل شماره ۳: Connection Overheadدر HTTP سنتی، هر request معمولاً شامل:TCP handshakeHTTP headersauthenticationrequest parsingاست.وقتی requestها مدام تکرار شوند، این overhead بسیار noticeable می‌شود.مشکل شماره ۴: Scalabilityدر مقیاس بالا، Polling می‌تواند backend را overload کند.خصوصاً وقتی:تعداد کاربران زیاد باشدinterval کوتاه باشدresponseها سنگین باشنددر چنین شرایطی، بخش بزرگی از منابع Server صرف بررسی requestهایی می‌شود که هیچ تغییر جدیدی ندارند.از نگاه معماریPolling در واقع تلاشی بود برای شبیه‌سازی realtime روی معماری‌ای که ذاتاً realtime نبود.و همین موضوع باعث شد محدودیت‌های آن خیلی زود مشخص شود.نتیجه چه شد؟توسعه‌دهنده‌ها به دنبال راهی بودند که:تعداد requestهای غیرضروری کمتر شودlatency کاهش پیدا کندrealtime طبیعی‌تر شوداما هنوز نمی‌خواستند کاملاً از مدل HTTP خارج شوند.نتیجه این تلاش‌ها: Long Polling بود؛مدلی که سعی می‌کرد Server را کمی «فعال‌تر» کند بدون اینکه معماری Web کاملاً تغییر کند.وقتی Server منتظر Event می‌ماند:  Long PollingPolling یک مشکل اساسی داشت:Client مدام request ارسال می‌کرد، حتی وقتی هیچ داده جدیدی وجود نداشت.این یعنی مقدار زیادی traffic و پردازش غیرضروری.برای حل این مشکل، ایده جدیدی شکل گرفت:«اگر Server به‌جای پاسخ فوری، کمی صبر کند چه؟»و این دقیقاً پایه Long Polling بود.Long Polling چگونه کار می‌کند؟در Long Polling، Client درخواست ارسال می‌کند، اما اگر داده جدیدی وجود نداشته باشد، Server connection را باز نگه می‌دارد و فوراً پاسخ نمی‌دهد.Client ---&gt; Request ---&gt; Server
             (wait...)
Client &lt;--- Response ---- ServerServer منتظر می‌ماند تا:event جدیدی اتفاق بیفتدداده‌ای تغییر کندیا timeout رخ دهدو بعد response را ارسال می‌کند.تفاوت اصلی با Pollingدر Polling معمولی:Request -&gt; Immediate Responseحتی اگر data جدیدی وجود نداشته باشد.اما در Long Polling:Request -&gt; Wait Until Updateاین تفاوت ساده، تعداد زیادی از requestهای useless را حذف می‌کرد.جریان ارتباط در Long Pollingمعمولاً روند به این شکل است:1. Client sends request
2. Server waits
3. Event happens
4. Server responds
5. Client immediately reconnectsیعنی connection دائمی نیست، اما تقریباً همیشه یک request فعال وجود دارد.آیا Long Polling realtime است؟تا حد زیادی بله.چون به‌محض رخ دادن event، Server پاسخ را ارسال می‌کند.Latency نسبت به Polling بسیار کمتر می‌شود.چرا Long Polling مهم بود؟چون برای اولین بار، Web را به چیزی نزدیک به realtime تبدیل کرد بدون اینکه نیاز به protocol جدیدی باشد.همه‌چیز هنوز روی HTTP انجام می‌شد.این موضوع در زمان خودش بسیار مهم بود، چون:Browserها محدود بودندInfrastructure برای WebSocket آماده نبودProxyها و Firewallها با HTTP راحت‌تر کار می‌کردندUse Case های رایجسال‌ها بسیاری از سیستم‌های realtime اولیه از Long Polling استفاده می‌کردند:Chat applicationsNotification systemsRealtime feedsCollaboration toolsحتی بعضی نسخه‌های اولیه:Facebook ChatGmail updatesSlackتا مدت‌ها از مدل‌هایی شبیه Long Polling استفاده می‌کردند.مزایای معماری Long Pollingکاهش requestهای غیرضروریبزرگ‌ترین مزیت آن نسبت به Polling همین بود.Realtime بهترServer می‌توانست به‌محض وقوع event پاسخ بدهد.سازگاری کامل با HTTPبدون نیاز به protocol جدید.Compatibility عالیبا:BrowserهاProxyهاFirewallهاCDNهاسازگارتر از بسیاری از راه‌حل‌های realtime اولیه بود.اما مشکل‌های جدید شروع شدندLong Polling نسبت به Polling بهتر بود، اما هنوز محدودیت‌های مهمی داشت.مشکل شماره ۱: Connectionهای طولانیدر HTTP سنتی، connectionها کوتاه‌مدت بودند.اما حالا Server باید هزاران connection باز را نگه می‌داشت:10,000 waiting connectionsو این از نظر resource management ارزان نبود.مشکل شماره ۲: Memory Pressureهر connection باز:memory مصرف می‌کندfile descriptor مصرف می‌کندresource نگه می‌دارددر scale بالا، این موضوع به bottleneck تبدیل می‌شود.مشکل شماره ۳: Reconnect Overheadبعد از هر response:Response -&gt; Reconnect -&gt; Wait AgainClient باید دوباره request جدید بفرستد.یعنی هنوز:reconnect وجود داردheaders تکرار می‌شوندHTTP overhead باقی می‌ماندمشکل شماره ۴: Half-Realtime بودنLong Polling هنوز ذاتاً:request/responseclient-drivenاست.Server فقط زمانی می‌تواند data ارسال کند که request فعالی وجود داشته باشد.از نگاه معماریLong Polling یک مرحله transitional بود.نه کاملاً realtime،نه کاملاً traditional HTTP.بلکه تلاشی برای نزدیک کردن معماری Request/Response به event-driven communication.نتیجه چه شد؟نیاز به ارتباطی وجود داشت که:دائمی باشدoverhead کمتری داشته باشدbidirectional باشدreconnect مداوم نداشته باشدواقعاً realtime باشدو اینجا بود که Web کم‌کم به سمت: Persistent Connections حرکت کرد.اولین قدم مهم در این مسیر: Server-Sent Events (SSE) بود؛مدلی ساده و lightweight که برای اولین بار اجازه می‌داد Server به‌صورت واقعی داده را به Client push کند.اولین Push واقعی در وب: Server-Sent Events (SSE)تا اینجا تمام مدل‌هایی که دیدیم، هنوز یک ویژگی مشترک داشتند:ارتباط همیشه توسط Client شروع می‌شد.حتی در Long Polling هم Server فقط زمانی می‌توانست داده ارسال کند که یک request فعال از سمت Client وجود داشته باشد.اما کم‌کم Web به سمت سیستم‌هایی حرکت کرد که نیاز داشتند Server بتواند مستقیماً و لحظه‌ای داده ارسال کند:Live notificationsMonitoring dashboardsNews feedsStreaming updatesAI response streamingو اینجا بود که معماری: Server-Sent Events (SSE) شکل گرفت.SSE چگونه کار می‌کند؟در SSE، Client یک request HTTP ارسال می‌کند، اما برخلاف HTTP معمولی، connection باز باقی می‌ماند.Client ---&gt; Connection ---&gt; Server
Client &lt;--- Stream of Events ---بعد از برقراری connection، Server می‌تواند هر زمان event جدیدی رخ دهد، داده را به Client ارسال کند.معماری SSESSE یک معماری:Push-basedPersistentServer-to-Client Streamingاست.یعنی:connection دائمی استServer فعالانه data ارسال می‌کندClient فقط listener استتفاوت مهم SSE با Pollingدر Polling:Client:
&quot;چیزی تغییر کرده؟&quot;اما در SSE:Server:
&quot;این هم update جدید.&quot;یعنی برای اولین بار، Web واقعاً push-based شد.جریان ارتباط در SSEروند معمول به این شکل است:1. Client opens connection
2. Connection stays alive
3. Server pushes events continuously
4. Client receives updates instantlyبدون reconnect مداوم،بدون polling،بدون requestهای تکراری.نمونه ساده SSEClient:const events = new EventSource(&#039;/events&#039;);

events.onmessage = (event) =&gt; {
  console.log(event.data);
};Server:data: New notification

data: User joined

data: Price updatedServer عملاً یک stream دائمی از eventها ارسال می‌کند.چرا SSE مهم بود؟چون نسبت به Long Polling:ساده‌تر بودlatency پایین‌تری داشتoverhead کمتری داشتrealtime طبیعی‌تری ایجاد می‌کردبدون اینکه complexity کامل WebSocket را وارد سیستم کند.مزایای معماری SSELightweight بودنSSE روی HTTP معمولی کار می‌کند.نیازی به protocol جدید ندارد.Push واقعیServer می‌تواند بدون request جدید data ارسال کند.Connection دائمیبرخلاف Polling، reconnect مداوم وجود ندارد.مناسب برای StreamingSSE برای data stream بسیار مناسب است.مثلاً:AI response streamingLive feedsMetricsNotificationsسازگاری خوب با Infrastructureچون SSE هنوز مبتنی بر HTTP است:proxyهاfirewallهاload balancerهامعمولاً راحت‌تر با آن کار می‌کنند.محدودیت‌های معماری SSEبا وجود مزایا، SSE هنوز محدودیت‌های مهمی داشت.مشکل شماره ۱: ارتباط یک‌طرفهSSE فقط:Server ---&gt; Clientاست.Client نمی‌تواند روی همان connection data ارسال کند.اگر Client بخواهد چیزی بفرستد، هنوز باید HTTP request جداگانه ارسال کند.مشکل شماره ۲: Binary DataSSE اساساً text-based است.برای binary streaming مناسب نیست.مشکل شماره ۳: Browser Connection Limitsدر بعضی browserها تعداد connectionهای هم‌زمان محدود بود و SSE می‌توانست به bottleneck تبدیل شود.مشکل شماره ۴: هنوز Stateful استهر connection باز:memory مصرف می‌کندresource نگه می‌داردlifecycle داردپس scaling همچنان سخت‌تر از HTTP سنتی است.Use Case های مناسب SSESSE برای سناریوهایی عالی است که:ارتباط mostly one-way باشدserver بیشتر producer باشدclient فقط consumer باشدمثلاً:Live notificationsActivity feedsMonitoring dashboardsRealtime analyticsAI token streamingStock tickersچرا ChatGPT به SSE شبیه است؟وقتی پاسخ ChatGPT کم‌کم stream می‌شود:Hello...
How are...این دقیقاً مدلی شبیه SSE است.Server به‌صورت incremental داده را push می‌کند.از نگاه معماریSSE اولین معماری mainstream در Web بود که:واقعاً push-based شدstreaming واقعی ارائه دادpersistent connection داشتاما هنوز یک محدودیت بزرگ باقی مانده بود:ارتباط فقط یک‌طرفه بود.Web کم‌کم به سمت اپلیکیشن‌هایی حرکت می‌کرد که نیاز داشتند:Client و Server هم‌زمان data ارسال کنندlatency بسیار پایین باشدارتباط کاملاً realtime باشدو اینجا بود که Web وارد دنیای: WebSocket شد؛معماری‌ای که ارتباط بین Client و Server را از Request/Response به یک connection دائمی و bidirectional تبدیل کرد. وقتی ارتباط واقعاً دوطرفه شد: WebSocketتا قبل از WebSocket، Web هنوز تا حد زیادی بر پایه مدل سنتی Request/Response حرکت می‌کرد.حتی SSE با وجود realtime بودن، هنوز یک محدودیت مهم داشت:ارتباط فقط از سمت Server به Client بود.اما نسل جدید اپلیکیشن‌ها به چیزی فراتر نیاز داشتند:Chat applicationsOnline gamingLive collaborationTrading systemsMultiplayer appsسیستم‌هایی که در آن‌ها:Client و Server باید هم‌زمان داده ارسال کنندlatency باید بسیار پایین باشدارتباط باید دائمی و realtime باشدو اینجا بود که معماری: WebSocket متولد شد.WebSocket چگونه کار می‌کند؟WebSocket ارتباط بین Client و Server را از مدل Request/Response به یک connection دائمی و دوطرفه تبدیل می‌کند.Client &lt;=======&gt; Serverبعد از برقراری connection:هر دو سمت می‌توانند هر زمان data ارسال کنندconnection باز باقی می‌ماندنیازی به reconnect مداوم نیستUpgrade از HTTP به WebSocketنکته جالب اینجاست که WebSocket معمولاً با یک HTTP request شروع می‌شود.Upgrade: websocket
Connection: Upgradeبعد از handshake اولیه، ارتباط از HTTP خارج می‌شود و وارد protocol مخصوص WebSocket می‌شود.از این لحظه دیگر خبری از:requestresponsepollingreconnect مداومنیست.معماری WebSocketWebSocket یک معماری:PersistentStatefulBidirectionalFull-Duplexاست.یعنی:connection دائمی استهر دو سمت active هستندdata می‌تواند هم‌زمان در هر دو جهت حرکت کندتفاوت بنیادی با HTTPدر HTTP:Request -&gt; Response -&gt; Closeاما در WebSocket:connect ================= Active Streamconnection تبدیل به یک channel دائمی می‌شود.چرا WebSocket انقلابی بود؟چون برای اولین بار Web توانست رفتاری شبیه applicationهای desktop یا network protocolهای realtime پیدا کند.یعنی:latency بسیار پایینrealtime واقعیevent-driven communicationbidirectional messagingنمونه ساده WebSocketClient:const socket = new WebSocket(&#039;ws://server&#039;);

socket.onmessage = (event) =&gt; {
  console.log(event.data);
};

socket.send(&#039;Hello&#039;);اینجا:Server می‌تواند هر زمان message ارسال کندClient هم هر زمان بخواهد data می‌فرستدبدون request جدید.مزایای معماری WebSocketRealtime واقعیتاخیر بسیار پایین است.ارتباط دوطرفههر دو سمت می‌توانند producer و consumer باشند.کاهش overheadدیگر برای هر message:HTTP headersreconnecthandshakeتکرار نمی‌شود.مناسب برای Event-Driven SystemsWebSocket ذاتاً event-oriented است.Use Case های مناسب WebSocketWebSocket برای سیستم‌هایی مناسب است که:ارتباط دائمی نیاز دارندlatency بسیار مهم استتبادل data دوطرفه استمثل:Chat systemsMultiplayer gamesCollaborative editorsTrading platformsLive dashboardsPresence systemsRealtime notificationsاما WebSocket هزینه داردو این دقیقاً جایی است که معماری اهمیت پیدا می‌کند.بسیاری از تیم‌ها فقط به realtime بودن WebSocket نگاه می‌کنند، اما complexity معماری آن را نادیده می‌گیرند.مشکل شماره ۱: Stateful Connectionsبرخلاف HTTP، حالا Server باید connectionها را نگه دارد.100,000 active socketsهر connection:memory مصرف می‌کندlifecycle داردباید مدیریت شودمشکل شماره ۲: Scaling سخت‌تر می‌شوددر HTTP هر request مستقل بود.اما حالا:Client A -&gt; Server 1
Client B -&gt; Server 2اگر Client A پیامی بفرستد و Client B روی node دیگری باشد، سیستم باید somehow message را بین serverها synchronize کند.اینجاست که سیستم‌ها وارد دنیای:Redis Pub/SubKafkaNATSMessage Brokersمی‌شوند.مشکل شماره ۳: Load Balancing پیچیده‌تر می‌شوددر HTTP:هر request می‌تواند به هر server بروداما در WebSocket:connection دائمی استserver state نگه می‌داردپس Load Balancer باید:sticky session داشته باشدconnection-aware باشدمشکل شماره ۴: Connection Lifecycleحالا باید این مسائل مدیریت شوند:reconnectheartbeattimeoutdead connectionsnetwork interruptionو این complexity کمی نیست.مشکل شماره ۵: Observability سخت‌تر می‌شوددر HTTP tracing ساده‌تر است چون requestها مستقل‌اند.اما در WebSocket:event stream طولانی داریمstate دائماً تغییر می‌کندdebugging سخت‌تر می‌شودWebSocket همیشه انتخاب درست نیستیکی از اشتباه‌های رایج این است که:«هر realtimeای = WebSocket»در حالی که بسیاری از سیستم‌ها اصلاً به bidirectional communication نیاز ندارند.مثلاً:Notification streamAI output streamingLive metricsممکن است با SSE ساده‌تر و scalableتر حل شوند.از نگاه معماریWebSocket نقطه‌ای بود که Web از مدل سنتی document-based فاصله گرفت و به سمت application-level communication حرکت کرد.اما complexity آن هم به همان اندازه افزایش پیدا کرد.در واقع WebSocket فقط یک protocol نیست؛ورود به دنیای:stateful systemsdistributed coordinationrealtime infrastructureاست.نتیجه چه شد؟با رشد سیستم‌های توزیع‌شده، کم‌کم مشخص شد که realtime communication تنها مسئله نیست.سیستم‌ها نیاز داشتند:سرویس‌ها با هم سریع‌تر صحبت کنندstreaming داخلی داشته باشندcommunication typed و efficient باشدlatency بین serviceها کمتر شودو اینجا بود که معماری‌های جدیدتری مثل: gRPC و بعد از آن:Event StreamingMessage QueuesRealtime Sync Enginesوارد معماری سیستم‌های مدرن شدند.جمع‌بندیمسیر تکامل Web را می‌توان تا حد زیادی از زاویه «معماری ارتباط» نگاه کرد.در ابتدا، Web بر پایه مدل ساده و قدرتمند HTTP Request/Response ساخته شد؛مدلی stateless، scalable و مناسب برای دنیایی که بیشتر از document و page تشکیل شده بود.اما با تبدیل شدن Web به یک platform برای applicationهای interactive، محدودیت‌های این معماری کم‌کم آشکار شد.نیازهای جدیدی به وجود آمد:realtime communicationlive updateslow latency interactionsbidirectional messagingpersistent synchronizationو هرکدام از معماری‌هایی که بررسی کردیم، در واقع پاسخی به همین نیازها بودند.Polling تلاش کرد realtime را روی HTTP شبیه‌سازی کند، اما به قیمت requestهای مکرر و مصرف بالای resource.Long Polling قدمی به جلو بود و توانست ارتباط را طبیعی‌تر و کم‌هزینه‌تر کند، اما هنوز در چارچوب Request/Response باقی مانده بود.SSE برای اولین بار مفهوم واقعی Push-based communication را وارد Web کرد و امکان streaming ساده و lightweight را فراهم ساخت.و در نهایت، WebSocket ارتباط بین Client و Server را از یک مدل سنتی مبتنی بر request، به یک connection دائمی، realtime و bidirectional تبدیل کرد.اما نکته مهم اینجاست که هیچ‌کدام از این معماری‌ها «بهترین» نیستند.هر مدل ارتباطی، مجموعه‌ای از trade-off ها را به همراه دارد.معمولاً هرچه:realtime بیشتر شود،latency کمتر شود،و synchronization قوی‌تر شود،complexity سیستم هم افزایش پیدا می‌کند.به همین دلیل انتخاب معماری ارتباط، فقط یک تصمیم تکنیکال نیست؛بلکه یک تصمیم معماری است که مستقیماً روی:scalabilityinfrastructuremaintainabilityobservabilityoperational costdeveloper experienceتأثیر می‌گذارد.یکی از اشتباه‌های رایج در طراحی سیستم‌ها این است که تکنولوژی‌ها صرفاً بر اساس trend یا hype انتخاب شوند.در حالی که در بسیاری از پروژه‌ها:HTTP کاملاً کافی است،Polling هنوز منطقی است،یا SSE انتخاب ساده‌تر و مناسب‌تری نسبت به WebSocket محسوب می‌شود.Realtime بودن همیشه ارزش complexity بیشتر را ندارد.در نهایت، معماری ارتباط فقط درباره انتقال data نیست؛بلکه درباره نحوه فکر کردن به interaction بین اجزای سیستم است.اینکه:چه کسی کنترل ارتباط را در دست دارد،state کجا نگهداری می‌شود،ارتباط چگونه scale می‌شود،و سیستم تا چه اندازه باید realtime، resilient و distributed باشد.و دقیقاً همین تصمیم‌ها هستند که تفاوت بین یک API ساده و یک سیستم realtime در مقیاس بزرگ را مشخص می‌کنند.در مقاله بعدی، از دنیای ارتباطات Web فراتر می‌رویم و سراغ معماری ارتباط در سیستم‌های توزیع‌شده مدرن می‌رویم؛جایی که مفاهیمی مثل:gRPCEvent StreamingKafkaMessage QueuesRealtime SynchronizationDistributed Messagingنقش اصلی را بازی می‌کنند.</description>
                <category>حامد پارسا</category>
                <author>حامد پارسا</author>
                <pubDate>Mon, 25 May 2026 22:10:31 +0330</pubDate>
            </item>
                    <item>
                <title>رئیس من کیه؟</title>
                <link>https://virgool.io/@parsahmd/who-is-my-boss-qxkqx1dmshfu</link>
                <description>وقتی کار را در آن شرکت شروع کردم، هنوز تیمی وجود نداشت. تیم در طول حدود دو سال آرام‌آرام ساخته شد؛ تیمی که بعدتر برای خیلی از ما بیشتر از یک محیط کاری بود.کار به‌شدت فشرده بود. تیم با مدل چابک جلو می‌رفت و همزمان که پروژه بزرگ‌تر می‌شد، آدم‌های جدید هم به تیم اضافه می‌شدند. بعضی شب‌ها لازم بود نیمه‌شب آنلاین شویم تا مشکل سامانه را حل کنیم یا انتشار نسخه را نجات بدهیم. فشار زیاد بود و در ابتدای مسیر حتی اعتماد زیادی هم به تیم وجود نداشت، اما خروجی کار واقعاً فوق‌العاده بود.با این حال چیزی که آن تیم را خاص می‌کرد فقط نتیجه فنی نبود. وسط همان فشارها برای درست کردن صبحانه وقت می‌گذاشتیم، برای هم تولد می‌گرفتیم و اگر کسی خسته یا تحت فشار بود، بقیه سعی می‌کردند بخشی از بارش را بردارند. بچه‌ها حین کار با هم شوخی می‌کردند و تیم معمولاً با روی خوش از آدم‌های تازه‌وارد استقبال می‌کرد.نکته جالب این بود که داخل تیم عملاً رئیس جدی‌ای وجود نداشت. آدم‌ها با هم هماهنگ می‌کردند، تصمیم می‌گرفتند و جلو می‌رفتند. اعتماد و رفاقت، بخش مهمی از چیزی بود که تیم را سرپا نگه می‌داشت.در همان روزهای خوب، مدیر جدیدی هم به مجموعه اضافه شد. اما برخلاف چیزی که شاید بشود حدس زد، همه‌چیز بلافاصله خراب نشد. تیم هنوز همان انرژی قبلی را داشت، آدم‌ها هنوز با هم می‌خندیدند و کار جلو می‌رفت. حتی مدتی بعد از اینکه من از آن مجموعه جدا شدم، هنوز از بیرون همه‌چیز عادی به نظر می‌رسید. هم‌زمان، تغییراتی هم در ساختار تیم شروع شده بود؛ تغییراتی که اثرشان همان روزها دیده نمی‌شد.اما چند ماه بعد، وقتی دوباره بعضی از بچه‌های تیم را دیدم، انگار همه‌چیز عوض شده بود.آدم‌هایی که زمانی بدون تعارف به هم کمک می‌کردند، حالا با احتیاط با هم حرف می‌زدند. بعضی‌ها دیگر حاضر نبودند با بعضی دیگر کار کنند و بعضی دیگر حتی از دیدن هم فرار می‌کردند.تیمی که روزی وسط فشار و خستگی برای هم صبحانه درست می‌کرد، حالا درگیر بازی‌های قدرت شده بود.و عجیب‌تر از همه این بود که هیچ‌کس دقیق نمی‌دانست این اتفاق از کجا شروع شد.چپتر و اسکوادبرای فهمیدن آن فروپاشی، باید اول خود ساختار را فهمید. همه‌چیز از جایی پیچیده شد که تیم دیگر فقط «یک تیم» نبود.آدم‌ها کم‌کم وارد ساختار جدیدی شدند؛ اسکوادها و چپترها.اسکوادها قرار بود تیم‌های مستقلی باشند که روی بخشی از محصول کار می‌کنند؛ تیم‌هایی کوچک و چندتخصصی که بتوانند بدون وابستگی زیاد، سریع تصمیم بگیرند و محصول را جلو ببرند.در کنار آن، چپترها شکل می‌گرفتند؛ گروهی از آدم‌ها با مهارت مشابه که در تیم‌های مختلف پخش شده بودند اما هنوز از نظر فنی و حرفه‌ای به هم وصل می‌ماندند. قرار بود آدم‌هایی که مهارت مشابه دارند، حتی اگر در تیم‌های مختلف کار می‌کنند، هنوز احساس کنند بخشی از یک مسیر مشترک‌اند.روی کاغذ، همه‌چیز منطقی به نظر می‌رسید.اما ساختار جدید، آرام‌آرام چیزی را وارد تیم کرد که قبلاً وجود نداشت:مرزهای جدید قدرت.رئیس واقعی کیست؟تا قبل از آن، بیشتر تصمیم‌ها به‌صورت جمعی گرفته می‌شد. حتی با وجود تفاوت تجربه و مهارت، تیم بیشتر شبیه یک گروه همکار عمل می‌کرد تا یک ساختار مدیریتی رسمی.اما با ورود مدل اسکواد و چپتر، نقش‌های جدیدی به وجود آمد. بعضی‌ها مسئول تحویل محصول شدند و بعضی دیگر مسئول رشد فنی و هماهنگی تخصصی.روی کاغذ، تقسیم مسئولیت منطقی به نظر می‌رسید؛ یک نفر مراقب کیفیت و رشد فنی بود و یک نفر روی سرعت و تحویل محصول تمرکز داشت.اما در عمل، همه‌چیز به این سادگی نبود.اگر اسکواد بخواهد سریع‌تر جلو برود ولی چپتر روی کیفیت حساس باشد چه می‌شود؟ اگر زمان انتشار نسخه نزدیک باشد و یکی از اعضای تیم بخواهد مرخصی برود، چه کسی تصمیم نهایی را می‌گیرد؟ اگر بین اولویت محصول و تصمیم فنی اختلافی به وجود بیاید، حرف آخر را چه کسی می‌زند؟مشکل دقیقاً از همین‌جا شروع می‌شود.وقتی مرز مسئولیت‌ها شفاف نباشد، نقش‌ها کم‌کم از «مسئولیت» فاصله می‌گیرند و به «جایگاه» نزدیک می‌شوند. بعضی‌ها نقش جدید را به‌عنوان ارتقای موقعیت می‌بینند و بعضی دیگر احساس می‌کنند بخشی از نفوذ قبلی‌شان را از دست داده‌اند.در ظاهر همه هنوز درباره همکاری حرف می‌زنند، اما آرام‌آرام آدم‌ها شروع می‌کنند به انتخاب طرف.بعضی جلسه‌ها بیشتر شبیه مذاکره‌اند تا همکاری.یک درخواست مرخصی ساده از طرف یکی از اعضای تیم، می‌تواند درگیری بزرگی تا سطح مدیریت ایجاد کند.و شاید مهم‌ترین اتفاق همین باشد:تیمی که قبلاً بر پایه اعتماد جلو می‌رفت، حالا آرام‌آرام دارد بر اساس قدرت تنظیم می‌شود.شاید مسئله اصلی چیز دیگری بودمدت‌ها فکر می‌کردم مشکل از خودِ ساختار است؛ از اسکواد، چپتر یا نقش‌های جدیدی که وارد تیم شدند.اما هرچه بیشتر به آن دوران فکر می‌کنم، بیشتر حس می‌کنم مسئله فقط ساختار نبود. انگار چیزی عمیق‌تر، آرام‌آرام داخل تیم تغییر کرده بود؛ چیزی که در ظاهر دیده نمی‌شد اما روی تمام تصمیم‌ها، رابطه‌ها و رفتار آدم‌ها اثر می‌گذاشت.واقعیت این است که اسکواد و چپتر، به‌خودیِ‌خود ایده‌های بدی نیستند. حتی در بسیاری از شرکت‌ها به‌خوبی کار می‌کنند. اما این ساختارها زمانی جواب می‌دهند که روی یک بستر درست سوار شوند.شاید مسئله هیچ‌وقت فقط اسکواد و چپتر نبود.شاید آن بستر، همان چیزی است که معمولاً دیر به آن فکر می‌کنیم: فرهنگ.شاید تیم ما خیلی قبل‌تر از آنکه متوجه شویم، شروع به فروپاشی کرده بود.</description>
                <category>حامد پارسا</category>
                <author>حامد پارسا</author>
                <pubDate>Mon, 18 May 2026 11:41:17 +0330</pubDate>
            </item>
                    <item>
                <title>اول مسئله را حل کن، بعد درباره معماری حرف بزن</title>
                <link>https://virgool.io/@parsahmd/software-architecture-ec0vwpoehpsq</link>
                <description>خیلی‌ها وقتی درباره معماری نرم‌افزار صحبت می‌کنند، ذهنشان سریع به سمت چیزهایی مثل Microservice، Clean Architecture، Event Driven، Kubernetes یا چند دیاگرام پیچیده می‌رود.اما به نظرم این‌ها خودِ معماری نیستند.بیشتر پروژه‌هایی که من در طول سال‌ها دیده‌ام، نه به خاطر ضعف تکنولوژی، بلکه به خاطر تصمیم‌های اشتباه شکست خورده‌اند.معماری نرم‌افزار در اصل توانایی گرفتن تصمیم‌های درست تحت محدودیت‌های واقعی است.معماری یعنی ساختن یک پلاگر بخواهم معماری را ساده تعریف کنم، می‌گویم:معماری نرم‌افزار یعنی ساختن یک پل بین نیازها، محدودیت‌ها و پیاده‌سازی.فرض کنید مشتری می‌خواهد یک وب‌سایت برای معرفی خدمات کسب‌وکارش راه‌اندازی کند.در چنین شرایطی، وظیفه معمار این نیست که سریع درباره REST API، Message Broker یا Kubernetes تصمیم بگیرد.اگر از همان ابتدا درگیر انتخاب تکنولوژی شویم، احتمال زیادی وجود دارد که مسئله اصلی را گم کنیم.قبل از هر چیز باید بفهمیم اولویت واقعی چیست.معماری از فهم مسئله شروع می‌شوداگر هدف مشتری دیده شدن در گوگل باشد، SEO اهمیت بالایی پیدا می‌کند.اگر قرار است کاربر تعامل زیادی با سیستم داشته باشد، تجربه کاربری اهمیت پیدا می‌کند.اگر سرعت رشد مهم باشد، Performance و سرعت بارگذاری تبدیل به اولویت می‌شوند.معماری یعنی بتوانیم تشخیص دهیم چه چیزی واقعاً مهم است و چه چیزی فقط پیچیدگی اضافه می‌کند.یک تجربه واقعیدر پروژه مدیریت سیستم تولید که برای پالایشگاه سرخس می‌ساختم، بزرگ‌ترین نگرانی مشتری نه scalability بود، نه Microservice و نه Event Driven Architecture.مسئله اصلی خیلی ساده‌تر بود.کاربران باید می‌توانستند اطلاعات را سریع، راحت و بدون اصطکاک وارد کنند.اگر ورود اطلاعات سخت می‌شد، عملاً کل سیستم شکست می‌خورد.به همین دلیل، اولین تصمیم مهم معماری ما ساختن یک اینترفیس ساده و سریع برای ورود اطلاعات بود.نه طراحی چندین سرویس پیچیده، نه optimization زودهنگام و نه abstraction اضافه.چون در آن مرحله، مهم‌ترین نیاز سیستم سرعت adoption بود.و این دقیقاً همان جایی است که معماری واقعی خودش را نشان می‌دهد.معماری یعنی تصمیم‌گیریمعمار نرم‌افزار دائماً باید تصمیم بگیرد:چه چیزی الان مهم‌تر است؟چه چیزی را باید ساده نگه داشت؟کجا انعطاف‌پذیری ارزش هزینه‌اش را دارد؟چه پیچیدگی‌هایی واقعاً لازم هستند؟و چه چیزهایی فقط ظاهر حرفه‌ای دارند؟خیلی وقت‌ها بهترین تصمیم معماری، ساده‌ترین تصمیم است.ساختن برای امروز، نه آینده خیالیطبیعی است که هنگام طراحی سیستم به آینده هم فکر کنیم.اما یکی از اشتباهات رایج این است که سیستم را برای آینده‌ای خیالی طراحی کنیم.به نظرم هدف اصلی معماری این نیست که همه مشکلات پنج سال آینده را امروز حل کنیم.هدف این است که سیستم امروز را طوری بسازیم که هزینه تغییر فردا قابل تحمل باشد.پیچیدگی؛ دشمن پنهان پروژه‌هایکی از مهم‌ترین وظایف معمار، کنترل و حذف پیچیدگی‌های غیرضروری است.چون پیچیدگی کنترل‌نشده یکی از اصلی‌ترین دلایل شکست پروژه‌هاست.هر abstraction، هر لایه، هر سرویس و هر تکنولوژی جدید هزینه‌ای دارد.معماری خوب فقط اضافه کردن قابلیت‌ها نیست.خیلی وقت‌ها معماری خوب یعنی حذف کردن چیزهایی که واقعاً لازم نیستند.اگر بخواهیم معماری را خلاصه کنیمیک معمار نرم‌افزار باید بتواند:اجزای لازم برای حل مسئله را طراحی کندرابطه بین اجزا را مشخص کندو بر اساس نیازها، محدودیت‌ها و اولویت‌های واقعی تصمیم بگیردبهترین معماری، پیچیده‌ترین معماری نیست.معماری خوب، معماری‌ای است که تصمیم‌های درستی گرفته باشد.در پست‌های آینده سعی می‌کنم نگاه دقیق‌تری به معماری‌های مختلف، الگوهای رایج و کاربرد واقعی آن‌ها در پروژه‌ها داشته باشم.نه صرفاً از زاویه تئوری، بلکه از زاویه تجربه، محدودیت‌های واقعی و تصمیم‌هایی که واقعاً روی موفقیت یا شکست پروژه تأثیر می‌گذارند.</description>
                <category>حامد پارسا</category>
                <author>حامد پارسا</author>
                <pubDate>Sat, 16 May 2026 15:10:35 +0330</pubDate>
            </item>
                    <item>
                <title>اسکواد، چه اسم شیکی!</title>
                <link>https://virgool.io/@parsahmd/squad-history-ob9rlve24z7m</link>
                <description>خیلی وقت‌ها تغییر در سازمان‌ها این شکلی اتفاق می‌افتد:یک مفهوم جدید می‌آید،یک اسم جذاب و مدرن دارد،چند شرکت بزرگ هم از آن استفاده کرده‌اند،و ناگهان همه می‌خواهند همان را تکرار کنند.«Spotify این کار را کرده.»«فلان شرکت ساختارش را اسکواد کرده.»«پس حتماً جواب می‌دهد.»بالاخره آن‌ها بزرگ‌اند،حتماً می‌فهمند چه کار می‌کنند.اما چیزی که معمولاً فراموش می‌شود این است که:اصلاً مسئله چه بود؟قرار بود چه چیزی حل شود؟در مقاله قبلی درباره این صحبت کردم که چطور تیم‌های تخصصی، با وجود تمام مزیت‌هایشان، کم‌کم باعث شکل‌گیری وابستگی‌های پیچیده و جدا شدن تیم‌ها از یکدیگر شدند.از تیم‌های تخصصی تا اسکواد؛ آیا واقعاً بهتر شدیم؟خیلی وقت‌ها چیزی که در عمل اتفاق می‌افتد فقط این است که چند نفر را از تیم جدا می‌کنیم و اسم جدیدی روی آن می‌گذاریم.یک جزیره جدید متولد می‌شود.اما مشکل اصلی هنوز سر جایش است.قرار بود اسکواد مسئله مالکیت را حل کند،اما مدیر همچنان می‌خواهد همه تصمیم‌ها را بگیرد.قرار بود وابستگی کمتر شود،اما تیم هنوز برای هر تصمیم مهمی وابسته به تأییدهای بیرونی است.از طرف دیگر، جدا شدن تیم‌ها کم‌کم باعث می‌شود هر اسکواد مسیر خودش را برود.هر تیم ابزار خودش را دارد،الگوی توسعه خودش را دارد،و تجربه‌هایی تولید می‌کند که هیچ‌وقت وارد حافظه واقعی سازمان نمی‌شوند.چیزی که قبلاً تلاش کرده بودیم با تیم‌های تخصصی حل کنیم، دوباره برمی‌گردد:ساختارهای جدا از هم،کارهای تکراری،و دانشی که به‌جای تبدیل شدن به دارایی شرکت، فقط در ذهن آدم‌ها باقی می‌ماند.ایده اسکواد از کجا آمد؟وقتی تیم‌ها بزرگ‌تر شدند و تعداد پروژه‌ها بیشتر شد، کم‌کم مشکلی به وجود آمد که تقریباً نقطه مقابل اجایل بود:بروکراسی.چیزی که می‌تواند خیلی آرام، بدون اینکه متوجهش شویم، چرخه مرگ یک تیم نرم‌افزاری را شروع کند.تیم‌ها کم‌کم به گروه‌هایی جدا از هم تبدیل می‌شوند.هر گروه در مقابل گروه دیگر قرار می‌گیرد.ارتباط‌ها کمتر می‌شود،تشریفات بیشتر می‌شود،و کارها به‌جای حل شدن، بین تیم‌ها جابه‌جا می‌شوند.مالکیت خطاها و مشکلات کم‌کم گم می‌شود.وقتی مشکلی پیش می‌آید،همه دنبال این هستند که ثابت کنند مسئله از سمت آن‌ها نبوده است.پاسکاری بین تیم‌ها شروع می‌شود:«مشکل از بک‌اند است.»«زیرساخت آماده نبود.»«تیم محصول دیر اعلام کرد.»«فرانت‌اند اشتباه پیاده‌سازی کرده.»و هم‌زمان، چیزی که قبلاً یک تیم مشترک بود، کم‌کم تبدیل می‌شود به چند جزیره جدا از هم.روابط دوستانه کمتر می‌شود،سلسله‌مراتب پررنگ‌تر می‌شود،و رقابت‌های درون‌سازمانی شکل می‌گیرد.در چنین شرایطی، سرعت توسعه کاهش پیدا می‌کند؛نه به خاطر ضعف فنی،بلکه چون انرژی تیم به‌جای حل مسئله، صرف هماهنگی، دفاع، و عبور از لایه‌های مختلف تصمیم‌گیری می‌شود.ایده اسکواد دقیقاً از دل همین مشکل به وجود آمد.قرار بود تیم‌هایی ساخته شوند که بتوانند مستقل‌تر تصمیم بگیرند،وابستگی کمتری داشته باشند،و به‌جای پاسکاری مسئولیت، مالک واقعی یک مسئله باشند.اسکواد؛ راه‌حلی برای کاهش وابستگیمفهوم اسکواد بیشتر از همه با Spotify شناخته شد؛شرکتی که در سال‌های رشد سریعش با مشکلی روبه‌رو شد که بسیاری از شرکت‌های نرم‌افزاری تجربه می‌کنند:تعداد تیم‌ها بیشتر شده بود،پروژه‌ها هم‌زمان جلو می‌رفتند،و هماهنگی بین تیم‌ها کم‌کم داشت سرعت توسعه را از بین می‌برد.مدل‌های سنتی دیگر جواب نمی‌دادند.تیم‌های تخصصی، با وجود مزیت‌های فنی، باعث ایجاد وابستگی‌های زیاد شده بودند.هر تغییر کوچک باید بین چند تیم هماهنگ می‌شد.در نتیجه:تصمیم‌گیری کند می‌شد،تحویل قابلیت‌ها زمان زیادی می‌گرفت،و مسئولیت واقعی کارها بین تیم‌ها پخش می‌شد.ایده اسکواد تلاش می‌کرد این مشکل را حل کند.به‌جای اینکه تیم‌ها بر اساس تخصص جدا شوند،تیم‌هایی کوچک و مستقل شکل گرفتند که همه مهارت‌های لازم برای حل یک مسئله را در خودشان داشتند.هر اسکواد قرار بود:روی یک مسئله مشخص تمرکز کند،بتواند مستقل تصمیم بگیرد،و بدون وابستگی دائمی به تیم‌های دیگر، ارزش تولید کند.در واقع، اسکواد بیشتر از اینکه یک ساختار سازمانی باشد، تلاشی بود برای کم کردن اصطکاک در فرایند توسعه نرم‌افزار.اما همان‌طور که بعدها مشخص شد،ساختن تیم مستقل فقط با تغییر چارت سازمانی اتفاق نمی‌افتد.وقتی استقلال، خودش تبدیل به مشکل می‌شودوقتی تیم‌ها مستقل‌تر شدند، خطر جدیدی هم به وجود آمد.هر اسکواد کم‌کم می‌توانست به دنیای خودش تبدیل شود؛با ابزارها، تجربه‌ها، و شیوه‌های کاری مخصوص خودش.چیزی که قرار بود وابستگی را کم کند،در بعضی سازمان‌ها دوباره به شکل جدیدی از جدایی بین تیم‌ها تبدیل شد.و دقیقاً همین‌جا بود که مفهوم دیگری وارد ماجرا شد:Chapter.مفهومی که تلاش می‌کرد تعادل بین استقلال تیم‌ها و یکپارچگی سازمان را حفظ کند.شاید مسئله اصلی هیچ‌وقت فقط ساختن اسکواد نبود؛بلکه پیدا کردن تعادل بین استقلال و هماهنگی بود.</description>
                <category>حامد پارسا</category>
                <author>حامد پارسا</author>
                <pubDate>Tue, 12 May 2026 18:41:23 +0330</pubDate>
            </item>
                    <item>
                <title>از تیم‌های تخصصی تا Squadها؛ آیا واقعاً بهتر شدیم؟</title>
                <link>https://virgool.io/@parsahmd/%D8%A7%D8%B2-%D8%AA%DB%8C%D9%85-%D9%87%D8%A7%DB%8C-%D8%AA%D8%AE%D8%B5%D8%B5%DB%8C-%D8%AA%D8%A7-squad%D9%87%D8%A7-%D8%A2%DB%8C%D8%A7-%D9%88%D8%A7%D9%82%D8%B9%D8%A7%D9%8B-%D8%A8%D9%87%D8%AA%D8%B1-%D8%B4%D8%AF%DB%8C%D9%85-wvvn9g1nnnyi</link>
                <description>توسعه نرم‌افزار پدیده عجیبی است.از سال‌های گذشته خاطرات و داستان‌های زیادی در ذهنم مانده؛ از روزهای اولی که فکر می‌کردیم توسعه هر نرم‌افزاری نهایتاً یک هفته زمان می‌خواهد، تا امروز که برای تخمین یک تسک کوچک هم باید بارها همه‌چیز را بالا و پایین کنیم.اما شاید جالب‌تر از توسعه نرم‌افزار، توسعه‌ی تیم نرم‌افزار باشد.سال‌ها پیش، زمانی که بیشتر درگیر پروژه‌های سفارشی و مذاکره با کارفرماها بودم، یکی از بحث‌های تکراری همیشه زمان تحویل پروژه بود.من می‌گفتم این پروژه حداقل ده ماه زمان نیاز دارد و کارفرما می‌گفت:«خب ۵ نفر دیگر اضافه کنید و دو ماهه جمعش کنید!»آن زمان همیشه یک مثال آماده در جیبم داشتم؛ مثالی که سال‌ها قبل در یکی از فروم‌ها خوانده بودم:برای به دنیا آمدن یک بچه، به یک زن و ۹ ماه زمان نیاز است.نمی‌شود ۹ زن را کنار هم گذاشت تا بچه در یک ماه متولد شود.راستش را بخواهید روی نحوه گفتنش هم خیلی کار کرده بودم!معمولاً هم تأثیر خودش را می‌گذاشت و طرف مقابل را به فکر فرو می‌برد.تا اینکه یک‌بار کسی جواب جالبی داد:«درسته… ولی میشه با ۹ زن، در ۹ ماه، ۹ بچه به دنیا آورد.»و حقیقت این است که آن جواب، از خیلی از بحث‌های مدیریتی عمیق‌تر بود.چون مسئله فقط تعداد آدم‌ها نیست.مسئله این است که چه بخش‌هایی از توسعه نرم‌افزار قابل موازی‌سازی هستند و چه بخش‌هایی نیستند.همین سؤال ساده، ما را به یکی از پیچیده‌ترین چالش‌های تیم‌های نرم‌افزاری می‌رساند:آیا بزرگ‌تر شدن تیم، الزاماً خروجی را بیشتر می‌کند؟در این نوشته می‌خواهم کمی درباره پاسخ‌های مختلفی که صنعت نرم‌افزار به این سؤال داده صحبت کنم؛ از تیم‌های محصول‌محور گرفته تا مرزهایی که بین تیم‌ها شکل می‌گیرد و گاهی خودشان تبدیل به بخشی از مشکل می‌شوند.تیم‌های اولیه؛ وقتی رشد یعنی اضافه کردن آدم بیشتراولین پاسخ صنعت نرم‌افزار به مشکل رشد، خیلی ساده بود:اگر پروژه بزرگ‌تر شد، آدم بیشتری اضافه کن.مدل ذهنی هم کاملاً منطقی به نظر می‌رسید.وقتی یک نفر نمی‌تواند کل پروژه را جلو ببرد، کار را تقسیم می‌کنیم و هر بخش را به یک نفر می‌دهیم.در ظاهر همه‌چیز عالی بود:سرعت بیشترتقسیم مسئولیتموازی‌سازی کارهافشار کمتر روی افراداین مدل حتی قبل از شکل‌گیری تخصص‌های امروزی وجود داشت؛ زمانی که هنوز فرانت‌اند، بک‌اند، DevOps یا Infrastructure به شکل امروزی از هم جدا نشده بودند.در بسیاری از تیم‌ها، هر توسعه‌دهنده مسئول بخشی از پروژه می‌شد:یکی ماژول کاربران را می‌نوشتیکی گزارش‌ها رایکی سیستم پرداخت راو یکی هم دیتابیس را جمع می‌کرددر نگاه اول، همه‌چیز منطقی و قابل مدیریت بود.اما کم‌کم یک مشکل خودش را نشان می‌داد:نرم‌افزار فقط مجموعه‌ای از بخش‌های جدا از هم نیست.هر بخش به بخش دیگر وابسته است.تصمیم‌های کوچک در یک قسمت می‌توانند رفتار قسمت‌های دیگر را تغییر دهند.هر عضو جدید تیم، علاوه بر کدی که می‌نویسد، یک هزینه پنهان هم وارد سیستم می‌کند:هزینه ارتباط.هرچه تعداد افراد بیشتر می‌شد:هماهنگی سخت‌تر می‌شددانش پروژه پخش‌تر می‌شدتصمیم‌گیری کندتر می‌شدو اختلاف در سبک توسعه بیشتر خودش را نشان می‌دادکم‌کم تیم‌ها متوجه شدند که اضافه کردن نیرو همیشه به معنی افزایش سرعت نیست.گاهی حتی برعکس، پروژه با وجود آدم‌های بیشتر، کندتر هم می‌شد.سال‌ها بعد، فرد بروکس در کتاب معروف The Mythical Man-Month این مسئله را با جمله‌ای معروف توضیح داد:Adding manpower to a late software project makes it later.اضافه کردن نیرو به یک پروژه عقب‌افتاده، ممکن است آن را حتی عقب‌تر بیندازد.تولد تیم‌های تخصصی؛ وقتی مرزها شکل گرفتندبا بزرگ‌تر شدن پروژه‌ها، دیگر تقسیم ساده‌ی ماژول‌ها کافی نبود.تکنولوژی‌ها پیچیده‌تر شدند و هر بخش از توسعه نیاز به دانش عمیق‌تری پیدا کرد.دیگر نمی‌شد انتظار داشت یک نفر هم رابط کاربری طراحی کند، هم API بنویسد، هم دیتابیس را مدیریت کند، هم Deployment انجام دهد و هم Performance سرورها را زیر نظر بگیرد.اینجا بود که تیم‌های تخصصی کم‌کم شکل گرفتند:تیم Frontendتیم Backendتیم Infrastructureتیم DevOpsتیم QAو بعدتر تیم‌های Data، Security، SRE و …این مدل، در مقایسه با ساختارهای قبلی، یک پیشرفت بزرگ محسوب می‌شد.تخصص باعث شد کیفیت بالاتر برود، ابزارها حرفه‌ای‌تر شوند و افراد بتوانند روی حوزه‌ی مشخصی عمیق شوند.برای مدتی به نظر می‌رسید صنعت بالاخره پاسخ درست را پیدا کرده است.اما مشکل جدیدی آرام‌آرام خودش را نشان داد.وقتی تیم‌ها بر اساس تخصص از هم جدا شدند، فقط مسئولیت‌ها جدا نشدند؛کم‌کم طرز فکرها هم جدا شد.هر تیم زبان خودش را پیدا کرد.هر تیم اولویت‌های خودش را داشت.و هر تیم دنیا را از زاویه‌ی خودش می‌دید.تیم Backend روی Performance و Stability حساس بود.Frontend بیشتر درگیر تجربه کاربری و سرعت توسعه بود.DevOps به Deployment و Reliability فکر می‌کرد.Infrastructure دغدغه‌ی هزینه، مانیتورینگ و منابع را داشت.در ظاهر همه برای یک محصول کار می‌کردند، اما در عمل گاهی شبیه کشورهایی بودند که فقط از طریق مرزها با هم ارتباط دارند.جالب اینجاست که این جدایی فقط بین تخصص‌ها باقی نماند.بعد از مدتی، حتی داخل یک تخصص هم مرزهای جدید شکل گرفت.مثلاً در شرکت‌هایی که چند محصول داشتند:هر محصول تیم Frontend خودش را داشتتیم Backend خودش راو استانداردها کم‌کم از هم فاصله می‌گرفتنددو تیم Frontend داخل یک شرکت ممکن بود:ساختار پروژه متفاوتی داشته باشندروش State Management متفاوتی انتخاب کننداستانداردهای تست متفاوتی داشته باشندو حتی درباره ساده‌ترین تصمیم‌های معماری هم نگاه کاملاً متفاوتی پیدا کننددر این مرحله، مشکل دیگر فقط توسعه نرم‌افزار نبود.مشکل، توسعه‌ی سازمان نرم‌افزاری شده بود.و شاید این همان جایی باشد که معماری نرم‌افزار دیگر فقط یک مسئله فنی نیست؛بلکه مستقیماً به ساختار تیم‌ها، ارتباطات و فرهنگ سازمان وابسته می‌شود.اسکوادها؛ وقتی تیم‌ها حول محصول شکل گرفتندبعد از سال‌ها تجربه‌ی تیم‌های تخصصی، صنعت نرم‌افزار کم‌کم متوجه یک مسئله مهم شد:مشکل فقط تخصص نیست، مشکل فاصله‌ی بین تخصص‌هاست.در بسیاری از شرکت‌ها، فرآیند توسعه شبیه یک خط تولید شده بود.Frontend منتظر Backend بود.Backend منتظر Infrastructure بود.QA منتظر همه بود.و در نهایت هر مشکلی بین تیم‌ها دست به دست می‌شد تا بالاخره یک نفر مسئولیتش را قبول کند.اینجا بود که مدل تیم‌های محصول‌محور یا همان Squadها محبوب شد.ایده در ظاهر خیلی جذاب بود:به جای اینکه تیم‌ها بر اساس تخصص جدا شوند، یک تیم کوچک تشکیل بدهیم که همه چیز لازم برای توسعه‌ی یک محصول را داخل خودش داشته باشد.مثلاً:چند Frontend Developerچند Backend DeveloperQAProduct Ownerشاید DevOps یا Designerهمه داخل یک تیم.هدف این بود که تیم بتواند بدون وابستگی دائمی به بخش‌های دیگر، یک محصول یا Feature را از ابتدا تا انتها جلو ببرد.این مدل چند مزیت بزرگ داشت:ارتباطات سریع‌تر شدتصمیم‌گیری ساده‌تر شدمسئولیت‌پذیری بیشتر شدو تیم‌ها حس مالکیت واقعی روی محصول پیدا کردنددر خیلی از شرکت‌ها، این مدل واقعاً سرعت توسعه را بالا برد.اما باز هم، یک مشکل جدید آرام‌آرام خودش را نشان داد.وقتی هر Squad مستقل‌تر شد، کم‌کم فرهنگ فنی خودش را هم ساخت.هر تیم ابزارهای خودش را انتخاب می‌کرد.هر تیم استانداردهای خودش را تعریف می‌کرد.و هر تیم به مرور شبیه یک شرکت کوچک داخل شرکت اصلی می‌شد.مثلاً دو تیم Frontend داخل یک سازمان ممکن بود:ساختار پروژه متفاوتی داشته باشندروش مدیریت State متفاوتی استفاده کننداستانداردهای تست متفاوتی داشته باشندDesign System را متفاوت پیاده‌سازی کنندو حتی نگاه متفاوتی به Clean Code داشته باشنددر کوتاه‌مدت این استقلال جذاب بود، چون تیم‌ها سریع‌تر حرکت می‌کردند.اما در بلندمدت، هزینه‌ی پنهان خودش را نشان می‌داد:Fragmentation یا تکه‌تکه شدن سازمان فنی.کم‌کم:جابه‌جایی نیرو بین تیم‌ها سخت‌تر می‌شددانش بین تیم‌ها منتقل نمی‌شدکدها قابل استفاده مجدد نبودندو هر تیم دوباره بخشی از مشکلات را از اول حل می‌کردجالب اینجاست که صنعت نرم‌افزار هر بار برای حل یک مشکل، ساختار جدیدی می‌ساخت؛اما همان ساختار، بعد از مدتی مشکل تازه‌ای ایجاد می‌کرد.شاید چون مسئله اصلی فقط ساختار تیم‌ها نیست.بلکه نحوه‌ی ارتباط، اشتراک دانش و ایجاد تعادل بین استقلال و هماهنگی است.جمع‌بندی؛ شاید مسئله اصلی خودِ تیم‌ها نیستنداگر بخواهم صادقانه بگویم، فکر نمی‌کنم صنعت نرم‌افزار هنوز پاسخ قطعی برای ساختار ایده‌آل تیم‌ها پیدا کرده باشد.ما سال‌ها تلاش کردیم با بزرگ‌تر کردن تیم‌ها سرعت را بیشتر کنیم و فهمیدیم ارتباطات می‌توانند از خود توسعه سخت‌تر شوند.بعد تخصص‌ها را جدا کردیم تا هرکس روی حوزه‌ی خودش عمیق شود، اما دیوارهایی بین تیم‌ها ساختیم که گاهی از دیوارهای فنی هم ضخیم‌تر شدند.بعد سراغ Squadها و تیم‌های محصول‌محور رفتیم تا وابستگی‌ها کمتر شوند و تیم‌ها مستقل‌تر عمل کنند؛ اما این بار خطر Fragmentation و چندپاره شدن فرهنگ فنی را تجربه کردیم.شاید مسئله اصلی این باشد که توسعه نرم‌افزار، فقط توسعه‌ی کد نیست.ما در واقع همزمان داریم:سیستم فنی می‌سازیمسیستم انسانی می‌سازیمو سیستم ارتباطی می‌سازیمو پیچیدگی واقعی معمولاً از جایی شروع می‌شود که این سه سیستم روی هم اثر می‌گذارند.به مرور زمان، شرکت‌های بزرگ فهمیدند که برای جلوگیری از این چندپارگی، فقط داشتن Developer خوب کافی نیست.آن‌ها شروع کردند به ساختن لایه‌های جدیدی از هماهنگی:ChapterهاGuildهاPlatform TeamهاArchitecture ReviewهاDesign SystemهاShared Standardsو حتی نقش‌هایی شبیه Engineering Architect یا Principal Engineerنه برای کنترل تیم‌ها، بلکه برای جلوگیری از این که هر تیم تبدیل به یک جزیره مستقل شود.شاید مهم‌ترین چالش تیم‌های نرم‌افزاری امروز همین باشد:چطور می‌توان هم استقلال تیم‌ها را حفظ کرد و هم انسجام فنی سازمان را از بین نبرد؟و احتمالاً پاسخ نهایی، نه در ساختارهای عجیب مدیریتی است و نه در فرآیندهای سنگین.بلکه در ایجاد فرهنگی است که آدم‌ها را تشویق کند:دانش را به اشتراک بگذارندمسئولیت مشترک داشته باشندو نرم‌افزار را به چشم یک سیستم واحد ببینند، نه مجموعه‌ای از مرزها و قلمروها.شاید در نهایت، موفق‌ترین تیم‌های نرم‌افزاری آن‌هایی نباشند که بیشترین تعداد Developer را دارند؛بلکه آن‌هایی باشند که بهتر از بقیه می‌توانند با هم فکر کنند.</description>
                <category>حامد پارسا</category>
                <author>حامد پارسا</author>
                <pubDate>Sat, 09 May 2026 16:31:07 +0330</pubDate>
            </item>
            </channel>
</rss>