ملاقات با مشتری در حین انجام پروژه

اکثر کسانی که به صورت پروژه‌ای کار می‌کنند (از جمله خود ما) از داشتن قرار ملاقات مکرر با مشتری، در حین انجام پروژه ترس دارند. مواردی که باعث این ترس می‌شوند از این قبیل هستند؛

  1. احتمالاً مشتری با دیدن چیز‌هایی که پیاده شده است چیز‌های جدیدتری به ذهنش می‌رسد
  2. توقع انجام خیلی از آن‌ها را به صورت رایگان دارد
  3. ممکن است با دیدن قسمتی از سیستم متوجه شود اصلاً چیزی که می‌خواسته این نبوده
  4. و …

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

به طور کی اعتقاد دارم، سودی که این ملاقات‌ها دارند بیشتر از هزینه‌ها‌ی مستقیم (وقت و هزینه رفت آمد) و غیر مستقیم (موارد اضافه شده و تغییر داده شده) هستند و برای این ادعا دلایل زیر را دارم؛

حذف موارد

همیشه هم موارد اضافه یا تغییر داده نمی‌شوند! بلکه برخی از موارد حذف می‌شوند. ممکن است مشتری یک ویژگی که نیمه کاره انجام شده و پر دردسر است را لازم نداشته باشد و بخواهد آن‌را حذف کنیم.

کم شدن هزینه‌های آتی

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

هزینه تبلیغات

البته هر مشتری با مشتری دیگر متفاوت است اما به تجربه، درخواست‌های فراتر از قرارداد یک مشتری معمولاً تا ۱۰ درصد از هزینه کل قرارداد می‌رسد. یعنی برای یک قرارداد ۱۰ میلیون تومانی معمولاً بیشتر از ۱ میلیون تومان هزینه بر دوش ما نخواهد گذاشت. به فرض اینکه بخواهیم تمامی این درخواست‌ها را انجام دهیم آیا حاضر نیستید یک مشتری خوب را با صرف ۱۰ درصد از هزینه کار، بیش از پیش جذب کنید؟ البته این بستگی به خود ما دارد و می‌توانیم پول همه کارهای اضافی را تمام و کمال دریافت کنیم. هر چند برای اجرای رایگان آن‌ها هم پیشنهاد نمی‌کنم بدون مطرح کردن آن با مشتری انجامش دهید. اجازه بدهید که مشتری بداند چقدر خرج او کردید بدون اینکه منتی بر سرش بگذارید (که کار سختی ست). نکته مهم‌تر این است که فقط در صورتی می‌توان این کارهای اضافه را برای مشتری توضیح داد و در صورت تمایل پولش را گرفت که قبل از شروع کار یا در ابتدای کار، پروژه و اهداف و مرزهای آن به طور کامل مشخص شده باشد در غیر این صورت تمام این موارد زیر سؤال خواهد بود.

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

نتیجه اخلاقی اینکه؛ قرار ملاقات مرتب و مکرر با مشتری یا جلوگیری از ضرر و شکست است و یا رسیدن به سود و موفقیت بیشتر.

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

این پست را در وبلاگ آی کلاب خواندم که ترجمه‌ی یک پست از یکی از کارمندان جوان مایکروسافت است؛ Ahmet Alp Balkan. کلیت آن انتقاد از فرهنگ حاکم بر محل کار اوست. خواندن پست او و ترجمه آن یک تجربه است و خواندن کامنت‌های پست اصلی یک تجربه دیگر. حتماً پیشنهاد می‌کنم کامنت‌ها را در وبلاگ اصلی مطالعه کنید، Hanselman هم در آنجا کامنت گذاشته. کاملاً قابل انتظار است که بسیاری از افراد از این پست برای تایید انتقادات خود از مایکروسافت یا شرکت‌های بزرگ دیگر استفاده کنند و جنگ مذهبی به راه بیفتد! اما من دوست دارم از این مطلب چیزهای مهم‌تری بیاموزم.

به نظر من همیشه مشکلات زیادی در شرکت‌های بزرگ وجود دارد که حتی فکر کردن به آن‌ها آزار دهنده است. هر چند مایکروسافت به قدری بزرگ است (بزرگترین شرکت نرم‌افزاری) که می‌توان آن را مثل یک کشور بزرگ تصور کرد که در هر منطقه از آن فرهنگ و سیاست خاصی حاکم است. این نمودار به زیبایی این موضوع را به تصویر کشیده؛

ms

 

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

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

به همین دلیل، همیشه تشکیل اجتماع و شبکه‌سازی را به تشکیل یک تیم بلند مدت ترجیح می‌دهم و همچنین پروژه‌های کوتاه مدت با ارزشی که بر روی تیم‌های کوتاه مدت استوار هستند را به پروژه‌هایی که برای اجرا به تیم‌های بلند مدت نیاز دارند، ترجیح می‌دهم.

منبع تصویر: http://haacked.com/archive/2013/05/13/applying-conways-law.aspx

برنامه‌نویسی برای ساعت با سی شارپ

watchشرکت Netduino یک ساعت بسیار جذاب ساخته که پلتفرم آن .NET Micro Framework است. شرکت Netduino سخت افزارهای ارزان قیمت (از ۳۴ دلار) بر روی پلتفرم .NET Micro Framework می‌سازد که می‌توان به راحتی با Visual Studio برای آن‌ها کد نوشت. اخیراً این شرکت یک ساعت جذاب تولید کرده که شبیه ساز آن نیز پنجشنبه همین هفته در وب سایتش قابل دانلود خواهد بود و بدون خریدن ساعت می‌توان برای آن کد زد. دقیقاً به همان شکلی که برای یک وب سایت کد می‌نویسیم می‌توانیم برای این ساعت هم کد بنویسیم؛ با زبان C#! برای اینکه کار کاملاً قانونی باشد می‌توانید Visual Studio 2012 Express و .NET Micro Framework را به صورت رایگان دانلود کرده و شروع به کار کنید (نسخه Visual Studio 2012 Ultimate هم مطمئناً قابل استفاده است).

منبع: وبلاگ Scott Hanselman

بروز رسانی ۱

سرمایه این پروژه (در حدود ۱ میلیون دلار) در Kickstarter تامین شد و طبق زمان‌بندی حدودی اعلام شده، تولید انبوه آن در دسامبر ۲۰۱۳ آغاز خواهد شد.

مشکل نصب یونیتی ۳ بر روی دات نت ۴

در زمان نوشتن این پست، نسخه ۳ از یونیتی (Unity) بر روی دات نت ۴.۵ نصب می‌شود. برای پروژه‌هایی که بر روی دات نت ۴ هستند، باید از نسخه ۲ یونیتی استفاده کرد. متاسفانه به نظر می‌رسد مشکلی در بسته‌بندی یونیتی ۳ وجود دارد که نسخه کنونی دات نت پروژه را تشخیص نمی‌دهد تا در صورت نیاز به جای استفاده از نسخه ۳ یونیتی از نسخه ۲ استفاده کند. خوشبختانه اجتماع یونیتی به اندازه کافی فعال است و در این زمینه به خوبی کمک کردند.

به راحتی می‌توان با استفاده از Package Manager Console در Visual Studio با استفاده از دستور زیر نسخه مورد نظر از یونیتی را نصب کرد؛

Install-Package Unity -Version 2.1.505.2

منبع: https://unity.codeplex.com/workitem/12731

روش جالب تبلیغات برای استخدام برنامه‌نویس

skydrive_headerداشتم وب سایت SkyDrive را بررسی می‌کردم. متوجه شدم که یک Custom HTTP Header در پاسخ هر درخواست ارسال می‌شود به نام x-We-Are-Hiring و مقدار آن برابر است با skydrivejobs[at]microsoft[d0t]com. واقعاً روش جالبی برای جذب نیروی کار است. به نظرم این خودش بهترین فیلتر است تا افراد گزینش شده تر و کنجکاوتری درخواست کار و رزومه ارسال کنند.

ایجاد اطمینان در پروژه‌های برون‌سپاری شده

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

به نظرم چند اصل برای کمک به موفقیت در اجرای پروژه‌های برون‌سپاری شده نرم‌افزاری، به عنوان پیمانکار، وجود دارد که در کارهای خودم به صورت مکرر تأثیر داشته‌اند. و از طرفی همیشه الگوهای تکرار شونده موفق، نشانه‌های خوبی هستند که با استفاده از آن‌ها می‌توان دوباره به تجربیات موفق دست پیدا کرد. این اصول حداقل برای من جواب سؤال مطرح شده هستند شاید برای خیلی‌های دیگر هم باشد. اما به نظرم مهم‌ترین آن‌ها، داشتن صداقت و دادن آگاهی به کارفرما (یا هر طرف دیگر) است.

متأسفانه من هم مثل خیلی از مردم قطعاً در زندگی دروغ گفته و خواهم گفت اما همیشه برای صداقت و راست گویی ارزش ویژه‌ای قائل هستم، همیشه سعی می‌کنم راست گو باشم. خوشبختانه همین رویکرد در کار هم برایم مفید واقع شد.

فکر می‌کنم برای ایجاد رابطه بهتر با کارفرما (یا هر فرد دیگر) بهتر است یک قدم فراتر رویم. درست است که مطرح نکردن یک موضوع با دیگران دروغ گویی نیست و در خیلی موارد کاملاً اخلاقی است اما یکی از ابزارهای نشان دادن حسن نیت، همین در میان گذاشتن اطلاعات غیر ضروری اما مفید است. ممکن است لازم نباشد برخی اطلاعات داخلی از تیم تولید را به کارفرما بگویم ولی در برخی شرایط این می‌تواند باعث ایجاد اطمینان بیشتر شود. منظور فقط تمجید و تعریف از خود نیست بلکه گفتن واقعیت‌هاست. وقتی یک فرد، با صداقت کامل، خودش را برای شما شرح می‌دهد شما بیشتر به او اطمینان می‌کنید خصوصاً وقتی نقطه ضعف‌هایش را با صراحت برای شما روشن می‌کند و راه حل‌هایی برای آن‌ها دارد، اطمینان شما بیشتر و بیشتر خواهد شد.

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

یک تجربه دیگر جالب دیگر در این خصوص این بود که؛ در خصوص ساخت یک وب سایت ساده، با یک شرکت غیر نرم‌افزاری وارد صحبت شدیم ولی متوجه شدیم که یک CMS متن باز و حتی یک وب سایت Static جواب کارشان را می‌دهد. دفترچه یادداشتم را بستم و صادقانه بهشان گفتم که با ۲۰۰ هزار تومان هم می‌توانید یک وب سایت ساده ثابت داشته باشید ولی معایبی هم دارد. خلاصه به طور کامل داستان را برایشان شرح دادم و در مورد اینکه احتمال دارد کار ما برای آن‌ها زیادی خرج داشته باشد (حدود ۲ میلیون تومان بدون گرافیک) و همین طور درباره محاسن کارمان گفتم و توقع داشتم که با خوبی و خوشی خداحافظی کنیم و برویم ولی مدیر شرکت گفت «بهترین کلک صداقت است» (البته فکر کنم جمله درست «بهترین سیاست صداقت است» باشد) و معتقد بود که ما بازاریاب‌های خوبی هستیم! قرارداد بستیم و به خوبی انجام دادیم. و البته یک بار دیگر هم همین ماجرا تکرار شد اما این‌بار پروژه را به ما ندادند که باز هم یک موفقیت بود چون در صورت ورود ما به چنین کاری دیر یا زود کارفرما متوجه اشتباه خود می‌شد و مشکلات مالی و غیر مالی گریبان ما را هم می‌گرفت.

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

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

پیاده‌سازی Abstract Factory در Unity

هنگام استفاده از Dependency Injection گاهی اوقات لازم است که از یک Factory برای ایجاد اشیاء جدید استفاده کنیم چون مسیر Composition Root جواب کار ما را نمی‌دهد. مخصوصاً در هنگام استفاده از Strategy Pattern.

برای این کار می‌توانیم یک کلاس داشته باشیم که Container را به عنوان ورودی دریافت کند (به عنوان Constructor Dependency) و از آن برای ایجاد اشیاء استفاده کند. فقط باید دقت داشته باشیم Factory ما قرار نیست هر چیزی را ایجاد کند و در واقع یک Abstract Factory است.

اینترفیس زیر را در نظر بگیرد؛

public interface ICommand
{
    void Execute();
}

و فرض کنید که کلاس‌های زیر آن را پیاده‌سازی کرده‌اند؛

public class FirstCommand : ICommand
{
    void Execute()
    {
        // Do something...
    }
}

public class SecondCommand : ICommand
{
    void Execute()
    {
        // Do something...
    }
}

و حالا می‌خواهیم به صورت Dynamic در جایی از برنامه، و بر اساس یک پارامتر خاص یکی از دو کلاس بالا را ایجاد کنیم. دقت کنید که در حال استفاده از Dependency Injection هستیم و نمی‌توانیم از کلمه کلیدی new استفاده کنیم. پس برای این کار یک Abstract Factory می‌سازیم که با دریافت نام یک Command آن را ایجاد می‌کند. در اینجا از Convention Over Configuration استفاده می‌کنیم؛

public interface ICommandFactory
{
    ICommand Create(string name);
}

public class CommandFactory : ICommandFactory
{
    private IUnityContainer container;

    public CommandFactory(IUnityContainer container)
    {
        this.container = container;
    }

    public static Type[] GetCommandTypes()
    {
        var commandInterfaceType = typeof(ICommand);
        return commandInterfaceType.Assembly
            .GetTypes()
            .Where(t => t.GetInterfaces().Any(i => i == commandInterfaceType))
            .ToArray();
    }

    public ICommand Create(string name)
    {
        var commandName = string.Format("{0}Command", name);

        var commandType = CommandFactory
            .GetCommandTypes()
            .FirstOrDefault(c => c.Name == commandName);

        if (commandType == null)
        {
            throw new Exception("Couldn't find a command with the specified name.");
        }

        return (ICommand)this.container.Resolve(commandType);
    }
}

همان طور که می‌بینید IUnityContainer به عنوان ورودی سازنده به این کلاس تزریق خواهد شد.

البته متد GetCommandTypes با Reflection کار می‌کند و مطمئناً از کارایی بالایی برخوردار نیست ولی در نسخه نهایی این موضوع را با استفاده از Singleton بهبود داده‌ام. لینک دانلود سورس این برنامه در پایان این پست موجود است.

جهت شبیه سازی بیشتر محیط واقعی، یک کلاس دیگر برای استفاده از این Factory می‌سازیم؛

public class MyService
{
    private ICommandFactory commandFactory;

    public MyService(ICommandFactory commandFactory)
    {
        this.commandFactory = commandFactory;
    }

    public void Invoke()
    {
        var command = this.commandFactory.Create("First");
        command.Execute();

        command = this.commandFactory.Create("Second");
        command.Execute();
    }
}

در این کلاس فقط از CommandFactory جهت ایجاد دو Command به صورت Dynamic استفاده می‌شود که می‌تواند کاربردهای زیادی داشته باشد.

و اما Composition Root برنامه که برای برنامه‌های Console همان متد Main است؛

class Program
{
    static void Main(string[] args)
    {
        // Setup DI container
        var container = new UnityContainer();
        container.RegisterType<ICommandFactory, CommandFactory>();

        // Resolve my composition root object
        var myService = container.Resolve<MyService>();

        // Execute
        myService.Invoke();

        // See what happened
        Console.ReadKey();
    }
}

همانطور که مشاهده می‌کنید، در خط ۷، فقط CommandFactory ثبت (Register) شده. اما در هنگام Resolve شدن CommandFactory لازم است تا IUnityContainer هم Resolve شود ولی ما آن را ثبت (Register) نکرده‌ایم. عملیات Resolve در خط ۱۰ به ترتیب زیر اتفاق می‌افتد:

  • MyService
    • ICommandFactory
      • CommandFactory
        • IUnityContainer

پس چطور برنامه اجرا می‌شود؟ نکته جالب اینجاست که Unity در هنگام Resolve به صورت پیشفرض IUnityContainer را Resolve کرده و خودش را به جای آن تزریق می‌کند و به عبارت ساده نیازی نداریم تا IUnityContainer را مثلاً به شکل زیر ثبت کنیم؛

container.RegisterType<IUnityContainer>(new InjectionFactory(c => c));

 

نسخه کامل برنامه را از اینجا دریافت و اجر کنید. برای اجرا به Visual Studio 2012 نیاز دارید.

هر چند در این پست پیاده‌سازی Abstract Factory با استفاده از Unity شرح داده شد اما این مطالب، به هر Dependency Injection Container دیگری (مثل Ninject) نیز قابل تعمیم است.

معجزه ایمیل

امروز می‌خواستم موضوعی را با بقیه اعضای تیم (۴ نفر) بررسی کنم. در صورتی که در یک محل حضور داشتیم معمولاً روال این‌طور بود که باید اول به همه اعلام می‌کردم بعد احتمالاً هر یک از افراد صحبت‌های متفاوتی می‌کردند که نیازمند بررسی حرف‌های هر یک به صورت جداگانه بود. در این صحبت‌ها هم همیشه حرف‌های تکراری زده می‌شود چون طبیعی است یک نفر به حرف دیگری گوش نداده باشد. برای یک کار به این کوچکی هم نمی‌توان جلسه گذاشت چون هنوز نمی‌دانم به همه مربوط می‌شود یا خیر؟ اما به هر حال همین کار حدود ۱۵ تا ۲۰ دقیقه از وقتم را می‌گرفت، اگر می‌خواستم با این شرایط، انتقال مطلب دهم.

اما از بخت خوش، همگی در منزل مشغول کار بودیم و به برخی از بچه‌ها دسترسی نداشتم پس یک ایمیل برای همه زدم و موضوع را کامل توضیح دادم و خواستم در صورتی که با موضوع مورد نظر درگیر هستند، کار خاصی را انجام دهند. در کمال نا باوری این ایمیل فقط ۵ دقیقه از وقت من را گرفت! اگر شرایط طوری نبود که مجبور به ایمیل زدن باشم، احتمالاً فکر می‌کردم ایمیل وقت بیشتری از من می‌گیرد پس احتمالاً وارد آن فاز ۱۵ تا ۲۰ دقیقه‌ای می‌شدم.

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

کار تیمی – در طول یا در عرض

دیروز یک مستند در خصوص یک مأموریت نظامی دیدم. مهم‌ترین نکته آن فیلم این بود که هر تیم کار خودش را انجام می‌داد و به تیم دیگر جز در خصوص ورودی‌ها و خروجی‌ها کاری نداشت. حتی در سطح تیم نیز هر یک از افراد تیم دارای مهارت خاصی بودند. مثلاً یک تیم کماندو که در آن یکی پزشک بود، یکی زبان‌شناس و … با وجود مشکلی که در روند مأموریت آن‌ها پیش آمد آن‌ها کاملاً موفق عمل کردند!

هر چند همه می‌دانیم که برای کار تیمی بهتر است هر عضو، تخصص خاصی داشته باشد اما من تا این اواخر همیشه در کار تیمی سعی می‌کردم کارها را در طول هم تقسیم کنم. یعنی هر یک از افراد تیم همه تخصص‌های لازم برای یک پروژه را داشته باشد. به عبارت دیگر به جای اینکه مثلاً یک نفر بر روی لایه UI کار کند و یکی بر روی Business و … هر فرد بر روی همه لایه‌های Task خودش کار می‌کند. به قول یکی از دوستان می‌توان یک ساختمان را تصور کرد که هر فرد، فقط یک اتاق از کل طبقات آن را به صورت مستقل از پی تا پشت‌بام ایجاد می‌کند. شاید در ساختمان این امر نشدنی باشد اما در تولید نرم‌افزار امکان‌پذیر است.

horizontalteam

اما محاسن و معایب این شیوه؛

محاسن

  • هر فرد تمامی تخصص‌های موجود در پروژه را فرا می‌گیرد
  • وابستگی به فرد کم‌تر است و امکان جابجایی افراد به راحتی وجود دارد
  • می‌توان با افراد غیر متخصص هم کار کرد (کافی ست Taskهای ساده‌تری را به آن‌ها داد)

معایب

  • ممکن است عمق تخصص افراد زیاد نشود
  • سلیقه افراد با هم متفاوت است و این در تمام لایه‌های نرم‌افزار مشاهده می‌شود (هر چند که استانداردها و مستندات وجود داشته باشند)
  • چالش‌های تیمی بیشتر است چون در هر لایه همه افراد مشغول کار هستند و تعدد نظر وجود دارد

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

مثلاً اگر کل کارهای HTML و CSS یک پروژه وب، به یک حرفه‌ای این کار سپرده شود قطعاً او استانداردهای خودش را به راحتی در سرتاسر پروژه (اما فقط در لایه HTML و CSS) اجرا خواهد کرد و سرباری برای کنترل، نظارت و اصلاح دیگر اعضاء نخواهد داشت. حتی می‌تواند تیم کوچکی برای خود تشکیل دهد و در حوزه تخصص خودش کار کند.

متأسفانه این روش (یا همان تخصص گرایی) در کشور ما خیلی مرسوم نیست. به جای اینکه افراد حرفه‌ای پرورش داده شوند، آچار فرانسه پرورش داده می‌شود.

verticalteam

و حالا محاسن و معایب تخصص گرایی؛

محاسن

  • افراد معمولاً در یک حوزه به طور کامل متخصص می‌شوند (بر خلاف شعار همه کاره هیچ کاره)
  • چالش افراد کمتر است
  • سربار کنترل و نظارت کمتر است

معایب

  • در این روش نمی‌توان به راحتی با افراد غیر متخصص کار کرد (شاید حسن باشد!)
  • یافتن افراد متخصص ممکن است مشکل باشد
  • وابستگی به افراد، بسیار بیشتر است و در صورت جابجایی افراد هزینه‌های بیشتری تحمیل می‌شود
  • در صورتی که تعداد افراد تیم زیاد شود باید تیم‌های کوچک‌تری ایجاد شود که از خصایص روش قبلی (تقسیم کار در طول هم) برخوردارند

در صورتی که در تشکیل تیم در مضیقه باشیم روش اول (تقسیم کار در طول هم) جواب می‌دهد اما در عوض کار تیمی مشکل‌تر خواهد شد. اما اگر بتوان افراد متخصص را دور هم جمع کرد و با توجه به اینکه این افراد قرار نیست در جزئیات کار هم دخالت کنند روش دوم (تخصص گرایی) جواب خواهد داد و احتمالاً خروجی نهایی نیز از کیفیت بالایی برخوردار است.