کد ساده

  • Readability
  • Maintainability
  • Speed of development
  • quality
  • فهمیدن راحت تر کد
  • نگهداری بهتر کد
  • سرعت بالای توسعه
  • کیفیت

مواردی که در بالا مشاهده کردید از عواملی هستند که تمامی برنامه نویسان در کد نویسی دوست دارند رعایت کنندولی واقعا چند درصد از ما به این کیفیت میرسیم به سرعت بالا می رسیم؟
کجای کار می لنگه چرا ما با اینکه مواردی که در بالا گفته شد مثل قران قبول داریم بهشون نمی رسیم؟
به نظرم دلیلش بر می گرده هم به تجربه هم به دانش.
تاحالا به روزی که یادگرفتید با ورد کار کنید فکر کردید؟احتمالا هر چی شما بلد بودید می خواستید تو سندتون ازش استفاده کنید و به کار بگیرید دست آخر هم که سندی که قرار بوده یک ربه تایپ بشه بعد یک ساعت شده یک سند گل و بوته دار.
دلیلش چیه؟
تجریه کم.
یک مثال دیگه:
می خواید یک تیکه کد بنویسید یه تابع باز می کنید کل کدو می نویسید داخل اون میشه ۱۰۰۰ خط نه DRY نه SRP نه هیچ اصولی.
دلیلش چیه؟
جهل برنامه نویس.
خب برگردیم به موضوع اصلی.یکی از کارایی که میشه کد نوشتن ساده است.

تعریف کد ساده:

کد ساده به این معنی نیست که کدرو جوری بنویسید که هیچ Patternی یا تکنیکی توش استفاده نکرده باشید بلکه به این مفهوم که اصول و رعایت کنید کدتون ساده میشه.یک اصل مهم وجود داره درباره اسم گذاری که اونم نباید فراموش بشه.

یادمون باشه کدرو فدای دانش کم همکارامون نکنیم از بقیه هم انتظار این کارو نداشته باشیم.به نظرم اگه اصول برنامه نویسی رو رعایت کنیم به احتمال زیاد میشه به ۸۰ درصد از موارد بالا رسید.

سادگی کد رو زنده نگه می داره.

مفهوم EventLoop در Node.Js

مفهوم EventLoop مفهوم جدیدی نیست.راستش قصد داشتم در این پست ادامه کار با Node.Js رو بگم ولی به نظرم پرداختن به این موضوع واجب تر از هر چیز دیگه ای است.

EventLoop فرایندی است که در آن به ما اجازه داده میشه دقیقا مشخص کنیم بعد از رخ دادن یک Event خاص چه اتفاقی رخ بده.این موضوع ممکن است برای برنامه نویسان جاوااسکریپت أشنا باشد.به طور مثال زمانی که روی دکمه کلیک کنیم و انتظار این است که تابعی که برای این موضوع به کلیک آن دکمه متصل کرده ایم اجرا شود.
Node از این موضوع استفاده کرده.به طور مثال زمانی که می خواهید یک فایل رابخوانید کافی است برای فایل مورد نظرتان یک Callback در نظر بگیرید به محض اینکه فایل خوانده شد Callback شما اجرا خواهد شد.
شما به EventLoop به شکل یک لیستی نگاه کنید که در آن یک سری وظایف مشخص شده که هر کدام از این وظایف به Event مشخص داده شده است.هر وقت آن Event رخ داد وظیفه یا وظایف ما اجرا می شوند.
توجه به این نکته ضروری است که تمام کدهایی که می نویسیم فقط در یک پردازش قابل اجرا است و در هر لحظه یک قطعه کد ما اجرا می شود.

// set function to be called after 1 second
setTimeout(function() {
   console.log('Timeout ran at ' + new Date().toTimeString());
}, ۱۰۰۰);

// store the start time
var start = new Date();
console.log('Enter loop at: '+start.toTimeString());

// run a loop for 4 seconds
var i = 0;
// increment i while (current time < start time + 4000 ms)
while(new Date().getTime() < start.getTime() + 4000) {
   i++;
}
console.log('Exit loop at: '
            +new Date().toTimeString()
            +'. Ran '+i+' iterations.');

Enter loop at: 20:04:50 GMT+0300 (EEST)
Exit loop at: 20:04:54 GMT+0300 (EEST). Ran 3622837 iterations.
Timeout ran at 20:04:54 GMT+0300 (EEST)
همانطور که مشاهده می کنید ۴ ثانیه طول میکشه درون setTimeout اجرا بشه.چون در اینجا وقفه معنی نداره و EventLoop مشخص می کنه چه کدی باید اجرا بشه.
اگر یک عملی ۴ ثانیه طول بکشد در این زمان نود قادر به پردازش درخواست دیگری نیست.
خیلی از برنامه نویسان نود رو بخاطر تک پردازشی بودن مورد انتقاد قرار می دن.چون این امکان وجود داره Thread قفل بشه.
مثل کدی که مشاهده کردید.ولی از طرفی در برنامه های چند Thread کد نوشتن سخته و مدیریت Threadها کاری سخت تر.
درسته میشه با Thread عملیات I/o رو مدیریت کرد ولی اینم در نظر داشته باشید که چه مقدار زمان بیخود از Threadهای CPU گرفته میشه و اونها عملا در زمان عملیات I/o بیکار هستند.
همانطور که گفته شد در نود عملیات I/o به صورت async اجرا میشن.

setTimeout(function() {
   console.log('setTimeout at '+new Date().toTimeString());
}, ۱۰۰۰);

require('fs').readFile('/etc/passwd', function(err, result) {
  console.log(result);
} );

در کد بالا اگر عملیات خواندن از فایل بیشتر از ۱ ثانیه طول بکشد کد setTimeout اجرا خواهد شد.
برای کاربر مشخص نیست که شما برنامرو با نود نوشتید.
همه چیز در نود به صورت موازی انجام می شود به غیر از کد شما.
به این مثال خوب توجه کنید:
کدشما مثل یک پادشاه است که چندین خدمتکار دارد.هروز صبح یک خدمت  کار پاداشاه را از خواب بیدار می کند و به او می گوید چه چیزهایی لازم دارد او لیست مواردی که پادشاه میخواهد را جمع آوری می کند و با باقی همکاران خود تقسیم می کند وپادشاه دوباره می خوابد.سپس وظایف یک خدمت کار تمام می شود و با اجازه پادشاه به اتاق او رفته و گزارش عملکرد خود را می دهد این را توجه داشته باشید که در هر زمان فقط یک نفر قادر است به پادشاه گزارش دهد و باقی در صف قرار می گیرند.این صف همان EventLoop وپادشاه کد ما و خدمتگذار Callback ما است.
همه کارهای پادشاه به صورت موازی انجام میشود ولی پادشاه کار ها را به صورت صف بررسی می کند.
دقت کنید در هر لحظه یک Callback اجرا می شود.
امیدوارم براتون جا افتاده باشه در مطلب بعدی درباره ماژول ها بیشتر صحبت می کنم.

چگونگی پردازش درخواست در Node.js

در مطلب قبلی نحوه نوشتن یک وب سرور ساده را آموختید.در این مطلب قصد دارم نحوه پردازش درخواست در یک وب سرور را به شما نشان دهم.
برای یک برنامه تحت وب ما نیاز به قسمت های زیر داریم.

  1. ما نیاز داریم تا یک صفحه را برای کلاینت بفرسیتم پس نیاز به یک وب سرور (Web Server)داریم
  2. نیاز داریم که به درخواست های مختلفی پاسخ دهیم و آن ها را به یک مدیریت کننده درخواست (Request Handler )هدایت کنیم پس نیاز به یک روتر داریم.
  3. برای پردازش درخواست های رسیده به هر روتر نیاز به به یک مدیریت کننده درخواست (Request Handler )نیازداریم.
  4. روتر باید قابلیت پردازش دادها ارسالی داشته باشد پس نیاز به یک Request Data Handler داریم.
  5. ما فقط نیاز به پردازش درخواست ها نداریم و نیاز داریم به کاربر محتوا نشان دهیم پس نیاز به یکView Logic داریم.
  6. مانیاز به آپلود داده ها داریم پس نیاز به یک Upload Handler داریم.
var http = require("http");
http.createServer(function (request, response) {
console.log("Request received");
response.writeHead(200, { "Content-Type": "text/plain" });
response.write("Hello World");
response.end();
}).listen(8888, "127.0.0.1");

تابعی که به عنوان ‌Callback به createServer پاس داده شدبعد از رسیدن درخواست اجرا خواهد شد و دو پارامتر به آن پاس داده خواهد شد.

از طریق آن پارامترها  می توانیم به جزییات Request دسترسی پیدا کنیم و همچنین به کلاینت جواب مناسب را ارسال می کنیم.به محض اینکه درخواستی به سمت سرور آمد با writeHeadکد ۲۰۰ را و همچنین  Content-Type را به  response اختصاص می دهیم در ادامه یک متن را write می کنیم.در آخر فرایند را با دستور End به اتمام می رسانیم.

در مطلب بعدی نحوه ساختن یک ماژول را  در Node.js بررسی می کنیم.

کاربران را جدی بگیرید

ما فکر می کنیم کاربران مثل ما رفتار می کنند.در فیزیولوژی به آن false-consensus bias گفته می شود.
زمانی که کاربران مخالف آنچه ما تصور میکنیم رفتار می کنند به آن ها می گوییم نادان.برای یک برنامه نویس یکی از سخت ترین کارها گذاشتن خودش جای کاربره.
به این نکته توجه کنید که برنامه نویس مثل کاربر فکر نمیکنه و کاربر هم مثل هم برنامه نویس فکر نمی کنه.

UX
کاربران ما اغلب در کامپیوتر سر رشته ای ندارن.حتی آن ها نمی دانند که کامپیوتر چگونه کار میکنه.
بهترین راه برای اینکه ببینیم اونها چه جوری رفتار می کنند اینکه یک کار را برای آن ها مشخص کنیم مثلا اگر نرم افزار حساب داری است بهتره بگیم برامون یک سند رو  وارد کنه.باید درحین کار کاربرو تماشا کنیم این کار باید بدونه راهنمایی برنامه نویس باشه.

مواردی که باید به أن توجه کرد:

  1. برخورد اغلب کابران با سیستم  یکسان است.
  2. کارهای خودشونو طبق یک ساختار انجام می دن.
  3. اشتباهاتشون در برخورد با سیستم به یک شکل است.

ما می تونیم با ارتباط نزدیک با کاربر نرم افزارمونو کاربر پسند تر بکنیم.
این موضوع با جلسه طراحی سیستم فرق می کنه.نرم افزار ما هرچی عاری از نقاط گیج کنندگی باشه کار با اون راحت تره.به عنوان مثال می تونم قسمت publish سایت در Visual Studio رو براتون مثال بزنم که برای برنامه نویس ها هم پر از ابهامه.
ٰVisual Studio Publish
باید به این نکته توجه کرد که کاربران داری رفتار های غلط هم هستند و صرفا نباید به خاطر رفتار غلط اونها نرم افزار ما هم غلط طراحی بشه.
کلاْ در طراحی و پیاده سازی نرم افزار یک سری مرزهایی وجود داره.من بهش میگم طراحی های مارتینی و طراحی های بی درو پیکر.باید یک مرزی وجود داشته باشه این وسط.
منظور از مارتینی طراحی های آکادمیک هست و اونهایی که بدون توجه به مواردی مثل Scale پروژه از الگوهای آقای فولر به شدت استفاده می کنن.
بهترین راه برای تجربه کاربری اینکه بگیم با سیستم کار کنه.

بدهی فنی

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

technical-debt
عواقب بد قولی

این قول سخته چون شما بعد چند روز باید تمرکزتونو محدود یک کاره دیگه بکنید و اینجاست که بدهی فنی حاصل می شه. حالا واقعاٌ کی میشه قرض کرد؟ زمانی که شما مطمئن بشید که واقعا قرضو پس می دید.چونکه اگه نتونید برید و کاری که باید خوب انجام می دادیدو اونو انجام سریع انجام دادید ،اصلاح کنید، بستر سیستم خودتونو رو پایه های سست بنا کردید و مشکلات روی هم مثل Stack میان روی هم و برطرف کردنشون به شدت سخت می شه.

دلایل قرض فنی از زبان ویکی پدیا:

Business pressures, where the business considers getting something released sooner before all of the necessary changes are complete, builds up technical debt comprising those uncompleted changes

  • Lack of process or understanding, where businesses are blind to the concept of technical debt, and make decisions without considering the implications

  • Lack of building loosely coupled components, where functions are hard-coded, when business needs change, the software is inflexible.

  • Lack of test suite, which encourages quick and less risky band-aids to fix bugs.

  • Lack of documentation, where code is created without necessary supporting documentation. That work to create the supporting documentation represents a debt that must be paid.

  • Lack of collaboration, where knowledge isn’t shared around the organization and business efficiency suffers.

  • Parallel Development at the same time on two or more branches can cause the build up of technical debt because of the work that will eventually be required to merge the changes into a single source base. The more changes that are done in isolation, the more debt that is piled up.

  • Delayed Refactoring. As the requirements for a project evolve, it may become clear that parts of the code have gotten unwieldy and must be refactored in order to support future requirements. The longer that refactoring is delayed, and the more code is written to use the current form, the more debt that piles up that must be paid at the time the refactoring is finally done.

  1. فشار Business
  2. درک نا صحیح.
  3. کامپننت های بهم چسبیده.
  4. نداشتن تست صحیح
  5. نداشتن مستند درست
  6. همکاری ناصیحیح
  7. برنامه نویسی هم زمان
  8. ریفکتورینگ با تاخیر

حالا راه حل چیه؟ نمیشه قرض نکرد ولی باید سره وقت پس داد و اندازه همون که گرفتیم پس بدیم. باید یک لیستی از قرضامون داشته باشیم و اولویت بندیشون کنیم و سره وقت بریم و رفعش کنیم.لازمه یک تجربه بگم این که To-do های داخل کد به درد این کار نمی خورن و باید به فکر راه حل دیگه ای باشد. من که هیچ ازشون استفاده نکردم.

فرایند technical-debt

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

ساخت یک وب سرور ساده به وسیله Node.js

در مطلب قبل نگاه کلی به ماهیت وجودی Node.js انداختیم.

اول بریم سراغ نصب Node.js:برای نصب بهترین راه نصب از طریق داکیومنت های سایت github.

بعداز نصب Node در یک فایل جاوااسکریپتی کد زیر را وارد کنید.

var http = require("http");
http.createServer(function (request, response) {
console.log("Request received");
response.writeHead(200, { "Content-Type": "text/plain" });
response.write("Hello World");
response.end();
}).listen(8888, "127.0.0.1");

اسم فایل را Server.js بگذارید.

برای اجرا کافی است سرور node server.js$ را در کنسول خود تایپ کنید.
و در مرورگر خود به آدرس http://127.0.0.1:8888/ بروید.

خب وقتی داریم با جاوا اسکریپت کد می زنیم باید یه زمینه ای از خود این زبان هم داشته باشیم.

همانطور که در کد مشاهده می کنید ما یک ماژول از ماژول های اصلی Node را require کردیم به این معنی که ما می خواهیم از امکانات این ماژول استفاده کنیم.
متد require یک شی از همان جنس به ما بر می گرداند در این جا ما یک شی http داریم که دارای یک متد به نام createServer است.
متد createServer در ورودی یک Callback می گیرد این به آن معنی است که Callback در زمان مشخصی بعد از یک Event خواص اجرا میشود.
در زمانی که Callback ما اجرا می شود دو پارامتر به آن پاس داده می شود request, response.
request: حاوی اطلاعاتی از قبیل مشخصات request دهنده و … که در ادامه مطالب بررسی می شود.
response: به وسیله response می توان به کلاینت مورد نظر جواب مناسب را ارسال کنیم.که در اینجا هدر مربوطه و Hello World است.
createServer شی را بر می گرداند که دارای متد listen است که روی پورت مشخص و آی پی مشخص گوش می دهد.
حال بحث multithread نبودن و پردازش هم زمان چند request پیش می اید که باید متذکر شوم در این جا از async استفاده شده است به کد بالا دقت کنید.ما یک function را پاس داده ایم این function به ازای هر request اجرا می شود.نحوه دقیق تر این موضوع در مطلب بعدی ذکر خواهد شد.یادتون باشه در هر زمان فقط یک Callback اجرا میشه به این معنی که اگه چند تا request بیاد در صف قرار می گیرن.

ارتباط با Asterisk به وسیله Socket Programming در C#

اول باید سراغ این رفت که Socket Programming دقیقاً چی هست؟

برای ارتباط بین دو Application می توان از مفهومی به اسم Socket استفاده کرد.جهت این ارتباط نیاز است به در موئلفه اصلی:

  1. IP
  2. Port

ما در این مطلب قصد داریم از C# استفاده کنیم و پروتکلی که مورد استفاده TCP است.

در این حالت اگر Request ی به سرور برسد تا زمانی که آن Request مدیریت نشود به باقی درخواست ها جواب داده نخواهد شد.برای همین است که ازMultithreading در این کار استفاده می شود.

در این مطلب قصد آموزش Socket Programming نیست و برای آن به شما توصیه می کنم به مقاله جالب سایت codeproject سر بزنید.

 Socket Programming Image
Socket Programming

کد زیر برای وصل شدن به Asterisk کافی است و می توان از آن تمامی Event های مربوط به آن را گوش کرد.

  • private static void Main(string[] args)
     {
     Console.WriteLine("Quick and Dirty Asterisk Manager Daemon Test:\n");
    
    var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     var serverEndPoint = new IPEndPoint(IPAddress.Parse("Ip"), 5038);
     clientSocket.Connect(serverEndPoint);
    
    clientSocket.Send(
     Encoding.ASCII.GetBytes("Action: Login\r\nUsername: Username\r\nSecret: Pass\r\nActionID: 1\r\n\r\n"));
     do
     {
     Console.WriteLine(clientSocket.Connected);
    
    var buffer = new byte[1024];
     int bytesRead = clientSocket.Receive(buffer);
    
    string response = Encoding.ASCII.GetString(buffer, 0, bytesRead);
    
    if (response != "")
     {
     Console.WriteLine(response);
     }
     } while (clientSocket.Connected);
    
    Console.WriteLine(clientSocket.Connected);
     Console.WriteLine("Connection to server lost.");
     Console.ReadLine();
     }
    
    

اگر مباحث  Socket Programming را خوانده باشید به راحتی می توان کد بالا را درک کرد.

 

 clientSocket.Connect(serverEndPoint);

در کدی که مشاهده کردید ما سعی کردیم به سرور وصل شویم.


 clientSocket.Send(
 Encoding.ASCII.GetBytes("Action: Login\r\nUsername: Username\r\nSecret: Pass\r\nActionID: 1\r\n\r\n"));

در خط بالا ما درخواست Login را به Asterisk می فرستیم.بعد به انتظار دریافت پیغام از استریسک می مانیم.

در آخر هم در یک Loop منتظر دریافت Message می ماند.

کار بیشتر != پول بیشتر

به عنوان کسی که چندین سال هست در حوزه فناوری مشغول به فعالیت هستم، به این نتیجه رسیده ام که کار بیشتر لزوما باعث درآمد بیشتر نمی شه.
موفقیت در حوزه ی IT مستلزم صرف زمان کافی برای بالابردن دانش، انگیزه بالا و استفاده از دانش کسب شده در عمل هست و شخصی که تعادلی بین این موارد داشته باشه میتونه توی این حوزه موفقیت کسب کنه. گاهی اوقات شما در یک پروژه راهکاری ارائه میکنید که بسیار تاثیر گذار هست و برای هم تیمی ها بسیار تحسین برانگیز هست و این حاصل زمانی هست که شما بر روی افزایش دانش خودتون گذاشتید و نه به واسطه سخت کار کردن بر روی پروژه!
در کتاب ۹۷Things Every Programmer Should Know یکی از مواردی که اشاره شده با این مضمون هست که Hard Work Does Not Pay Off! این قسمت نوشته آقای Olve Maudal هست که من در ادامه برگردان فارسی این نوشته رو براتون میذارم:

“به عنوان یک برنامه نویس احتمالا شما هم تاکنون متوجه این قضیه شده اید که کار سخت لزوما موجب در آمد بیشتر نمی شود. شما ممکن است در ذهن خودتان و برخی از همکارانتان این تصور را ایجاد کنید که در حال فعالیت شدید و صرف زمان زیاد روی یک پروژه در دفتر شرکت هستید، اما واقعیت این است که شاید شما با کار کمتر بازدهی بهتری داشته باشید (گاها خیلی بیشتر). اگر میخواهید بر روی کارتان تمرکز داشته باشید و بهره وری بیشتری داشته باشید و در عین حال در هفته بیشتر از ۳۰ ساعت کار می کنید احتمالا شما در حال سخت کار کردن هستید. اما این موضوع را در نظر داشته باشید که باید سعی کنید حجم کاری خود را کمتر کنید تا بهره وری بیشتری داشته باشید و بتوانید کارهای بیشتری انجام بدهید.
این موضوع شاید در نگاه اول بسیار تامل برانگیز باشد، اما حقیقت این است که برنامه نویسی و به طور کلی توسعه نرم افزار شامل فرآیند یادگیری مداوم می باشد.

برنامه نویسی حرفه ای مانند ماراتون سرعت نیست که هدف شما قابل مشاهده باشد. اکثر پروژه های نرم افزاری بیشتر شبیه ماراتون استقامت هستند و شما مسیری طولانی را در پیش رو دارید و گاها تصویری مبهم از انتهای پروژه! بنابراین اگر شما سعی کنید به سرعت هرچه تمامتر کارتان را جلو ببرید اگرچه ممکن است عده ای را تحت تاثیر بگذارید اما در نهایت موفقیتی حاصل نخواهید کرد.بهتر است در کارتان سرعت یکنواختی داشته باشید.
علاوه بر این شما به طور کل باید در زمینه توسعه نرم افزار و به طور خاص در مورد برنامه نویسی دانش خود را افزایش دهید. شما باید کتاب بخوانید، به کنفرانس بروید، با متخصصان دیگر در ارتباط باشید و با ابزارهایی که کار شما را تسهیل میکند آشنا بشوید. به عنوان یک برنامه نویس حرفه ای باید در زمینه کاری خودتان به روز باشید. دقیقا مشابه یک جراح مغز یا خلبانی که انتظار می رود در زمینه کاری و تخصصشان به روز باشند. شما باید عصرها بعد از کار و حتی روزهای تعطیل هم در حال تحصیل و کسب دانش باشید. بنابراین شما نباید عصرها و روزهای تعطیل هم بر روی کار بر روی پروژه تان باشید. آیا به نظر شما منطقی است که یک جراح مغز ۶۰ ساعت در هفته کار کند یا یک خلبان ۶۰ ساعت در هفته پرواز کند؟ البته که نه! تحصیل و کسب دانش بخش حیاتی فعالیت شما به عنوان یک برنامه نویس است.
بر روی پروژه تان متمرکز باشید، با هم تیمی ها در تعامل باشید، سعی کنید راهکارهای مناسبی جهت پیشبرد اهداف پروژه ارائه کنید، مهارت های خودتان را ارتقا دهید و سعی کنید مانند یک همستری (Hamster) که دائما در قفس خود درحال درجا زدن است نباشید.

مانند یک همستر نباشید!
سعی کنید این موضوع را درک کنید که به عنوان یک برنامه نویس اگر میخواهید بر روی کارتان متمرکز باشید و فردی با بهره وری مناسب باشید کار کردن ۶۰ ساعت در هفته کاری منطقی نیست.
پس مانند یک حرفه ای عمل کنید:آماده باشید، تاثیر گذار باشید، نظاره گر باشید و تغییر بدهید.”