Rambler's Top100
Главная
Новости
Статьи
Форумы
Книги
Коды
Сообщество
Блоги
О нас
 

Логин

Email:
  Пароль:

Войти
Зарегистрироваться
Забыл пароль

Поиск

 Искать :
 
Вперед


Соглашения о кодировании

Соглашения о кодировании

Автор: Serg Vorontsov aka V©R©N (voron@aspnetmania.com)
Опубликовано: 30 September 2002
Уровень: Совет

Версия для печати

Проголосовало 98 читателей
Средняя оценка 3.50

1. О руководстве "Стиль кодирования на С#" в рамках Gray LLC

Данный документ написан на основе неофициального стандарта предложенного Mike Krueger. (The SharpDevelop C# Coding Style Guide by Mike Krueger). Благодаря данному документу у Вас есть возможность разрабатывать "читабельный" код и как следствие надежный и легко переносимый. Основным в нем является правила форматирования кода, написанного на языке C#, но большинство приемов можно применить и для других языков программирования.

Документ разрабатывался для компании Gray LLC.

2. Организация файлов

2.1 Исходные файлы на C#

Старайтесь сохранять структуру классов/файлов небольшими размерами, до 2000 строк кода. Разделяйте код на файлы, это поможет Вам создавать более четкую инфраструктуру приложения. Помещайте каждый класс в отдельный файл с одноименным названием (совпадающее с названием класса) и расширением .cs.

2.2 Дерево файловых директорий

Создавайте директорию для каждого namespace.

Например для: MyProject.TestSuite.TestTier иерархия директорий будет иметь следующий вид: MyProject / TestSuite / TestTier.

Как видно из пример точка в строке namespace заменяется на символ слеша ("/") при написании директорий.

3. Структурированное расположение текста

3.1 Длина строки

Старайтесь избегать (насколько это возможно) строк, длинной более 80–ти символов. Присутсвие линейки в редакторе кода значительно облегчает этот контроль. Если строка превышает размер 80-ти символов используйте синтаксис переноса строки (см. 3.2)

3.2 Перенос длинных строк

В том случае, если строка превышает длину 80 символов, то для ее переноса используются основные принципы описанные ниже.

Строку можно переносить в случае, если:

  • Перенос после запятой.
  • Перенос после оператора.
  • Перенесенная линия по отношению к верхней должна быть сдвинута вправо как минимум на один стандартный символ табуляции либо на уровне начала переносимого выражения (см. примеры).
  • Символ Табуляции в редакторе устанавливается размером, равным 4-м стандартным символам.

Пример разбиения строки при вызове аргументов метода:

		longMethodCall(expr1, expr2, expr3,
			expr4, expr5);

Пример переноса арифметического выражения несколькими способами. Первый стандартным образом (с одинарным символом табуляции).

		var = a * b / (c - g + f) +
			4 * z; // PREFER

и вторым (с форматированием по переносимому выражению)

		var = a * b / (c - g +
			  f) + 4 * z; // AVOID

3.3 Пробелы

Никто, кто хочет достичь качественного уровня написания кода не должен использовать пробелы для форматирования отступов в коде. И делается это потому, что разные разработчики используют различное число для символов табуляции. Один – размер 2-х символов, другой 4-ре третий 8-мь. В случае, если вы будете использовать стандартный табулятор для отступа, то любой разработчик может перенастроить его под свой стандарт, что значительно облегчит модификацию написанного кода в будущем.

Вот несколько аргументов в пользу использования табулятора:

  • Каждый может настроить отступ под свой стандар;
  • Использование одного символа вместо 2-х, 4-х или 8-ми. И что самое важное легкость в выравнивании отступов: сделать это одним нажатием гораздо легче, чем несколькими;
  • Если Вы захотите передвинуть выделенный текст на одну табуляцию вправо (клавиша Tab) или влево (Shift+Tab) то сделать это не составит труда. Большинство редакторов имеют эту возможность.

Этих аргументов должно быть достаточно для того, что бы ни использовать пробелы при форматировании исходного кода.

!!! НЕ ИСПОЛЬЗУЙТЕ ПРОБЕЛЫ ВМЕСТО СИМВОЛОВ ТАБУЛЯЦИИ !!!!

4. Comments

4.1 Блочный комментарий

Как правило, используется блочный комментарий для описания, а так же стандартный «///» комментарий для самодокументирования.

Для стандартных блочных комментариев используются следующие стили:

		/*
		* Line 1
		* Line 2
		* Line 3
		*/

либо такой стиль:

		/* blabla */

4.2 Комментарий "до конца строки"

Для комментариев в одну строку используется «С++» подобный стиль: «//» Этот стиль наиболее удобен при документировании параметров. Предпочтительно использовать данный стиль вместо /* комментарий */ там, где это возможно.

		int i; // переменная для цикла

4.3 Комментарии для самодокументирования

Теги для самодокументирования, также могут использоваться разработчиками для описания. Но должен учитываться и тот факт, что он должен согласовываться с требованиями к документированию исходного кода.

<c> <para> <see>
<code> <param> <seealso>
<example> <paramref> <summary>
<exception> <permission> <value>
<include> <remarks>  
<list> <returns>  

Данный раздел подробно описан в документации Microsoft

5. Объявления

5.1 Количество объявлений на одной линии

Общепринятым стандартом в объявлениях является одна строка на экземпляр. Благодаря этому появляется удобство чтения и написания комментария:

		int level; // indentation level
		int size; // size of table

не размещайте объявления в одну строку!

		int a, b; // Неправильно !

5.2 Инициализация

Инициализируйте локальные переменные в том же месте где и объявляете.

Например:

		string name = myObject.Name;

либо

		int val = time.Hours;

5.3 Объявление классов и интерфейсов

В процессе разработки классов и интерфейсов, следуйте следующим правилам:

  • Между названием метода и открывающей скобкой с перечислением параметров не должно присутствовать пробела.
  • Открывающая фигурная скобка «{« должна начинаться на следующей строке сразу под названием класса или его метода.
  • Код, который следует под открывающей фигурной скобкой «{«, должен находится на смещении одного Tab символа вправо.
  • Закрывающая фигурная скобка «}» должна находится на уровне открывающей и охватывать весь блок кода.

Например:

	class MySample : MyClass, IMyInterface
	{
		int myint;

		public MySample(int myint)
		{
			this.myint = myint;
		}

		void Inc()
		{
			++myint;
		}	

		void EmptyMethod()
		{
		}
	}

6 Операторы

6.1 Обычные операторы

Желательно, чтобы в каждой строке присутствовал один оператор

6.2 Операторы возврата

Операторы возврата не должны использовать скобок.

6.3 If, if-else, if else-if else операторы

Код с использованием операторов if, if-else и if else-if else должен выглядеть следующим образом:

В простом случае:

	if (condition) 
	{
		DoSomething();
		...
	}

В более усложненном:

	if (condition) 
	{
		DoSomething();
		...
	}
	else 
	{
		DoSomethingOther();
		...
	}

И в самом сложном:

	if (condition) 
	{
		DoSomething();
		...
	} 
	else if (condition) 
	{
		DoSomethingOther();
		...
	} 
	else 
	{
		DoSomethingOtherAgain();
		...
	}

6.4 For / Foreach операторы

Стиль оформления кода для оператора For должен иметь следующий вид:

	for(int i = 0; i < 5; ++i) 
	{
		...
	}

Также допускается формат в одну строку:

	for(initialization; condition; update) ;

А оператор foreach должен выглядеть следующим образом:

	foreach(int i in IntList) 
	{
		...
	}

6.5 While/do-while операторы

Оператор While подлежит следующему форматированию:

	while(condition) 
	{
		...
	}

Пустой оператор While может быть иметь вид:

	while(condition);

Для Do-While применим следующий формат:

	do 
	{
		...
	} while (condition);

6.6 Switch операторы

Оператор Switch должен отвечать следующему формату:

	switch (condition) 
	{
		case A:
			...
			break;
		case B:
			...
			break;
		default:
			...
			break;
	}

6.7 Try-catch операторы

Формат написания операторов try – catch должен иметь следующий вид:

	try 
	{
		...
	} 
	catch (Exception) 
	{}

либо

	try 
	{
		...
	} 
	catch (Exception e) 
	{
		...
	}

либо

	try 
	{
		...
	} 
	catch (Exception e) 
	{
		...
	} 
	finally 
	{
		...
	}

7 Пустые строки и пробелы в форматировании кода

7.1 Пустые строки

Пустые строки помогаю разбивать код приложения на логические сегменты.

Несколькими строками могут отделяться:

  • секции в исходном файле;
  • классы и интерфейсы;

Одной пустой строкой отделяются друг от друга:

  • методы;
  • локальные переменные от первых операторов;
  • логические секции внутри метода для более удобного чтения

7.2 Пробелы

Один пробел используеться в объявлении методов после запятой, но не перед скобками:

	TestMethod(a, b, c); 

Пример неправильного использования:

	TestMethod(a,b,c);

либо

	TestMethod( a, b, c );

Так же одиночный пробел может быть использован для выделения операторов:

	a = b;  

неправильное использование:

	a=b;

Также пробелы используються и при форматировании циклов:

	for (int i = 0; i < 10; ++i) ;

так не нужно использовать:

	for (int i=0; i<10; ++i)

либо

	for(int i=0;i<10;++i)

7.3 «Табличное» форматирование

При объявлении и инициализации переменных желательно использовать «табличное» форматирование:

	string name	=	"Mr. Ed";
	int myValue	= 	5;
	Test aTest	= 	Test.TestYou;

8 Соглашение об именовании

8.1 Форматы именования

8.1.1 Pascal Casing

При этом стиле, каждое логическое слово должно начинаться с заглавной буквы. (например: TestCounter)

8.1.2 Camel Casing

Это соглашение устанавливает правила написания по следующей схеме: первый символ первого логического слова с маленькой буквы, остальные логические слова с большой, подобно Pascal Casing. (Например: testCounter)

8.1.3 Upper case

При этом соглашении в именовании используются только заглавные буквы. Этот стиль используется только при именовании «коротких» констант, например PI или E. В остальных случаях желательно использовать Pascal Casing.

Например:

	public class Math
	{
		public const PI = ...
		public const E = ...
	}
8.1.4 Сводная таблица использования именований
Type Case Notes
Class / Struct Pascal Casing  
Interface Pascal Casing Starts with I
Enum values Pascal Casing  
Enum type Pascal Casing  
Events Pascal Casing  
Exception class Pascal Casing End with Exception
public Fields Pascal Casing  
Methods Pascal Casing  
Namespace Pascal Casing  
Property Pascal Casing  
Protected/private Fields Camel Casing  
Parameters Camel Casing  

8.2 Классы и члены классов.

На текущий момент крайне не рекомендуется использовать венгерскую нотацию при помощи символа подчеркивания. В венгерской нотации использовалась суффиксная и постфиксная приставка для именования переменных.

В текущем документе Венгерская нотация рассматриваться не будет.

8.2.1 Именование классов
  • Класс должен именоваться как существительное в единственном или множественном числе;
  • Используется Pascal Casing (см 8.1.1);
  • Не используйте никаких префиксов при именовании класса.
8.2.2 Именование интерфейсов
  • При именовании интерфейс должен иметь имя существительное в единственном или множественном числе, которое максимально описывает его предназначение. (Например: IComponent or IEnumberable)
  • Используется Pascal Casing (см 8.1.1);
  • Используется в качестве префикса заглавная буква “I”, являющаяся первой буквой слова interface.
8.2.3 Именование перечислений
  • Используется Pascal Casing (см 8.1.1) как для именования enum так и для его значений;
  • Суффиксы и префиксы не используются;
  • Не используйте названий в единственном числе для именования enum;
  • Не используйте множественного числа при именовании «полей» enum.
8.2.4 Константы и поля Read Only
  • Используется Pascal Casing (см 8.1.1);
8.2.5 Параметры и нестатические поля
  • Используйте «описательные» названия для именования полей, которые достаточно полно описывают их функциональные требования, а так их же тип.
  • Используется Camel Casing (см 8.1.2);
8.2.6 Именование переменных
  • Используется следующий префикс для указания типов переменных:
C# Type

.NET Framework type Префикс
bool System.Boolean b

byte System.Byte by

sbyte System.SByte sby

char System.Char c

decimal System.Decimal dc

double System.Double d

float System.Single f

int System.Int32 i

uint System.UInt32 ui

long System.Int64 l

ulong System.UInt64 ul

object System.Object o

short System.Int16 sh

ushort System.UInt16 ush

string System.String s

  • Используйте переменные i, j, k, l, m, n для оформления циклов;
  • Используется Camel Casing (см 8.1.2);
8.2.7 Именование переменных внутри методов
  • Для внутренних переменных методов кроме условия 8.2.6 используется префикс "_", например: _iNewRec;
  • Используется Camel Casing (см 8.1.2);
8.2.8 Именование методов
  • Называйте методы глагольными формами единственного или множественного числа;
  • Используется Pascal Casing (см 8.1.1);
8.2.9 Именование свойств
  • Называйте свойства существительными единственного или множественного числа;
  • Используется Pascal Casing (см 8.1.1);
  • Именуйте свойства таким же имеменем как и закрытая переменная, которое использует свойство если она есть.
8.2.10 Именование событий
  • При именовании событий используйте суффикс EventHandler
  • Используйте два параметра именованные "sender" и "e"
  • Используется Pascal Casing (см 8.1.1);
  • Для именования классов аргументов событий используйте суффикс EventArgs
  • Согласуйте названия с глагольной формой

9 Советы по написанию кода

9.1 "Видимость"

Старайтесь применять максимум инкапсуляции для экземпляров объектов которые вы создаете. Не ставте public там где это не нужно. Используйте максимальный уровень защиты. Т.е. старайтесь открывать доступ от минимального (private) до максимального (public).

Используйте Свойства вместо прямого открытия public, для переменных класса.

9.2 "Магические числа"

Не используйте так называемых «магических чисел». Вместо этого объявляйте константы и статические переменные:

	public class MyMath
	{
		public const double PI = 3.14159...
	}

10 Примеры кода

10.1 Пример размещения фигурных скобок

	namespace ShowMeTheBracket 
	{
		public enum Test 
		{
			TestMe,
			TestYou
		}

		public class TestMeClass
		{
			Test test;

			public Test Test 
			{
				get 
				{
					return test;
				}
				set 
				{
					test = value;
				}
			}
			void DoSomething()
			{
				if(test == Test.TestMe) 
				{
					...
				} 
				else 
				{
					...
				}
			}
		}
	}

10.2 Пример именования переменных

вместо:

	for(int i = 1; i < num; ++i) 
	{
		meetsCriteria[i] = true;
	}

	for(int i = 2; i < num / 2; ++i) 
	{
		int j = i + i;
		while (j <= num) 
		{
			meetsCriteria[j] = false ;
			j += i;
		}
	}

	for(int i = 0; i < num; ++i) 
	{
		if(meetsCriteria[i]) 
		{
			Console.WriteLine(i + " meets criteria");
		}
	}

старайтесь использовать более «интеллектуальное» именование:

	for(int primeCandidate = 1; primeCandidate < num; ++primeCandidate) 
	{
		isPrime[primeCandidate] = true;
	}

	for (int factor = 2; factor < num / 2; ++factor) 
	{
		int factorableNumber = factor + factor;
		while (factorableNumber <= num) 
		{
			isPrime[factorableNumber] = false;
			factorableNumber += factor;
		}
	}

	for(int primeCandidate = 0; primeCandidate < num; ++primeCandidate) 
	{
		if(isPrime[primeCandidate]) 
		{
			Console.WriteLine(primeCandidate + " is prime.");
		}
	}

 

Copyright © 2002 Serg Vorontsov (voron@aspnetmania.com) Предоставляются права для копирования, распространения и модификации этого документа в рамках GNU Free Documentation License, Version 1.1 или более поздней версии опубликованной Free Software Foundation.



Вернуться к статьям в категории Немного оффтопа
Вернуться к списку категорий
Перейти к форуму Немного оффтопа
 
Apartments for Rent

Rambler's Top100
Рейтинг@Mail.ru
Идея: Dimon aka Manowar Программирование: Dimon aka Manowar Дизайн: Dan Lebedev
Хостинг от компании Parking.ru
Карта сайта