Способы написать действительно надежный код в 1Сv7.7

24.10.08

Разработка - Рефакторинг и качество кода

Первая редакция статьи, набросок на скорую руку. Приведенные здесь методы не претендуют на полноту и уникальность или единственность. Оставляйте свои комментарии, чтобы дополнить статью и дать возможность начинающим освоить приемы и методы разработки приложений. Понравившиеся комментарии будут включаться в статью, с указанием автора комментария, если Вы, конечно, не против.
«Это настоящее искусство: создавать здравый код, буквально на ходу изобретая соглашения, которые заставляют ошибки выделиться на экране.»

«Вы преднамеренно строите свой код так, что ваша чувствительность к нечистоплотности делает большей вероятность того, что ваш код будет работать правильно.»

«Способ написать действительно надежный код состоит в том, чтобы пытаться использовать простые инструменты, которые учитывают типичную человеческую ненадежность, а не сложные инструменты со скрытыми побочными эффектами и дырявыми абстракциями, которые требуют безошибочности программиста.»

Джоэл Спольски ( http://www.joelonsoftware.com/articles/Wrong.html )


Не строгий синтаксис в сочетании с динамической типизацией встроенного языка 1С 7.7 на самом деле означает лишь, что контроль за синтаксисом (в той мере, в которой он смягчен) и типами переменных ложится на плечи программиста, а не интерпретатора. И программисту не стоит пренебрегать этими вещами, ведь это может привести иногда к довольно интересным эффектам работы программы и долгому поиску ошибок, причем хорошо, когда эти ошибки были выявлены еще до внедрения…

И вот, чтобы начинающие осваивать 1С, прочувствовали на примерах, к чему может привести небрежное отношение к этим вещам, приведем несколько простых правил и способов этого избежать и также рассмотрим несколько упрощенных ситуаций, в которых это может произойти, если этим правилам не следовать.

Стоит использовать в именах переменных префиксы, указывающие на признак «глобальности» переменной и тип данных, который будет использоваться для хранения в этой переменной. На подобии венгерской аннотации.

Например:
// Локальная строковая переменная процедуры или функции
стрМояПеременная = "Моя строка"; 
// Локальная переменная процедуры или функции для хранения дат
датЕщеПеременная = '08.08.08'; 
// Локальная переменная процедуры или функции для чисел
чслПростоПеременная = 5; 
// Глобальная переменная глобального модуля для справочника сотрудников
гл_спрСотрудники = СоздатьОбъект("Справочник.Сотрудники");
// Переменная не глобального модуля для справочника сотрудников
г_спрСотрудники = СоздатьОбъект("Справочник.Сотрудники");

Тут стоит обратить внимание на то, что, если имена глобальных переменных в глобальном и не глобальном модуле будут совпадать, то в не глобальном модуле будет использоваться именно не глобальная переменная, тоже про имена функций и процедур. А вот с локальными переменными функций и процедур несколько наоборот, если имя локальной переменной будет совпадать с глобальной, то локальная переменная будет использоваться только в том случае, если она явно объявлена оператором Перем, в остальных случаях будет использоваться глобальная переменная. Но привычка явно объявлять все локальные переменные процедуры или функции, например:
Перем МояПеременная; 

На самом деле не так хороша, как кажется на самом деле. Так как она несет в себе некоторые минусы в применении к 1С.

Например, если Вы явно объявите переменные и забудете их определить присвоением начальных значений, задав тем самым их тип, и начнете использовать их в выражениях или передаче параметров в функции и процедуры, то интерпретатор не сообщит Вам об этой ошибке и результат выполнения такого кода будет не совсем ожидаем Вами:
Процедура Выполнить()
      Перем чслПер, чслРез;
      чслРез = чслПер + 3;
      Сообщить("" + чслРез);
КонецПроцедуры


Это относится и к передаче переменных в параметры функций:
Функция ПриемПараметров1(чслПар1, чслПар2, чслПар3)
      Возврат чслПар1 + чслПар2 + чслПар3;
КонецФункции

Процедура Выполнить()
      Перем чслПер1;
	  
      //
      // Текст процедуры
      //
	  
      Сообщить(""+ПриемПараметров1(чслПер1, 2, 3));
КонецПроцедуры

А вот если не иметь привычки явно объявлять, а только определять присвоением, то в таком случае, при интерпретации Вам интерпретатор выдаст ошибку: «Переменная не определена (ИмяПеременной)», что позволит отловить такие вещи еще на этапе компиляции. Например:
 
 Процедура Выполнить()
      чслРез=0; чслПер1=0;
      чслРез = чслПер1 + чслПер2 + 3;
      Сообщить("" + чслРез);
КонецПроцедуры

Или:
Функция ПриемПараметров1(чслПар1, чслПар2, чслПар3)
      Возврат чслПар1 + чслПар2 + чслПар3;
КонецФункции

Процедура Выполнить()
	  чслПер1=0;
	  
	  //
	  // Текст процедуры
	  //
	  
	  Сообщить(""+ПриемПараметров1(чслПер1, чслПер2, 3));
КонецПроцедуры


Поэтому, я бы рекомендовал явно объявлять только глобальные переменные модулей, а локальные переменные процедур и функций, определять не явно в начале процедуры или функции начальными значениями:
Процедура Выполнить()
      // Объявления локальных переменных процедуры или функции
      стрМояПеременная = ""; // Строковая переменная
      датЕщеПеременная = '00.00.00'; // Переменная для хранения дат
      чслПростоПеременная = 0; // Переменная для чисел
      // Переменная для справочника сотрудников
      спрСотрудники = СоздатьОбъект("Справочник.Сотрудники"); 
      
      //
      // Операторы процедуры или функции
      //
КонецПроцедуры

Единственно, когда в таком случае, интерпретатор не выдаст Вам ошибку, если Вы без определения переменной присвоением начального значения запишете:
чслПер= чслПер+1; // Переменная не увеличится на 1, она останется пустой

Но, если в начале функции Вы будете иметь привычку присваивать начальные значения переменным, то Вы напишете:
чслПер=0;
//
// Операторы процедуры или функции
//
чслПер= чслПер+1; 

И получите ожидаемый результат, не тратя усилия на воспоминания о том, имеет эта переменная числовой тип и присваивали ли Вы ей начальное значение.

И как бы нудным Вам не казалась необходимость определять в начале функции все локальные переменные, которые могут Вам понадобиться в ней с самого начала, это дисциплинирует мышление, т.к. если Вы в состоянии учесть все переменные, которые Вам понадобятся для написания процедуры или функции, значит, велика вероятность того, что Вы успешно ее напишете, т.к. это один из признаков того, что Вы четко и ясно представляете задачу и алгоритм ее решения. А в крайнем случае, если понадобилась еще одна, то не сложно подняться в начало функции и дописать строчку с присвоением ей начального значения.

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

Так как при вызове процедур, по мимо динамической типизации переменных, еще и позволительно опускать не только параметры, которым заданы значения по умолчанию при определении функции, но и параметры без значений по умолчанию. Например, Вы вполне можете вызвать функцию таким образом и интерпретатор примет Ваш вызов ни слова не сказав:
Функция ПриемПараметров1(чслПар1, чслПар2, чслПар3)
      Возврат чслПар1 + чслПар2 + чслПар3;
КонецФункции

Процедура Выполнить()
      Сообщить(""+ПриемПараметров1( , 3, ));
КонецПроцедуры

Также существует нюанс при передаче параметров описанный в статье:

Занимательная передача параметров
//infostart.ru/profile/20743/blogs/628/

Поэтому, принимая параметры процедур и функций, стоит проверять их типы и приводить к нужным типам принудительно. Например:
Функция ПриемПараметров1(чслПар1, чслПар2, чслПар3)
      чслПар1=Число(чслПар1);
      чслПар2=Число(чслПар2);
      чслПар3=Число(чслПар3);
      Возврат чслПар1+чслПар2+чслПар3;
КонецФункции

А для агрегатных типов:
Функция ПриемПараметров1(чслПар1, спрПар2)
      чслРез=1; // Результат: =1 – удачно, =0 – не удачно
      чслПар1=Число(чслПар1);
      Если ТипЗначения(спрПар2)<>11 Тогда // 11 – тип Справочник
             // Возможно еще вывод сообщения или другие действия
             чслРез=0;
             Возврат чслРез;
      Иначе
             Если спрПар2.Вид()<>"Сотрудники" Тогда
                    // Возможно еще вывод сообщения или другие действия
                    чслРез=0;
                    Возврат чслРез;
             КонецЕсли;  
      КонецЕсли;
	
      //
      // Операторы процедуры или функции
      //
	
      Возврат чслРез;
КонецФункции

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


Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. venger 2124 10.10.08 02:53 Сейчас в теме
Это по мотивам прочтения 2-5 глав описания языка:-)
2. artbear 1565 10.10.08 07:25 Сейчас в теме
Еще нужно не забыть создавать простой код, разделяя его на небольшие и процедуры/функции, у которых из названия понятно их назначение. Также очень желательно переменным давать внятные и понятные наименования.
.
Код, занимающий кучу экранов, как правило, очень сложен для понимания, прочтения и исправления. Но 1С это очень любит в своих типовых :(
motogon; lustin; JohnyDeath; Vitek; noprogrammer; +5 Ответить
5. vasilykushnir 63 10.10.08 09:06 Сейчас в теме
(2) А еще:
- писать толковые комментарии
- обязательно писать в среде 1С (кода делфи 1с не понимает)
- и наконец - писать программы так, чтобы они работали.

Но шутки в сторону:
1. "А вот если не иметь привычки явно объявлять, а только определять присвоением, то в таком случае, при интерпретации Вам интерпретатор выдаст ошибку: «Переменная не определена (ИмяПеременной)», что позволит отловить такие вещи еще на этапе компиляции."
- очень и очень спорная технология. Ловить свои же сознательно встроенные в код ошибки? Я дико извиняюсь...
2. "Стоит использовать в именах переменных префиксы, указывающие на признак «глобальности» переменной и тип данных"
Этим пользуюсь. Даже больше: функциям и процедурам имена даю по такому же принципу:
ПриОткрытии () - локальная
глОбработкаВизуальности () - в глобальном модуле
дгм1ПарсерСЗ () - в дополнительном глобальном модуле №1
и т.д.
9. Abadonna 3969 10.10.08 12:46 Сейчас в теме
(5) Вась, твоя привычка объявлять по делу и не по делу ВСЕ функции и процедуры форвардом - ваще зубная боль :( И не лень тебе ;)
10. Abadonna 3969 10.10.08 12:49 Сейчас в теме
+(9) Не фиг вообще в 1С объявлять переменные, кроме тех случаев, когда они являются принимающими, например
ТекущееВремя(Час, МИнут, Сек) - тут уж никуда не денешься
3. Vitek 10.10.08 08:18 Сейчас в теме
4. Vitek 10.10.08 08:19 Сейчас в теме
А так, плюс, идея хорошая.
6. vinsentfire 10.10.08 11:38 Сейчас в теме
Мне как начинающему осваивать 1С - это действительно очень важные вещи. Это как при начале строительства - как заложен фундамент, так дальше и будет идти строительство. Тут тоже самое. Одним словом - спасибо. Тем более, что и много специалистов делятся своим опытом, тоже можно многое чего узнать и избежать в дальнейшем ошибок.
7. coder1cv8 3477 10.10.08 12:17 Сейчас в теме
Никогда не объявляю переменные в начале процедуры/функции... ) Только по мере необходимости.
motogon; artbear; +2 Ответить
8. artbear 1565 10.10.08 12:42 Сейчас в теме
(7) Ага, нужно как в С++ - объявлять/инициализировать по мере необходимости.
Это намного более надежно.
11. venger 2124 10.10.08 12:54 Сейчас в теме
А вот по поводу глобальных процедур и функций в глобальном модуле, я все-таки стараюсь объявлять их все в начале модуля со словом Далее, это как документация по библиотеке функций, не надо долго выискивать в тексте глоб. модуля, какие функции там есть, чтоб понять, что можно применить и с какими параметрами и что делают. Все перед глазами в начале модуля, надо уточнить, имя из объявления скопировал, поиск запустил и спустился к определению, посмотрел, если нужно как она организована.
12. venger 2124 10.10.08 12:55 Сейчас в теме
+(11) Ну и не паришся с порядком вызова. Это про глобальный модуль в основном я говорю.
13. venger 2124 10.10.08 12:59 Сейчас в теме
Кстати, по поводу префиксов в именах функций и процедур, можно еще в префиксах задавать принадлежность к "классу", т.е., например, все функции и процедуры для работы с Excel через Ole в глоб. модуле, могут начинаться с префикса гл_xlsole, префикс в данном случае просто пример, можно получше придумать.
14. venger 2124 10.10.08 13:00 Сейчас в теме
+(13) Главное в этом деле однообразие и последовательность в применении.
15. Abadonna 3969 10.10.08 13:14 Сейчас в теме
Вот пример на мой взгляд совершенно ничем не оправданного объявления переменных внутри процедуры, ктр. строит конструктор запросов в 7-ке:
Перем Запрос, ТекстЗапроса, Таб;
Ну и толку от этого объявления?
16. CheBurator 2684 10.10.08 13:30 Сейчас в теме
(15) толк имхо есть - по "заголовку" процедуры и объявлениям переменных я уже пойму про что речь...
..
было бы хорошо, если бы автор систематизировал вопросы именования переменных...
у мну например последнее время в этом смысле разброд какой-то...
20. Abadonna 3969 10.10.08 13:38 Сейчас в теме
(16) Смотри код от Камина. Там четко описаны переменные с префиксами типа л_МряПеременная и что префиксы означают.
22. venger 2124 10.10.08 13:40 Сейчас в теме
(20) А что за код от Камина?
46. Abadonna 3969 27.10.08 09:17 Сейчас в теме
(22)>А что за код от Камина?
Во! Нашел у себя систему обозначения переменных от Камина
// Система префиксов для именования объектов от фирмы КАМИН
// Гл_ - глобальная переменная, процедура или функция. Описана
// в глобальном модуле с ключевым словом ЭКСПОРТ.
// м_ - переменная, описанная явно или неявно в текущем программном модуле.
// л_ - переменная, описанная явно или неявно в текущей процедуре или функции.
// п_ - параметр текущей процедуры или функции.
// рд_ - реквизит диалога. Описан в форме диалога.
21. venger 2124 10.10.08 13:39 Сейчас в теме
(16) Так можно писать в начале процедуры или функции, например:
зпрПоСкладу=СоздатьОбъект("Запрос"); стрЗапроса=""; табВывод=СоздатьОбъект("Таблица");

И все видно...
17. venger 2124 10.10.08 13:33 Сейчас в теме
(15) На то он и конструктор. Кстати, а прикиньте лет так через 100, создадут исскуственный интеллект, который ведь сможет программировать. И будем мы наблюдать процесс программирования, как сейчас на подобии, когда два компа между собой в шахматы играют:-)
18. venger 2124 10.10.08 13:35 Сейчас в теме
+(17) Хотя это уже будет саморазвитие и самосовершенствование компа, так он и до медитации может дойти:-)
19. venger 2124 10.10.08 13:36 Сейчас в теме
+(17) Хотя до медитации, по-моему, уже дошел, вспомните Win98, зависания всякие и т.п.:-)
27. artbear 1565 10.10.08 14:25 Сейчас в теме
(15)Цитата:
>>Вот пример на мой взгляд совершенно ничем не оправданного объявления переменных внутри процедуры, ктр. строит конструктор запросов в 7-ке:
>>Перем Запрос, ТекстЗапроса, Таб;
>>Ну и толку от этого объявления?
Для конструктора толк есть.
В этом случае тот текст, который он вставляет, 100% независим от остальных переменных модуля и ГМ, и не влияет на переменные модуля и ГМ.
Например, в модуле может быть переменная модуля ТекстЗапроса и т.д.
28. Abadonna 3969 10.10.08 14:26 Сейчас в теме
(27) С точки зрения Конструктора - согласен:))) Тем более я сам по образованию инженер-конструктор;)
23. Vitek 10.10.08 13:48 Сейчас в теме
Ссылку из 3 никто я так понимаю и не посмотрел :(
25. venger 2124 10.10.08 14:01 Сейчас в теме
(23) Я просто отложил на вечер почитать, но почитаю непременно. Спасибо.
24. Abadonna 3969 10.10.08 13:48 Сейчас в теме
А это самая что ни на есть суперская прога по расчету зарплаты на базе 7.7 рядом с которой ЗиК и делать не фиг
26. venger 2124 10.10.08 14:02 Сейчас в теме
(24) Это про Камина? А эту прогу можно посмотреть?
29. WiseSnake 1521 11.10.08 18:56 Сейчас в теме
(24) Абсолютно не согласен с Вами. Многие отказываются от Камина, слишком геморно там Все сделано. Хотя ЗиК тоже сложна для понимания пользователями, но работает и успешно... в отличии от камина... Ну и обслуживание....
30. CheBurator 2684 11.10.08 19:22 Сейчас в теме
Как пример, ваял отчет сегодня для древней конфы, в отчете юзаю множественный фильтр (из штатного ТиСа) - временно пришлось В МОДУЛЬ отчета передрать из ТиСа процедуры и функции и ГМ ТиСа - не работаю!!! Потому как на форме лежит ТаблицаМФ, а в процедуре, которая раньше была в ГМ выглядит вот так:
Процедура ЧтоТоДляМФ(Конт)
ТаблицаМФ = Конт.таблицаМФ;
в итоге имеем ошибку...
..а вот так
Процедура ЧтоТоДляМФ(Конт)
Перем ТаблицаМФ;
ТаблицаМФ = Конт.ТаблицаМФ;
- не ругается!!
31. alexqc 150 15.10.08 17:37 Сейчас в теме
Я категорически :) не согласен с тем что НЕ следует объявлять переменные в ф-циях. Наоборот, все локальные переменные НУЖНО объявлять! Сам бы так делал, да вот лень, лень (вот если б была допустима конструкция вида "Перем а=1+2;" в любом месте)... Поскольку в таком случае локальные переменные не пересекаются с переменными вышестоящего уровня (текущего модуля, текущего контекста и ГМ). В этом смысле мне кстати больше подход в PHP нравится: все переменные - локальные, а хочешь до глобальной достучаться - объявляй ее global явно.

Кстати, говорите интерпретатор ругнется? Попробуйте это
Код
 
Процедура ГдеТутРугань()
А=А+1;
КонецПроцедуры;
Показать полностью


По поводу префиксов - вешь конечно нужная, но злоупотреблять ими также не следует. Достаточно когда префикс отражает НАЗНАЧЕНИЕ переменной, а не тип.
Для себя я выработал примерно такую систему: то что в ГМ - всегда "гл". Флаги имеют префикс "ф", списки - "спис", таблицы значений - "тз". Строковые представления каких-либо значений - "стр", и т.п. Переменные в "локальной части" алгоритма (например, промежуточные результаты, вобщем то что будет использовано пределах ближайших нескольких строчек) - префикс "т". НО: все эти префиксы (коме префиксов "места" - "гл", "т") - диктуются не типом переменной, а необходимостью алгоритма. То есть, грубо говоря, если у меня есть строка, показывающая адрес, и строка, показывающая представление клиента - то в первом случае переменная скорее всего так и будет "Адрес", а во втором - "стрКлиент". И ИМХО, уж совсем изврат - префиксы перед числами. Вот только посмотрите: чслСумма=чслЦена*чслКоличество. Неужели красиво?
При этом, как ни странно, иногда и
33. venger 2124 15.10.08 21:48 Сейчас в теме
(31) > ...если б была допустима конструкция вида "Перем а=1+2;" в любом месте

Ну, если б...

> Поскольку в таком случае локальные переменные не пересекаются с переменными вышестоящего уровня (текущего модуля, текущего контекста и ГМ)

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

> Кстати, говорите интерпретатор ругнется? Попробуйте это
> Процедура ГдеТутРугань()
> А=А+1;
> КонецПроцедуры;

Прямо в блоге и говорю, что:
----------------------------------------------
Единственно, когда в таком случае, интерпретатор не выдаст Вам ошибку, если Вы без определения переменной присвоением начального значения запишете:
Код
чслПер= чслПер+1; // Переменная не увеличится на 1, она останется пустой
Показать полностью

Но, если в начале функции Вы будете иметь привычку присваивать начальные значения переменным, то Вы напишете:
Код
чслПер=0;
//
// Операторы процедуры или функции
//
чслПер= чслПер+1;
Показать полностью

И получите ожидаемый результат, не тратя усилия на воспоминания о том, имеет эта переменная числовой тип и присваивали ли Вы ей начальное значение.
----------------------------------------------

И что?

> По поводу префиксов - вешь конечно нужная, но злоупотреблять ими также не следует. Достаточно когда префикс отражает НАЗНАЧЕНИЕ переменной, а не тип.

Назначение можно передать и именем, но в принципе в 1С большинство перфиксов будут отражать тип (в общем случае я считаю, что "ф" - это тот же тип в каком-то смысле). Да и проще тогда ориентироваться, что это, особенно в чужом коде.
32. alexqc 150 15.10.08 17:48 Сейчас в теме
** что-то сбилось, продолжу
иногда создается впечатление, что мои префиксы определяются типом (списКлиенты, стрКлиент, зпрКлиент). Но это не так - они определяются именно значением для алгоритма (а тип просто является "следствием" этого значения).
34. maljaev 789 15.10.08 22:43 Сейчас в теме
Мне не понравилось предложение прописывать в начале каждой переменной ее тип. Это сильно затруднит работу с телепатом, так как при наборе имени переменной он ищет ее по начальным символам. Соответственно вместо того чтобы вывалить список наиболее вероятных переменных через 2-3 введенных символа, я буду вынужден каждый раз вводить уже 5-6 символов, и хорошо еще если я помню тип переменной. Лучше уж тип переменной дописывать в конце, тогда при тех же достоинствах не будет описанных неудобств.
35. CheBurator 2684 16.10.08 00:42 Сейчас в теме
(34) я тоже так думал.. фиг там.. телепат ищет по последовательности в любом месте!
37. maljaev 789 16.10.08 08:42 Сейчас в теме
(35) Я не знаю, какой там у тебя телепат стоит, лично у меня версии "t" и ни хрена подобного не происходит. Проверьте: в конфигураторе создаете пустую обработку, в модуле "сформировать" пишете:

датНачалоПериода="";
датКонецПериода="";
Если на...

И что вам телепат вывалит? Лично у меня в списке телепата отсутствует "датНачалоПериода", когда начинаешь набирать с "да" - присутствует.
36. Shagan 16.10.08 07:10 Сейчас в теме
38. Cifer 157 16.10.08 14:50 Сейчас в теме
Да, это все конечно интересно, особенно когда пишешь "с нуля". Но как же быть с внедрением типовых конфигураций? Большая часть кода значит будет написана по одним правилам, а новые участки кода по другим?
Впрочем с конфигурациями написанными "с нуля" тоже ведь придется разбираться людям, которые привыкли к общепринятым правилам написания кода 1С. Считаю, что к 1С такой подход неприменим, и нужно придерживаться одного стиля.
39. venger 2124 16.10.08 15:45 Сейчас в теме
(38) А про общепринятые правила написания кода 1С можно поподробней?
40. Душелов 4021 16.10.08 15:46 Сейчас в теме
(39) по-моему на ИТС-е было где-то...
41. Cifer 157 17.10.08 12:05 Сейчас в теме
ИТС -> 1С:Предприятие. Работаем с программами -> 1С. Система стандартов и методик разработки конфигураций для платформы 1С:Предприятие 8
42. nickVZ 10 20.10.08 16:26 Сейчас в теме
датНачалоПериода...
чслСумма....
стрАдресПрописки....

Не назвать ли нам кошку "Кошкой"?@стиш детский
43. maljaev 789 20.10.08 17:03 Сейчас в теме
(42) Ну да, иногда получается масло масляное... Но если уж вводить такую систему именования, то исключений быть не должно.
44. venger 2124 20.10.08 17:04 Сейчас в теме
(42) В меру, в меру и там, где есть смысл:-)
45. venger 2124 20.10.08 17:06 Сейчас в теме
(42) Просто в условиях когда среда не может сказать мне тип переменной во время программирования, особенно с чужим кодом это не удобно, когда работаешь, а и еще за меня проверять на соответствия типам переменные, то вполне даже стоит...
47. ADirks 187 27.10.08 14:13 Сейчас в теме
И опять Джоэл Спольски: статья "Making Wrong Code Look Wrong"
http://www.joelonsoftware.com/articles/Wrong.html
По английски, но очень поучительно
48. venger 2124 30.10.08 23:40 Сейчас в теме
Есть переводы многих его блогов и на русском:

http://local.joelonsoftware.com/mediawiki/index.php/Russian

Это Вам не fixin:-))))
50. CheBurator 2684 30.10.08 23:56 Сейчас в теме
49. CheBurator 2684 30.10.08 23:50 Сейчас в теме
рд_ - мало!
я типа так
рНастройка - рамка
рб - радиобатон
фл - флажок
т - текст
кн - кнопка
.. и т.д.
Оставьте свое сообщение