PDA

View Full Version : آموزش: Fluent Code (Fluent Interface) in PHP



Sajjad.Aghapour
چهارشنبه 06 مرداد 1389, 12:56 عصر
سلام دوستان...
چند وقت پیش مقاله ای (http://sajjadaghapour.wordpress.com/2010/04/16/%d8%ae%d9%88%d8%a7%d9%86%d8%a7%d8%aa%d8%b1-%da%a9%d8%b1%d8%af%d9%86-%da%a9%d8%af%d9%86%d9%88%db%8c%d8%b3%db%8c-%d8%af%d8%b1-net/) رو در مورد Fluent Interface در NET. نوشته بودم که چون حالا تو فاز کدنویسی PHP بودم گفتم یه معرفی از این تکنیک داشته باشم....

البته چون نوع خروجی باید مشخص شود، نتونستم نام اون رو Fluent Interface بگذارم چون در PHP نوع خروجی رو نمیتوان در Signature تابع مشخص کرد(فکر میکنم باید تدابیری برای این موضوع اندیشیده بشه)، در نتیجه برای ایجاد یک Interface و Implementation اون توسط یک کلاس دچار مشکل خواهیم بود.البته مشکل نمی توان اسمش رو گذاشت ولی به هر حال یک حالت امن برای Implementation هم به ما نخواهد داد.
اما شاید این موضوع برایتان گنگ باشد چون هنوز مفهوم این تکنیک رو شاید ندونید.و اما توضیح:
(مثالی که برای این موضوع میزنم فارق از مسائل و روش های Object Initialization هستش و فقط جهت رساندن مفهوم مطلب است)...

بهترین تعداد آرگومانهای یک تابع صفر(niladic) است.بعد از آن یک(monadic) و بعد از آن دو(dyadic).تعداد سه آرگومان(triadic) تا جائیکه ممکن است نباید استفاده شود.اما بیش از سه آرگومان(polyadic) نیاز به اصلاح دارد و تحت هر شرایطی نباید استفاده شود.
اما گاهی اوقات ممکن است توابع و آبجکت هایی وجود داشته باشند که سه یا بیشتر از سه آرگومان را می پذیرند و معمولا هم توسط یک سازنده مقدار اولیه خواهند گرفت.ممکن است بعضی از آرگومان های آنها نیاز نباشد که در این صورت شما می توانید با دادن مقدار پیش فرض در موقع لزوم به آنها مقدار بدهید.اما با این حال نباید از اصل موضوع دور بشویم و بی خیال به کدنویسی خود ادامه بدهیم.
مفهوم Fluent در مهندسی نرم افزار به این دلیل ابداع شد که بتوان واسط کاربری را تهیه کرد که از لحاظ خوانایی بیشترین کیفیت را داشته باشد...

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

class Person
{
private $fullName = '';

public function Name($name)
{
$this->fullName .= (empty($this->fullName)) ? "$name" : " $name";
}

public function NickName($nickName)
{
$this->fullName .= (empty($this->fullName)) ? "$nickName" : " $nickName";
}

public function Family($family)
{
$this->fullName .= (empty($this->fullName)) ? "$family" : " $family";
}

public function GetFullName()
{
return $this->fullName;
}
}

و برای استفاده از آن:

$person = new Person();
$person->Name('Sajjad');
$person->NickName('sajjadlove');
$person->Family('Aghapour');
$fullName = $person->GetFullName();
echo $fullName;


این دوباره به کارگیری یک Object و استفاده از آن برای به کارگیری توابعی که به یک کار نسبت داده میشوند کار جالبی نیست.اگر بخواهیم آن را با استفاده از تکنیک Fluent Interface پیاده سازی کنیم به این صورت خواهد بود:

class Person
{
private $fullName = '';

public function Name($name)
{
$this->fullName .= (empty($this->fullName)) ? "$name" : " $name";
return $this;
}

public function NickName($nickName)
{
$this->fullName .= (empty($this->fullName)) ? "$nickName" : " $nickName";
return $this;
}

public function Family($family)
{
$this->fullName .= (empty($this->fullName)) ? "$family" : " $family";
return $this;
}

public function GetFullName()
{
return $this->fullName;
}
}

به مقدار برگشتی توابع دقت کنید که this$ یا خود کلاس را برخواهد گرداند....
و استفاده از آن :

$person = new Person();
$fullName = $person->Name('Sajjad')
->NickName('sajjadlove')
->Family('Aghapour')
->GetFullName();
echo $fullName;


اطلاعات بیشتر
http://en.wikipedia.org/wiki/Fluent_interface

و یک لینک کمکی
http://mikenaberezny.com/2005/12/20/fluent-interfaces-in-php/

موفق باشید/

mohmadd
چهارشنبه 06 مرداد 1389, 14:27 عصر
سلام
از مطالب مفیدی که تو این بخش میزارید ممنونم
یه سئوالی داشتم اینکه بهتر نیست تو کلاس تابع چندمی بزاریم که شرط هارو تست بکنه ؟


public function iff ($str)
{
$this->fullName .= (empty($this->fullName)) ? "$str" : " $str";
return $this;
}

Sajjad.Aghapour
چهارشنبه 06 مرداد 1389, 15:47 عصر
خواهش میکنم....

بله %100....
شما هر جا اعمال یکسان و مرتبط با یکدیگری دیدید میتونید این کار رو انجام بدید و اونها رو در قالب توابعی مجزا پیاده سازی کنید....

پیشنهاد میکنم بحث Refactoring رو حتما مطالعه کنید و سری به تاپیک زیر بزنید که این بحث رو هم شامل میشه...
http://barnamenevis.org/forum/showthread.php?t=224704

موفق باشید/