#2 - نکات و اصول مهم در برنامه نویسی #C
1- مفهوم و تفاوت Concurrency(همزمانی) و Parallel(موازی):
- پردازش Parallel نوعی از Concurrent هستش. درواقع Parallel زیرمجموعه Concurrency هستش.
- نوع Concurrent میتونه با یک پردازنده اعمال بشه (single/multi thread). اما نوع Parallel باید در چند پردازنده اعمال بشه. یعنی یک پردازنده به ازای هر پروسس.
نکته: عمل Multithreading زیرمجموعه Concurrency محسوب میشه و میتونه با پردازندههای تکی هم انجام بشه.
2- با استفاده از کلمه کلیدی volatile
در متغیرها می تونید thread های برنامه رو وادار کنید تا اطلاعات متغیر رو مستقیماً از حافظه بخونن و نه کش CPU. (این عمل درواقع نوعی thread-safety محسوب میشه)
3- یادتون باشه که synchronized
و Thread-Safe در .Net یک مفهوم دارن: دسترسی همزمان به کد توسط چند Thread بدون بروز مشکلات. یعنی کد/متد synchronized
اجازه دسترسی همزمان چند Thread به کد/متد رو نمیده، پس Thread ها باید نوبتی به کد/متد دسترسی پیدا کنن بنابراین آخرین وضعیت کد/متد در همه Thread ها مشترک هستش.
نکته: این مسئله فقط در مورد برنامه های Multi-Thread صدق میکنه و نه Single-Thread.
نکته 2: در .Net باید از تکنیکهایی مانند lock
برای Thread-Safe کردن کد استفاده کرد.
4- وقتی که می شود از byte
استفاده کرد پس چرا int
؟ وقتی که می شود از short
استفاده کرد پس چرا int
؟
5- جهت افزایش خوانایی کد, همیشه static initializer های کلاس رو در بالاترین قسمت کلاس قرار بدید.
public class Foo() { static { // Static codes. } private int number; public static void Main() {} // ... }
6- وقتی که با SQLite کار می کنید، هرگز Index
گذاری رو فراموش نکنید. اینکار سرعت پیمایش در جداول رو بسیار افزایش میده.
7- سعی کنید متغیرهای کلاس رو در خارج از متد constructor آماده سازی/Initialize کنید. (اینها مقادیر پیشفرض دارن و حتی قبل از اینکه سازنده کلاس صدا زده بشه مقدار دهی می شوند. پس دوباره به اونها مقدار ندید. بعلاه خوانایی کلاس راحت تر و سریع تر انجام میشه)
8- ترتیب اجرای initializerها درکلاس در صورت وجود فیلدهای static، همیشه بصورت: Static initializer -> Constructor هستش.
public class MyClass { // Constructor initializer public MyClass() { // #2 } // Static initializer static { // #1 } }
9- مفهوم Loose Coupling یعنی عدم وجود وابستگی در دسته ای از کلاس. یعنی متصل اما مستقل. یعنی افزایش flexibility و re-usability کد. یعنی استقلال در حین وابستگی. یعنی عدم وابستگی در روابط بین کلاس ها.
و مفهوم Tight Coupling یعنی وجود وابستگی سخت/تودرتو در دسته ای از کلاس. یعنی متصل و به هم وابسته. یعنی کاهش flexibility و re-usability کد. یعنی وابستگی در روابط بین کلاس ها.
10- نکاتی راجب الگوهای Dependency Injection, Inversion of Control:
- اصول Dependency Inversion Principle (DIP) منتسب به تجزیه کردن کد هستش، به این صورت که کلاسهای سطح بالا نباید به قسمت های سطح پایینتر وابستگی مستقیم داشته باشه، بلکه باید توسط لایه abstract یا interface به سطوح پایینتر وابستگی داشته باشند.
- Dependency Injection یک الگو هست اما Container و Inversion of Control یک روش برای اجرای الگوی DI.
- توسط روش Inversion of Control قادرید dependency اشیا رو بعد از compile یا در محیط production هم تغییر بدید.
- IoC یک مفهوم کلی است که DI به عنوان یکی از الگوهای پیاده سازی آن در نظر گرفته میشود.
11- نکته جزیی: وظیفه نوشتن کدهای تست برای Unit Testing بعهده فرد برنامه نویس هستش نه فرد Tester. زیرا:
- بدلیل حفظ مالیکت کدها/پروژه، Tester نباید به سورس پروژه دسترسی داشته باشه.
- بدلیل مسایل امنیتی و کاهش تهدیدها، Tester نباید به داخل کدها و مکانیزم سیستم دسترسی داشته باشه.
- همچنین Tester قادر نیست به همه ابزارها، سبکها و زبانهای مختلفی که در پروژه استفاده شده مسلط بشه و test case طراحی کنه.
- تنها برنامه نویس هستش به کدهایی که پیاده سازی کرده مسلطه و test case رو در کمترین زمان با بالاترین کیفیت تولید میکنه.
12- درصورتیکه از C# 6 یا جدیدتر استفاده می کنید، از عملگر Null-conditional نوع ?. برای بررسی NULL بودن/نبودن اشیا استفاده کنید.
یعنی بجای این کد:
if (MyObject != null) { MyObject.MyMethod(); }
از این کد استفاده کنید:
MyObject?.MyMethod();
13- همیشه اطلاعات حساس رو قبل از serialize کردن، ابتدا رمزنگاری کنید.
14- همیشه اطلاعات ورودی/کاربر رو قبل از ثبت کردن در log، ابتدا فیلترسازی کنید.
15- نکته جزیی: در .Net عملیات overloading مربوط به compile-time هستش، اما عملیات overrding مربوط به run-time هستش.
16- هنگام صدا زدن متد های static
بهتره از کلاس اصلی استفاده بشه و نه نمونه های کلاس یا اشیا فرزند.
public class Vehicle { public static int getId() { return 123; } } // غلط Vehicle bmw = new Vehicle; int id = bmw.getId(); // صحیح int id = Vehicle.getId();
چون متدهای static متعلق به class هستند، نه به instance ساختهشده از آن کلاس. به این معنی که وقتی یک متد static تعریف میشود، به یک instance خاص از کلاس وابسته نیست و میتواند بدون نیاز به ساختن شیء از کلاس فراخوانی شود. اینطور خوانایی و وضوح کد هم افزایش می یابد.
17- مفهوم refactory به زبان ساده: تغییر کد، بدون تغییر رفتار کد. یا تغییر کد، بدون شکستن API کد.
18- در .Net، عمل auto boxing و auto unboxing توسط کامپایلر(compile-time) انجام میشه و نه ماشین مجازی(run-time). این امر به برنامهنویس اجازه میده تا بتونه، نوعهای Value و Ref رو به یکدیگر تبدیل کنه و از اونها استفاده کنه.
Integer myInt = new Integer(22); if (myInt < 11) // Auto unboxing internally { // ... } myArrayList.Add(22); // == myArrayList.add(Integer.valueOf(22));
نکته: عمل Unboxing درواقع تبدیل نوع داده شی(wrapper) به نوع داده اولیه(primitive) هست و عمل Autoboxing تبدیل خودکار نوع داده اولیه(primitive) به نوع داده شی(wrapper) مربوطه هست.
19- در encapsulation(یا detail hiding) کلاس، دسترسی تمامی فیلدها باید private
باشند.
20- شباهت ها و تفاوت های کلاس Abstract با Interface
- هر دو در پیاده سازی الگوی polymorphism استفاده می شن.
- هر دو برای پیروی از یک شِمای و اسکلت ثابت هستند.
- هردو گزینه خوبی برای استاندارد سازی API داخلی هستن.
- هردو بهترین گزینه برای کار تیمی/گروهی هستن.
- هر دو میتونن تعیین کنن که چه چیز باید پیاده سازی بشه بی توجه به اینکه چطور پیاده سازی بشه.
- هر دو برای انجام dependency injection می تونن استفاده بشن.
اما:
- متدهای کلاس Abstract میتونن حاوی کد/محتوا باشن تا یک عملیات رو برای همه کلاس های مصرف کننده فراهم کنن. ولی Interface ها نمی تونن.
- کلاس Abstract میتونه متد private و protected داشته باشه، اما Interface نمی تونه.
- کلاس Abstract در واقع ترکیبی از Interface و کلاس هستش ولی Interface یک کلاس مجازی.
- کلاس Abstract قابلیت instantiation یا همون new شدن رو نداره. فقط میشه inheritance/extend بشه. و درطرف دیگر Interface رو فقط میشه implement کرد.
- یک کلاس فقط از یک کلاس Abstract می تونه extend بشه. ولی یک کلاس میتونه از 65535 عدد interface مختلف implement بگیره.
- یک Interface می تونه از چندین Interface مختلف extend بشه. اما کلاس Abstract نمی تونه.
- اینترفیس معمولاً در طراحی Listener ها، Callback ها، تزریق وابستگی و سازگارسازی کلاس های غیرمرتبط استفاده داره، اما abstract در همه جا.
- کلاس Abstract میتونه فیلد نوع sealed static و متد داشته باشه. اما Interface فقط می تونه متد(خالی) و فیلد sealed static داشته باشه.
- یک کلاس معمولی(concrete) باید همه متدهای interface رو implement کنه، اما در کلاس Abstract اجباری نیست.
- سطوح دسترسی متدها و فیلدها در Abstract میتونه public, private, protected باشه. اما در Interface فقط public میتونه باشه.
زمانی از abstract class استفاده کنید که بدنه متد هم لازمه از قبل کدنویسی بشه، و زمانی از interface استفاده کنید که لازم نیست بدنه متد از قبل کدنویسی بشه یا کلاس نیاز داره که چندین interface رو پیاده سازی کنه.
21- همیشه encoding فایلهای پروژه های .Net رو UTF8-BoM قرار بدید.
22- بجای شروط تودرتو if/else if
، از Lookup table یا switch
استفاده کنید.
23- از قرار دادن فضاهای خالی بی مورد و نامناسب بین کدها خودداری کنید.
24- هنگام نوشتن RegEx برای پردازش اعداد، بهتره از مقدار \d
بجای 0-9
استفاده کنید. با اینکار بازه اعداد unicode (فارسی، عربی...) رو هم پوشش میدید.
25- مقایسه کوتاه بین فرم ورکهای Unit Test:
NUnit 3.x |
MSTest 2.x |
xUnit.net 2.x |
توضیحات |
---|---|---|---|
[Test] |
[TestMethod] |
[Fact] |
Marks a test method. |
[TestFixture] |
[TestClass] |
n/a |
Marks a test class. |
[SetUp] |
[TestInitialize] |
Constructor |
Triggered before every test case. |
[TearDown] |
[TestCleanup] |
IDisposable.Dispose |
Triggered after every test case. |
[OneTimeSetUp] |
[ClassInitialize] |
IClassFixture<T> |
One-time triggered method before test cases start. |
[OneTimeTearDown] |
[ClassCleanup] |
IClassFixture<T> |
One-time triggered method after test cases end. |
[Ignore("reason")] |
[Ignore] |
[Fact(Skip="reason")] |
Ignores a test case. |
[Property] |
[TestProperty] |
[Trait] |
Sets arbitrary metadata on a test. |
[Theory] |
[DataRow] |
[Theory] |
Configures a data-driven test. |
[Category("")] |
[TestCategory("")] |
[Trait("Category", "")] |
Categorizes the test cases or classes. |
(c) automatetheplanet.com
26- جهت خوانایی بهتر همیشه اعضای public
کلاس رو در ابتدای کلاس قرار بدید و اعضای private
رو در آخر کلاس.
27- بجای نوشتن type های طولانی و پیچیده، از var
استفاده کنید.
بجای:
List<Repository.DataAccessLayer.Whatever> listOfBlah = _repo.DataAccessLayer.GetWhatever();
بنویسید:
var listOfBlah = _repo.DataAccessLayer.GetWhatever();
28- جهت چسباندن رشته ها بجای + از string.Format()
یا string interpolation ($) استفاده کنید.
string name = "Vynn"; string greetings = string.Format("Hello {0}!", name); string greeting = $"Hello, {name}!;
29- توسط نرم افزار Winium میتونید UI برنامه های دسکتاپ رو تست کنید.
30- جهت افزایش پرفورمنس نرم افزار Visual Studio, میتونید تنظیمات Just My Code و Diagnostic Tools و CodeLens و map mode رو تغییر بدید:
Tools > Options > Debugging > General > enable Just My Code.
Tools > Options > Debugging > General > disable Automatic adjust visual experience
Tools > Options > Debugging > General > disable Enable rich client visual experience
Tools > Options > Debugging > General > disable Diagnostic Tools while debugging
Tools > Options > Text Editor > All Languages > disable CodeLens
Tools > Options > Text Editor > All Languages > Scroll Bar > Behavior > disable Use map mode
31- نکته جزیی: در .Net کلاسهای نوع static
در پشت پرده abstract sealed
هستن.
32- ترجیحاً از null
جهت optional کردن پارامترها استفاده نکنید. با اینکار یک پارامتر three-state تولید می کنید...
// غلط public class Test { public MyMethod(string name, int? age); }
// صحیح public class Test { public MyMethod(string name, int age); public MyMethod(string name); }
33- در داخل متد Equals هرگز exception پرتاب نکنید. دو شی یا باهم برابر هستن یا نیستن! این متد فقط باید مقدار true/false برگرداند.
34- کلاس TimeSpan بهترین گزینه جهت ایجاد timeout برای انجام عملیات.
35- هنگام دانلود/نصب MS VS حتماً به 64bit ای یا 32bit بودن این IDE توجه کنید تا هنگام تولید/compile/load پروژه ها با معماری های متفاوت به مشکل برنخورید.
VS 2022 و جدیدتر 64bit هستن اما VS 2019 و قدیمیتر 32bit ای هستن.
36- زمانی از کلاس Thread استفاده کنید که Task های long run دارید. یا نیاز به جابجایی thread بین foreground و background دارید. یا تغییر thread priority. یا به ویژگی های پیچیده thread نیاز دارید.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.