نظرات مطالب
C# 7 - Pattern matching and switch expressions
یک نکته‌ی تکمیلی
برای اجبار به استفاده‌ی از patterns matching بجای استفاده‌ی از as و سپس بررسی null بودن، می‌توان به فایل editorconfig. تنظیم زیر را اضافه کرد:
# Use Pattern Matching to Avoid ‘As’ Followed by A ‘Null’ Check
dotnet_diagnostic.IDE0019.severity = warning
نظرات مطالب
شروع به کار با DNTFrameworkCore - قسمت 3 - پیاده‌سازی سرویس‌های موجودیت‌ها
قصد پشتیبانی از ASP.NET Core Identity را به طوری که مدنظر شما می‌باشد، ندارم. 
‌‌‌‌
مطالب تکمیلی مرتبط با روشی که قصد پشتیبانی از آن را دارم:
نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 21 - بررسی تغییرات Bundling و Minification
{
    "outputFileName": "out.js",
    "inputFiles": [ "in.js" ],
    "minify": {
        "enabled": true,
        "preserveImportantComments": true
    }
}
برای فایل‌های css هم:
 {
    "outputFileName": "output/bundle.css",
    "inputFiles": [
      "css/lib/**/*.css", // globbing patterns are supported
      "css/input/site.css"
    ],
    "minify": {
        "enabled": true,
        "commentMode": "all"
    }
  },
این تنظیمات را باید از فایل‌های سورس آن استخراج کرد. در اینجا و اینجا.
نظرات مطالب
EF Code First #11
سلام آقای نصیری. آیا این روش که در خود سایت asp.net انجام شده هم اشتباه هستش؟

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
اشتراک‌ها
پیاده سازی Domain-Driven Design با EF

The Intersection of Microservices, Domain-Driven Design and Entity Framework Core
Domain-Driven Design (DDD) provides much of the strategic design guidance that we can use to determine the boundaries around and interactions between Microservices in our solutions. DDD also follows up with tactical design patterns for your business logic. In this session we'll take a look at some of these patterns and how EF Core naturally, or with some additional configuration, persists the data that your microservices depend on. 

پیاده سازی Domain-Driven Design با EF
نظرات مطالب
معرفی ASP.NET Identity
در پست‌های آتی پیاده سازی یک تامین کننده (Provider) برای MySQL رو بررسی می‌کنم. برای اطلاعات بیشتر به Implementing a Custom MySQL ASP.NET Identity Storage Provider مراجعه کنید.
هنوز مستندات کامل و رسمی برای این فریم ورک عرضه نشده اما مطالب مفید زیادی در اینترنت وجود دارند. چند لینک در زیر لیست شده:
درباره تطابق با آموزش‌های سایت: دقیقا متوجه نشدم منظورتون کدوم الگوها است، اما چند نکته تکمیلی:
بصورت پیش فرض وقتی ASP.NET Identity به پروژه اضافه میشه کلاسی بنام ApplicationDbContext ایجاد میشه که بعنوان DbContext پیش فرض برای دیتابیس عضویت استفاده خواهد شد. اگر موجودیت جدیدی برای پروفایل کاربران بسازید باید بعنوان یک <DbSet<T به این کلاس افزوده بشه. اگر نیازی به تفکیک دیتابیس سیستم عضویت و دیتابیس اپلیکیشن نیست، بهتره از یک DbContext استفاده کنید. لایه بندی مدل ها، سرویس‌ها و کد دسترسی به داده‌ها هم ساده است چرا که کل سیستم توسط EF Code First مدیریت میشه. بنابراین استفاده از الگوهای رایج مانند تزریق وابستگی‌ها و غیره مشابه دیگر سناریو‌های EF Code First است.
نظرات مطالب
آشنایی با NHibernate - قسمت هشتم
برای اینکه از بحث دور نشیم، در NHibernate این الگوها قابل مشاهده است:
الگوی Facade که همان session و ISession معروف آن است و کار آن فراخوانی تعداد قابل ملاحظه‌ای زیر سیستم و مخفی کردن آن‌ها از دید کاربر نهایی است. به این صورت شما توانایی کار کردن با انواع بانک‌های اطلاعاتی را بدون درگیر شدن با جزئیات آن‌ها از طریق یک اینترفیس عمومی پیدا می‌کنید.
الگوی proxy که پایه و اساس lazy loading آن است.
الگوی object pool جهت مدیریت اتصالات آن به بانک اطلاعاتی
الگوی Interpreter جهت مدیریت کوئری‌های ویژه آن
و ...

الگوی Repository هم یک نوع نگارش سفارشی الگوی Facade است. در اینجا یک سیستم پیچیده (یک سطح بالاتر است از ISession که کارش مخفی کردن ساختار داخلی NHibernate است) یا همان ORM مورد نظر را دریافت کرده و یک اینترفیس ساده، قابل درک و عمومی را از آن را ارائه می‌دهد. هدف آن مخفی کردن ریز جزئیات روش کار با یک ORM خاص است. به همین جهت به آن Persistence Ignorance هم گفته می‌شود.
الگوی Repository یکی از الگوهای اصلی DDD یا Domain driven design است.
مطالب
دنیای چابک-قسمت اول
داخل وبلاگها و وب سایتهای فارسی زبان(مربوط به برنامه نویسی) که جستجو میکنیم شاهد  کلمه ای هستیم که تازه به چشممان میخورد:Agile(چابک). البته لازم به ذکر است این کلمه چیز جدیدی نیست و سابقه ای در حدود 10 سال دارد(February 2001 ).که جمعی از برنامه نویسان بیانیه ای را تحت عنوان چابک (Agile ) تهیه کردند که متن آن به شرح زیر است:

 ما با توسعه نرم افزار و کمک به دیگران در انجام آن . در حال کشف راه‌های بهتری برای توسعه نرم افزار هستیم. از این طریق باید دست یابیم به ارزش :
  1. افراد و تعاملات بالاتر از فرآیندها و ابزارها 
  2. نرم افزار کارکننده بالاتر از مستندات جامع
  3. مشارکت مشتری در انجام کار بالاتر از قرارداد کار
  4. پاسخگویی به تغییرات بالاتر از پیروی یک طرح
با وجود اینکه موارد سمت چپ نیز ارزشمند هستند ولی ما برای موارد سمت راست ارزش بیشتری قائل هستیم .
که این بیانیه بر پایه 12 اصل(Agile  principles)
  1. بالاترین اولویت ما جلب رضایت مشتری با تحویل زود و مداوم نرم افزاری ارزشمند می‌باشد 
  2. استقبال از تغییر نیازمندی ها، حتی در اواخر فرآیند توسعه. فرآیند‌های چابک، تغییر را در جهت مزیتِ رقابتی مشتری مهار میکنند
  3. تحویل زود به زود نرم‌افزار قابل استفاده دو، سه هفته یک بار تا دو ، سه ماه یک بار با ترجیح بر فاصله‌های زمانی کوتاه‌تر
  4. ذی نفعان کسب و کار و توسعه دهنده‌ها می‌بایست به صورت روزانه در طول پروژه با هم کار کنند
  5. پروژه‌ها را بر دوش افراد با انگیزه بنا کنید. فضای لازم رابه آنها بدهید و از نیازهای آن‌ها پشتیبانی کنید وبه آنها اعتماد کنید تا کارها را انجام دهند
  6. کارآمدترین و موثرترین روش انتقال اطلاعات به تیم توسعه و تبادل آن در میان اعضای تیم ، گفتگوی چهره به چهره است
  7. نرم افزار قابل استفاده اصلی‌ترین معیار سنجش پیشرفت است 
  8. فرآیند‌های چابک توسعه پایدار را ترویج می‌دهندحامیان مالی , توسعه دهندگان و کاربران باید بتوانند سرعت پیشرفت ثابتی را برای مدت نامحدودی حفظ کنند
  9. توجه مداوم به برتری فنی و طراحی خوب باعث افزایش چابکی می‌شود
  10. سادگی -- هنر به حداکثر رساندن مقدار کار انجام نشده -- ضروری است
  11. بهترین معماری‌ها , نیاز مندی‌ها و طراحی‌ها از تیم‌های خود سازمانده پدید آور می‌شود
  12. در فواصل منظم , تیم برچگونگی موثرتر شدن تامل وتفکر می‌نماید و سپس تیم رفتار خود را بر اساس بازتاب این تفکر تنظیم و هم سو می‌نماید
متاسفانه در ایران حالا یا به علت سواد کم و یا به هر علتی از این بیانیه برداشتهایی متفاوت و غلط عده ای اونو به بازی تشبیه کردن و عده ای هم با اون کار میکنن ولی هیچکدوم از اصل‌های اونو رعایت نمیکنن و بعد که پروژه شکست خورد میگن:متدولوژی خوب نبود و ... .
وقتی کتاب Agile Principles, Patterns, and Practices in C# رو مطالعه میکنید به این نتیجه میرسید که بیشترین چیزی که تاکید داره روی ارتباطات هستش.
قصد دارم در قالب چند پست به شما این اصول رو معرفی کنم.
مطالب
C# 8.0 - Pattern Matching
در نگارش‌های پیشین #C، بهبودهایی در زمینه‌ی Pattern matching وجود داشتند. در نگارش 8 نیز این بهبودها ادامه پیدا کرده‌اند که نتیجه‌ی آن به‌وجود آمدن روش جدیدی برای نوشتن عبارات switch است.


معرفی روش جدید نوشتن عبارات switch در C#8.0

فرض کنید یک enum که معرف تعدادی رنگ است را تعریف کرده‌ایم:
    public enum Rainbow
    {
        Red,
        Orange,
        Yellow,
        Green,
        Blue,
        Indigo,
        Violet
    }
همچنین کلاسی را نیز جهت تشکیل اشیاء رنگ مبتنی بر RGB تدارک دیده‌ایم:
    class RGBColor
    {
        internal byte Red { get; }
        internal byte Green { get; }
        internal byte Blue { get; }

        internal RGBColor(byte red, byte green, byte blue)
        {
            Red = red;
            Green = green;
            Blue = blue;
        }

        public override string ToString() => $"rgb({Red}, {Green}, {Blue})";
    }
اکنون هدف ما این است که اگر یکی از اعضای این enum را انتخاب کردیم، بتوانیم معادل رنگ RGB آن‌را نیز داشته باشیم. برای این منظور می‌توان switch ساده‌ی زیر را تشکیل داد:
        internal static RGBColor FromRainbow(Rainbow rainbowBolor)
        {
            switch (rainbowBolor)
            {
                case Rainbow.Red:
                    return new RGBColor(0xFF, 0x00, 0x00);
                case Rainbow.Orange:
                    return new RGBColor(0xFF, 0x7F, 0x00);
                case Rainbow.Yellow:
                    return new RGBColor(0xFF, 0xFF, 0x00);
                case Rainbow.Green:
                    return new RGBColor(0x00, 0xFF, 0x00);
                case Rainbow.Blue:
                    return new RGBColor(0x00, 0x00, 0xFF);
                case Rainbow.Indigo:
                    return new RGBColor(0x4B, 0x00, 0x82);
                case Rainbow.Violet:
                    return new RGBColor(0x94, 0x00, 0xD3);
                default:
                    throw new ArgumentException(message: "invalid enum value", paramName: nameof(rainbowBolor));
            };
        }
این کاری است که تا پیش از C# 8.0 به صورت متداولی انجام می‌شود. اکنون در C# 8.0 می‌توان عبارت switch فوق را به صورت زیر خلاصه کرد:
        internal static RGBColor TasteTheRainbow(Rainbow rainbowColor) =>
            rainbowColor switch
        {
            Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
            Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
            Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
            Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
            Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
            Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
            Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
            _ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(rainbowColor)),
        };
- در این روش جدید، بجای اینکه با ذکر switch و سپس، مقداری/نوعی شروع شود، ابتدا با نوع شروع می‌شود و سپس واژه‌ی کلیدی switch ذکر خواهد شد.
- در ادامه تمام caseها حذف می‌شوند و بجای آن‌ها صرفا مقادیر مدنظر باقی می‌ماند. در اینجا <= به صورت expressed as خوانده می‌شود.
- caseهای مختلف با کاما از هم جدا می‌شوند.
- همچنین در سطر آخر آن نیز از یک discard استفاده شده‌است که معادل همان حالت default یا حالتی است که هیچ تطابقی صورت نگرفته باشد.
- به علاوه اگر دقت کنید، نتیجه‌ی نهایی این switch جدید، به صورت یک مقدار، توسط متد TasteTheRainbow، بازگشت داده شده‌است. بنابراین نوشتن یک چنین عباراتی در C# 8.0، مجاز است:
var operation = "+";
int a = 1, b = 2;
var result = operation switch
{
   "+" => a + b,
   "-" => a - b,
   "/" => a / b,
     _ => throw new NotSupportedException()
};


معرفی Property Patterns در C# 8.0

کلاس زیر را درنظر بگیرید که از تعدادی خاصیت عمومی تشکیل شده‌است:
    class Address
    {
        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string CountryRegion { get; set; }
    }
اکنون فرض کنید که می‌خواهیم مالیات فروش را بر اساس آدرس و محل آن، محاسبه کنیم. در C# 8.0 با معرفی قابلیت الگوهای خواص، می‌توان بر روی آدرس، یک switch را تشکیل داد و سپس تک تک خواص آن‌را ارزیابی کرد:
    static class PropertyPatterns
    {
        internal static decimal ComputeSalesTax(
            Address location,
            decimal salePrice) =>
            location switch
        {
            { State: "Fars" } => salePrice * 0.06m,
            { State: "Tehran", City: "Tehran" } => salePrice * 0.056m,

            // Other cases removed for brevity...
            _ => 0M
        };
    }
در اینجا، سمت چپ هر case، داخل یک {} قرار می‌گیرد و در آن می‌توان مقادیر چندین خاصیت شیء location دریافتی را بررسی کرد. برای نمونه در سطر دوم آن، روش ارزیابی بیش از یک خاصیت را نیز مشاهده می‌کنید که روش ذکر آن شبیه به تعریف شیء‌های JSON است. در آخر نیز توسط یک discard، حالت default ذکر شده‌است.


معرفی Tuple Patterns در C# 8.0

در switch‌های C# 8.0، می‌توان از tuples نیز برای تشکیل قسمت case و همچنین مقداری که قرار است switch بر روی آن صورت گیرد، استفاده کرد:
    static class TuplePatterns
    {
        internal static string RockPaperScissors(
            string first,
            string second)
            => (first, second) switch
        {
            ("rock", "paper") => "Rock is covered by Paper. Paper wins!",
            ("rock", "scissors") => "Rock breaks Scissors. Rock wins!",
            ("paper", "rock") => "Paper covers Rock. Paper wins!",
            ("paper", "scissors") => "Paper is cut by Scissors. Scissors wins!",
            ("scissors", "rock") => "Scissors is broken by Rock. Rock wins!",
            ("scissors", "paper") => "Scissors cuts Paper. Scissors wins!",
            (_, _) => "tie"
        };
    }
در اینجا بر روی tuple ای که به صورت (first, second) تعریف شده، یک switch تعریف می‌شود. سپس برای نمونه 6 حالت مختلف برای آن پیش‌بینی شده و یک حالت default که آن نیز توسط discards معرفی می‌شود.


بهبودهای Pattern Matching بر روی اشیاء در C# 8.0

فرض کنید شیء پایه‌ی Shape را تعریف و بر اساس آن دو شیء جدید دایره و مستطیل را ایجاد کرده‌ایم:
    class Shape
    {
        protected internal double Height { get; }
        protected internal double Length { get; }

        protected Shape(double height = 0, double length = 0)
        {
            Height = height;
            Length = length;
        }
    }

    class Circle : Shape
    {
        internal double Radius => Height / 2;
        internal double Diameter => Radius * 2;
        internal double Circumference => 2 * Math.PI * Radius;

        internal Circle(double height = 10, double length = 10)
            : base(height, length) { }
    }

    class Rectangle : Shape
    {
        internal bool IsSquare => Height == Length;

        internal Rectangle(double height = 10, double length = 10)
            : base(height, length) { }
    }
امکان Pattern Matching بر روی اشیاء، در C# 7x نیز وجود دارد؛ اما در C# 8.0 می‌توان از روش جدید بیان عبارت switch آن به صورت زیر نیز در این حالت استفاده کرد:
    static class ObjectPatterns
    {
        internal static string ShapeDetails(this Shape shape)
            => shape switch
        {
            Circle c => $"circle with (C): {c.Circumference}",
            Rectangle s when s.IsSquare => $"L:{s.Length} H:{s.Height}, square",
            Rectangle r => $"L:{r.Length} H:{r.Height}, rectangle",
            _ => "Unknown shape!" // Discard
        };
    }
در اینجا یک شیء، به متد ShapeDetails ارسال شده و سپس جزئیاتی از آن دریافت می‌شود. مطابق روش C# 8.0، در اینجا نیز کار با ذکر نوع و سپس عبارت switch، شروع می‌شود. در ادامه روش بررسی نوع‌ها را در caseهای این سوئیچ ملاحظه می‌کنید. اگر در قسمت case آن Circle c ذکر شد، یعنی نوع shape از نوع دایره بوده و همچنین در همینجا می‌توان متغیر c را بر این اساس تعریف کرد و از آن استفاده نمود و یا می‌توان به کمک واژه‌ی کلیدی when، بر روی این متغیری که جدید تعریف شده، شرطی را نیز بررسی کرد. حالت default آن هم توسط discards معرفی می‌شود.


معرفی Positional Patterns در C# 8.0

در اینجا یک Point را داریم که می‌خواهیم بر اساس آن یک Quadrant را استخراج کنیم:
    class Point
    {
        public int X { get; }

        public int Y { get; }

        public Point(int x, int y) => (X, Y) = (x, y);

        public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
    }

    enum Quadrant
    {
        Unknown,
        Origin,
        One,
        Two,
        Three,
        Four,
        OnBorder
    }
برای این منظور می‌توان از الگوهای موقعیتی C# 8.0 استفاده کرد:
    static class PositionalPatterns
    {
        internal static Quadrant AsQuadrant(Point point) => point switch
        {
            (0, 0) => Quadrant.Origin,
            var (x, y) when x > 0 && y > 0 => Quadrant.One,
            var (x, y) when x < 0 && y > 0 => Quadrant.Two,
            var (x, y) when x < 0 && y < 0 => Quadrant.Three,
            var (x, y) when x > 0 && y < 0 => Quadrant.Four,
            (_, _) => Quadrant.OnBorder, // Either are 0, but not both
            _ => Quadrant.Unknown
        };
    }
اگر به کلاس Point دقت کنید، یک قسمت Deconstruct هم دارد. به همین جهت در قسمت‌های case این switch، زمانیکه برای مثال (0,0) ذکر می‌شود (که یک tuple literal است)، به صورت خودکار یک شیء Point متناظر را با مقادیر X و Y آن، تشکیل می‌دهد. همچنین روش‌های مختلف مقایسه‌ی مقادیر x و y این tuple را نیز در caseهای مختلف آن مشاهده می‌کنید.
در اینجا اگر دقت کنید و case مخصوص discards معرفی شده‌است. اولی برای حالت‌هایی است که هیچکدام از شرایط پیش از آن را برآورده نمی‌کند، مانند حالت (1,0)، در غیراینصورت سطر بعد از آن بازگشت داده می‌شود.
مطالب
چرا توسعه چابک (Agile Development)؟

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

همین که با شکستی مواجه می­شویم از تکرار چنین پروژه هایی اجتناب می­کنیم. ترس ما باعث می­شود تا فرآیندی بسازیم که فعالیت­های ما را محدود نموده و ایجاد آرتیفکت­ها[۱] را الزامی کند. در پروژه­ جدید از  چیزهایی که در پروژه‌های قبلی به خوبی کار کرده­اند، استفاده می­کنیم. انتظار ما این است که آنها برای پروژه جدید نیز به همان خوبی کار کند.

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

فرآیندهای بزرگ و حجیم می­تواند مشکلات زیادی را ایجاد کند. متاسفانه این مشکلات باعث می­شود که خیلی از افراد فکر کنند که علت مشکلات، نبود فرآیندهای کافی است. بنابراین فرآیندها را حجیم­تر و پیچیده­تر می­کنند. این مسئله منجر به تورم فرآیندها می­گردد که در محدوده سال ۲۰۰۰ گریبان بسیاری از شرکت­های نرم افزاری را گرفت.

اتحاد چابک

در وضعیتی که تیم­های نرم افزاری در بسیاری از شرکت­ها خود را در مردابی از فرآیندهای زیاد شونده می­دیدند، تعدادی از خبره‌­های این صنعت که خود را اتحاد چابک[۲] نامیدند در اویل سال ۲۰۰۱ یکدیگر را ملاقات کرده و ارزش هایی را معرفی کردند تا تیم­های نرم افزاری سریعتر نرم افزار را توسعه داده و زودتر به تغییرات پاسخ دهند. چند ماه بعد، این گروه ارزش­هایی تعریف شده را تحت مانیفست اتحاد چابک در سایت http://agilemanifesto.org منتشر کردند.

مانیفست اتحاد چابک

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

۱- افراد و تعاملات بالاتر از فرآیندها و ابزارها

۲- نرم افزار کار کننده بالاتر از  مستندات جامع

۳- مشارکت مشتری بالاتر از قرارداد کاری

۴- پاسخگویی به تغییرات بالاتر از پیروی از یک برنامه

با آنکه موارد سمت چپ ارزشمند هستند ولی ما برای موارد سمت راست ارزش بیشتری قائل هستیم.

افراد و تعاملات بالاتر از فرآیندها و ابزارها

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

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

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

نرم افزار کار کننده بالاتر از  مستندات جامع

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

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

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

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

مشارکت مشتری بالاتر از قرارداد کاری

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

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

قراردادی که مشخص کننده نیازمندیها، زمانبندی و قیمت پروژه است، اساسا نقص دارد. بهترین قرارداد این است که تیم توسعه و مشتری با یکدیگر کار کنند.

پاسخگویی به تغییرات بالاتر از پیروی از یک برنامه

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

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

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

اصول چابک

۱- بالاترین اولویت ما عبارت است از راضی کردن مشتری با تحویل سریع و مداوم نرم افزار با ارزش. تحویل نرم افزار با کارکردهای کم در زود هنگام بسیار مهم است چون هم مشتری چشم اندازی از محصول نهایی خواهد داشت و هم مسیر کمتر به بیراهه می‌رود.

۲- خوش آمدگویی به تغییرات حتی در انتهای توسعه. اعضای تیم چابک، تغییرات را چیز خوبی می‌بینند زیرا تغییرات به این معنی است که تیم بیشتر یاد گرفته است که چه چیزی مشتری را راضی می‌کند.

۳- تحویل نرم افزار قابل استفاده از چند هفته تا چند ماه با تقدم بر تحویل در دوره زمانی کوتاهتر. ما مجموعه از مستندات و طرحها را به مشتری نمی‌دهیم.

۴- افراد مسلط به بیزنس و توسعه دهندگان باید روزانه با یکدیگر روی پروژه کار کنند. یک پروژه نرم افزاری نیاز به هدایت مداوم دارد.

۵- ساخت پروژه را بر توان افراد با انگیزه بگذارید و به آنها محیط و ابزار را داده و اعتماد کنید.  مهمترین فاکتور موفقیت افراد هستند، هر چیز دیگر مانند فرآیند، محیط و مدیریت  فاکتورهای بعدی محسوب می­شوند که اگر تاثیر بدی روی افراد می­گذارند، باید تغییر کنند.

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

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

۸- فرآیندهای چابک توسعه با آهنگ ثابت را ترویج می‌دهد. حامیان، توسعه دهندگان و کاربران باید یک آهنگ توسعه ثابت را حفظ کنند که بیشتر شبیه به دو  ماراتون است یا دوی ۱۰۰ متر. آنها با سرعتی کار می‌کنند که بالاترین کیفیت را ارائه دهند.

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

۱۰-  سادگی هنر بیشینه کردن مقدار کاری که لازم نیست انجام شود، است. تیم چابک همیشه ساده‌ترین مسیر که با هدف آنها سازگار است را در پیش می­گیرند. آنها وقت زیادی روی مشکلاتی که ممکن است فردا رخ دهد، نمی­گذارند.  آنها کار امروز را با کیفیت انجام داده و مطمئن می­شوند که تغییر آن در صورت بروز مشکلات در فردا، آسان خواهد بود.

۱۱-  بهترین معماری و طراحی از تیم‌های خود سازمان ده بیرون می‌آید. مدیران، مسئولیت‌ها را به یک فردی  خاصی در تیم نمی‌دهند بلکه بر عکس با تیم به صورت یک نیروی واحد برخورد می­کنند. خود تیم تصمیم می­گیرد که هر مسئولیت را چه کسی انجام دهد. تیم چابک با هم روی کل جنبه‌های پروژه کار می­کنند. یعنی یک فرد خاص مسئول معماری، برنامه نویسی، تست و غیره نیستند. تیم، مسئولیتها را به اشتراک گذاشته و هر فرد بر کل کار تاثیر دارد.

۱۲-  در بازهای زمانی مناسب تیم در می­یابد که چگونه می­تواند کاراتر باشد و رفتار خود را متناسب با آن تغییر دهد. تیم می­داند که محیط دائما در حال تغییر است، بنابراین خود را با محیط تغییر می­دهد تا چابک بماند.

ضرورت توسعه چابک

امروزه صنعت نرم افزار دارای سابقه بدی در تحویل به موقع و با کیفیت نرم افزار است. گزارشات بسیاری تایید می­کنند که بیش از ۸۰ درصد از پروژه‌های نرم افزاری با شکست مواجه می­شوند؛ در سال ۲۰۰۵ موسسه IEEE  برآورد زده است که بیش از ۶۰ بیلیون دلار صرف پروژه‌های نرم افزاری شکست خورده شده است. عجب فاجعه­ای؟

شش دلیل اصلی شکست پروژه‌های نرم افزاری

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

۱- درگیر نشدن  مشتری

۲- عدم درک درست نیازمندها

۳- زمان بندی غیر واقعی

۴- عدم پذیریش و مدیریت تغییرات

۵- کمبود تست نرم افزار

۶- فرآیندهای غیر منعطف و باد دار

چگونه چابکی این مشکلات را رفع می­کند؟

با آنکه Agile برای هر مشکلی راه حل ندارد ولی برای مسائل فوق بدین صورت کمک می­کند:

مشتری پادشاه است!

برای رفع مشکل عدم همکاری کاربر نهایی یا مشتری، Agile مشتری را عضوی از تیم توسعه می­کند. به عنوان عضوی از تیم، مشتری با تیم توسعه کار می­کند تا مطمئن شود که نیازمندها به درستی برآورده می­شوند. مشتری همکاری می­کند در شناسایی نیازمندی­ها، تایید می­کند نتیجه نهایی را و حرف آخر را در اینکه کدام ویژگی به نرم افزار اضافه شود، حذف شود و یا تغییر کند، را می­زند.

نیازمندی‌ها به صورت تست­های پذیرش[۳] نوشته می­شوند

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

زمانبندی با مذاکره بین تیم توسعه و سفارش دهنده تنظیم می­شود

برای حل مشکل زمان بندی غیر واقعی، Agile زمان بندی را به صورت یک فرآیند مشترک بین تیم توسعه و سفارش دهنده تعریف می­کند. در شروع هر نسخه از  نرم افزار، سفارش دهنده ویژگی‌های مورد انتظار را به تیم توسعه می­گوید. تیم توسعه تاریخ تحویل را بر اساس ویژگی­ها برآورد می­زد و در اختیار سفارش دهنده قرار می­دهد. این تعامل تا رسیدن به یک دیدگاه مشترک ادامه می­یابد.

هیچ چیزی روی سنگ حک نشده است، مگر تاریخ تحویل

برای رفع مشکل ضعف در مدیریت تغییرات، Agile اصرار دارد که هر کسی باید تغییرات را بپذیرد و نسبت به آنها واقع بین باشد. یک اصل مهم Agile  می­گوید که هر چیزی می­تواند تغییر کند مگر تاریخ تحویل! به عبارت دیگر همین که محصول به سمت تولید شدن حرکت می­کند، مشتری (در تیم محصول) می­تواند بر اساس اولویت­ها و ارزش­های خود ویژگی­های محصول را کم یا زیاد کرده و یا تغییر دهد. به هر حال او باید واقع بین باشد. اگر او یک ویژگی جدید اضافه کنید، باید تاریخ تحویل را تغییر دهد. به این ترتیب همیشه تاریخ تحویل رعایت می­گردد.

تست­ها قبل از کد نوشته می­شوند و کاملا خودکار هستند

برای رفع مشکل کمبود تست، Agile تاکید می­کند که ابتدا باید تست­ها نوشته شوند و همواره ارزیابی گردند. هر برنامه نویس باید اول تست­ را بنویسد، سپس کد لازم برای پاس شدن آن را. همین که کد تغییر می­کند باید تست­ها دوباره اجرا شوند. در این راهکار، هر برنامه نویس مسئول تست­های خود است تا درستی برنامه از ابتدا تضمین گردد.

مدیریت پروژه یک فعالیت جداگانه نیست

برای رفع مشکل فرآیندهای غیر منعطف و باددار، Agile مدیریت پروژه را درون فرآیند توسعه می­گنجاند. وظایف مدیریت پروژه بین اعضای تیم توسعه تقسیم می­شود. برای مثال هر ۷ نفر در تیم توسعه نرم افزار (متدلوژی اسکرام) زمان تحویل را با مذاکره تعیین می­کنند. همچنین کد برنامه به صورت خودکار اطلاعات وضعیت پروژه را تولید می­کند. به عنوان مثال  نمودار burndown ، تست­های انجام نشده، پاس شده و رد شده به صورت خودکار تولید می­شوند.

به کار گیری توسعه چابک

یکی از مشکلات توسعه چابک این است که شما اول باید به خوبی آن را درک کنید تا قادر به پیاده سازی درست آن باشید. این درک هم باید کلی باشد (مانند Scrum و XP) و هم جزئی (مانند TDD و جلسات روازنه). اما چگونه باید به این درک برسیم؟ کتاب­ها و مقالات انگلیسی زیادی برای یادگیری توسعه چابک و پیاده سازی آن در سازمان وجود دارند، ولی متاسفانه منابع فارسی کمی در این زمینه است. هدف این کتاب رفع این کمبود و آموزش عملی توسعه چابک و ابزارهای پیاده سازی آن است.

برای این یک توسعه دهنده چابک شوید، باید به مهارت­های فردی و تیمی چابک برسید. در ادامه این مهارت­ها معرفی می­شوند.

مهارت­های فردی

قبل از هر چیز شما باید یک برنامه نویس باشید و مقدمات برنامه نویسی مانند الگوریتم و فلوچارت، دستورات برنامه نویسی، کار با متغیرها، توابع و آرایه­‌ها را بلد باشید. پس از تسلط به مقدمات برنامه نویسی می­توانید مهارت­های برنامه نویسی چابک را فرا بگیرید که عبارتند از:

- برنامه نویسی شیءگرا

- توسعه تست محور

- الگوهای طراحی

در ادامه نحوه کسب این مهارت­ها بیان می­شوند.

برنامه نویسی شیءگرا

اساس طراحی چابک بر تفکر شیءگرا استوار است. بنابراین تسلط به مفاهیم و طراحی شیءگرا ضروری است. 

توسعه تست محور

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

الگوهای طراحی

الگوهای طراحی راه حل­های انتزاعی سطح بالا هستند. این الگوها بهترین تکنیک­های[۴] طراحی نرم افزار هستند و بسیاری از مشکلاتی که در طراحی نرم افزار رخ می­دهند با استفاده از این الگوها قابل حل هستند.

مهارت­های تیمی

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

اسکرام

تمامی مهارت­های تیمی توسعه چابک توسط اسکرام آموزش داده می­شوند. اسکرام فریم ورکی برای توسعه چابک است که با تعریف فرآیندها، نقش­ها و آرتیفکت­های مشخص به تیم­های نرم افزاری کمک می­کند تا چابک شوند.


[۱] Artifact : خروجی یک فرآیند  است. مثلا خروجی طراحی شیءگرا، نمودارهای UML است.

[۲] Agile Alliance

[3] Acceptance Tests

[4] Best Practice

--------------------------------

اطلاعات بیشتر در http://AgileDevelopment.ir