در اولین تلاش برای ساخت یک عامل، طبیعی است که تمام وظایف را به همان یک عامل واگذار کنید: یک مدل، چند ابزار و مقداری حافظه. این ترکیب برای بسیاری از کارها کفایت میکند. اما با گسترش و پیچیدهتر شدن ابعاد پروژه، این پرسش مطرح میشود که آیا همچنان باید همهچیز را درون یک عامل متمرکز نگه داشت یا بهتر است کارها را میان چند عامل تخصصی تقسیم کرد. پاسخ به این پرسش بیش از آنکه به «پیشرفتهتر» به نظر رسیدن یک معماری خاص بستگی داشته باشد، تابع پیچیدگی خودِ پروژه است.
عامل تنها چیست
در سادهترین تعریف، یک عامل متشکل از یک مدل زبانی، توان تصمیمگیری، چند ابزار کاربردی و حافظهای برای پیگیری روند انجام کار است. عامل تنها تمام این امکانات را بهطور یکجا در اختیار دارد و وظایف را بهصورت متوالی پیش میبرد: ورودی را درک میکند، تصمیم میگیرد، ابزار مناسب را فرا میخواند و در نهایت نتیجه را بازمیگرداند.
بزرگترین مزیت این رویکرد، سادگی بیاندازهٔ آن است؛ یعنی داشتن یک مسیر مشخص، یک حافظه واحد و یک نقطه متمرکز برای اشکالزدایی. در سناریوهای سادهای که تنها به چند ابزار محدود نیاز است، عامل تنها معمولاً بهترین گزینه به شمار میرود و اضافه کردن عاملهای بیشتر، دستاوردی جز افزایش بار پردازشی و پیچیدگی بیمورد نخواهد داشت.
وقتی یک عامل تنها کم میآورد
با افزایش پیچیدگی وظایف، عامل تنها بهسرعت به گلوگاه سامانه تبدیل میشود. برای نمونه، کاربری را تصور کنید که قصد برنامهریزی یک سفر را دارد: این کار شامل جستوجوی پرواز، یافتن هتل مناسب و پیشنهاد فعالیتهای تفریحی است. هر یک از این اقدامات به ابزارها و تخصصهای متفاوتی نیاز دارند و هیچ لزومی ندارد که حتماً بهصورت پیاپی انجام شوند. با این حال، یک عامل تنها مجبور است تمام این مراحل را یکی پس از دیگری و در یک پنجرهٔ زمینهٔ شلوغ و انباشته از اطلاعات پیش ببرد. دقیقاً در چنین نقطهای است که ضرورت تقسیم کار آشکار میشود.
الگوی هماهنگکننده-کارگر
متداولترین شیوه برای سازماندهی ساختارهای چندعاملی، بهرهگیری از یک الگوی مبتنی بر سه نقش است. در این الگو، یک هماهنگکننده درخواست اولیه را دریافت، آن را تحلیل و راهبرد کلی را مشخص میکند. سپس اجرای کار را به چند کارگر تخصصی واگذار میکند که هرکدام بخش مجزایی از پروژه را پیش میبرند. از آنجا که این کارگران مستقل از یکدیگر عمل میکنند، میتوانند بهطور همزمان فعال باشند. در نهایت، نتایج بهدستآمده تجمیع شده و در قالب پاسخی یکپارچه ارائه میشوند.
در نمونهٔ برنامهریزی سفر، هماهنگکننده کار را میان سه کارگر تقسیم میکند: یکی برای پرواز، دیگری برای هتل و سومی برای فعالیتهای تفریحی. هر سه کارگر فرآیند جستوجو را بهطور همزمان آغاز میکنند و خروجی را بازمیگردانند. مزایای این روش کاملاً آشکار است: تخصص کارگران افزایش مییابد زیرا تمرکز هرکدام تنها بر یک وظیفه معطوف است؛ کارهای مستقل به موازات یکدیگر پیش میروند و سرعت کلی فرآیند افزایش مییابد؛ و در نهایت، اضافه کردن یک قابلیت جدید دیگر نیازی به بازنویسی کلِ یک عامل غولپیکر ندارد، بلکه بهسادگی با افزودن یک کارگر جدید میسر میشود.
چرا کارگرهای موازی امن هستند
در نگاه نخست، اجرای همزمان چندین کارگر ممکن است مخاطرهآمیز به نظر برسد؛ مگر نه اینکه ممکن است در کار یکدیگر تداخل ایجاد کنند؟ اما در عمل چنین نیست و دلیل آن، یک قاعدهٔ طراحی بنیادین است که شایسته است بهروشنی بیان شود: تمامی کارگرها «بدون حالت» (stateless) هستند. یک کارگر بین فراخوانیهای مختلف هیچ اطلاعاتی را نزد خود نگه نمیدارد؛ هر آنچه نیاز دارد در قالب ورودی به او سپرده میشود و پس از پایان کار، نتیجه را بازمیگرداند، بیآنکه خاطره یا اثری از اجرای خود باقی بگذارد. دو کارگر که وظیفهٔ مشابهی را انجام میدهند، هیچ حالت پنهان مشترکی ندارند؛ از این رو، اجرای همزمانشان چیزی را خراب نمیکند. اگر یک ورودی یکسان را دو بار به کارگر بدهید، روی هر ماشینی که اجرا شود، دقیقاً همان خروجی را دو بار تحویل خواهید گرفت.
دقیقاً همین ویژگی است که تقسیم کار را مقیاسپذیر میکند. از آنجا که کارگر هیچ حالتی را با خود حمل نمیکند، میتوان ده نسخه از آن را با همان امنیت و اطمینانِ یک نسخه اجرا کرد؛ با افزایش بار کاری، نسخههای بیشتری اضافه نمود و هر نتیجه را صرفاً با اجرای دوبارهٔ ورودیاش بازتولید کرد. آن حالتی که واقعاً باید پایدار و ماندگار بماند — یعنی خواست دقیق کاربر و چگونگی پیشرفت کل کار — بهجای آنکه در دل کارگرها پراکنده باشد، در یک فضای مشترک ذخیره میشود که هماهنگکننده آن را مدیریت میکند. اگر کارگرها را بدون حالت نگه دارید، دشوارترین چالشهای اجرای موازی تا حد زیادی ناپدید میشوند.
کدام الگو را انتخاب کنیم؟
انتخاب میان این دو رویکرد، تصمیمی مهندسی و مبتنی بر نیازهای فنی است، نه ترجیحات سلیقهای. اگر شرایط زیر برقرار است، عامل تنها گزینهٔ بهتری خواهد بود:
- فرایند کاری ساده و کوتاه باشد.
- تعداد ابزارها محدود باشد و تداخلی میان آنها پیش نیاید.
- مراحل کار به یکدیگر وابسته باشند و موازیسازی ارزش افزودهای ایجاد نکند.
در مقابل، تقسیم کار میان چند عامل زمانی توصیه میشود که:
- به تخصصهای گوناگون و مجزایی نیاز باشد که نباید با هم ترکیب شوند (مانند فرآیند مستقل جستوجوی پرواز نسبت به جستوجوی هتل).
- بخشهایی از کار از یکدیگر مستقل باشند و اجرای موازی آنها باعث افزایش سرعت شود.
- تصمیم داشته باشید سامانه را با افزودن نقشهای جدید توسعه دهید، بدون آنکه هربار نیازی به دستکاری کل معماری باشد.
بهای بهکارگیری چند عامل
تقسیم وظایف بیهزینه نیست. با ورود چند عامل به میدان، مدیریت هماهنگی میان آنها الزامی میشود: تخصیص وظایف به عوامل مختلف، نحوهٔ ترکیب و یکپارچهسازی نتایج، و چگونگی برخورد با خطای احتمالی هر کارگر. پذیرش این پیچیدگی جدید تنها زمانی منطقی است که مقیاس پروژه به اندازهٔ کافی بزرگ باشد. یک قاعدهٔ طلایی در این زمینه وجود دارد: کار را با سادهترین ساختاری که پاسخگوی نیازهاست آغاز کنید و تنها زمانی به سراغ تقسیم کار بروید که عامل تنها واقعاً به سقف کارایی خود رسیده باشد.
تقسیم زودهنگام وظایف همانقدر به پروژه آسیب میزند که به تأخیر انداختن بیهودهٔ آن. هنر اصلی یک مهندس، تشخیص درست همین زمان انتقال است؛ نقطهای که عبور از آن را نه جذابیتهای ظاهری معماریها، بلکه پیچیدگی واقعی خود پروژه تعیین میکند.