وقتی مهارت فنی کافی نیست

روایتی از نقطه بلوغ تیمی و اهمیت مهارت های نرم: تیم زمانی رشد میکند که آدمها بدانند چطور باید با هم کار کنند
در یک مقطع از مسیر کاری خودم، درست مثل خیلی از رئیس ها یا مدیرانی که ابتدا بار پروژه ها را روی دوش تخصص فنی میگذارند، من هم تصورم این بود که اگر فردی از نظر تکنیکال قوی باشد، میتواند همه چرخ ها را به حرکت دربیاورد. سالها همین نگاه را داشتم. اما هر چه پروژه ها بزرگ تر شدند، هر چه تعاملات بین واحدی پیچیده تر شد و هر چه فشار زمانی و مسئولیتهای واقعی بیشتر شد، کم کم دیدم که آن چیزی که تیم را جلو میبرد فقط مهارت فنی نیست؛ بلکه چیزی عمیق تر و انسانی تر به اسم مهارت نرم یا سافت اسکیل (Soft Skill) است.
این جا بود که نقطه عطف من شروع شد؛ جایی که فهمیدم “توانایی انجام کار”، با “توانایی همکاری”، “توانایی پذیرفتن مسئولیت” و “توانایی مدیریت رفتار و احساسات” زمین تا آسمان فرق دارد. تخصص فنی مثل یک موتور قوی است، اما سافت اسکیل ها سیستم کنترل و هدایت همان موتورند. موتور بدون هدایت، سرعت ایجاد میکند ولی تصادف هم رخ خواهد داد.


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


مشکل این نبود که بلد نیست کار فنی را انجام بدهد. مشکل این بود که:
• در لحظه فشار، به جای تحلیل، واکنش احساسی نشان میداد
• در مواجهه با اشتباه، بیشتر دنبال دفاع بود تا اصلاح
• گزارش کارها نامنظم بود و تیم عقب میافتاد
• مسئولیتهایش گاهی نیمه کاره میماند
• در همکاری، شنیدن و فهمیدن طرف مقابل ضعیف بود
• در تعاملات بین واحدی، زبان حرفه ای نداشت
• در مدیریت زمان، تخمینها واقعی نبود
• در مواجهه با تغییرات سریع، انعطاف رفتاری نداشت
اینها دقیقا چیزهایی هستند که هیچ کامپایلری خطا نمیگیرد اما تیم را از درون دچار سکته میکند.
من در این نقطه فهمیدم که اگر این فرد سافت اسکیل های خودش را تقویت نکند، هم خودش در مسیر حرفه ای آسیب میبیند و هم تیم در یک سقف نامرئی گیر میکند. هیچ تیمی با صرفا یک یا چند نفر فنی قوی رشد نمیکند؛ تیم زمانی رشد میکند که آدمها بدانند چطور باید با هم کار کنند.
این مرحله برای من تبدیل شد به یکی از بزرگترین درسهای مدیریتی ام. اینکه:
• آدم فنی قوی، الزاماً یک هم تیمی خوب نیست
• تیم حرفه ای بدون بلوغ رفتاری شکل نمیگیرد
• خروجی نهایی فقط نتیجه مهارت نیست، نتیجه رفتار است
• اعتبار فرد در تیم، از نحوه برخوردش با سختی ها ساخته میشود
• توانایی کنترل احساسات، مهمتر از توانایی حل مسئله است
• شفاف حرف زدن و شفاف گزارش دادن، نصف مدیریت پروژه است
• مسئولیت پذیری واقعی یعنی قبول کردن اشتباه بدون توجیه


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

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

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

در اسکرین شاتی که مشاهده میشود، نویسنده پست در لینکدین از دوستانش درخواست میکند در مورد قیمت گذاری یک پروژه وب با او همفکری کنند. اما درست در بخش کامنت ها، یکی از کاربران بدون اینکه به هیچ یک از اصول حرفه ای قیمت گذاری، تعریف پروژه، سطح پیچیدگی، ریسک ها، تسک ها، یا حتی ساختار تیم اشاره کند، یک عدد خام و بسیار ساده ارائه می‌دهد:
«ساعتی کار بدین، مثلا ۲۰۰ ساعت به ازای هر ساعت ۱ تومن.»
این دقیقا همان سوتی بزرگ است؛ سوتی ای که نه تنها برای تیم های حرفه ای گران تمام می‌شود، بلکه باعث می‌شود برداشت عمومی از ارزش کار نرم افزاری به شکل خطرناک و اشتباه کاهش پیدا کند.
پروژه نرم افزاری مثل سفارش پیتزا نیست که بشود در چند ثانیه قیمتش را حدس زد. هر پروژه نیاز به تحلیل، تعریف دقیق، تخمین زمان، درک ارزش، بررسی ریسک ها و محاسبه جزئیات دارد. اینکه بدون شناخت کامل پروژه، فقط یک ضرب ساده «تعداد ساعت × نرخ ساعتی» را به عنوان نسخه نهایی ارائه دهیم، نه حرفه ای است و نه به نفع فعالان این صنعت.
این مقاله، دقیقا به همین دلیل و از دل همین سوتی شکل گرفته است. برای اینکه نشان دهد چرا قیمت گذاری نرم افزار نمیتواند «حدسی و سرانگشتی» باشد، و چرا تیم های ۱ تا ۳ نفره باید از یک روش علمی، منطقی و قابل دفاع استفاده کنند.
اینکه برخلاف کامنت ناشیانه زیر آن پست، قیمت گذاری واقعی شامل چندین مرحله مهم است که اگر نادیده گرفته شوند، نتیجه آن برای تیم، برای مشتری و برای کل بازار مخرب خواهد بود.
قیمت گذاری پروژه های نرم افزاری برای تیم های کوچک
قیمت گذاری پروژه های نرم افزاری یک مرحله مهم و تأثیرگذار در شروع همکاری است. تیم های کوچک که معمولا بین 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 = میانگین زمان ترمیم

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