چگونه برای پروژه‌ های ۱ تا ۳ نفره قیمت‌ گذاری کنیم؟

پروژه نرم افزاری مثل سفارش پیتزا نیست که بشود در چند ثانیه قیمتش را حدس زد. هر پروژه نیاز به تحلیل، تعریف دقیق، تخمین زمان، درک ارزش، بررسی ریسک ها و محاسبه جزئیات دارد. اینکه بدون شناخت کامل پروژه، فقط یک ضرب ساده «تعداد ساعت × نرخ ساعتی» را به عنوان نسخه نهایی ارائه دهیم، نه حرفه ای است و نه به نفع فعالان این صنعت.

در اسکرین شاتی که مشاهده میشود، نویسنده پست در لینکدین از دوستانش درخواست میکند در مورد قیمت گذاری یک پروژه وب با او همفکری کنند. اما درست در بخش کامنت ها، یکی از کاربران بدون اینکه به هیچ یک از اصول حرفه ای قیمت گذاری، تعریف پروژه، سطح پیچیدگی، ریسک ها، تسک ها، یا حتی ساختار تیم اشاره کند، یک عدد خام و بسیار ساده ارائه می‌دهد:
«ساعتی کار بدین، مثلا ۲۰۰ ساعت به ازای هر ساعت ۱ تومن.»
این دقیقا همان سوتی بزرگ است؛ سوتی ای که نه تنها برای تیم های حرفه ای گران تمام می‌شود، بلکه باعث می‌شود برداشت عمومی از ارزش کار نرم افزاری به شکل خطرناک و اشتباه کاهش پیدا کند.
پروژه نرم افزاری مثل سفارش پیتزا نیست که بشود در چند ثانیه قیمتش را حدس زد. هر پروژه نیاز به تحلیل، تعریف دقیق، تخمین زمان، درک ارزش، بررسی ریسک ها و محاسبه جزئیات دارد. اینکه بدون شناخت کامل پروژه، فقط یک ضرب ساده «تعداد ساعت × نرخ ساعتی» را به عنوان نسخه نهایی ارائه دهیم، نه حرفه ای است و نه به نفع فعالان این صنعت.
این مقاله، دقیقا به همین دلیل و از دل همین سوتی شکل گرفته است. برای اینکه نشان دهد چرا قیمت گذاری نرم افزار نمیتواند «حدسی و سرانگشتی» باشد، و چرا تیم های ۱ تا ۳ نفره باید از یک روش علمی، منطقی و قابل دفاع استفاده کنند.
اینکه برخلاف کامنت ناشیانه زیر آن پست، قیمت گذاری واقعی شامل چندین مرحله مهم است که اگر نادیده گرفته شوند، نتیجه آن برای تیم، برای مشتری و برای کل بازار مخرب خواهد بود.
قیمت گذاری پروژه های نرم افزاری برای تیم های کوچک
قیمت گذاری پروژه های نرم افزاری یک مرحله مهم و تأثیرگذار در شروع همکاری است. تیم های کوچک که معمولا بین 1 تا 3 نفر هستند، باید از روش های ساده و دقیق برای تخمین قیمت استفاده کنند تا هم هزینه های خود را پوشش دهند و هم اعتماد مشتری حفظ شود. قیمت گذاری درست، زمینه مدیریت زمان، کنترل ریسک و تضمین سود تیم را فراهم می کند.
شناخت دقیق نیاز ها
اولین گام، درک کامل از خواسته های مشتری است. هر نقطه مبهم می تواند زمان انجام پروژه را چند برابر کند. این موارد باید شفاف باشند: توضیح کامل امکانات، تعداد ماژول ها و بخش ها، فناوری های مورد نیاز، ارتباط بخش های مختلف و سطح امنیت و زیرساخت باشد.
نادیده گرفتن این مرحله معمولا باعث ضرر مالی می شود.
تخمین زمان واقعی
تیم کوچک نباید خوشبینانه قیمت دهد. هر بخش باید جداگانه زمان بندی شود: تحلیل، طراحی، توسعه، تست و اصلاحات.
بهتر است زمان تخمینی را ضرب در 1.3 کنید تا ریسک تاخیر پوشش داده شود.
تعیین مدل قیمت: ساعتی یا ثابت
مدل ساعتی
در این روش مبلغ مشخصی برای هر ساعت تعریف می شود. مناسب برای پروژه های مبهم است.
مزیت: انعطاف بالا
عیب: نامشخص بودن مبلغ نهایی برای مشتری
مدل ثابت
مناسب برای پروژه های کوچک و مشخص.
مشتری از اول مبلغ نهایی را می داند.
تیم باید حدود 20 درصد برای تغییرات احتمالی لحاظ کند.
توجه به ارزش پروژه
قیمت فقط زمان نیست. گاهی پروژه ارزش بسیار بزرگتری برای مشتری ایجاد می کند: افزایش فروش، اتومات کردن فرآیند های زمان بر، کاهش هزینه های نیروی انسانی، پروژه های با ارزش اقتصادی بالا باید قیمت بالاتری داشته باشند.
ارزیابی ریسک ها
ریسک ها مستقیما روی هزینه تأثیر دارند. ریسک های رایج برای تیم های کوچک: تغییر نیاز های مشتری، نیاز به یادگیری فناوری جدید، وابستگی به سرویس های خارجی، محدودیت زمانی، ابهام در داده ها.
قیمت باید بخشی برای پوشش این موارد داشته باشد.
روش محاسبه ساده برای تیم های 1 تا 3 نفر

  1. زمان کل را حساب کنید
  2. نرخ ساعتی هر نفر را مشخص کنید
  3. 20 تا 30 درصد ریسک اضافه کنید
  4. 10 تا 20 درصد برای پشتیبانی بعد از تحویل بگذارید
  5. مبلغ نهایی را رند کنید
    نمونه:
    اگر پروژه 120 ساعت زمان ببرد با نرخ 300 هزار تومان:
    • هزینه پایه: 36 میلیون
    • ریسک 20 درصد: 7 میلیون
    • پشتیبانی 10 درصد: 3.6 میلیون
    • مبلغ نهایی: حدود 46 میلیون تومان
    قرارداد شفاف
    قرارداد واضح اختلافات را کاهش می دهد. باید شامل این موارد باشد: محدوده دقیق کار، زمان بندی، تعداد دفعات اصلاح، شیوه پرداخت، شرایط فسخ، پشتیبانی.
    نحوه ارائه قیمت
    نحوه بیان قیمت به اندازه عدد آن مهم است. وقتی روند، زمان، چالش ها و دلیل قیمت واضح توضیح داده شود، احتمال پذیرش آن بالاتر می رود. تیم کوچک باید منظم و قابل اعتماد دیده شود.

برنامه ریزی برای شکست

در دسترس پذیر بودن یک نرم افزار ارتباط مستقیمی با نوع معماری دارد. یکی از بخش های تاثیر گذار در مبحث دسترس پذیری، مدیریت خطاها، اشتباهات و شناخت دقیق مسیرهای منجر به خاموشی سیستم است.
یکی از دغدغه های معماران نرم افزار، مدیریت اشتباهات، خطاها و درنهایت شکستهای سیستم است. این مساله به قدری اهمیت دارد که یک بخش کامل در کتاب Software architecture in practice نوشته ی Paul Clements را به خود اختصاص داده است.

مدیریت خطاها همچنین بخشی زمانبر، پرهزینه اما به همان اندازه پرفایده از فرآیند توسعه و نگهداری نرم افزار است که باید در لایه ی معماری به آن پرداخته شود.
اما قبل از اینکه وارد مبحث اصلی شوم، مایلم با مفاهیمی که شاید برای شما و من که بخصوص در ایران فعالیت میکنیم تازگی داشته باشد شروع کنم. این مفاهیم به تفاوت های اساسی بین واژه های اشتباه و خطا می پردازد که میتواند دید ما را به معماری سیستم در لایه تحلیل بهبود بخشد.
یک تعریف ساده اما بسیار کلیدی:
مجموعه ای از اشتباهات باعث ایجاد خطا میشوند. تکرار و تداوم خطاها باعث شکست سیستم میشود.
بنابراین از نظر من یک اشتباه به خودی خود و به تنهایی شاید مهم نباشد. احتمالا اصلا دیده هم نمیشود و از زیر چشم تحلیلگران، توسعه دهندگان، تک لیدها و حتی QA عبور کرده باشد. اما توالی اشتباهات در یک سیستم قطعا منجر به بروز خطا خواهد شد. سیستم های پیچیده معمولا از جانب اشتباهات تکراری، ساده و کوچک شکست میخورند.
در دنیای امروز که اعتقاد دارم مرز بین تکنولوژی های فرانت اند و بک اند دیگر مثل دهه های قبل خیلی قابل تفکیک نیست، اشتباهات فرانت هم در بروز خطا و شکست در بک اند و در نهایت کل سیستم موثر است. برای شما مثالی میزنم:
تصور کنید در یک سیستم توسعه داده شده با React شما کلیدی دارید که با کلیک بر روی آن سرویسی فراخوانی میشود. تا آنجا که به کاربرنهایی و آنچه بر روی مانیتور خود میبیند مربوط است، اگر با یکبار کلیک بر روی این کلید، تا زمان دریافت Response (درست یا غلط) کلید Disable نشود، کاربر میتواند به طور مداوم روی آن کلیک کند و میتوانید حدس بزنید که اتفاقی خواهد افتاد: بالا رفتن بی دلیل بار ریکوئستها به سمت سرور و در نهایت بروز خطا در بهترین حالت و یا کرش کردن سیستم در بدترین حالت و از دسترس خارج شدن سیستم.
هرچند که برای این موضوع روشهای متداولی در بک اند مانند Rate limiting و روشهای متنوع دیگری وجود دارد که از بروز این اتفاق جلوگیری کند، اما در اینجا یک اشتباه در فرانت صورت گرفته. چون طبق آنچه ما از فرآیندهای کاری یک تیم نرم افزاری میدانیم، فارغ از اینکه آیا تیم بک اند کار خود را بلد است و میداند کجا باید از Rate limit استفاده کند، توسعه دهنده فرانت هم باید کار خود را در نهایت ظرافت و وسواس پیش ببرد. پیش فرض هردو تیم باید این باشد که تیم مقابل ممکن است اشتباه کند پس ما باید تسک جاری را با رعایت حداکثر احتمالات ممکن تمام کنیم.
در سناریوی بالا غیرفعال نکردن کلید فراخوانی سرویس در لایه فرانت زمانی که ریکوئست ارسال میشود، لزوما یک خطا نیست، اما حتما یک اشتباه است.
روشن کردن یک نخ سیگار در انبار کاه و روشن کردن همان نخ سیگار در یک بیابان پیامدهای خیلی متفاوتی خواهد داشت. هنر معمار نرم افزار در برنامه ریزی برای شکستهای سیستم، هدایت تیم ها و تحلیلگران به سمتی است که کمترین خسارت ممکن حتی در صورت بروز برخی اشتباهات رخ دهد.
چنین اشتباهاتی معمولا از دید تحلیلگران و حتی تیم QA پنهان هستند اما من معتقدم مسئولیت مستقیم آن برعهده ی Code Reviewer و تک لید تیم فنی ست.
از مهمترین موضوعات در ساخت سیستمهایی با قابلیت دسترس پذیری بالا، درک ماهیت شکست هایی است که ممکن است در حین کار رخ دهد. وقتی به ماهیت شکست ها پی بردیم، میتوانیم استراتژیهای کاهش خسارت را در نرم افزار فراهم کنیم.
علت شکست را خطا میگوییم. به طور مشخص لغت fault به خطا اشاره میکند. حالا این خطا میتواند دلایل داخلی یا خارجی داشته باشد. حالت های میانی بین وقوع خطا و وقوع یک شکست را اشتباهات مینامیم که به طور مشخص با لغت errors ساخته میشوند.
ما همیشه به اشتباه خطاها را errors توصیف میکنیم، در حالی که خطا یک fault در سیستم است که میتواند حاصل چندین error یا اشتباه باشد.
محاسبه دسترس پذیری
تمام این مباحث برای بالابردن امکان در دسترس بودن سیستم است. ممکن است شما برای فروش یک سرویس یا سیستم مجبور به امضای یک SLA (توافق سطح سرویس) باشید. اگر در هر صورتی نتوانید یک SLA خود ارائه کنید، احتمالا بیزینس شما که بر مبنای آن سیستم بناشده است به ورشکستگی میرسد.
درک تمایز بین اشتباهات و خطاها در زمان معماری سیستم میتواند ما را به طراحی نرم افزار برساند که در برابر شکستهای سیستمی مقاوم باشد.اما برای اینکه بسنجیم یک سیستم نرم افزاری چقدر برابر شکست ها مقاوم است فرمولی وجود دارد:
MTBF = میانگین زمان بین شکست ها
MTTR = میانگین زمان ترمیم

این فرمول باید به این صورت تفسیر شود که هنگام فکر کردن درباره ی دسترس پذیری، باید راجع به چیزی فکر کنید که موجب شکست سیستم شما میشود، احتمال وقوع آن شکست چیست و باید در یک مدت معین ترمیم شود.

معماری نرم افزار یا تفکر سیستمی؟

تفاوت بنیادی بین معماری نرم افزار و تفکر سیستمی از یک منظر کاربردی آغاز میشود. اما واقعا چه تفاوتی بین معماری نرم افزار با تفکر سیستمی وجود دارد و درک این تفاوت چه فایده ای برای ما خواهد داشت؟
در یکی از پروژه های مهم شرکت که به محصولی استراتژیک ختم میشود، تیم توسعه با تیم محصول دچار یک مشکل اساسی شد. تیم توسعه معتقد بود جریان تولید محصول به دلیل فقدان تفکر سیستمی منحرف شده و ایرادات اساسی در پروژه وجود دارد. ادامه ی این اختلاف منجر به توقف موقت پروژه برای ارزیابی مشکل شد. آنچه از دید من بعنوان تک لید تیم توسعه رخ داده، حذف تفکر سیستمی و پرداختن جزئی به معماری نرم افزار در این محصول بود که به بهانه ی توسعه ی با متدولوژی اجایل اتفاق افتاد.
این موضوع بهانه ای شد برای نوشتن این مقاله. در واقع من معتقدم بخش بزرگی از تعارضات بین تیم های توسعه و محصول از عدم درک تفاوت های ذاتی بین معماری نرم افزار و تفکر سیستم است.
از منظر معماری نرم افزار، ساختار داخلی یک سیستم نرم افزاری اهمیت دارد. اینکه ماژولها، سرویسها، لایه ها و قراردادها بین بخش های مختلف چگونه با پیاده سازی میشوند.
درواقع هدف اصلی معماری نرم افزار این است که بتواند با نقاط مشخص تماس و قراردادهای واضح، رفتار سیستم در مواجهه با نیازهای کاربر، مقیاس پذیری، نگهداری، امنیت و کارایی را تضمین کند.
بنابراین وقتی به معماری نرم افزار نگاه میکنیم، معمولا سوالهایی در ذهن مطرح میشود: این ماژول‌ها چه نقشی ایفا می‌کنند؟ داده‌ها چگونه در میان اجزا جریان پیدا می‌کنند؟ چه قراردادهایی برای ارتباط بین سرویس‌ها تعریف شده است؟ چگونه می‌توان در آینده با تغییرات کوچک، سیستم را با کمترین هزینه تغییر داد؟
اما در تفکر سیستمی دامنه ای گسترده تر وجود دارد که فراتر از مرزهای نرم افزار را شامل میشود. این رویکرد به تحلیل و طراحی کل سیستم و محیط آن نگاه میکند به ویژه در تعاملات میان اجزا، بازخوردها و پویایی بین فرآیندها و ذینفعان توجه میکند.
تفکر سیستمی بر این نکته تاکید دارد که هر جز هر فرآیند و هر فناوری در یک شبکه ی پیچیده قرار دارد و تغییر در یک نقطه میتواند اثرات غیرمستقیم و گاهی پنهان در سایر بخش ها ایجاد کند. بنابراین در تفکر سیستمی باید به همپوشانی اجزا و Dependency های متقابل نگاه کرد.
سوالات کلیدی که در تفکر سیستمی ایجاد میشود شامل این موارد است: هدف سیستم چیست؟ ورودی‌های اصلی آن چه هستند و چه بازخوردهایی تولید می‌شوند؟ چه محدودیت‌هایی وجود دارد و چگونه می‌توان به پایداری بلندمدت دست یافت؟ تغییر در یک بخش چگونه بر کل سیستم اثر می‌گذارد و چه هم‌آهنگی با فرایندهای کسب‌وکار و ذینفعان وجود دارد؟
معماری نرم افزار و تفکر سیستمی
در معماری نرم افزار (در دل سیستم) در تفکر سیستمی (دیدگاهی کلان تر)
این ماژول‌ها چه نقشی ایفا می‌کنند؟ هدف سیستم چیست؟
داده‌ ها چگونه در میان اجزا جریان پیدا می‌کنند؟ ورودی‌ های اصلی آن چه هستند و چه بازخوردهایی تولید می‌شوند؟
چه قراردادهایی برای ارتباط بین سرویس‌ها تعریف شده است؟ چه محدودیت‌هایی وجود دارد و چگونه می‌توان به پایداری بلندمدت دست یافت؟
چگونه می‌توان در آینده با تغییرات کوچک، سیستم را با کمترین هزینه تغییر داد؟ غییر در یک بخش چگونه بر کل سیستم اثر می‌گذارد و چه هماهنگی با فرایندهای کسب‌وکار و ذینفعان وجود دارد؟
از نظر دامنه، معماری نرم‌افزار محدود به ساختار و رفتار نرم‌افزار است و با تصمیم‌های فنی مربوط به طراحی، پیاده‌سازی و نگهداری سروکار دارد. تفکر سیستمی اما کل سیستم و محیط آن را می‌بیند؛ از ابعاد فنی تا فرایندهای کسب‌وکار، داده‌ها، فناوری‌های دیگر و محدودیت‌های محیطی و اقتصادی را در یک چارچوب یکپارچه مطالعه می‌کند.
از منظر ذینفعان به چه صورت است؟
در رابطه با ارتباط با ذینفعان، معماری نرم‌افزار عمدتاً با تیمهای فنی، مدیران فناوری و سایر افراد دخیل در توسعه نرم‌افزار در تعامل است و غالباً در جلسات طراحی و تصمیم‌گیری درباره فناوریها و معماری لازم به‌کار گرفته می‌شود. تفکر سیستمی اما با نقـشها و فرآیندهای کسب‌وکار، کاربران نهایی، تأمین‌کنندگان، سازمان‌های مربوط به محیط قانونی و اقتصادی و حتی جامعه‌ی کاربران سروکار دارد. به این معنا، تفکر سیستمی دیدی از سیستم است که با فشارها و محدودیت‌های محیطی و اقتصادی نیز سروکار دارد و به پایداری بلندمدت و هم‌زمانی میان اجزا و فرایندها اهمیت میدهد.
جمع بندی
رویکرد عملی به ترکیب این دو نگاه منجر می‌شود تا بتوان سیستم‌های پیچیده را به‌روایت دقیق‌تری طراحی کرد. از یکسو باید معماری نرم‌افزار را با استفاده از الگوهای معماری مناسب، APIهای واضح، قراردادهای بین سرویس‌ها و نگرش‌های مدرن مانند میکروسرویس یا رویکرد سرویس‌گرایی به‌گونه‌ای طراحی کرد که اجزای نرم‌افزار با هم به خوبی کار کنند و قابلیت نگهداری و گسترش‌پذیری را فراهم کنند. از سوی دیگر باید با تفکر سیستمی به تحلیل الزامات کسب‌وکار، فرایندها، داده‌ها و محدودیت‌های محیطی پرداخت تا بتوان به یک راه‌حل جامع دست یافت که نه تنها از منظر فنی کارایی خوبی داشته باشد بلکه با محیط کسب‌وکار و ذینفعان همسویی کامل داشته باشد.



ذینفع کیست؟
کاربران نهایی، مالکین محصول/بنگاه، تیم‌های توسعه و فنی، تیم‌های عملیات و پشتیبانی، ذینفعان سازمانی/سایر واحدها، تامین‌کنندگان و شرکای فناوری، کاربران خارجی و جامعه، نهادهای قانونی و استاندارد.

از کدنویسی تا تفکر سیستمی در نرم افزار

با حضور پررنگ هوش مصنوعی، برخورداری از تفکر سیستمی میتواند در آینده ی نزدیک از بیکار یا کم کار شدن برنامه نویسها جلوگیری کند.اما چگونه یک برنامه نویس به مهندس نرم افزار تبدیل میشود؟ در این مقاله مسیر حرکت برای تبدیل شدن یک کدنویس به فردی دارای تفکر سیستمی را بررسی خواهیم کرد.

سیستم چیست؟

برای درک فرآیند تفکر سیستمی، ابتدا باید مفهوم سیستم را به خوبی درک کنیم. سیستم چیست و اصولا به چه چیزی میگوییم سیستم؟

به زبان ساده، سیستم مجموعه ای از عناصر یا اجزاست که با هم کار میکنند تا یک هدف یا نتیجه خاصی را ایجاد کنند.هر جز در عملکرد یک سیستم نقش دارد و با سایر اجزا تعامل برقرار میکند.

بنابراین وقتی میگوییم سیستم، معمولا به سه نکته اشاره میکنیم:

  • اجرا یا عناصر: هر سیستم از چند جز تشکیل شده است.
  • روابط و تعامل ها: این اجزا از طریق قوانین یا فرآیندهای مشخصی با هم در ارتباط هستند.
  • هدف یا خروجی: یک سیستم برای دستیابی به یک هدف یا تولید یک خروجی مشخص ایجاد میشود.

حال سیستم ها ویژگیهای رایجی هم دارند. مانند بازخورد از خروجی سیستم به ورودی برای مثلا تنظیمات بهتر، محیط سیستم، مثل اینکه ورودیهای سیستم از چه محیط دریافت میشودو مجموعه پذیری و ساختارمندی که میتواند سیستم را به صورت سلسله مراتبی یا شبکه ای با زیرسیستمهای دیگر هماهنگ کند.

بنابراین میتوانیم از طریق این نکات وجود یک سیستم را به روشهای زیر تشخیص دهیم:

  • وجود چند جز که با هم کار میکنند.
  • وجود هدف یا نتیجه مشخص.
  • وجود ارتباطات و بازخوردها بین اجزا.
  • وجود محدودیت‌ ها و محیطی که سیستم در آن عمل میکند.

بعد از درک اینکه سیستم چیست، میتوانیم تعریف مشخصی از سیستم در دنیای نرم افزار داشته باشیم. شاید نزدیکترین تعریف از سیستم، ایجاد فرآیندی است که با دریافت ورودیهایی، خروجی های مورد انتظار را برای کاربر تولید میکند. از لحظه دریافت ورودی یا لحظه ایجاد خروجی، در دل این فرآیند سیستمی، اجزایی پیچیده یا ساده مشغول اجرای مجموعه کارهایی هستند که با تعامل با یکدیگر هدف نهایی را تولید میکنند.

بعنوان مثال، عملیات ورود کاربران به یک سامانه را برای شما ساده سازی و تشریح میکنم و میبینیم که آیا این عملیات میتواند یک سیستم باشد؟

برای چنین هدفی، باید فرمی برای ورود نام کاربر و رمز عبور وجود داشته باشد. سپس یک فرآیند باید نحوه ورود اطلاعات را در فرم ارزیابی کند. بعد از آن اطلاعات دریافت شده باید با مخرنی از اطلاعات از قبل ذخیره شده تطابق داده شوند. در صورت صحیح بودن این اطلاعات عملیاتی برای تثبیت کاربر در سامانه انجام و یا در غیر اینصورت، پیام خطایی به کاربر نمایش داده شود.

کل این فرآیند از اجزای فرم، مکانیسم Validation، ارتباط با دیتابیس، بانک اطلاعاتی و پیام رسانی تشکیل شده اند که به تنهایی کار خاصی انجام نمیدهند اما در تعامل با هم در یک سلسله مراتب مشخص، هدف ارزشمندی را انجام میدهند. هدف مشخصی دارد، ارتباطات و بازخورد دارد، از محیط پیرامون خود جهت دریافت ورودی استفاده میکند و محدودیتهایش مشخص شده است. بنابراین به این فرآیند میتوانیم سیستم احراز هویت بگوییم.

تفکر سیستمی

پس از درک مفهوم سیستم، وقت آن است که به موضوع تفکر سیستمی بپردازیم. منظور از تفکر سیستمی چیست و یک برنامه نویس چطور میتواند سیستمی فکر کند و این چه تاثیری در او و عملکرد او ایجاد میکند؟

یک برنامه نویس را (بدون توجه به سطح آن – حرفه ای یا غیر حرفه ای) در نظر بگیرید که درک کاملی از تمام اجزای یک سیستم دارد. اما اگر به شکل بالا که نمونه یک سیستم ساده ی Authentication (احراز هویت) است نگاه کنید، میبینید که خطوطی که تعامل اجرا را با یکدیگر شکل داده اند درنهایت اجزا را به یک دیگر متصل کرده و تشکیل یک سیستم داده اند.

به این که این خطوط و این تعامل چگونه بین اجزای یک سیستم شکل میگیرند، تفکر سیستمی میگوییم.

حال بیایید همان شکل شماتیک را بدون خطوط متصل کننده اجزا ببینیم:

بدون خطوط تعاملی و متصل کننده اجزا به هم، سیستم ما شکل منسجمی ندارد. درواقع یکسری اجزا خواهند بود که نوع ارتباط آنها با یکدیگر مشخص نیست. این سیستم اکنون از دید یک برنامه نویس بدون تفکر سیستمی، تنها لیستی نامرتب از اجزایی خواهند بود که در یک سیستم احراز هویت از او خواسته شده تا تولیدشان کند:

میبینید که از دید فردی که بجای مکانیسم، لیستی از فیچرها را میبینید، همه چیز بهم ریخته، مبهم و پیچیده است. یک برنامه نویس بدون درک سیستمی که مشغول خلق آن است حتی نمیتواند چیدمان درستی از اولویت فیچرها را ترسیم کند. هرچند که ممکن است بتواند یک فیچر را با دقت عملکردی زیادی بنویسید اما از کنار هم چیدن درست آنها و درک تعامل آنها باهم احتمالا عاجز است. بنابراین زمانی میتوانیم بگوییم یک برنامه نویس مجهز به تفکر سیستمی شده است که بتواند اجزای سیستم را به هم متصل و خروجی مورد انتظار را از آن دریافت کند.

مسیر رسیدن به تفکر سیستمی برای یک برنامه نویس چگونه است؟

من یک رودمپ مشخص برای شما ترسیم میکنم. مسیری که خودم رفتم و از نظر من پاسخگو است.

ابتدا باید بتوانید دید معماری و طراحی خودتان را تقویت کنید. بهتر است اول به سراغ مفاهیم معماری ساده و متداولی مثل MVC/MVVC بروید. بعد ذهن خودتان را به سمت معماری های سرویس گرا (SOA)، میکروسرویس ها و Event-driven هدایت کنید. این معماری ها به دلیل وجود کامیونیتی های بسیار منابعی غنی از یادگیری معماری و اصول آنرا به در اختیارتان قرار میدهند.

سپس شروع به تمرین کنید: طراحی سیستمهای کوچک. بعنوان مثال با چند ماژول ساده شروع کنید و سعی کنید قابلیتها و محدودیتهای ناشی از تعامل با سایر ماژول ها مدل کنید.

مدل سازی در نرم‌افزار به فرایند ایجاد نمایش های مبهم یا پیچیدهٔ یک سیستم به صورت ساده و قابل فهم است تا بتوان با آن طراحی، تحلیل و پیاده‌سازی را بهتر انجام داد. مدل‌ها نماینده‌ ای انتزاعی (ساده شده) از بخش‌های مختلف سیستم‌ اند که الزامات، رفتارها و ارتباطات بین اجزا را بیان می‌کنند بدون اینکه به جزئیات پیاده‌سازی ریزه‌کاریهای کد اشاره کنند.

گام بعدی میتواند تحلیل سیستم عملی باشد. بعنوان مثال وب سرویس سفارش آنلاین را کاملا تجزیه و تحلیل کنید. نقشه ارتباطات و تعاملات آنرا رسم کنید و سعی کنید بفهمید اولویتها در این چنین سیستمی چطور ترسیم شده.

فراموش نکنید باید در مقام طراح و معماری سیستم دوستی بخصوصی با کاغذ و قلم یا ابزارهای دیجیتال برای رسم ارتباطات داشته باشید. من ابزار آنلاین Draw.io را که مدتهاست خودم از آن استفاده میکنم پیشنهاد میکنم. این سامانه یک ابزار غنی برای رسم سریع از چرکنویس تا طراحی های نهایی در فازهای تحلیل و طراحی سیستمهای نرم افزاری ست. حتی اگر مثل من سنتی باشید، علاقه بسیاری پیدا خواهید کرد تا معماری هایتان را پرینت کنید تا وقتی دراز کشیده اید بتوانید بازهم آنها را مطالعه و گره های دیده نشده طراحی تان را پیدا کنید.

پیشنهاد میکنم هر هفته یک پروژه یا بخشی از سیستم را به طور هدفمند بررسی کنید. اینکه چخ مشکلاتی دارد؟ رفتارها چگونه است؟ چه بازخوردی از کاربران یا سایر اجزا میگیرید؟

سپس هر دوهفته یک “بازبینی معماری” ساده انجام دهید. آیا شرایط تغییر میکند؟ آیا طراحی پاسخگوی نیازهای آینده است؟

استفاده از نقشه های معماری

نقشه های معماری کمک بسیار بزرگی در ویژوال کردن افکار یک طراح سیستم دارند. آنها میتوانند پیچیده ترین مسائل را به صورت انتزاعی رسم کنند تا هم بتوانند دید وسیعتری از افکارشان بدست آورند و هم قادر باشند آنرا به دیگران با پیچیدگی کمتری توصیف کنند.

در این بین من شخصا علاقه خاصی به UML دارم. حتی اگر در ابتدایی ترین قدمهای ورود به عرصه ی طراحی یک سیستم باشید، تنها با رسم چند شئی از UML میتوانید یک سیستم ساده طراحی کنید. اما آنچه باید در UML در تفکر سیستمی به دنبالش باشید، مدلهای ساختاری یا Structure diagrams است. 

مدلهای ساختاری UML تمرکز اصلی شان تبین ساختار سیستم به صورت ویژوال است تا رفتار آن را بتوان با خیال راحت تری طراحی کرد. در این مدلها بیشتر به اینکه “چه چیزهایی وجود دارند و چگونه به هم وصل می‌شوند” پرداخته میشود تا اینکه “چه اتفاقی می‌افتد و چگونه اجرا می‌شود”. دوراقع وجود اشیا در سیستم و ارتباط آنها با یکدیگر در این فاز اولویت دارد به درک اینکه چه اتفاقی در این تعامل میوفتد یا چگونه اجرا میشوند.

اما فایده ی ذاتی مدلهای ساختاری UML چیست؟ میتونم به طراحی قابل نگهداری اشاره کنم. شما با مشاهده کلاسها و روابط میتوانید نقاط تکرار، وابستگی های سنگین و نقص ها را در طراحی تان کشف کنید.

همینطور مشخص میشود چه ارتباطی با دیگر ذینفعان غیرفنی پروژه خواهید داشت. مانند مدیرپروژه یا تحلیلگران کسب و کاری.

مدیریت پیچیدگی ها که حاصل از تفکیک سیستم به ماژولها و تعریف قراردادهای واضح بین آنهاست از فواید دیگر استفاده از مدلهای ساختاری است. در نهایت ارتباطی که این شکل طراحی در نگاه به کل سیستم، روابط بازخوردی و جریان داده دارد به فرایند ایجاد تفکر سیستمی در فرد کمک میکند.

جایگاه تحلیل در تفکر سیستمی

تحلیل به تعیین حدود سیستم، عناصر کلیدی و روابط به آنها منجر میشود. با تحلیل میتوان مرزهای زیرسیستمها را مشخص کرد تا نگاه شما به کل سیستم روشنتر شود.بنابراین تحلیل در تفکر سیستمی میتواند دامنه کار را واضح تر کند.

تفکر سیستمی به بازخوردهای مثبت و منفی اهمیت میدهد.تحلیل کمک میکند تا بفهمیم چه بازخوردهایی وجود دارد، چگونه موجب پایداری یا ناپایداری میوشند و چگونه تاخیرها میتوانند رفتار سیستم را تغییر دهند. با مدلسازی که در بالا اشاره کردم میتوانید مسیر این بازخوردها را دنبال کنید.

همچنین تحلیل کمک میکند تا لایه های تصمیم گیری و قیود را مشخص کنید و میتوانید ببینید در چه جاهایی تصمیم ها و فشارهای فنی به یکدیگر میرسند. این کار به طراحی راهکارهایی با پایداری بلندمدت و قابلیت ارتقا میکند.

تحلیل قبل از اجرا به تشخیص اثرات جانبی تغییرات در یک جز میپردازد که برای جلوگیری از شکستهای غیرمنتظره در سیستمهای پیچیده حیاتی است. 

در تحلیل میتوانید از سناریوی جادویی what-if پاسخ سیستم به تغییرات را پیشبینی کنید.

سناریوهای what-if، تمرینی است برای بررسی “اگر فلان اتفاق بیفتد چه میشود؟” با هدف درک اثرات احتمالی و انتخاب بهینه، بسیار در تحلیل یک سیستم و واکنش به بازخوردها موثر است.

اما شروع یک تحلیل در کمک به تفکر سیستمی چگونه باید باشد؟ از نظر من همیشه با سوال های کلیدی شروع کنید:

– هدف سیستم چیست؟
– کاربران چه کار میخواهند انجام دهند؟
– چه بازخوردی وجود دارد؟

برای پاسخ به این سوالات از مدلهای سطح بالا شروع کنید و به تدریج به جزئیات بپردازید. منظور از مدلهای سطح بالا، مدلهای بسیار ساده سازی شده انتزاعی است که جزئیات بسیار محدودی در آنها وجود دارد. در انتها باید تحلیلهای انجام شده را با ذینفعان به اشتراک بگذارید و بازخوردها را دریافت و از این طریق تحلیلتان را اعتبارسنجی کنید.

تمرینی برای تفکر سیستمی

امیدوارم تا اینجا مفهوم تفکر سیستمی، اجزای آن و کاربرد آن برای شما روشن باشد. اگر بخواهید میتوانید با تمرین زیر این مسیر را ادامه دهید: طراحی یک سیستم مدیریت موجودی ساده با دیدگاه تفکر سیستمی.

هدف از این تمرین درک بازخوردها و اثرات جانبی تغییرات در یک سیستم کاملاً ساده و مرکز بر روابط بین تقاضا، موجودی، سفارش و هزینه است.

گامها:

  1. تعیین هدف سیستم
  • مثلاً: نگهداری موجودی به‌گونه‌ای که هزینه نگهداری کمین باشد و سطح سرویس مشتری بالا بماند.
  1. شمای کلی اجزا (IDEA را در ذهن تمرین کنید)
  • Demand (تقاضا)
  • Inventory (موجودی)
  • Reorder Point/Order Quantity (نقطه بازنشانی و مقدار سفارش)
  • Supplier/Lead Time (فروشنده و زمان تحویل)
  • Costs (هزینه‌های نگهداری، خرید، کاهش موجودی، تاخیر در تحویل)
  1. مشخص کردن بازخوردهای کلیدی
  • بازخورد منفی: اگر موجودی خیلی پایین باشد، سطح سرویس کاهش می‌یابد و مشتریان از دست می‌روند.
  • بازخورد مثبت: اگر تقاضا بالا رود و موجودی محدود باشد، شاید سفارش بیشتری بدهیم، اما هزینه نگهداری افزایش می‌ابد.
  • تاخیرهای زمانی: با طولانی شدن زمان تحویل، نیاز به افزایش امن‌سای یا سطح موجودی داریم.
  1. مدل ساده (زبان ساده یا نمودار کُدی)
  • یک مدل مفهومی با سه متغیر:
    • موجودی فعلی (I)
    • تقاضای دوره‌ای (D)
    • سفارش جدید (Q)
  • قوانین ساده:
    • اگر I <= reorder_point، سفارش جدید به اندازه (Q) داده می‌شود.
    • هزینه‌ها: نگهداری = نگه‌داشتن موجودی در هر دوره، خرید=قیمت واحد * مقدار سفارش، کمبود = هزینه بابت عدم تامین در صورت کمبود.
  1. سناریوهای what-if ساده
  • سناریو A: تقاضا افزایش می‌یابد (D ↑)
  • سناریو B: زمان تحویل از supplier طولانی‌تر می‌شود (Lead Time ↑)
  • سناریو C: قیمت واحد کالا کاهش می‌یابد (قیمت ↓)
    برای هر سناریو: تخمین کنید چگونه I، هزینه‌ها و احتمال کمبود تغییر می‌کند.
  1. تحلیل نتایج
  • مقایسه سه سناریو با حالت پایه: کدام سناریو کمترین هزینه کل را دارد با حفظ سرویس مناسب؟
  • سوالات تفکر سیستمی: آیا تغییر در یک جزء (مثلاً Lead Time) چه اثراتی بر سایر اجزا دارد؟ آیا باید تغییراتی در reorder_point یا Q بدهیم؟