احسان رضایی

یک توسعه دهنده، شاید هم نه.

کتاب الگوهای طراحی به بیان ساده(design patterns/دیزاین پترن)

در مهندسی نرم افزار، design patterns(الگوهای طراحی) راه حل‌های قابل استفاده برای مشکلاتی هستند که معمولاً در طراحی نرم‌افزار اتفاق می افتند.

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



تم روشن یا تیره؟ کدام برای چشم مفیدتر هست؟

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

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

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

نامگذاری چیزها

معمولا توسعه دهنده زمان بیشتریُ برای خواندن کد نسبت به نوشتن اون صرف میکنه. این یه موضوع  مهمه که سورس خوانایی لازم رو داشته باشه. در ادامه بر اساس تجربه چند مورد برای نام گذاری آورده شده.

- مفهوم.

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

1) از نام های دقیق استفاده کنید.

 اگر کسی بدون کامنت های شما نمیتونه ایده و هدف شما رو بفهمه اصلا خوب نیست. بدترین حالت زمانی هست که نام به کسی که اون رو میخونه دروغ بگه!

2) اجتناب از نام های بی معنی.

نام هایی مثل i,j,k و... تنها زمانی قابل قبول هستن که در یک حلقه استفاده بشن. در باقی موارد خوانایی رو سخت میکنن.

معمولا توی کتاب های علوم کامپیوتر از این روش برای تعریف یک فرمول(با استفاده از شبه کد به منظور سریعتر نوشتن) استفاده میشه در صورتی که اگر پاراگراف بالای اون فرمول رو مطالعه نکنید چیزی ازش نخواهید فهمید.

3) نام کلاس ها، اینترفیس و پراپرتی ها.

نام کلاس میتونه شامل یک یا چند اسم باشه. از فعل نباید استفاده کرد. از “data”, “manager”, “info”, “processor”, “handler”, “maker”, “util” و موارد مشابه به علت مبهم بودنشون اجتناب کنید.

Interface ها معمولا اسم یا صفت هستن. میتونید از پیشوند (مثلا Interface) هم استفاده کنید.

namespace Psr\Log;

/**
 * Describes a logger instance
 */
interface LoggerInterface
{

property ها اسم یا صفت هستن. برای پراپرتی هایی با مقدار دودویی(0 یا 1) میشه از پسوند هایی مثل “Is”, “Can”یا “Has” در جاهای مناسب استفاده کرد.

نام Method باید شامل یک یا چند فعل باشه و کاری که انجام میده رو توضیح بده. نه اینکه چطور اون کار رو انجام میده.

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

 

 

class Exception {}

class InvalidArgumentException extends Exception {}
ادامه...

فهرستی از نکات امنیتی در PHP

php-security-checklist

- از php 7 یا نسخه های بالاتر استفاده کنید.

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

- تمام داده ها رو فیلتر و اعتبار سنجی کنید.

صرف نظر از اینکه داده ها از کجا اومدن و به کجا خواهند رفت!(داده های ورودی و خروجی منظورمه) یاید فیلترها و اعتبار سنجی های مختلف روی اونها اعمال بشه. اگر از فریمورک های موجود استفاده میکنید ابزار های خوبی رو در این زمینه براتون فراهم کردن. اگر هم استفاده نمیکنید که پیشنهاد میکنم استفاده کنید!

- استفاده از Whitelist به جای Blacklist.

به بیان ساده Blacklist یعنی فیلتر کردن موارد غیر قابل قبول! که به مراتب تعداد این موارد خیلی بیشتر از قابل قبول هاست. اصلا ممکنه نتونید همه رو توی این لیست جا بدین و چیزهایی از قلم بیوفتن. پس هرگز سعی نکنید لیست از مواردی داشته باشید که برای app شما غیر قابل قبول هست(Blacklist) و به جای اون Whitelist بسازید.

- strict typing

اگر از عملگر == برای مقایسه استفاده میکنید مراقب باشید که PHP به علت تبدیل عجیب و غریبی که انجام میده ممکنه اسکریپت شما رو آسیب پذیر کنه. مثلا عدد 1 برابر هست با رشته 1 و خود 1 یعنی true! و... .(Type Hinting)

 - از الگوریتم های امنیتی/رمزنگاری من درآوردی خودت استفاده نکن!

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

ادامه...

چرا از framework استفاده میکنم؟

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

موضوع بعدی کار کوچک و کار بزرگ هست و به نظرم درسته که برای انجام یک کار کوچک نباید از یک فریمورک بزرگ استفاده کرد. این موضوع اصلا ربطی به استفاده یا عدم استفاده از فریمورک نداره. 

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

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

- آیا از نظر فنی اینقدر کامل و بی عیب و نقص هستین که در این کار اشتباه نکرده باشید؟

- امنیت چطور؟ آیا امنیت رو به خوبی تضمین میکنید؟

- مستندات کاملی برای اون نوشتین و امکان این وجود داره که نفر جدیدی بدون درد و خونریزی وارد تیم بشه؟

- و سوال اخر، آیا مطمئن هستید به پرفورمنسی که دنبالش بودین رسیدین و بهتر از پرفورمنس سایر فریمورک هاست؟!

کامنت فارسی! کاچی به از هیچی

اولین بار زمانی که داخل کدهام فارسی کامنت گذاشتم توبیخ شدم اما به کارم ادامه دادم، به مرور باقی همکارانم همین کارُ انجام دادن. حالا داخل سورس هامون کمتر متدی پیدا میشه که توضیحات نداشته باشه. معمولا زمانی که توانایی لازم برای خواندن و نوشتن زبان انگلیسی رو نداشته باشیم نوشتن توضیحات برامون سخت و غیر قابل تحمل میشه. این کار شاید غیر استاندارد باشه اما چند خط کامنت فارسی یا حتی ناقص از نبودنش بهتره. میگم غیر استاندارده چون اکثر Editor و IDE ها به دلیل عدم پشتیبانی کامل از فارسی باعث میشن نوشته ها رو به طور غیر نرمال مثلا برعکس ببینیم! وگرنه سورس های زیادی رو دیدم که داخلشون به زبان های مختلفی کامنت گذاشته شده بود(روسی، چینی و...).

درس های yii2 شماره 24: Array Helper

تقریبا تمام فریم ورک ها Helper دارن تا به توسعه دهنده شون کمک کنن کارهای روتین شون رو ساده و سریع تر انجام بدن. Array Helper یه سری توابع اضافی برای کار با آرایه ها در اختیارتون قرار میده.

1) getColumn. متد بسیار پر استفاده ای هست مخصوصا اونجایی که یک مدل رو find میکنید. مقادیر یک ستون مشخص در آرایه رو بهتون میده. پارامتر اول آرایه مورد نظر و پارامتر دوم نام ستون هست. 

$array = [
    ['id' => '123', 'data' => 'abc'],
    ['id' => '345', 'data' => 'def'],
];
$result = ArrayHelper::getColumn($array, 'id');
// the result is: ['123', '345']

// using anonymous function
$result = ArrayHelper::getColumn($array, function ($element) {
    return $element['id'];
});
ادامه...

اجرای collection های postman

برای اجرای collection ها در نوار کناری سمت چپ روی فلش مجموعه ی مورد نظرتون کلیک و سپس دکمه ی run رو بزنید. میتونید تمام collection ها یا فقط یک پوشه رو اجرا کنید. اگر در زمان اجرا با خطایی برخورد کردین میتونید داخل postman console که قبلا در موردش توضیح دادم جزئیات کاملش رو ببینید.

run collection

collection ها در postman

collection چیزی مثل folder هست که به منظور دسته بندی درخواست های مشابه از یک نوع یا یک گروه استفاده میشه. مستندات خود postman توضیحات خوبی در مورد ایجاد و مدیریت collection داده که در اینجا سعی میکنم نمونه ای رو مثال بزنم.

در قسمت سمت چپ نرم افزار و با کلیک روی دکمه new folder میتونید یک یا چند collection ایجاد کنید. زمانی که درخواست جدیدی رو ایجاد میکنید با کلیک روی گزینه ی save میشه اون رو داخل folder های تعریف شده ذخیره کرد.

create collection

امکانش وجود داره به این توافق برسیم که یک ساختار ساده گزینه ی خوبیه پس میشه برای هر feature یک collection ساخت. داخل application ما دوره های آموزشی وجود داره به اضافه اینکه کاربران میتونن داخل دوره ها ثبت نام و بعد از اون دوره های خودشون رو داخل پنل کاربریشون مشاهده کنن. میتونیم برای این feature یک collection بسازیم.

کتابخانه های کمکی postman

اعتبار سنجی پاسخ ها و بررسی خروجی JSON که اغلب شامل attribute های زیادی هست به مرور خسته کننده میشه. postman شامل کتابخانه های مفیدی هست که به شما برای test کمک میکنه. به ویژه lodash و tv4 JSON schema validator. میتونید لیست کامل این کتابخانه ها رو اینجا ببینید. بیایید دوباره عملیات test صفحه ی login رو که در پست های قبلی انجام دادیمُ ادامه بدیم.

از اونجایی که login ما فقط یک token برمیگردونه میتونیم ست بودن مقدار token رو بررسی کنیم.

let jsonData = JSON.parse(responseBody);
let ok = responseCode.code === 200;
tests["Successful request"] = ok;
tests["Token is set"] = _.has(jsonData, "token");

if(ok) {
    pm.environment.set("token", jsonData.token);
}
ادامه...

استفاده از console در postman

گاهی اوقات نیاز دارین اطلاعات درخواست و پاسختون رو با دقت بیشتری بررسی کنید. ابزار console این اطلاعات ارسال شده و دریافتی شما رو با جزئیات بیشتری ثبت میکنه. برای باز کردن console از کلید ترکیبی cmd+alt+C استفاده کنید یا اینکه به آدرس View > Show Postman Console برید.

عملیات test در postman

هنگام توسعه ی application نیاز داریم از صحت نتایج API اطمینان حاصل کنیم. با استفاده از testing میتونیم انواع مختلفی از اعتبار سنجی ها رو برای نتایج ایجاد کنیم. به عنوان مثال برای درخواست login در زبانه tests کد زیرُ بنویسید و روی دکمه Send کلیک کنید.

 

tests["Successful request"] = responseCode.code === 200;

 

postman tests

ادامه...

تعریف متغییر های محیطی در postman

Environment Variables ها امکان خوبی هستن که انجام عملیات copy/paste رو کاهش میدن و تمام متغییر های ما رو در یک جا نگه میدارن. environment یک محیط اجراست. ما میتونیم محیط های متفاوتی داشته باشیم مانند، محیط ارزیابی، عملیاتی/استقرار و... 

postman انواع مختلفی از متغییر ها رو در اختیار ما میذاره(Global، Environment، Local و Data). متغییر های Global  که اینجا مثالی در موردش خواهیم زد همه جا قابل استفاده هستند. شما میتونید در مورد متغییر ها اینجا بیشتر بخونید.

به عنوان مثال، ما به سه متغییر نیاز داریم.

domain: یک subdomain فعال که در حال حاضر ازش استفاده میکنیم مثل company1، company2 یا هر چیز دیگه ای.

url: آدرس اپلیکیشن مون.

token: توکنی که برای احراز هویت ازش استفاده میکنیم.

ادامه...

احراز هویت یا authorization در postman

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

خیلی ساده، در هر درخواست token رو در header ارسال میکنیم. سمت نرم افزار این توکن رو دریافت و بررسی میکنه تا از معتبر بودنش مطمئن بشه.

postman authorization

ادامه...

آموزش postman ایجاد یک request

اولین گام برای کار با postman، ایجاد یک request و مشاهده پاسخ یا خروجی اون هست. 

postman request

ادامه...

‏احساس تعلق خاطر به محل کار

روز اولی که اومدم شرکت داشتن نیرو جذب می‌کردن. بعد از مدتی دیدم خیلی هوام‌ُ دارن و همه جور امکاناتی برام فراهم می‌کنن. می‌گفتم اینا چقدر دلسوز کارمنداشون هستن. تا اینکه موضوع تعدیل نیرو داغ شد و عده‌ای رو اخراج کردن.

‏اما خوشبختانه من موندم. رئیس شرکت می‌گفت متاسفیم اما مجبوریم. اون موقع من فهمیدم چقدر کودکانه فکر می‌کردم. همیشه موضوع منفعت هست. تاسف اون هیچ ارزشی برای کسایی که اخراج شدن نداشت. اون از روز اول هم برای کسی دلسوزی نمی‌کرد. برای اون چیزی که مهمه بازدهی بیشتر نیروهاش بود و هست.

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

ادامه...

آپلود فایل های پروژه به وسیله ی ftp هنگام استفاده از git

اگر از git استفاده بکنیم یا نکنیم در نهایت نیاز داریم تا پروژمون رو داخل سرور قرار بدیم. ftp یک روش مرسوم برای این کار هست و Git-ftp این امکان رو بهمون میده تا با آپلود آخرین تغییرات پروژه در سرور زمان و پهنای باند کمتری رو صرف این کار بکنیم. برای تشخیص تغییرات، گزارشی از فایل های آپلود شده در قالب یک فایل log بر اساس شناسه commit داخل سرور نگه داری میشه بنابراین میتونیم به راحتی از branch های مختلف استفاده و یا به عقب برگردیم و یک نسخه ی قدیمی رو آپلود کنیم :)

# Setup
git config git-ftp.url "ftp://ftp.example.net:21/public_html"
git config git-ftp.user "ftp-user"
git config git-ftp.password "secr3t"

# Upload all files
git ftp init

# Or if the files are already there
git ftp catchup

# Work and deploy
git commit index.txt -m "Add new content"
git ftp push
# 1 file to sync:
# [1 of 1] Buffered for upload 'index.txt'.
# Uploading ...
# Last deployment changed to ded01b27e5c785fb251150805308d3d0f8117387.

داستان اول شخص بودن یک توسعه دهنده

یه دوستی میگفت در همین لحظه که داری به موضوعی فکر میکنی به طور میانگین حدود 16 نفر دیگه هم مثل تو دارن هم زمان به این موضوع فکر میکنن!

به نظرم توی برنامه نویسی اول شخص بودن یعنی ادعا. اینکه بگیم اولین نفری بودیم که این کارُ انجام دادیم یا مثلا تنها کسی بودم که انجامش دادم و...

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

درس های yii2 شماره 23: بهینه سازی SEO با pretty URLs برای صفحه بندی ها

در ادامه مطلب قبلی که به اصطلاح آدرس صفحات رو قشنگشون کردیم! یا به عبارت دیگه اونها رو به شکلی تغییر دادیم که گوگل دوست داره و برای کاربران هم قابل فهم تره میرسیم به صفحه بندی ها که به طور پیشفرض چیزی مثل http://example.com/schools/schoolTitle?page=2 میمونه. تصمیم بر اینه که صفحه بندی به صورت http://example.com/schools/schoolTitle/2 تغییر کنه. فایل پیکره بندی yii رو باز کنید چون لازمه به urlManager یک قانون جدید اضافه کنیم.

$config = [
        // ...
        'urlManager' => [
            // ...
            'rules' => [
              'schools/<title:\w+>/<page:\d+>' => 'site/schools', // new rule
              'schools/<title:\w+>' => 'site/schools',
            ],
        ],
        ....

 میتونید برای مشاهده قانون های بیشتر نگاهی به urlManager رسپینا بندازید.

همین :)

ذخیره و تجزیه و تحلیل apache logs در elasticsearch

filebeat-1

elastic اخیرا ماژول های filebeat رو معرفی کرده، که برای پردازش و به دست آوردن یک بینش بصری از log های رایج طراحی شده. filebeat در kibana به عنوان نقطه ی شروع یک داشبورد از پیش طراحی شده در اختیارتون قرار میده که میتونید بعدا نمودار های دیگه ای هم بسته به نیازتون بهش اضافه کنید. ماژول Apache2 که اینجا در موردش حرف میزنیم، اطلاعات مربوط به log های apache رو از مسیر های پیشفرض جمع آوری میکنه، اگر مسیر های پیشفرض رو هم تغییر دادین امکان پیکره بندی این ماژول وجود داره.
اطلاعات جمع آوری شده توسط filebeat به elasticsearch ingest node ارسال خواهد شد(به گره هایی که قبل از شاخص گذاری روی پرونده ها عملیات پیش پرازش رو انجام میدن ingest node گفته میشه) تا عملیات تجزیه و تحلیل قبل از شاخص گذاری در elasticsearch انجام بگیره.

ادامه...

رسپینا، تجربه شیرین اوپن سورس

داستان رسپینا اولین بار برمیگرده به چند سال پیش. قرار بود در انجمن ایران پی اچ پی که هنوز یکی از اعضای اون هستم آموزش پروژه محور داشته باشیم. چه چیزی بهتر و ساده تر از سیستم وبلاگ نویسی؟ به دلیل عدم مشارکت بچه ها پروژه(رسپینا) سال ها عقب افتاد تا زمانی که من yii2 رو برای یادگیری انتخاب کردم. خب چه چیزی بهتر از یک آموزش پروژه محور؟ بنا بر این تصمیم گرفتم رسپینا رو توسعه بدم. در نهایت یک نسخه پر از اشکال مدت زیادی بدون انتشار باقی موند تا اخیرا که دستی به سر و روش کشیدم و گذاشتمش داخل github. ما از ابتدا قرار نبود چرخ رو دوباره اختراع یا یک سیستم با ویژگی های متفاوت ایجاد کنیم. هدف آموزش بود بنا بر این اگر در مورد yii کمی تجربه داشته باشید و نگاهی به سورس بندازید متوجه خواهید شد کار سطح بالا و پیچیده ای انجام نشده. همه چیز ساده و با امکانات پایه خود فریمورک انجام گرفته. برای من همین کافیه تا کسی از روی سورس چیزی یاد بگیره مثل خودم که در گیت هاب از پروژه های دیگران استفاده میکنم.