Правила программирования и автоматизации. Правила программирования Правила программирования

Все мы люди и нам свойственно ошибаться. И даже компьютеры ошибаются, если программа, за счет которой они работают, была написана с ошибкой. Чтобы помочь Вам избежать некоторых ошибок при написании программ на любом языке программирования я расскажу о некоторых правилах используемых при написании программ и о методах программирования. Соблюдение ниже описанных методов поможет не только избежать некоторых ошибок, но также предупредит их появление и упростит отладку Вашей программы. Все ниже приведенные примеры и код программ написаны на языке Visual Basic 6.0. Вы можете использовать материал данной статьи и для других языков программирования. Статья не привязывает Вас к какому-либо конкретному языку и является универсальной.

Метод проектирования программных средств

Для решения задач программирования используется "Метод проектирования программных средств". Этот метод состоит из нескольких этапов:

1. Определение условий задачи.
2. Анализ задачи.
3. Создание алгоритма решения задачи.
4. Реализация алгоритма.
5. Тестирование и отладка готовой программы.
6. Поддержка и обновление готовой программы.

На первом этапе определяются условия задачи и необходимо ясно понять, что требуется для её решения. Основная цель в данном случае - отсеять второстепенные аспекты от основной сути задачи.

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

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

Наверное, всем кто изучал программирование или информатику в учебных заведениях рассказывали, как нужно чертить блок-схемы. И наверняка большинство не любит их чертить. Ваш покорный слуга также относится к их числу. Но не стоит думать, что блок-схемы абсолютно бесполезны в программировании. Лично я никогда не черчу блок-схемы при разработке программ, но я умею хорошо это делать. И настоятельно советую Вам, научится чертить их лучше всех. Если Вы не научитесь самостоятельно и правильно чертить блок-схемы, Вы не сможете осознать суть того, как работает программа! Именно блок-схема позволяет наглядно и понятно (схематически) показать, как пошагово (построчно) выполняется программа. Ведь блок-схема это и есть алгоритм выполнения самой программы. А что такое алгоритм?

Алгоритм - это описание точного, пошагового выполнения действий решающих поставленную задачу должным образом. Поэтому если Вы сможете написать алгоритм выполнения программы, Вы сможете написать и саму программу, причем на любом языке программирования (который конечно будете знать). Научившись чертить блок-схемы, Вы научитесь построчно анализировать код программы, обрабатывая его в голове, так как это делает компьютер. Это очень важно при отладке программы (пятый этап).

Когда перед Вами стоит решение очень сложной задачи, можно (и нужно) применить метод "декомпозиции". Суть метода заключается в разбиении одной сложной задачи на множество взаимосвязанных, маленьких и простых подзадач, решив которые в отдельности Вы получите необходимый результат. Здесь можно привести аналогию с веником. Весь веник целиком сломать очень трудно, но если его ломать по одному прутику, то все получится.

Четвертый этап метода проектирования программных сред заключается в записи созданного алгоритма в виде программы на определенно языке программирования.

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

Также в процессе тестирования программы используется "эталонное решение". Это решение поставленной задачи другим методом (например, математически), которое позволяет получить заведомо верные результаты вычисления. Причем в эталонном решении используются не единичные данные, а множество различных данных позволяющих охватить все возможные ситуации вычисления. На основе такого "эталонного решения" можно выявить все возможные "подводные камни" и ошибки программы или ситуации, в которых программа не будет работать должным образом. Также необходимо реализовать в своей программе "защиту от дурака". Это когда учитываются такие ситуации, для которых программа в принципе не предназначена. Например, ввод цифр в поле или переменную, предназначенную для хранения фамилии.

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

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

Переменные

Имена переменных

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

For i = 1 to 10 Step 1
For j = 1 to 10 Step 1
dmsTable(i, j) = i * j
Next j
Next i

Если нам нужно сохранить в переменную чей-то год рождения. Назовите переменную "vblYearsBorn", а не "A". Старайтесь чтобы имя переменной отражало суть тех данных для хранения которых она предназначена, чтобы оно было интуитивно понятно. Пусть от этого имя переменной будет немного длинным, но зато это не даст вам запутаться и исключит повторное использования данной переменной в других вычислениях, для которых она не предназначена. Имя переменной желательно обязательно начинать с прописных букв vbl, от английского variable (переменная). Это особенно актуально в Объектно-Ориентированном Программировании (далее ООП). Так как имя переменной можно спутать с названием, какого либо объекта на форме (об этом пойдет речь ниже).

Давайте для понятности назовем эти три начальные буквы - "Идентификатором объекта", так как дальше я буду упоминать о них не однократно.

После идентификатора, без пробелов, следует писать имя переменной. Его нужно начинать с большой буквы, чтобы при просмотре листинга программы Вы видели, что это переменная, или какой-то другой объект, чтобы буквы выделялись, а не сливались в одну строку.

Объявление переменных

Некоторые языки программирования (например, Visual Basic) позволяют работать с переменными не объявляя их в коде программы. Я считаю это большой ошибкой и не солидностью языка программирования (но это не значит что этот язык программирования плох)!

Объявление переменной это определение ее типа и имени.

Dim vblFirstName as String (Visual Basic)
Var vblFirstName: String; (Turbo Pascal)
Char vblFirstName; (C++)

Т.е. мы как бы указываем программе, что будем использовать переменную с именем vblFirstName и тип данных этой переменной String (текстовый/литеральный).

Почему это важно (это касается только тех языков программирования, которые разрешают так делать. Например, если Вы не объявите переменную в С++ или Turbo Pascal-е, при компиляции будет сгенерирована ошибка, что используемая переменная не объявлена)? Все очень просто. Если мы не объявим переменную ей автоматически будет присвоен тип Variant, это значит что в переменную можно будет сохранять данные почти любого типа. Во-первых, мы сможем записать в переменную, которая хранит фамилию числовые данные или наоборот. ЭТО НЕПРАВИЛЬНО! Так как фамилия не может содержать цифры. Мы заведомо делаем в программе брешь, возможность для совершения ошибки. Вот такими ошибками и пользуются хакеры для взлома систем и прочее. Во-вторых, тип, присваиваемый автоматически, очень "много" занимает места в оперативной памяти. А хорошая программа должна как можно меньше весить. И не важно, сколько гигабайт оперативки у Вас на компьютере. В-третьих, явное объявление переменных позволит назначить им тот тип данных, который Вам необходим. И Вам будет намного легче узнать, какие переменные уже используются в программе. Достаточно будет посмотреть в начале программного кода или модуля, какие переменные уже заданы, а не перелопачивать весь код программы. Вы никогда не сможете повторно объявить уже объявленную переменную в одном и том же модуле, или перепутать их имена, а значить не используете переменную в тех вычислениях, для которых она не предназначена.

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

Инициализация переменных

После того как Вы объявили переменную её необходимо инициализировать, т.е. присвоить ей какое либо значение или обнулить. Это очень актуально для переменных используемых в вычислениях. Дело в том, при объявлении переменной для нее выделяется (резервируется) память. Резервирование памяти не отчищает ячейки от значений, которые ранее в них хранились, поэтому если за объявлением переменной не следует её инициализация, то текущее значение этой переменной будет непредсказуемым, а не нулевым, как думают многие. Не обязательно, что именно так и будет, но если это произойдет причину неправильных вычислений порой трудно выявить, так как код программы верен синтаксически и логически, но все равно вычисления идут неверные.

Если это переменная числового типа и используется в накоплении суммы, то достаточно её просто обнулить.

vblSum = 0
For I = 1 to 10 Step 1
vblSum = vblSum + i
Next i

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

vblSum = 1
For I = 1 to 10 Step 1
vblSum = vblSum * i
Next i

Если это строковая переменная просто отчистите ее.

vblFirstName = ""

Лично я всегда инициализирую переменные, даже если в следующей строке присвою ей другое значение.

Глобальные и локальные переменные

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

Локальные переменные - это переменные объявленные внутри какой-либо функции (подпрограммы). Они видимы только в пределах данной функции и не могут быть непосредственно вызваны из основного текста программы. Когда выполнение программы возвращается из функции к основному коду программы или другой функции, локальные переменные удаляются из памяти.

Глобальные переменные - это переменные, определенные вне тела какой-либо функции (для ООП, переменные объявленные в модулях проекта). Эти переменные имеют глобальную область видимости и доступны из любой процедуры, функции в подпрограмме.

Очень часто возникают ошибки при использовании глобальных переменных.

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

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

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

Константы

О константах буквально в двух словах. С их использованием в программе также необходимо быть внимательным (как и вообще занимаясь программированием). Имена констант лучше всего начинать с трех буков con, от английского constant (константа).

Const conPi = 3.14159265

Помните, что значения констант нельзя изменить в программе (ведь они константы, а значить постоянные), в противном случае будут сгенерированна ошибка. Лучше всего использовать константы, когда есть какое-либо значение, участвующее во многих вычислениях и его значение никогда не меняется в программе. Либо когда необходимо использовать коэффициент (а они, как правило, тоже постоянны).

Структурное программирование

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

Операторы начала и конца цикла пишутся строго друг под другом, а все операторы внутри цикла чуть правее. Все отступы делаются с помощью табуляции (клавиша Tab). Точно также пишутся логические схемы. Благодаря такому написанию ваша программа становится более читабельной и легкой для восприятия. Также облегчается отладка программы. Вы можете сами сравнить приведенный ниже пример, написания кода по принципу структурированного программирования и без него. Пример приведен на языке Turbo Pascal (часть кода сортировки массива).

Пример "Структурированный код":

For i:=1 to 9 do
begin
vblMin:=A[i];
k:=i;
For j:=1+i to 10 do
begin
If (vblMin>A[j]) Then
begin
vblMin:=A[j];
k:=j;
end;
end;
vblStuf:=A[i];
A[i]:=vblMin;
A[k]:=vblStuf;
end;

Пример "Обычный код":

For i:=1 to 9 do
begin
vblMin:=A[i];
k:=i;
For j:=1+i to 10 do
begin
If (vblMin>A[j]) Then
begin
vblMin:=A[j];
k:=j;
end;
end;
stuf:=A[i];
A[i]:=vblMin;
A[k]:=vblStuf;
end;

Какой вариант более читабелен и понятен? Несомненно, первый.

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

Ошибки

Программы очень редко работают правильно с первого раза. Закон Мерфи гласящий "Если что-то плохое может случиться, оно непременно случиться", похоже, был написан как раз применительно к компьютерным программам.

Ошибки, возникающие в процессе работы программы можно разделить на несколько типов:

1. Синтаксические ошибки
2. Ошибки времени выполнения
3. Логические ошибки

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

Ошибки времени выполнения выявляются компьютером во время выполнения программы. Подобные ошибки имеют место, когда программа дает компьютеру указание выполнить неверную операцию (например, деление на ноль или манипулировать неописанными или неверными данными).

Ошибки ввода данных - также являются ошибками времени выполнения. Причиной таких ошибок является попытка ввести данные неверного типа (например, переменной целочисленного типа присваивается строковый параметр или число вещественного типа).

Логические ошибки имеют место, когда программа выполняет неверный алгоритм. Данные ошибки являются самыми коварными, их очень сложно выявить, потому что они не фиксируются при компиляции. Данные ошибки проявляются при выводе неверных результатов программой. Единственно возможные способы выявления таких ошибок это использование методов: "эталонного решения" и "ручной отладки".

Умелое использование всех этих методов и правил: метод декомпозиции, структурное программирование, метод проектирования программных средств, эталонное решение и другие, говорят о профессионализме.

15 правил написания качественного кода

Есть мириады способов написать плохой код. К счастью, чтобы подняться до уровня качественного кода, достаточно следовать 15 правилам. Их соблюдение не сделает из вас мастера, но позволит убедительно имитировать его.

Правило 1. Следуйте стандартам оформления кода.

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

Например, в этом куске кода в соответствии со стандартом есть 12 ошибок:

For(i=0 ;i

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

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

Правило 2. Давайте наглядные имена.

Ограниченные медленными, неуклюжими телетайпами, программисты в древности использовали контракты для имён переменных и процедур, чтобы сэкономить время, стуки по клавишам, чернила и бумагу. Эта культура присутствует в некоторых сообществах ради сохранения обратной совместимости. Возьмите, например, ломающую язык функцию C wcscspn (wide character string complement span). Но такой подход неприменим в современном коде.

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

Гораздо важнее, чтобы вы долго и хорошо думали перед тем, как что-то назвать. Является ли имя точным? Имели ли вы в виду highestPrice или bestPrice? Достаточно ли специфично имя, дабы избежать его использования в других контекстах для схожих по смыслу объектов? Не лучше ли назвать метод getBestPrice заместо getBest? Подходит ли оно лучше других схожих имён? Если у вас есть метод ReadEventLog, вам не стоит называть другой NetErrorLogRead. Если вы называете функцию, описывает ли её название возвращаемое значение?

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

Правило 3. Комментируйте и документируйте.

Начинайте каждый метод и процедуру с описания в комментарии того, что данный метод или процедура делает, параметров, возвращаемого значения и возможных ошибок и исключений. Опишите в комментариях роль каждого файла и класса, содержимое каждого поля класса и основные шаги сложного кода. Пишите комментарии по мере разработки кода. Если вы полагаете, что напишете их потом, то обманываете самого себя.

Вдобавок, убедитесь, что для вашего приложения или библиотеки есть руководство, объясняющее, что ваш код делает, определяющий его зависимости и предоставляющий инструкции для сборки, тестирования, установки и использования. Документ должен быть коротким и удобным; просто README-файла часто достаточно.

Правило 4. Не повторяйтесь.

Никогда не копируйте и не вставляйте код. Вместо этого выделите общую часть в метод или класс (или макрос, если нужно), и используйте его с соответствующими параметрами. Избегайте использования похожих данных и кусков кода. Также используйте следующие техники:

  • Создание справочников API из комментариев, используя Javadoc и Doxygen.
  • Автоматическая генерация Unit-тестов на основе аннотаций или соглашений об именовании.
  • Генерация PDF и HTML из одного размеченного источника.
  • Получение структуры классов из базы данных (или наоборот).

Правило 5. Проверяйте на ошибки и реагируйте на них.

Методы могут возвращать признаки ошибки или генерировать исключения. Обрабатывайте их. Не полагайтесь на то, что диск никогда не заполнится, ваш конфигурационный файл всегда будет на месте, ваше приложение будет запущено со всеми нужными правами, запросы на выделение памяти всегда будут успешно исполнены, или что соединение никогда не оборвётся. Да, хорошую обработку ошибок тяжело написать, и она делает код длиннее и труднее для чтения. Но игнорирование ошибок просто заметает проблему под ковёр, где ничего не подозревающий пользователь однажды её обнаружит.

Правило 6. Разделяйте код на короткие, обособленные части.

Каждый метод, функция или блок кода должн умещаться в обычном экранном окне (25-50 строк). Если получилось длиннее, разделите на более короткие куски. Даже внутри метода разделяйте длинный код на блоки, суть которых вы можете описать в комментарии в начале каждого блока.

Более того, каждый класс, модуль, файл или процесс должен выполнять определённый род задач. Если часть кода выполняет совершенно разнородные задачи, то разделите его соответственно.

Правило 7. Используйте API фреймворков и сторонние библиотеки.

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

Правило 8. Не переусердствуйте с проектированием.

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

Правило 9. Будьте последовательны.

Делайте одинаковые вещи одинаковым образом. Если вы разрабатываете метод, функциональность которого похожа на функциональность уже существующего, то используйте похожее имя, похожий порядок параметров и схожую структура тела. То же самое относится и к классам. Создавайте похожие поля и методы, делайте им похожие интерфейсы, и сопоставляйте новые имена уже существующим в похожих классах.

Ваш код должен соответствовать соглашениям вашего фреймворка. Например, хорошей практикой является делать диапазоны полуоткрытыми: закрытыми (включающими) слева (в начале диапазона) и открытыми (исключающими) справа (в конце). Если для конкретного случая нет соглашений, то сделайте выбор и фанатично придерживайтесь его.

Правило 10. Избегайте проблем с безопасностью.

Современный код редко работает изолированно. У него есть неизбежный риск стать мишенью атак. Они необязательно должны приходить из интернета; атака может происходить через входные данные вашего приложения. В зависимости от вашего языка программирования и предметной области, вам возможно стоит побеспокоиться о переполнении буфера, кросс-сайтовых сценариях, SQL-инъекциях и прочих подобных проблемах. Изучите эти проблемы, и избегайте их в коде. Это не сложно.

Правило 11. Используйте эффективные структуры данных и алгоритмы.

Простой код часто легче сопровождать, чем такой же, но изменённый ради эффективности. К счастью, вы можете совмещать сопровождаемость и эффективность, используя структуры данных и алгоритмы, которые даёт ваш фреймворк. Используйте map, set, vector и алгоритмы, которые работают с ними. Благодаря этому ваш код станет чище, быстрее, более масштабируемым и более экономным с памятью. Например, если вы сохраните тысячу значений в отсортированном множестве, то операция пересечения найдёт общие элементы с другим множеством за такое же число операций, а не за миллион сравнений.

Правило 12. Используйте Unit-тесты.

Сложность современного ПО делает его установку дороже, а тестирование труднее. Продуктивным подходом будет сопровождение каждого куска кода тестами, которые проверяют корректность его работы. Этот подход упрощает отладку, т.к. он позволяет обнаружить ошибки раньше. Unit-тестирование необходимо, когда вы программируете на языках с динамической типизацией, как Python и JavaScript, потому что они отлавливают любые ошибки только на этапе исполнения, в то время как языки со статической типизацией наподобие Java, C# и C++ могут поймать часть из них во время компиляции. Unit-тестирование также позволяет рефакторить код уверенно. Вы можете использовать XUnit для упрощения написания тестов и автоматизации их запуска.

Правило 13. Сохраняйте код портируемым.

Если у вас нет особой причины, не используйте функциональность, доступную только на определённой платформе. Не полагайтесь на то, что определённые типы данных (как integer, указатели и временные метки) будут иметь конкретную длину (например, 32 бита), потому что этот параметр отличается на разных платформах. Храните сообщения программы отдельно от кода и на зашивайте параметры, соответствующие определённой культуре (например, разделители дробной и целой части или формат даты). Соглашения нужны для того, чтобы код мог запускаться в разных странах, так что сделайте локализацию настолько безболезненной, насколько это возможно.

Правило 14. Делайте свой код собираемым.

Простая команда должна собирать ваш код в форму, готовую к распространению. Команда должна позволять вам быстро выполнять сборку и запускать необходимые тесты. Для достижения этой цели используйте средства автоматической сборки наподобие Make , Apache Maven , или Ant . В идеале, вы должны установить интеграционную систему, которая будет проверять, собирать и тестировать ваш код при любом изменении.

Правило 15. Размещайте всё в системе контроля версий.

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

Заключение.

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

Лет 5-7 назад я сформулировал свод правил, которым руководствовался при работе над проектами (в основном автоматизация управления предприятиями), ну и плюс в этом же духе пытался учить подчинённых (в роли прожект менеджера). Сегодня вот наткнулся на эти правила, почитал, пустил слезу:) Со временем взгляды меняются и с некоторыми правилами я уже не совсем согласен, что лишний раз говорит о том, что составлять подобные списки — дело неблагодарное. А ещё, когда находишься внутри предметной области (напомню — автоматизация предприятий), сталкиваешься с ежедневными ошибками проектирования, то эти правила вполне разумны, понятны и применимы на реальных ситуациях. А с точки зрения непрограммиста или программиста из другой отрасли, некоторые из правил наверняка звучат пафосно, банально или бессмысленно. Так что не уверен, что все поймут, но всё же опубликую.

Первое правило программиста

Разделяй и властвуй.
(© предположительно Гай Юлий Цезарь)

Смысл: дели большую задачу на маленькие и решай их по очереди. Однако помни о задаче в целом: все маленькие решения должны в конечном итоге вести к решению большой задачи.

Второе правило программиста

Лучше день потерять, зато потом за пять минут долететь.
(© Орёл из м/ф «Крылья, ноги, хвосты»)

Признак хорошего программиста — автоматизация собственной деятельности.
(© ibigdan)

Никогда нет денег и времени, чтоб сделать всё как надо. Но на то, чтоб потом переделывать, и время и деньги находятся.
(© Закон Хеопса)

Смысл: недостаточно успешно закончить задачу, нужно выйти из неё с новым багажом. Создавай не только конечные решения, но и методы + инструменты — всё это пригодится в этом и в следующих проектах. Делай это, даже если поджимают сроки, потому что если ты не растёшь — ты отстаёшь. Заказчику и начальнику на это плевать, тебе нет.

Третье правило программиста

Read The Fucking Manual
(© отчаявшийся сисадмин)

Знание некоторых принципов легко компенсирует незнание некоторых фактов.
(© Гельвеций)

Воображение важнее знания. Знание ограничено. Воображение охватывает весь мир.
(© А.Эйнштейн)

Смысл: вы должны уметь взлетать высоко и нырять глубоко. Уметь увидеть задачу в целом и уметь разобрать её до мельчайших деталей. Без системного мышления и аналитического склада ума в программировании делать нечего.

Четвёртое правило программиста

Зри в корень.
(© Козьма Прутков)

Не так много сущностей, как взглядов на них. Сущность — основа решения, взгляд на неё — доработка под конкретную задачу.
(© ibigdan)

Смысл: например «директор» — это не человек, это должность, которую может занимать человек (а может никто не занимать). И «Иванов Пётр Сидорович» — не человек, а фамилия, имя и отчество, то есть атрибуты человека. Человек — это тело, живое или мёртвое, с кучей атрибутов:) Обычно до таких нюансов при проектировании не опускаются, поэтому большинство автоматизированных систем управления очень негибкие.

Пятое правило программиста

Правильно назвать — значит правильно понять.
(© неизвестный автор)

Ответь на вопрос «что это?» — получишь термин. Ответь на вопрос «зачем это?» — получишь смысл. Возможно на вопрос «как лучше это сделать?» отвечать уже не придётся.
(© ibigdan)

Суть программирования в том, что бы разобрать предметную область на мелкие куски (анализ) и воссоздать её в компьютере в виде работающей модели (синтез).
(© ibigdan)

Смысл: всё программирование сводится к чередованию анализа и синтеза. Причём анализ может быть математическим, функциональным, объектным — любым. И язык синтеза тоже значения не имеет. Важно только понимание и грамотное выполнение этих двух этапов.

Шестое правило программиста

Не плоди сущностей сверх необходимого.
(© В.Оккам)

Пусть это будет просто: просто, как только можно, но не проще.
(© А.Эйнштейн)

Совершенство достигнуто не тогда, когда нечего добавить, а когда нечего удалить.
(© неизвестный автор)

Дублирование и избыточность — признак неправильного понимания предметной области.
(© ibigdan)

Смысл: если сущность появляется в автоматизированной системе более одного раза, значит вы серьёзно накосячили при проектировании. Пример: «Иванов Пётр Сидорович, должность: врач, место работы: урологическое отделение». Потом у него случается инфаркт и опа! — объект номер два: «Иванов Пётр Сидорович, пациент, кардиологическое отделение». На самом деле это один и тот же человек, но в системе числится как два разных, не связанных между собой. Причём это типовая и элементарная ошибка проектирования, а есть куда более запутанные. Большинство АСУП состоят из таких ошибок более чем полностью.

Седьмое правило программиста

Сложные проблемы всегда имеют простые, лёгкие для понимания, неправильные решения.
(© айтишный фольклор)

Если маленький простой предмет увеличить в 100 раз, то он станет большим и сложным.
(© ibigdan)

Когда мы пытаемся вытащить что-нибудь одно, оказывается, что оно связано со всем остальным.
(© Закон Мура)

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

Восьмое правило программиста

Программный продукт, моделирующий некую предметную область, физически не может быть проще этой предметной области.
(© ibigdan)

Следствие: универсальный программный продукт на несколько порядков сложнее специализированного, поскольку охватывает группу взаимосвязанных областей.
(© ibigdan)

Следствие: программный продукт который может всё — бесконечно сложен, а значит невозможен в принципе.
(© ibigdan)

Смысл: увы, никто не выделит вам ресурсы на поиск ответа на «главный вопрос жизни, вселенной и ваще». Ищите компромиссы между желаемым и возможным.

Девятое правило программиста

При автоматизации организационного управления на основе использования ЭВМ следует помнить, что главным залогом ее успеха является коренное изменение традиционной технологии организационного управления.
(© В.М.Глушков)

Автоматизация не самоцель, а инструмент оптимизации деятельности предприятия. Если автоматизация не оптимизирует, то в ней нет никакой необходимости.
(© ibigdan)

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

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

Пожалуйста, поймите меня правильно, я вовсе не советую намеренно выискивать посредственных программистов. Разумеется, все хотят нанимать только самых талантливых и опытных программистов. В решениях о найме ставки высоки. Ваше решение повлияет на работу всей команды и ее отдельных участников. Как говорят:

«Отвергнуть хорошего кандидата гораздо лучше, чем принять плохого… Если у вас возникнут хотя бы малейшие сомнения - Не нанимайте»

Но стандартный совет все равно меня раздражает. Дело даже не столько в самом совете, сколько в том, что люди склонны понимать его неверно. Если применять его без дополнительных поправок, эта практика в основном формирует чувство собственного превосходства. Этот эффект особенно часто распространен среди программистов, поскольку элитарность так или иначе присуща нам. Когда мы слышим, что нанимать нужно только «самых лучших», этот совет проходит подсознательное преобразование:

«Самых лучших?» Но это же я! Я «самый лучший». Разумеется, я должен нанимать людей, таких же одаренных, таких умных и симпатичных, как я сам. Да и зачем засорять мою прекрасную команду всяким сбродом?

Кто они, самые лучшие программисты?

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

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

Начальник

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

Наверное, в крупной компании с таким подходом можно прожить. Я сильно подозреваю, что Лохматый Начальник в комиксах про Дилберта был срисован с натуры.

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

Кадры программистов

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

Ищите людей, склонных к самоанализу

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

Одним из важнейших критериев при оценке кандидатов я считаю то, что я про себя называю «первой производной». Учится ли этот человек? Движется ли он вперед или стоит на месте? (Некоторые мои размышления на эту тему опубликованы в статье «Career Calculus» в моем блоге).

Люди, серьезно настроившиеся на свой будущий успех, с большой вероятностью добиваются успеха. Часто этот настрой является самым сильным признаком для принятия решений при найме.

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

Как найти такого человека?

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

На собеседованиях кандидату часто предлагается описать свою основную слабость. Хотя этот вопрос до ужаса традиционен, он мне нравится.

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

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

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

Нанимайте разработчиков, а не программистов

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

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

Вместо «программистов» (людей, специализирующихся на написании кода) вам необходимы «разработчики» (люди, вносящие многосторонний вклад в успех продукта)».

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

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

Итак, стандартное правило работает вполне нормально, но от общих рекомендаций необходимо перейти к более конкретным. Чтобы подвести итог тому, о чем говорилось в предыдущих разделах, я предлагаю 10 вопросов, которые следует задать себе при рассмотрении кандидата на должность разработчика:

  1. Способен ли этот кандидат сделать для группы то, что не сможет никто другой?
  2. Находится ли он в процессе постоянного обучения?
  3. Знает ли этот кандидат о своих слабостях и может ли спокойно обсуждать их?
  4. Насколько этот кандидат универсален и способен сделать «все, что потребуется», чтобы обеспечить коммерческий успех продукта?
  5. Принадлежит ли кандидат к числу «десятикратных» программистов?
  6. Обладает ли он степенью бакалавра, полученной в одном из уважаемых университетов?
  7. Если кандидат обладает докторской степенью, имеются ли другие признаки, свидетельствующие о его способностях к разработке коммерческих продуктов?
  8. Имеется ли у кандидата опыт работы в группах, занимавшихся разработкой коммерческих продуктов?
  9. Может ли кандидат представить примеры хорошего кода?
  10. Любит ли кандидат программирование настолько, чтобы писать код в свободное время?

Положительный ответ на все 10 вопросов не обязателен. Я даже не собираюсь указывать максимальное количество положительных ответов, необходимых для принятия кандидата. Наем - это лотерея, и каждый вопрос может послужить признаком для оценки пригодности кандидата.

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

  1. Перед началом каких-либо операций проверьте существование всех нужных файлов, папок и переменных. Например, если файл не будет найден, то вы его сможете создать и избавиться от ошибок.
  2. Проверяйте все входные данные, которые передаются по форме. Например, если в переменной должна прийти дата - проверьте являются ли пришедшие данные датой. Даже если в форме предлагается выбор этих самых дат. Помните, форму всегда можно сохранить локально и поправить ее на свое усмотрение.
  3. Проверяйте входные данные, чтоб они были только в пределах диапазона, указанного вами. Например, если вы поставили ограничение на 1000 символов в сообщении, а вам написали 2000.
  4. Длина слов и другие, так как в простую форму можно вести очень много символов, из которых вам нужно будет всего лишь 3-4 десятка с начала, то на форму лучше всего тоже поставить ограничение.
  5. Длина слов и другое. Если ввести слов 20 без пробела, то на странице это будет выглядеть некрасиво, а вам это не надо, поэтому либо запрещайте ввод таких длинных слов, либо разделяйте длинные слова самостоятельно, либо укорачивайте слова и другое
  6. Вы знаете, что в поле имени (скрипты: гостевые книги, форумы…) пользователь может ввести что угодно, в том числе и ваше имя. Но так как в интернете не все честные, то некоторые, подписавшиеся вашим именем могут наговорить много всего нехорошего. Чтобы подобного не произошло, создайте список с запрещенными именами и проверяйте не совпадает ли имя пользователя с именем из этого списка.
  7. Никогда не показывайте в форме пароля его текущее значение. Помните о том, что в этом случае пароль может попасть остаться в компьютере в так называемом каталоге временных файлов Интернета. А если это общественный компьютер? Тогда следующий кто сядет за него может легко узнать пароль. Кроме того форму с паролями обязательно отправляйте по методу POST.
  8. В вашем скрипте обязательно должно быть предусмотрено модерирование. Согласитесь, гораздо проще и удобнее зайти на сайт, зайти в на страницу модерирования и нажать на пару кнопок и заполнить пару форм, чем заходить по FTP на сайт, открывать нужную страницу и ковыряться в HTML коде.
  9. Кавычки. Заменяйте в получаемых данных все кавычки на ESCAPE - последовательность. Например, кавычку ["] на [\"]. Данные в форму можно ввести так, что при отображении может много чего натворить с вашей страницей. Например, можно вставить скрипт на Java, изменить оформление. Кроме того если это у вас форум или гостевая, можно заменять два пробела на пробел, для того чтоб количество пробелов отображалось верное.
  10. Храните пароли в закодированном виде. Ведь если какой-нибудь пользователь и сумеет скопировать себе этот файл с паролями, то он пароль не сможет расшифровать. Если пользователь забыл пароль - меняйте его на абракадабру и отправляйте на Email. При этом обязательно выдавайте вначале ссылку для подтверждения, чтобы никто не узнал пароль.
  11. Всегда заменяйте метки и разделители, которые вы используете для сохранения информации или отображения, на что-то подобное. Иначе имеется какой-то шанс, что его пользователь введет в форму ваш разделитель и на странице появится целый список ошибок.
  12. Никогда не забываете ставить error_reporting (0) в начало страницы, благодаря этому параметру все ошибки, если они будут, не будут отображаться на странице и злоумышленник не сможет узнать слабое место в вашем скрипте.
  13. При подгрузке какого-нибудь файла сначала удостоверьтесь в его существовании, а если он и вправду существует, то подгружайте его с помощью функции require, а не include, потому что в 1 случае если будет ошибка то файл совсем не будет подгружаться, а во 2 он подгрузится с ошибками.
  14. Проверяйте откуда пользователь пришел. Потому что пользователь может сохранить форму ввода у себя на компьютере и подправить ее, но если он попытается отправить через нее данные, то ничего не получится, так как он его запрос придет не с той страницы, с которой нужно.