۱۳۸۷/۱۱/۲۷

توصيه‌هايي در مورد overloading متدها


مطلب زير چكيده‌اي است از كتاب Framework Design Guidelines در مورد سربارگذاري توابع

الف) از يك نوع خروجي استفاده كنيد

مثال زير را در نظر بگيريد:

public User[] GetGroupMembers(int groupId)
public List<User> GetGroupMembers(string groupName)

هر دوي اين متدها گروهي از كاربران را بازگشت مي‌دهند. خروجي متد اول از نوع آرايه است و خروجي متد دوم از نوع يك ليست جنريك مي‌باشد.
مشكل اينجا است كه هنگام فراخواني هر كدام، نحوه‌ي استفاده متفاوت خواهد بود. بنابراين بايد از اين نوع سربارگذاري پرهيز كرد.

ب) نام‌هاي آرگومان‌هاي توابع سربارگذاري شده شما بايد يكسان باشند

در مثال زير، از اولين آرگومان جهت دريافت شناسه‌ي يك گروه استفاده مي‌شود:

public List<User> GetGroupMembers(int groupId)
public List<User> GetGroupMembers(int id, int pageIndex, int pageSize)

اما همانطور كه ملاحظه مي‌كنيد در يكي از groupId استفاده شده و در ديگري از نام id . اين روش مزموم است! از آن پرهيز كنيد! (هر دو يا بايد groupId باشند و يا id . اين هماهنگي و يكسان بودن بايد در توابع سربارگذاري شده‌ي شما حفظ شود)

ج) ترتيب آرگومان‌ها را در توابع سربارگذاري شده حفظ و رعايت نمائيد

لطفا به مثال زير دقت كنيد:

public List<User> GetGroupMembers(int groupId)
public List<User> GetGroupMembers(int pageIndex, int pageSize, int groupId)

در اينجا شناسه‌ي گروه يكبار به عنوان آرگومان اول معرفي شده و بار ديگر به عنوان آرگومان سوم. اين كار نيز مزموم است، زيرا برنامه نويس‌ها از روي عادت به اولين آرگومان توابع سربارگذاري شده‌ي شما، همان شناسه‌ي گروه را ارسال خواهند كرد و اين مورد سبب بروز باگ‌هايي خواهد شد كه رديابي آن مشكل است. بنابراين اگر شناسه‌ي گروه به عنوان اولين آرگومان معرفي شده، در تمامي overload هاي اين تابع نيز اولين آرگومان بايد همان شناسه‌ي گروه باشد.

د) از call forwarding استفاده كنيد

جهت توضيح بهتر call forwarding به مثال زير دقت نمائيد:
public List<User> GetGroupMembers(int groupId)
{
return GetGroupMembers(groupId, 0, 10);
}

public List<User> GetGroupMembers(int groupId, int pageIndex, int pageSize)
{
return GetGroupMembers(groupId, pageIndex, pageSize, SortOrder.Ascending);
}

public List<User> GetGroupMembers(int groupId, int pageIndex, int pageSize, SortOrder sortOrder)
{
var query = new GroupQuery();
query.GroupID = groupId;
query.PageIndex = pageIndex;
query.PageSize = pageSize;
query.SortOrder = sortOrder;

return GetGroupMembers(query);
}

public List<User> GetGroupMembers(GroupQuery groupQuery)
{
// Actual implementation to get group members goes here
}

معناي call forwarding اين است كه هنگام پياده سازي توابعي از اين دست، كوچكترين تابع سربارگذاري شونده بايد تابع بزرگتر بعدي خود را صدا بزند و همين‌طور الي آخر كه در مثال فوق به خوبي آشكار است. در اين مثال چهارمين تابع سربارگذاري شده، بيشترين حوضه‌ي تمركز را در خود دارد و توابع ديگر مي‌توانند از آن بهره جويند بدون اينكه پياده سازي خاصي را ارائه دهند.

ه) زياده‌ روي نكنيد!

آخرين موردي كه توصيه شده اين است كه در تهيه توابع سربارگذاري شده زياده روي نكنيد. در اين نوع موارد بايد قانون 80/20 را در نظر گرفت. 2 تا 3 تابع سربارگذاري شده ارائه دهيد كه 80 درصد كار را انجام مي‌دهند و سپس يك تابع سربارگذاري شده‌ي ديگر ارائه دهيد كه 20 درصد باقيمانده را پوشش دهد.


پ.ن.
در سي شارپ 4 ، با معرفي optional parameters ، شايد كمتر به سربارگذاري نياز باشد.