الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Best Practice - ما رأيك حول كتابة Comments في الأكواد؟

بدأه موليان في 1 أبريل 2012 · 10 رد · 1,000 مشاهدة · في الأخبار والنقاشات التقنية
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

اليوم شاهدت شخص يقول حاول الاجتناب عن كتابة التعليقات في كودك، في نظرة اولية يظهر راي غير جيد، لكن أرى الحق معه!

في الحقيقة، لا معني للتعليقات، لا تؤثر في الكود النهائي و الـCompiler يتجاهل التعليقات.

لماذا أملئ الشاشة و أتعب أصابعي لكتابتها خاصة لو كانت لوحة المفاتيح من منتجات Acer - لا قدر الله.

لكتابة الـComments سبب واحد، وهو شرح هدف الكود، يمكن القيام بهذا بدون تعليق وبشكل واضح، كيف؟

مثلا هذا الكود:

// ensure we don't send a notification to
// important people

if (account.IsVip && account.IsPastDue)
{
	SendNotification = false;
}

يمكن كتابته بشكل آخر، واضح، جميل وبدون تعليق:

CancelNotificationForVipAccounts();

طبعا لا أقصد التعليقات التي نستخدم للـDocumentation أو Intellisense في Visual Studio مثلا.

-----------------

اثناء القراءة حول هذا الموضوع رايت مواضيع جميلة، هذا مثلا :D :

public class Program
{
	static void Main(string[] args)
	{
    	/* This is a for loop that prints the
     	* words "I Rule!" to the console screen
     	* 1 million times, each on its own line. It
     	* accomplishes this by starting at 0 and
     	* incrementing by 1. If the value of the
     	* counter equals 1 million the for loop
     	* stops executing.*/
    	for (int i = 0; i < 1000000; i++)
    	{
        	Console.WriteLine("I Rule!");
    	}
	}
}

طالع أكثر (هنا..) (هنا..).

4 −1

..:: رَبِّ زِدْني عِلْمًا ::..

#2

كمثال انظر هذه الداله

// get t from decimal string
template<typename t>
bool mathx_int_fdec(const_astr str, t& value)
{
	typedef global_int<t> gint;
	typedef typename t::ucomp uc;

	// result sign
	bool sign = false;
	// skip head whites
	while(mathx_isWhite(*str)) ++str;


	// In Next Statement: VC++, Intel C++ Level 4 WARNING: assignment of constant in Boolean context. Consider using '==' instead.
	// assigning true to [sign] variable ain't typo mistake, it is intended, DON'T CHANGE IT TO '=='
	//
	// if [t] is signed check for negative sign in input string, or check for positive sign
	if((gint::sign_t && *str == '-' && (sign=true)) || *str == '+') ++str;

	// skip leading zeros
	while(*str == '0') ++str;

	// set result to zero
	value = gint::zero;

	// if it all zero then mission accomplished
	if (!*str) return true;

	// a pointer to check invalid digits
	astr str2 = (astr)str;

	// check base digits
	while(*str2) if (!mathx_isDec(*str2++)) return false;

	// size of part to convert
	uintX strLen = str2 - str;

	// if number of digits more than a type can handle then
	// an overflow will occur.
	if (strLen > log10_for_type<t>::value + 1) return false;

	// number of digits store inside uc without overflow
	const uint32 digitCount = log10_for_type<uc>::value - 1;

	// do convert
	while(*str)
	{
		// value of single component
		uc result = 0;

		// get component value
		for(uint32 i=0; *str && i<digitCount; ++i, --strLen)
			result = result * 10u + (*str++ - '0');

		// update out value
		value += result;

		// if remain characters more than [digitCount]
		// then shift [value] by [digitCount]
		if (digitCount <= strLen)
			value *= power10_for_type_helper<uc, digitCount>::value;
		// if there is characters less than [digitCount] but not zero
		else if (strLen)
		{
			// get number of digits to shift
			uc pwr = 10;
			for(uint32 i=1; i<strLen; ++i) pwr *= 10;
			// update number
			value *= pwr;
		}
	}

	// if signed and sign exist get the complement
	if (gint::sign_t && sign) value = ++~value;

	return true;
}

تخيل انك تقرأ هذه الداله بدون تعليقات، و اعلمنى ماذا ستفهم منها، أيضا لاحظ ان هذه الداله يتم ترجمتها من خلال اكثر من مترجم لذا تم وضع عليها احد سطورها تعليق هام يخص هذه النقطه، فلنفرض عدم وجود التعليق هذا السطر حينها عندما تقوم بترجمة الداله من خلال مترجم VC مثلا ستقوم يتغيير الـ assignment إلى equality.

------------------------------------

عموما الداله تقوم بحل مشكله و التعليق المكتوب اعلاها يظهر نوع المشكله التى تحلها، اما محتوى الداله فهو الكيفيه التى يتم حل المشكله بها و هي تحتاج توضيح من كاتبها حتى يستطيع من يقرءها ان يفهم لماذا كتب الكود بهذا الشكل.

عند كتابة المشاريع الكبيره يتم كتابة whitepapers منفصله تشرح الـ big picture و مع كل جزئيه من البرنامج يوجد لها مجموعة whitepapers تشرح اسباب وجود هذا الجزء و كيف من المفترض ان يعمل بالتفصيل، داخل الكود يتم كتابة شرح مفصل للخطوات المتبعه للكود.

قم بالإطلاع على اى مكتبات مفتوحة المصدر مثل QT أو Net Framework، أيضا القي نظره على كود ويندوز 2000/2003 و ستعرف لماذا وجود التعليقات هام جدا.

و الله ولي التوفيق

2

مدونتي: C++ Tips and Tricks

#3

إنني مؤيد لكتابة التعليقات في الأكواد ، حتى وإن كانت التسميات التي تختارها واضحة. في بعض الأحيان ، كتابة التعليقات فرض عين على كل مبرمج ، خصوصاً لو كان الـ naming convention المستخدم سيء مثل المستخدم في لغة C :

	if ((gid = getgid()) < 0) {
	  perror("
getgid error");
	} else {
	  printf("
The group id is : %d", gid);
	}

	if ((gid = getegid()) < 0) {
	  perror("
getegid error");
	} else {
	  printf("
The effective group id is : %d", gid);
	}

	printf("

");

أيضاً التعليقات قد تشرح سبب ما لا تستطيع شرحه من خلال اسم "الدالة" . مثلاً ، ستقول أن هذا السطر هو workaround لمشكلة X التي ظهرت على نظام Y .. فلا مفر ..

التعليقات وجودها لن يضر ، وهناك Tools تزيل التعليقات لو كانت مزعجة .

1

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#4

حسب فهمى فإنه يتم الإستغناء عن التعليقات بالكود نفسه

هذا جزء من الكود الذي قام بكتابته الأخ محمد علاء قمت بكتابته بالطريقه التى اتحدث عنها >>>>

// get t from decimal string
template<typename t>
bool mathx_int_fdec(const_astr str, t& value)
{
        typedef global_int<t> gint;
        typedef typename t::ucomp uc;

        bool resultSign = false;
	skip_head_whites(str);


        // In Next Statement: VC++, Intel C++ Level 4 WARNING: assignment of constant in Boolean context. Consider using '==' instead.
        // assigning true to [sign] variable ain't typo mistake, it is intended, DON'T CHANGE IT TO '=='
        //
        // if [t] is signed check for negative sign in input string, or check for positive sign
        if((gint::sign_t && *str == '-' && (sign=true)) || *str == '+') ++str;

        skip_leading_zeros(str)

        value = gint::zero;

	all_zeros(str) && return true;

	astr str2 = chk_invalid_digits(str);

        check_base_digits (str) && return false;

	// ….
	// ……

}

تم تعديل هذه المشاركة بواسطة __Unknown في 1 أبريل 2012 في 20:25

2
#5

انصحك بالكتاب دا

http://ofps.oreilly.com/titles/9780596802295/

قريته ممتاز بصراحة لكن مع بعض التكلف...

(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

#6
اقتباس
حسب فهمى فإنه يتم الإستغناء عن التعليقات بالكود نفسه

لقد رأيتها تستخدم فى العديد من البرامج و لكن احيانا يصبح إسم الداله كبير نسبيا، مثل WhatYouThinkOfThisFunctionName او what_you_think_of_this_function_name.

مدونتي: C++ Tips and Tricks

#7

اهلا بالاساتذة محمد علاء الدين والشمري،

إضافة: وبقية الإخوة :-)

-----

طبعا لا مشكلة في الـDocumentations. بل العكس، كتابتها فرض عين.

الأخ محمد علاء الدين:

هنا يظهر الفرق بين مبرمج يجيد عمله ويعلم ما يكتب ومبرمج يصنع شوربة.

يمكن ان يكتب مبرمج مثد تقوم بوحدها كل المهام، يعني يتم تعريف المتغيرات ويتم عمل Doing, Deciding, Knowing كلها داخل هذه المثد وحدها، بالطبع سيحتاج بالتعليقات، بل صدقني، التعليقات ايضا لن تنفع في فهم هذا الكود الذي صنعه.

وفي المقابل، مبرمج اخر، يتعب نفسه في الـDesign،يخصص مثد للـKnowing، مثد اخرى للـDeciding، اخرى للـDoing. لكل شيء اسم يدل على عمله. والنتيجة، يكتب كود جميل واضح وبدون تعليق البتة.

لننظر بهذا المثال لشرح الفكرة:

هذا الكود من النوع الأول، كل شيء داخل دالة، مرة يقوم بتعريف متغير، مرة يقرأ قيمة، مرة يكتب.. إلخ، هذا الكود السيء يحتاج بالتعليق، لا مفر منه:

static void Main(string[] args)
{
	var date = new List<DateTime>();
	var open = new List<decimal>();
	var high = new List<decimal>();
	var low = new List<decimal>();
	var close = new List<decimal>();

	var lines = File.ReadAllLines(args[0]);
	for (int i = 1; i < lines.Length; i++)
	{
		var data = lines.Split(',');
		date.Add(DateTime.Parse(data[0]));
		open.Add(decimal.Parse(data[1]));
		high.Add(decimal.Parse(data[2]));
		low.Add(decimal.Parse(data[3]));
		close.Add(decimal.Parse(data[4]));
	}

	for (int i = 0; i < date.Count - 1; i++)
	{
		if (open > high[i + 1] && close < low[i + 1])
		{
			Console.ForegroundColor = ConsoleColor.Red;
			Console.WriteLine("Pivot downside {0}", date.ToShortDateString());
		}
		if (open<low[i+1] && close > high[i+1])
		{
			Console.ForegroundColor = ConsoleColor.Green;
			Console.WriteLine("Pivot upside {0}", date.ToShortDateString());
		}
	}

	Console.ForegroundColor = ConsoleColor.White;
}

لكن هذا من النوع الثاني،يقوم بنفس العمل، لكن لكل عملية دالة خاصة بها، و كل شيء واضح من اسمه، والتعليق شيء غير لازم:

public class StockQuote
{
	//..
}

public class StockQuoteLoader
{
	//..
}

public enum ReversalDirection
{
	//..
}

public class Reversal
{
	//..
}

public class ReversalLocator
{
	//..
}

class StockQuoteAnalyzer
{
	//..
}

class Program
{
	static void Main(string[] args)
	{
		var analyzer = new StockQuoteAnalyzer(args[0]);
		foreach (var reversal in analyzer.FindReversals())
		{
			PrintReversal(reversal);
		}
	}
	private static void PrintReversal(Reversal reversal)
	{
	}
}

كذلك في مثال الاخ الشمري، يمكن تبديل ذلك السطر بدالة، نستعملها وقت الحاجة وعملها معلوم من اسمها.

بالاختصار، لو كتب المبرمج الكود بشكل صحيح، لا حاجة بالتعليقات.

تم تعديل هذه المشاركة بواسطة موليان في 1 أبريل 2012 في 22:32

..:: رَبِّ زِدْني عِلْمًا ::..

#8

انا اؤيد وجود التعليقات في الكود

حاول العمل بمشروع كبير واتركه لمدة من الزمن وحاول الرجول اليه من دون التعليقات سيحتاج منك وقت اكبر لاعاده فهم المشروع من جديد

من الممكن ان تغني الداله عن عمل التعليق لكن يجب ان لا ننسا ان لكل شيء وظيفته في الكود هناك اجزاء معينه من الكود تحتاج لتعليق بسيط لشرح عمليه ما خصوصا عندما يتعلق الكود بخوارزمية معينه

#9
R@ND_CiS كتب:

انا اؤيد وجود التعليقات في الكود

حاول العمل بمشروع كبير واتركه لمدة من الزمن وحاول الرجول اليه من دون التعليقات سيحتاج منك وقت اكبر لاعاده فهم المشروع من جديد

يعني لن نفهم ماذا يفعل هذا الكود؟:

CancelNotificationForVipAccounts();

لفهم المشروع نقرأ الـDocumentations، أنا لم أعارضها.

عموما لا يمكن الاستغناء عن التعليقات نهائيا في بعض الأحيان،

لكن كتابة تعليق فوق كل سطر، عمل "غير لازم"

..:: رَبِّ زِدْني عِلْمًا ::..

#10

بالتأكيد كل شيء يزيد عن حدو يصبح خطأ

لكن لا مانع من وجود تعليق صغير داخل الكود

#11

إذا كان التعليق يشرح شيئاً في اللغة المستخدمة أو المكتبات فهذا يعتبر سيئاً.

إذا كان التعليق يشرح الـ domain الذي بني عليه الكود فهذا سيء أيضاً.

إذا كان التعليق يشرح لماذا اختيرت هذه الطريقة لحل المشكلة فهذا هو المطلوب. على سبيل المثال, تم استخدام اختصار لحساب أمر ما, فيتم توضيح لماذا تم اختيار الطريقة و ما تأثيرها على عمل الكود.

2

مواضيع مشابهة