مطالب
تغییرات اعمال شده در C++11 قسمت اول (enum)
نوع شمارشی enum
نوع شمارشی، یک نوع صحیح است و شامل لیستی از ثوابت می‌باشد که توسط برنامه نویس مشخص می‌گردد . انواع شمارشی برای تولید کد  خودمستند  به کار می‌روند یعنی کدی که به راحتی قابل درک باشد و نیاز به توضیحات اضافه نداشته باشد. زیرا به راحتی توسط نام ، نوع کاربرد و محدوده مقادیرشان قابل درک می‌باشند . مقادیر نوع شمارشی منحصربه فرد می‌باشند (unique) و شامل مقادیر تکراری نمی‌باشند در غیر این صورت  کامپایلر خطای مربوطه را هشدار میدهد . نحوه تعریف نوع شمارشی :
enum typename{enumerator-list}
enum کلمه کلیدی ست ، typename  نام نوع جدید است که برنامه نویس مشخص میکند و enumerator-list مجموعه مقادیری ست که این نوع جدید می‌تواند داشته باشد بعنوان مثال :
enum Day{SAT,SUN,MON,TUE,WED,THU,FRI}
اکنون Day  یک نوع جدید است و متغیرهایی که از این نوع تعریف می‌شوند میتوانند یکی از مقادیر مجموعه فوق را دارا باشند .
Day  day1,day2; 
day1 = SAT; 
day2 = SUN;
مقادیرSAT و SUN و MON  هر چند که به همین شکل بکار میروند ولی در رایانه به شکل اعداد صحیح  0 , 1 , 2 , ... ذخیره می‌شوند . به همین دلیل است که به هر یک از مقادیر SAT و SUN و ...  یک شـمارشـگر می‌گویند . وقتی فهرست شمارشگرهای یک نوع تعریف شد به طور خودکار مقادیر 0 و 1 و ... به ترتیب به آنها اختصاص داده میشود . می‌توان مقادیر صحیح دلخواهی به شمارشگرها نسبت داد به طور مثال :
enum Day{SAT=1,SUN=2,MON=4,TUE=8,WED=16,THU=32,FRI=64}
اگر چند شمارشگر مقدار دهی شده باشند آنگاه شمارشگرهایی که مقدار دهی نشده اند ، مقادیر متوالی بعدی را خواهند گرفت .
enum Day{SAT=1,SUN,MON,TUE,WED,THU,FRI}
دستور بالا مقادیر 1 تا 7 را بترتیب به شمارشگرها اختصاص میدهد .
میتوان به شمارشگرها مقادیر یکسانی نسبت داد
enum Answer{NO=0,FALSE=0,YES=1,TRUE=1,OK=1}
ولی نمی‌توان نامهای یکسانی را در نظر گرفت  ! تعریف زیر بدلیل استفاده مجدد از شمارشگر YES با خطای کامپایلر مواجه می‌شویم .
enum Answer{NO=0,FALSE=0,YES=1,YES=2,OK=1}
چند دلیل استفاده از نوع شمارشی عبارت است از :
1- enum سبب میشود که شما مقادیر مجاز و قابل انتظار را به متغیرهایتان نسبت دهید .
2- enum  اجازه میدهد با استفاده از نام به مقدار دستیابی پیدا کنید پس کدهایتان خواناتر میشود .
3- با استفاده از enum  تایپ کدهایتان سریع میشود زیرا IntelliSense در مورد انتخاب گزینه مناسب شما را یاری میدهد .

چند تعریف از enum :
enum Color{RED,GREEN,BLUE,BLACK,ORANGE} 
enum Time{SECOND,MINUTE,HOUR} 
enum Date{DAY,MONTH,YEAR} 
enum Language{C,DELPHI,JAVA,PERL} 
enum Gender{MALE,FEMALE}
تا اینجا خلاصه ای از enum و مفهوم آن داشتیم

اما تغییراتی که در  c++11 اعمال شده : Type-Safe Enumerations 

فرض کنید دو enum  تعریف کرده اید و به شکل زیر می‌باشد
enum Suit {Clubs, Diamonds, Hearts, Spades};
enum Jewels {Diamonds, Emeralds, Opals, Rubies, Sapphires};
اگر این دستورات را کامپایل کنید با خطا مواجه می‌شوید چون در هر دو enum  شمارشگر Diamonds تعریف شده است . کامپایلر اجازه تعریف جدیدی از یک شمارشگر در enum  دیگری نمیدهد هر چند برخی اوقات مانند مثال بالا نیازمند تعریف یک شمارشگر در چند enum  بر حسب نیاز میباشیم .
برای تعریف جدیدی که در  c++11 داده شده کلمه کلیدی  class  بعد از کلمه enum  مورد استفاده قرار میگیرد . به طور مثال تعریف دو enum  پیشین که با خطا مواجه میشد بصورت زیر تعریف میشود و از کامپایلر خطایی دریافت نمیکنیم .
enum class Suit {Clubs, Diamonds, Hearts, Spades};
enum class Jewels {Diamonds, Emeralds, Opals, Rubies, Sapphires};
همچنین استفاده از enum در گذشته و تبدیل آن به شکل زیر بود :
enum Suit {Clubs, Diamonds, Hearts, Spades};
Suit var1 = Clubs;
int var2= Clubs;
یک متغیر از نوع Suit بنام var1  تعریف میکنیم و شمارشگر Clubs را به آن نسبت میدهیم ، خط بعد متغیری از نوع int تعریف نمودیم و مقدار شمارشگر Clubs که 0 می‌باشد را به آن نسبت دادیم . اما اگر تعریف enum  را با قوائد C++11  در نظر بگیریم این نسبت دادنها باعث خطای کامپایلر میشود و برای نسبت دادن صحیح باید به شکل زیر عمل نمود .
enum class Jewels {Diamonds, Emeralds, Opals, Rubies, Sapphires};
Jewels typeJewel = Jewels::Emeralds;
int suitValue = static_cast<int>(typeJewel);
همانطور که مشاهده میکنید ، Type-Safe یودن enum  را نسبت به تعریف گذشته آن مشخص می‌باشد .
یک مثال کلی و جامع‌تر :
// Demonstrating type-safe and non-type-safe enumerations
#include <iostream>
using std::cout;
using std::endl;
// You can define enumerations at global scope
//enum Jewels {Diamonds, Emeralds, Rubies}; // Uncomment this for an error
enum Suit : long {Clubs, Diamonds, Hearts, Spades};
int main()
{
// Using the old enumeration type...
Suit suit = Clubs; // You can use enumerator names directly
Suit another = Suit::Diamonds; // or you can qualify them
// Automatic conversion from enumeration type to integer
cout << "suit value: " << suit << endl;
cout << "Add 10 to another: " << another + 10 << endl;
// Using type-safe enumerations...
enum class Color : char {Red, Orange, Yellow, Green, Blue, Indigo, Violet};
Color skyColor(Color::Blue); // You must qualify enumerator names
// Color grassColor(Green); // Uncomment for an error
// No auto conversion to numeric type
cout << endl
<< "Sky color value: "<< static_cast<long>(skyColor) << endl;
//cout << skyColor + 10L << endl; // Uncomment for an error
cout << "Incremented sky color: "
<< static_cast<long>(skyColor) + 10L // OK with explicit cast
<< endl;
return 0;
}
نظرات اشتراک‌ها
زبان برنامه نویسی Erlang
NodeJS یک فریم ورک سمت سرور بر پایه زبان جاوا اسکرپیت می‌باشد. قبلا جاوا اسکریپت فقط توسط مفسرهای مرورگرهای وب تفسیر می‌شد (یعنی فقط می‌تونستیم باهاش کدهای سمت کاربر بنویسیم)، اما حالا با NodeJs می‌تونید کدنویسی سمت سرور کنید. از طرفی چون با جاوا اسکریپت کدنویسی می‌کنید قابلیت استقلال از پلتفرم رو براتون به ارمغان میاره. ارتباط بین سرور و کلاینت موقعی که از NodeJs در طرف سرور استفاده می‌کنید دو طرفه هست، بدین معنی که علاوه بر اینکه کلاینت می‌تونه به سرور درخواست بده بعد سرور به درخواست اون پاسخ بده، سرور هم می‌تونه بدون داده شدن یک درخواست توسط کلاینت داده ای رو به طرف کلاینت ارسال کنه.

زبان Erlang در سال 1986 توسط شرکت Ericson سوئد به منظور استفاده در سرور‌های switching تلفن ساخته شد. این زبان توسط تیمی به سرپرستی  Joe Armstrong معرفی شد تا بتواند از برنامه‌های توزیع‌شده، مقاوم در برابر خطا، بلادرنگ و بی‌وقفه پشتیبانی کند. بعدها این زبان به شکل متن‌باز در اختیار عموم قرار گرفت. یکی از روش‌های برنامه نویسی که توسط این برنامه میشه ازش استفاده کرد، روش تابعی (Functional Programming) هست. این روش قبلا وجود داشت و مدتی هم از مد افتاد، ولی با اومدن پردازنده‌های چند هسته ای استفاده از زبان‌های برنامه نویسی که میشه با اونها تابعی نوشت از سر گرفته شد و حتی مایکروسافت در سال 2010 زبان برنامه نویسی #F رو معرفی کرد. یکی از قابلیتهای زبانهای تابعی سرعت اجرا شدن کدهای اونها هست که اونها رو از زبانهای امری مثل #C و Java جدا می‌کنه.

Scala هم یک زبان برنامه نویسی همه منظوره هست که ویژگی هایی رو از زبان‌های برنامه نویسی شیء گرا داره و همچنین توسط اون میشه برنامه نویسی تابعی انجام داد. از اون به عنوان جانشینی برای جاوا یاد می‌کنند چون قابلتهای اضافه بر جاوا رو داره.
مطالب
چندین Submit در یک Html Form و انتساب Action های مجزا به هر یک از Submit ها در MVC
تا به حال به این نکته برخورد کردید که برای یک فرم Html نیاز به چندین Submit داشته باشید که هر کدوم یک Action مجزا داشته باشن و یک کار متفاوت انجام بدن ؟
برای مثال فرمی داریم که داده‌های وارد شده در ان باید به دو صورت برای یک کاربر ارسال بشن یا از طریق پیامک یا از طریق ایمیل (این فقط یک مثال پیش فرض هست) و .... در حالت عادی ما در یک فرم نمیتونیم دو عدد Submit  داشته باشیم که هر کدوم به یک Action جدا بسط داده بشه خب راه حل چیه ؟ شاید با خودتون بگید خب دو input از نوع radio قرار میدیم و در یک اکشن کنترل میکنیم که کدوم یکی انتخاب شده و عملیات رو با اون معیار انجام میدیم ... به نظرتون زیباتر نیست برای هر عملیات که ممکن باشه هر کدوم کاملا روال کاری متفاوتی داشته باشه یک Action وجود داشته باشه ؟ در این صورت خوانایی کد خیلی بالاتر میره و Unit Test هر Action کاملا مشخص هست که قراره چه فرایندی رو مورد تست قرار بده و مجبور نیستیم چندین حالت رو با عبارات شرطی از هم جدا کنیم و همه چی قاطی بشه با هم ... من در کل با امکاناتی که C# و MVC در اختیارم قرار میده حاظر نیستم تن به کد نویسی به صورت کلاسیک و قاطی پاتی بدم سعی میکنم با مطالعه‌ی سورس MVC بهترین حالت رو انتخاب کنم شما چطور ؟ معلومه که همه همینو میخوان پس بریم سر اصل مطلب .
قطعه کد Html و Razor ساده‌ی زیر رو در نظر بگیرید برای View :
@model Models.MyModel
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <title>ViewPage1</title>
</head>
<body>
    <div>
        @using (Html.BeginForm("SendMessage", "Home", FormMethod.Post))
        {

            @Html.LabelFor(x => x.Name); 
            @Html.TextBoxFor(x => x.Name);

            <input type="submit" value="ارسال توسط پیامک" name="Send_sms" />
            <input type="submit" value="ارسال توسط ایمیل" name="Send_email" />
        }
    </div>
</body>
</html>

خب ما دو تا Submit داریم . یکم اگه شیطنت کنید و مقادیر ارسال شده بعد از submit این فرم رو توسط ابزارهای مانیتورینگ بررسی کنید میبینید که روی هر کدوم از Submit‌ها که کلیک میشه داده ای با نام اون که در خاصیت name اون و مقدار موجود در value اون همراه اون فرم به سرور ارسال میشه و اون یکی Submit از این اتفاق بی نصیب میمونه ... خب ما هم استفاده‌ی لازم رو از این موضوع شیرین میبریم و با یک تکنیک تهاجمی از این موضوع برای رسیدن به هدفمون استفاده میکنیم .

این هم کلاس Model ماست :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;

namespace Models
{
    public class MyModel
    {
        [DisplayName("نام خود را وارد کنید :")]
        public string Name { get; set; }
    }
}
 و اما یک نکته‌ی دیگه . توجه داشته باشید که ما در قسمت View نام Action رو در فرم, SendMessage مشخص کردیم . ولی ... اصلا در واقع همچین اکشنی وجود نداره ! پس چرا ما همچین نامی رو واسه اکشن فرم گذاشتیم !؟
دلیل اینه که ما قصد داریم با یک ActionNameSelectorAttribute درخواست کاربر رو شکار کنیم و اون رو به اکشن دلخواه ارجاع بدیم ... جالبه نه ؟ ولی چه جوری ... کلاس زیر رو بهش دقت مضاعف کنید و در پروژتون ایجادش کنید :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Reflection;

namespace ActionHandlers
{
    public class SendMessageHandlerAttribute : ActionNameSelectorAttribute
    {
        public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
        {
            if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
                return true;

            if (!actionName.Equals("SendMessage", StringComparison.InvariantCultureIgnoreCase))
                return false;

            var request = controllerContext.RequestContext.HttpContext.Request;
            return request[methodInfo.Name] != null;
        }
    }
}
 خب حالا بخش Controller رو بهش دقت کنید که ما در اون دو اکشن رو با نام هایی که برای هر Submit مشخص کردیم مینویسیم و ActionNameSelectorAttribute نوشته شده رو به اونها بسط میدیم. 
    [SendMessageHandler ]
        [HttpPost]
        public ContentResult Send_sms(MyModel mdl)
        {
            /// Do something ...
           return string.Empty ;
        }

        [SendMessageHandler ]
        [HttpPost]
        public ContentResult Send_email(MyModel mdl)
        {
           /// Do something ...
          return  string.Empty; 
        }
 خب حالا بعد از کلیک بر روی هر Submit اکشن متناظر با اون اجرا میشه . بعد از ارسال درخواست به سرور MVC در بین اکشن‌های موجود در Controller مشخص شده به دنبال اکشن معین شده میگرده و وقتی به اکشن‌های ما میرسه میبینه عجب ! اون دوتا ActionNameSelectorAttribute سفارشی دارن پس میره ببینه چه خبره اونجا که ما با یک حرکت تهاجمی بررسی میکنیم که اگه  نام اکشن مشخص شده در فرم با نام اکشن در حال بررسی مساوی بود که همینو اجرا کن ( یعنی ما میتونی اکشنی با نام SendMessage هم داشته باشیم ) . اگه نام اکشن مشخص شده در فرم اون نامی نبود که ما میخوایم که کلا بیخیال هندل کردن اکشن میشیم میزاریم خود MVC تصمیم بگیره . و در اخر بررسی میکنیم که ایا در درخواست جاری مقداری با نام اکشن در حال بررسی وجود داره !؟ اگه داشت یعنی همون Submit که ما میخوایم وصل بشه به این اکشن کلیک شده پس اکشن در حال بررسی رو بسط میدیم به درخواست ارسال شده ... به همین سادگی ...

پیروز و موفق باشید . 
نظرات مطالب
مفاهیم برنامه نویسی ـ مروری بر فیلدها، متدها و ساخت اشیاء
ممنون بابت مطلب آموزشی تون،
تاکیدتان بر استفاده از قرار دادهای نامگذاری، تاکید مثبتی است و واقعا مهم، 
کتاب Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries در این زمینه اطلاعات کاملتر و دقیقتری در بر داره.
یکی از روش هایی که در رعایت استاندارهای کد نویسی تاثیر مفیدی داره این هستش که در قطعه کد هایی که به عنوان مثال در آموزش‌ها ارائه می‌شه تا حد امکان سعی بشه این اصول رعایت بشه تا به صورت تدریجی این روش کد نویسی جزئی از عادات برنامه نویسی ما بشود.
نظرات مطالب
Functional Programming یا برنامه نویسی تابعی - قسمت اول
تفاوت‌ها که زیاده. برنامه نویسی تابعی یه ویژگی خیلی مهم به اسم Immutable  داره. یعنی مقدار متغیرها رو نمیشه تغییر داد. این ویژگی هم به این دلیل هستش که برنامه دیگه نگران thread safety نباشه و بتونه از حداکثر هسته‌های پردازنده و موازی سازی استفاده کنه. کلا برای برنامه نویسی تابعی باید برنامه تون و مساله ای که می‌خواید حل کنید امکان مدلسازی ریاضی رو داشته باشه که حتما کار سختی هستش و نمیشه همه چی رو به راحتی مدسازی ریاضی کرد. در کل هدف oop و functioanal و فلسفه استفاده شون متفاوته و مقایسه اونها درست بنظر نمیرسه.
نظرات مطالب
ارسال فایل و تصویر به همراه داده‌های دیگر از طریق jQuery Ajax
برای این View که از ویژگی multiple مربوط به HTML5 استفاده می‌کند و با نام کنترل files
@using (Html.BeginForm("Multiple", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { 
    <input type="file" name="files" multiple />
    <button class="btn btn-default">Upload</button>   
}
و یا این View که سه کنترل هم نام (با نام files) ارسال فایل را تعریف کرده‌است:
@using (Html.BeginForm("Multiple", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) {  
    <input type="file" name="files" /><br />
    <input type="file" name="files" /><br />
    <input type="file" name="files" /><br />
    <button class="btn btn-default">Upload</button>   
}
هر دو یک اکشن متد سمت سرور را خواهند داشت (اگر نام کنترل‌های سمت کلاینت یکسان باشند، در سمت سرور، یک آرایه را تشکیل می‌دهند):
[HttpPost]
public ActionResult Multiple(IEnumerable<HttpPostedFileBase> files)
{
    foreach (var file in files)
    {
        if (file != null && file.ContentLength > 0)
        {
            file.SaveAs(Path.Combine(Server.MapPath("/uploads"), Guid.NewGuid() + Path.GetExtension(file.FileName)));
        }
    }
    return View();
}
نظرات مطالب
مراحل تنظیم Let's Encrypt در IIS

یک نکته‌ی تکمیلی

ACME V1 تا چند ماه دیگر به پایان خواهد رسید:
In June of 2020 we will stop allowing new domains to validate via ACMEv1.
در این حالت برای ارتقاء به نگارش 2 آن، تنها کافی است نگارش جدید win-acme را دریافت و اجرا کنید (که برای اجرا نیاز به نصب NET Core 3.1. را دارد). همچنین scheduled task قدیمی را هم که در سیستم برای نگارش 1 داشتید، disable کنید.
یک نمونه لاگ اجرای نگارش جدید آن به صورت زیر است:
 A simple Windows ACMEv2 client (WACS)
 Software version 2.1.3.671 (RELEASE, PLUGGABLE)
 IIS version 7.5
 Running with administrator credentials
 Scheduled task not configured yet
 Please report issues at https://github.com/PKISharp/win-acme

 N: Create new certificate (simple for IIS)
 M: Create new certificate (full options)
 L: List scheduled renewals
 R: Renew scheduled
 S: Renew specific
 A: Renew *all*
 O: More options...
 Q: Quit

 Please choose from the menu: m

 Running in mode: Interactive, Advanced

  Please specify how the list of domain names that will be included in the
  certificate should be determined. If you choose for one of the "all bindings"
  options, the list will automatically be updated for future renewals to
  reflect the bindings at that time.

 1: IIS
 2: Manual input
 3: CSR created by another program
 C: Abort

 How shall we determine the domain(s) to include in the certificate?: 1

  Please select which website(s) should be scanned for host names. You may
  input one or more site identifiers (comma separated) to filter by those
  sites, or alternatively leave the input empty to scan *all* websites.

 1: Default Web Site (2 bindings)

 Site identifier(s) or <ENTER> to choose all: 1

 1: dotnettips.info (Site 1)
 2: www.dotnettips.info (Site 1)

  You may either choose to include all listed bindings as host names in your
  certificate, or apply an additional filter. Different types of filters are
  available.

 1: Pick specific bindings from the list
 2: Pick bindings based on a search pattern
 3: Pick bindings based on a regular expression
 4: Pick *all* bindings

 How do you want to pick the bindings?: 4

 1: dotnettips.info (Site 1)
 2: www.dotnettips.info (Site 1)

  Please pick the most important host name from the list. This will be
  displayed to your users as the subject of the certificate.

 Common name: 2

 1: dotnettips.info (Site 1)
 2: www.dotnettips.info (Site 1)

 Continue with this selection? (y*/n)  - yes

 Target generated using plugin IIS: www.dotnettips.info and 1 alternatives

 Suggested friendly name '[IIS] Default Web Site, (any host)', press <ENTER> to
accept or type an alternative: <Enter>

  The ACME server will need to verify that you are the owner of the domain
  names that you are requesting the certificate for. This happens both during
  initial setup *and* for every future renewal. There are two main methods of
  doing so: answering specific http requests (http-01) or create specific dns
  records (dns-01). For wildcard domains the latter is the only option. Various
  additional plugins are available from https://github.com/PKISharp/win-acme/.

 1: [http-01] Save verification files on (network) path
 2: [http-01] Serve verification files from memory (recommended)
 3: [http-01] Upload verification files via FTP(S)
 4: [http-01] Upload verification files via SSH-FTP
 5: [http-01] Upload verification files via WebDav
 6: [dns-01] Create verification records manually (auto-renew not possible)
 7: [dns-01] Create verification records with acme-dns (https://github.com/joohoi/acme-dns)
 8: [dns-01] Create verification records with your own script
 9: [tls-alpn-01] Answer TLS verification request from win-acme
 C: Abort

 How would you like prove ownership for the domain(s) in the certificate?: 2

  After ownership of the domain(s) has been proven, we will create a
  Certificate Signing Request (CSR) to obtain the actual certificate. The CSR
  determines properties of the certificate like which (type of) key to use. If
  you are not sure what to pick here, RSA is the safe default.

 1: Elliptic Curve key
 2: RSA key

 What kind of private key should be used for the certificate?: 2

  When we have the certificate, you can store in one or more ways to make it
  accessible to your applications. The Windows Certificate Store is the default
  location for IIS (unless you are managing a cluster of them).

 1: IIS Central Certificate Store (.pfx per domain)
 2: PEM encoded files (Apache, nginx, etc.)
 3: Windows Certificate Store
 C: Abort

 How would you like to store the certificate?: 3

 1: IIS Central Certificate Store (.pfx per domain)
 2: PEM encoded files (Apache, nginx, etc.)
 3: No additional storage steps required
 C: Abort

 Would you like to store it in another way too?: 3

  With the certificate saved to the store(s) of your choice, you may choose one
  or more steps to update your applications, e.g. to configure the new
  thumbprint, or to update bindings.

 1: Create or update https bindings in IIS
 2: Create or update ftps bindings in IIS
 3: Start external script or program
 4: Do not run any (extra) installation steps

 Which installation step should run first?: 1

 Use different site for installation? (y/n*)  - no

 1: Create or update ftps bindings in IIS
 2: Start external script or program
 3: Do not run any (extra) installation steps

 Add another installation step?: 3

 Enter email(s) for notifications about problems and abuse (comma seperated): name@site.com

 Terms of service:   C:\ProgramData\win-acme\acme-v02.api.letsencrypt.org\LE-SA-v1.2-November-15-2017.pdf

 Open in default application? (y/n*)  - no

 Do you agree with the terms? (y*/n)  - yes

 Authorize identifier: dotnettips.info
 Authorizing dotnettips.info using http-01 validation (SelfHosting)
 Authorization result: valid
 Authorize identifier: www.dotnettips.info
 Authorizing www.dotnettips.info using http-01 validation (SelfHosting)
 Authorization result: valid
 Requesting certificate [IIS] Default Web Site, (any host)
 Store with CertificateStore...
 Installing certificate in the certificate store
 Adding certificate [IIS] Default Web Site, (any host) @ 2020/2/1 9:43:55 to store My
 Installing with IIS...
 Updating existing https binding www.dotnettips.info:443 (flags: 0)
 Updating existing https binding dotnettips.info:443 (flags: 0)
 Committing 2 https binding changes to IIS
 Adding Task Scheduler entry with the following settings
 - Name win-acme renew (acme-v02.api.letsencrypt.org)
 - Path C:\Programs\win-acme.v2.1.3.671.x64.pluggable
 - Command wacs.exe --renew --baseuri "https://acme-v02.api.letsencrypt.org/"
 - Start at 09:00:00
 - Time limit 02:00:00

 Do you want to specify the user the task will run as? (y/n*)  - no
مطالب
بررسی Bad code smell ها : کامنت
برای مشاهده طبقه بندی Bad code smell‌ها می‌توانید به اینجا مراجعه کنید.
استفاده از کامنت، به خودی خود یک الگوی بد کد نویسی نیست. ولی ممکن است این امکان به درستی استفاده نشده و فایده مد نظر توسعه دهنده را نداشته باشد.  
زمانیکه متدی پر از کامنت‌های توضیحی در مورد متد و پیاده سازی آن باشد، احتمالا مشکلی به وجود خواهد آمد. معمولا کامنت‌های توضیحی زمانی استفاده می‌شوند که کد به اندازه کافی گویای کاری که انجام می‌دهد نباشد. زمانیکه چنین شرایطی بوجود آمد، یکی از اولین راه حل‌ها، اعمال تغییراتی بر روی کد، برای درک بهتر آن است.  
نامگذاری مناسب و استفاده از نام‌های معنی دار برای بخش‌های مختلف کد مانند نام کلاس‌ها، نام متدها، نام متغیرها و پارامتر‌ها، نقش بسیار مهمی را در زمینه کاهش کامنت‌های نامناسب خواهند داشت. 
اما وجود کامنت‌های توضیحی در مورد کد چه اشکالی را ایجاد می‌کنند؟ یکی از بزرگترین اشکالاتی که چنین کامنت‌هایی با خود به همراه می‌آورند، نگهداری سخت آنها است. فرض کنید کامنتی وجود دارد که عملیات انجام شده توسط کدی را توضیح می‌دهد. زمانیکه آن مکانیزم تغییر کرد، نیاز خواهد بود که کامنت مربوطه نیز به دقت بررسی شود و تغییر کند. در تولید نرم افزارهای پیچیده این کار بسیار دشوار و زمینه ساز خطا خواهد بود و اگر به دلیل سختی کار یا عجله در تولید، کامنت‌ها بروز نشوند، دیگر هیچ یک از کامنت‌های نوشته شده در کد، مورد اعتماد نخواهند بود و کار به مراتب سخت‌تر نیز خواهد شد.  
چند مورد از انواع کامنت‌هایی که بهتر است از آنها پرهیز کنیم، در ادامه مطرح شده‌اند.  

کامنت‌های اضافی یا توضیح واضحات   

کامنت‌هایی که بالای متد‌ها یا کلاس‌ها مشاهده می‌شوند و توصیف کننده کاری هستند که آن کلاس یا عضو آن انجام می‌دهد. هنگام توصیف یک کلاس یا عضوی از آن حتما باید توجه داشت که توضیح واضحات انجام نشود. به طور مثال کد زیر را در نظر بگیرید:  
// Computes the employee salary  
public int CalculateSalary(int emplyeeId)  
{  
      return int.MaxValue;  
}
امضای متد به اندازه کافی نشان دهنده این است که چه کاری را انجام می‌دهد. پس نیازی به کامنت بالای آن وجود نخواهد داشت. در این مثال، کامنت معمولی بالای متد استفاده شده است. در مثال مذکور این امکان وجود داشت که  از مدل xml documentation استفاده شود؛ ولی در اصل موضوع تفاوتی ایجاد نمی‌کرد.   

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

زمانیکه در بدنه متدها با محاسبه یا چک‌هایی روبرو هستیم که به اندازه کافی واضح نیستند، یکی از اولین راهکارهایی که به نظر می‌رسد، نوشتن کامنت برای آنها است. به طور مثال در متدی که مسئول پاک کردن یک حساب، در یک نرم افزار حسابداری است، چکی به صورت زیر داشته باشیم:  
// checks that an account is used or not and checks that an account has childs or not  
if (voucherLineRepository.Any(dd => dd.PostingAccountId == accountId)   
                || accountRepository.Any(dd => dd.ParentId == accountId]))  
{  
       return;  
}
یک راه بهتر برای انجام این کار، ایجاد دو متد است که نشان دهنده موضوع مورد چک باشند. به صورت زیر:  
if (UsedInVouchers(accountId) || HasChilds(accountId))  
{  
      return;  
}
حتی می‌توان یک قدم جلوتر رفت و به طور کلی منطق بررسی این که حساب قابل حذف هست یا نه را هم به متد دیگری منتقل کرد. مانند کد زیر:  
if (!CanDeleteAccount(accountId)) {  
    return;  
}  
...
public bool CanDeleteAccount(int accountId)  
{  
    if (UsedInVouchers(accountId) || HasChilds(accountId))  
    {  
        return false;  
    }  
    return true;  
}


کدهای کامنت شده  

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


کامنت‌های اجباری 

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


لاگ تغییرات  

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

کامنت در زبان‌های برنامه نویسی امکان خوبی است؛ به شرطی که به خوبی مورد استفاده قرار گیرد. 
نظرات مطالب
Functional Programming یا برنامه نویسی تابعی - قسمت اول
آیا میتونید پروژه بزرگی نام ببرید با کاربردهای معمول، که توش صرفا از روش فانکشنال استفاده شده باشه؟ آیا در گیت هاب میشه نمونه هایی پیدا کرد؟ مثلا CMS مطرحی داریم که کاملا بر اساس برنامه نویسی فانکشنال باشه؟ یعنی میخوام بگم چقدر اینکه کسی دغدغه است این باشه که باید شی گرا یاد بگیره یا فانکشنال معنی داره؟ از نظر من دست کم نو آموز‌ها نباید چنین دغدغه ای داشته باشن!

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