Классификация знаний в области программирования. Что такое уровень языка программирования

Язык программирования - язык (знаковая система), предназначенный для записи компьютерных программ. Язык программирования определяет набор лексических, синтаксических и семантических правил, определяющих внешний вид программы и действия, которые выполнит исполнитель (обычно - ЭВМ) под её управлением. Язык программирования предназначен для написания компьютерных программ, которые представляют собой набор правил, позволяющих компьютеру выполнить тот или иной вычислительный процесс, организовать управление различными объектами, и т. п. Язык программирования отличается от естественных языков тем, что предназначен для взаимодействия человека с ЭВМ, в то время как естественные языки используются для общения людей между собой.

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

Если язык близок к естественному языку программирования, то он называется языком высокого уровня, если ближе к машинным командам, – языком низкого уровня.

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

К языкам программирования высокого уровня относят Фортран (переводчик формул), Алгол , Кобол (коммерческий язык – используется, в первую очередь, для программирования экономических задач), Паскаль , Бейсик , Си , Пролог и т.д.

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

Языки программирования также можно разделять на поколения:

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

языки второго поколения : с мнемоническим представлением команд, так называемые автокоды.

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

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

языки программирования пятого поколения : языки декларативные, объектно–ориентированные и визуальные. Например, Пролог, ЛИСП (используется для построения программ с использованием методов искусственного интеллекта), Си++, Visual Basic, Delphi.

7. Прикладное программное обеспечение. Ппп ms Office.

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

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

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

Различают следующие типы ППП:

· общего назначения (универсальные);

· метод-ориентированные;

· проблемно-ориентированные;

· глобальных сетей;

· организации (администрирования) вычислительного процесса

ППП общего назначения – универсальные программные продукты, предназначенные для автоматизации разработки и эксплуатации функциональных задач пользователя и информационных систем в целом.

Метод-ориентированные ППП отличаются тем, что в их алгоритмической основе реализован какой-либо экономико-математический метод решения задачи.

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

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

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

ППП финансового менеджмента (ППП ФМ ) появились в связи с необходимостью финансового планирования и анализа деятельности фирм.

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

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

Для обеспечения организации администрирования вычислительного процесса в локальных и глобальных сетях ЭВМ в более чем 50% систем мира используется ППП фирмы Bay Networks (США), управляющий администрированием данных, коммутаторами, концентраторами, маршрутизаторами, трафиком сообщений.

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

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

По этому критерию можно выделить следующие уровни языков программирования:

    машинные;

    машинно-оpиентиpованные (ассемблеры);

    машинно-независимые (языки высокого уровня).

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

Языки высокого уровня делятся на:

    процедурные (алгоритмические) (Basic, Pascal, C и др.), которые предназначены для однозначного описания алгоритмов; для решения задачи процедурные языки требуют в той или иной форме явно записать процедуру ее решения;

    логические (Prolog, Lisp и др.), которые ориентированы не на разработку алгоритма решения задачи, а на систематическое и формализованное описание задачи с тем, чтобы решение следовало из составленного описания;

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

Высокоуровневый язык программирования

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

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

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

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

Примеры: C++, C#, Java, JavaScript, Python, PHP, Ruby, Perl, Паскаль, Delphi, Лисп. Языкам высокого уровня свойственно умение работать с комплексными структурами данных. В большинстве из них интегрирована поддержка строковых типов, объектов, операций файлового ввода-вывода и т. п.

Первым языком программирования высокого уровня считается компьютерный язык Plankalkül, разработанный немецким инженером Конрадом Цузе ещё в период 1942-1946 годах. Однако транслятора для него не существовало до 2000 года. Первым в мире транслятором языка высокого уровня является ПП (Программирующая Программа), он же ПП-1, успешно испытанный в 1954 году. Транслятор ПП-2 (1955 год, 4-й в мире транслятор) уже был оптимизирующим и содержал собственный загрузчик и отладчик, библиотеку стандартных процедур, а транслятор ПП для ЭВМ Стрела-4 уже содержал и компоновщик (linker) из модулей. Однако, широкое применение высокоуровневых языков началось с возникновением Фортрана и созданием компилятора для этого языка (1957)

Какие бывают языки программирования? Что за концепции в них заложены? Как они развивались? В данной статье рассмотрим виды языков программирования основываясь на так называемых уровнях - от машинных кодов (низкий уровень, приближённый к компьютерному "железу") до таких языков, как Java или С# (высокий уровень). Чем меньше преобразований пройдёт текстовый листинг программы по пути превращения в набор нулей и единичек – тем ниже уровень. Далее мы рассмотрим:
  1. Языки низкого уровня (машинные коды и ассемблер)
  2. Средний уровень (C, Фортран ….)
  3. Высокий уровень (C++, Java, Python, Ruby, JavaScript ...)
Уровень также характеризует насколько подробно нужно детализировать листинг будущей программы для воплощения реализации. Насколько этот процесс прост для человека. Не стоит считать уровень языка однозначным показателем его возможностей. Язык программирования – это инструмент, который эффективен в одной области и менее полезен в других. И столяр, и плотник работают с деревом. У первого основной инструмент – набор стамесок, у второго – топор. Однако резной шкаф изящнее сделает столяр, а дом быстрее поставит плотник. Хотя каждый и способен выполнить работу другого, но сделает это гораздо менее эффективно. Различные данные в компьютере представлены в виде наборов нулей и единиц. Управляющие команды для её обработки – те же данные, содержащие внутри себя инструкции, которые определяют местоположение необходимой информации и способ модификации.

Машинные языки (Самый низкий уровень)

Нам придётся совершить краткий визит из Software области в Hardware. Рассмотрим в упрощенном виде. Процессор – основной «мозг» компьютера. Материнская плата, на которой он установлен, содержит контроллеры, служащие для взаимодействия с прочими устройствами через шины (каналы данных для связи).

Некоторые работают с большой скоростью (красные стрелки): процессор черпает из памяти команды и манипулирует данными, видеокарта – особенно в 3D играх, потребляет огромные объёмы текстур, фигур, координат пикселей и прочих объектов для построения изображения на экране монитора. Другим (в силу ограничения скорости обмена информацией) столь высокие показатели и не нужны. Разнообразные внутренние и внешние устройства подключены на схеме зелёными стрелками.

Внутренний мир процессора

Все команды процессора поступают из памяти на выполнение в двоичном виде. Формат, количество, подмножество инструкций зависят от его архитектуры. Большинство из них несовместимо друг с другом и следуют разным идеологиям. А также вид команды сильно зависит от режима (8/16/32… разрядность) и источника данных (память, регистр, стек…), с которыми работает процессор. Одно и то же действие может быть представлено различными инструкциями. Процессор имеет команды сложения двух операндов (ADD X,Y) и прибавления единицы к указанному (INC X). Добавление тройки к операнду можно выполнить как ADD X,3 или троекратно вызвав INC X. И, в отношении разных процессоров, нельзя предсказать какой из этих способов будет оптимальным по скорости или объёму занимаемой памяти. Для удобства двоичную информацию записывают в 16-ричном виде. Рассмотрим часть привычной программы (язык C, синтаксис которого сходный с Java) int func () { int i = getData ("7" ) ; return ++ i; . . . } Код, реализующий те же действия в виде последовательности инструкций для процессора: ... 48 83 ec 08 bf bc 05 20 00 31 c0 e8 e8 fe ff ff 48 83 c4 08 83 c0 01 ... Вот так, собственно и выглядит низкоуровневый язык программирования для процессора intel. Фрагмент, вызывающий метод с аргументом и возвращающий увеличенный на единицу результат. Это и есть машинный язык (код), который передается непосредственно сразу, без преобразований, на исполнение процессору. Плюсы:
  • Мы полностью хозяева положения, имеем самые широкие возможности использования процессора и аппаратуры компьютера.
  • Для нас доступны все варианты организации и оптимизации кода.
Минусы:
  • Необходимо обладать обширными знаниями по функционированию процессоров и учитывать большое количество аппаратных факторов при выполнении кода.
  • Создание программ чуть более сложных чем приведенный пример приводит к резким увеличениям затрат времени по написанию кода и его отладку.
  • Платформозависимость: программа, созданная для одного процессора, как правило, не будет функционировать на других. Возможно, и для данного процессора, в остальных режимах его работы, потребуется редактирование кода.
Машинные коды широко использовались на заре появления компьютеров, других способов программирования в эпоху пионеров ЭВМ не было. В данное время ими изредка пользуются инженера в области микроэлектроники при разработке или низкоуровневом тестировании процессоров.

Язык ассемблера (низкий уровень)

В отличие от компьютера мы с вами лучше воспринимаем информацию в текстовом/смысловом, а не цифровом виде. Вы с легкостью назовете полсотни имён контактов в вашем смартфоне, но вряд ли сможете наизусть написать соответствующие им номера телефонов. Аналогично и с программированием. На лестнице типов мы поднимемся выше, сделав три основных шага:
  • Сопоставим группам цифровых инструкций процессора, выполняющих соответствующие действия, одну символьную команду.
  • Выделим аргументы инструкций процессора отдельно.
  • Введем возможность именовать области памяти, переменные, местоположение отдельных команд.
Сравним фрагменты прошлой программы в машинных кодах (по центру) и на языке ассемблера (справа): 2004 b0 48 83 ec 08 sub $0x8 , % rsp 2004 b4 bf bc 05 20 00 mov $0x2005bc , % edi 2004 b9 31 c0 xor % eax, % eax 2004 bb e8 e8 fe ff ff callq getData 2004 c0 48 83 c4 08 add $0x8 , % rsp 2004 c4 83 c0 01 add $0x1 , % eax Как видим, процесс написания программы упростился: нет необходимости пользоваться справочниками формирования цифровых значений команд, рассчитывать длины переходов, распределение данных в памяти по её ячейкам и иные особенности процессора. Мы описываем нужное действие из набора символьных команд и необходимых для логики из выполнения аргументов, а далее программа-транслятор переводит текстовый файл на понятный процессору набор нулей и единиц. Плюсы:
  • Процесс написания и модификации кода упростился.
  • Сохранился контроль ко всем ресурсам аппаратуры.
  • Относительно легче переносить программу на другие платформы, но требуется их модификация в зависимости от аппаратной совместимости.
Минусы:
  • Ассемблер относится к низкоуровневым языкам программирования. Создание даже небольших участков кода затруднено. К тому же также необходимо учитывать специфику работы аппаратуры.
  • Платформозависимость.
Самый популярный демонстрационный Java пример: public static void main (String args) { System. out. println ("Hello World!" ) ; } будет выглядеть (NASM синтаксис, с использованием Windows API и kernel32.lib) следующим образом: global _main extern _GetStdHandle@4 extern _WriteFile@20 extern _ExitProcess@4 section . text _main: ; DWORD bytes; mov ebp, esp sub esp, 4 ; hStdOut = GetstdHandle ( STD_OUTPUT_HANDLE) push - 11 call _GetStdHandle@4 mov ebx, eax ; WriteFile ( hstdOut, message, length (message) , & bytes, 0 ) ; push 0 lea eax, [ ebp- 4 ] push eax push (message_end - message) push message push ebx call _WriteFile@20 ; ExitProcess (0 ) push 0 call _ExitProcess@4 ; never here hlt message: db "Hello, World" , 10 message_end: Как и машинные коды, ассемблер чаще используется инженерами и системными программистами. На нём пишут аппаратно-зависимые части ядра операционных систем, критические по времени или особенностям реализации драйвера различных периферийных устройств. Но в последнее время к нему прибегают всё реже и реже, так как его применение сильно сужает переносимость программ на другие платформы. Иногда используют процесс дизассемблирования – создают ассемблерный листинг программы из цифровых кодов для разбора логики выполнения небольших фрагментов. В редких случаях, если первоначальный высокоуровневый код недоступен: анализ вирусов для борьбы с ними или потере исходного текста. Язык ассемблера причисляют к первому/второму поколению (мы не будем рассматривать отдельно псевдокоды до возникновения ассемблера и их отличие от символьных команд). Хотелось бы выделить использование ассемблера в Demo Scene (демо-сцена): сплав искусства, математики и низкоуровневого кодирования, воплощающие художественные замыслы своих создателей в виде программ, генерирующих видеоклипы при ограничениях в ресурсах. Часто общий размер файла программы и данных не должен превышать 256 байт (также популярен и формат в 4/64 килобайта). Вот пример 4 Кб программы:

Языки группы C/Фортран (средний/высокий уровень)

С развитием возможностей вычислительной техники объём функциональности и сроки реализации кода на ассемблере уже не устраивали. Затраты для написания, тестирования и сопровождения программ росли на порядок быстрее их возможностей. Необходимо было снизить требования от программиста в плане знаний функционирования аппаратуры, дать ему инструмент, позволяющий писать на языках, приближенных к человеческой логике. Перейти к новому уровню типов языков программирования. Предоставить возможность разбивать на разнообразные модули с дальнейшим последовательным вызовом (парадигма процедурного программирования), предоставить различные типы данных с возможностью их конструирования и т. п. Дополнительно эти меры привнесли улучшенную переносимость кода на другие платформы, более комфортную организацию командной работы. Одним из первых языков, поддерживающий всё вышеперечисленное был разработанный в 50-е годы прошлого века Фортран . Возможность создавать в текстовом виде с описанием логики выполнения используя циклы, ветвления, подпрограммы и оперируя массивами и представляя данные в виде вещественных, целых и комплексных чисел приводила инженеров и учёных в восторг. За короткое время были созданы научные «фреймворки» и библиотеки. Всё это и стало следствием того, что Фортран и поныне имеет актуальность, пусть и в узкой научной среде, и развивается, так как багаж наработок очень велик, одна только библиотека IMSL активно развивается с 1970 (!) года, много ли вспомните подобных актуальных software-старожилов? Другая ветка развития языков этого уровня – C . Если Фортран стал инструментом учёных, то C создавался в помощь программистам, создающим прикладное ПО: операционные системы, драйвера и т. д. Язык позволяет вручную управлять распределением памяти, даёт прямой доступ к аппаратным ресурсам. C-программистам приходится контролировать низкоуровневые сущности, поэтому многие придерживаются мнения, что язык C – усовершенствованный ассемблер и его часто называют языком «среднего» уровня. Привнеся в ассемблер типизацию данных, элементы процедурного и модульного программирования язык C и сегодня является одним из основных для системного программирования, чему также способствует и бурное развитие микроэлектроники в последнее время. Всевозможные гаджеты, контроллеры, сетевые и прочие устройства нуждаются в драйверах, реализации протоколов для совместной работы и прочем относительно низкоуровневом ПО для реализации взаимодействия с аппаратурой. Все вышеперечисленное способствует востребованности языка и в настоящее время. Объектно-ориентированные и функциональные принципы получили дальнейшее развитие в виде C++, C#, Java, взяв многое от синтаксиса C. Плюсы:
  • Упрощение процесса создания кода: введение типов, разбивка на модули, сокращение листинга программ.
  • Прозрачная логика заложенного алгоритма вследствие ухода от машинных кодов к более понятным для человека командам в семантически описательном стиле.
  • Переносимость. Стало достаточно перекомпилировать текст программы для выполнения на другой платформе (возможно, с небольшой модификацией).
  • Скорость откомпилированных программ.
Минусы:

Развитие языков высокого уровня

Высокоуровневые языки программирования, в плане создания ПО, стали всё по большей части удаляться от машинных кодов и реализовывать различные, помимо процедурного, парадигм программирования. К ним относят также и реализацию объектно-ориентированных принципов. C++, Java, Python, JavaScript, Ruby… – спектр языков данного типа наиболее популярен и востребован сегодня. Они предоставляют больше возможностей для реализации разнообразного ПО и нельзя однозначно определить «специализацию» каждого из них. Но популярность применения в соответствующих областях обусловлена библиотеками/фреймворками для работы с ними, например: JavaScript – Frontend. Язык был разработан для взаимодействия клиентского веб-браузера с пользователем и удалённым сервером. Наиболее популярные библиотеки: Angular, React и VUE. В данное время относительно активно употребляется и на web и т. п. серверах (backend), особенно популярен Node.js. Ruby – Backend. Применяется для создания скриптов (служебных сервисных файлов) и на web серверах. Основной фреймворк - Ruby On Rails. Python – научная и инженерная сфера (помимо веб-области). Является альтернативой стандартным вычислительным и математическим пакетам (Mathematica, Octave, MatLab…), но имеет привычную семантику языка и большое число библиотек. Имеет много поклонников в области систем машинного обучения, статистики и искусственного интеллекта. Из часто используемых библиотек необходимо упомянуть django, numpy, pandas, tensorflow. С++ – Универсал, эволюционное развитие языка C. Предоставляет возможности функционального и объектно-ориентированного программирования и не потеряв при этом способность низкоуровневого взаимодействия с аппаратным обеспечением. За счёт чего реализуется производительность и гибкость при создании ПО, но и цена соответствует: высокий порог вхождения за счёт сложной спецификации языка, необходимости самостоятельного контроля за ресурсами при выполнении программы. Многие однопользовательское и системное ПО написано с его применением: модули операционных систем (Windows, Symbian…), игры, редакторы (Adobe Photoshop, Autodesk Maya…), базы данных (MSSQL, Oracle…), проигрыватели (WinAmp…) и т. д. Следует отметить, что современное ПО является сложным продуктом, в разработке которого используется сразу несколько языков программирования и расставлять степень участия каждого из них в общий результат бывает весьма затруднительно.

Дальнейший прогресс

В последнее время набирает популярность и иной вид программирования - функциональное (дальнейшее развитие уровня языка) . Здесь уже другой вид абстракции для вычислений – функции, которые берут в качестве аргументов набор функций и возвращают другую. Роль переменных играют те же функции (привычные нам переменные – просто константные выражения, аналогичные final перед объявлением типа в Java). Собственно функция замкнута в своей области видимости, результат её работы зависит только от переданных аргументов. Отсюда вытекают два замечательных свойства:
  • Для тестирования нам необходимы только аргументы функций (результат работы не зависит от внешних переменных и т. п.).
  • Программа в функциональном стиле чудесным образом готова к параллельной работе: последовательные вызовы функций можно пускать в соседних потоках (так как на них не действуют внешние факторы) и им не нужны блокировки (то есть, проблемы синхронизации отсутствуют). Хороший стимул уделить время этой теме, учитывая повальное распространение многоядерных процессоров.
Однако и порог вхождения выше, чем для ООП: для эффективного кода необходимо строить программу, описывая в виде функций алгоритм выполнения. Но также для чистого функционального стиля неплохо бы знать азы логики и теории категорий. Наиболее популярные – Haskell, Scala, F#. Но не бойтесь, в Java (как и в других современных языках третьего поколения) появились элементы функционального программирования и их возможно комбинировать вместе с ООП. Более подробно вы познакомитесь со всеми этими подробностями на онлайн-стажировке JavaRush. Область логического программирования (следующий уровень языков) пока не нашла широкого практического применения в силу малой востребованности. Построение программ требует знание основ дискретной математики, логики предикатов, средств ограничений и других разделов математической логики. Наиболее популярный активный язык – Prolog.

Заключение

В настоящее время самые распространённые – языки ООП. Java, с момента возникновения, всегда находится в топе, обычно в тройке, востребованных языков. Помимо ООП, содержит элементы функционального программирования, и вы можете комбинировать разные стили составления ваших программ. Спектр применения Java весьма широк – это бизнес задачи, реализация веб-серверов (backend), основной язык создания Android-приложений, кроссплатформенные среды программирования и рабочих мест (IDE/АРМ) и моделирования и многое другое. Особенно сильны позиции Java в Enterprise секторе – области корпоративного программного обеспечения, которая требует качественный и долгоживущий код, реализацию самых сложных бизнес-логик.

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

Г. Х. Андерсен. Принцесса на горошине

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

Практика предварительной беседы с соискателями не подошла из-за временных затрат. Этап первичного отбора передали специалисту кадровой службы. Сначала соискатель проходит анкетирование, самостоятельно оценивая компетентность в областях программирования по 5-балльной шкале. Указывает срок использования технологии, заполняет таблицу «Выполненные проекты». Полученные сведения дают общее представление об опыте соискателя и профессиональном кругозоре. Начинающим разработчикам свойственно завышать оценку. К примеру, кандидат считает уровень знания Рython на 4, «готов решить любую задачу», а опыт использования языка указывает 2 недели.

Компетентность соискателя оценивается на практике. Кандидат выполняет тестовое задание. На основании анализа определяется уровень.

Первый фактор оценки - время выполнения

На идентичное задание Junior-разработчику понадобится неделя. Senior выполнит тест за несколько часов. Показательна и оценка срока выполнения тестового задания от соискателя. Разработчик уровня «Junior» смотрит на поставленную задачу чересчур оптимистично, недооценивает сложность. И из-за нехватки опыта не укладывается в сроки. Специалист уровня «Middle» склонен пессимистично смотреть на задачу. Сказывается опыт в качестве Junior-разработчика. Чрезмерно увеличивает прогнозируемый срок реализации. Senior-разработчик реалистичен. Закладывает риски разумно без лишнего завышения сроков.

Второй момент - качество кода

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

Сейчас у нас десятки вариантов выполнения проверочного задания. Тестировщики EDISON выбрали 3 фрагмента кода (обработка запроса веб-приложения), написанные на PHP разработчиками разного уровня, и добавили комментарии.

Начнем с примера так называемого «говнокода».

$user = userRequestWithPassword($_COOKIE ["login" ], $_COOKIE ["password" ]);

Хранение логина и пароля пользователя в куках. Явная ошибка безопасности. Куки передаются от браузера к серверу при запросе (открытии/обновлении страницы). Потенциальная возможность перехвата.

if ($user != null ) { if (isset ($_POST ["submitEdit" ])) {

Определение действий сайта на основе параметра POST-запроса последовательными условными блоками. Код усложняется, становясь громоздким и нечитаемым. Для облегчения реализации задачи опытные программисты придумали маршрутизацию и паттерны, например MVC.

$deal = dealRequest($_GET ["dealId" ]); $connect = mysqli_connect (BAZA_SERVER, BAZA_USER, BAZA_PASSWORD, BAZA_MYSQL); $name = mysqli_real_escape_string($connect , $_POST ["name" ]); $date = mysqli_real_escape_string($connect, $_POST ["date" ]); $insured = mysqli_real_escape_string($connect, $_POST ["insured" ]); $obligor = mysqli_real_escape_string($connect, $_POST ["obligor" ]); $countryObligor = mysqli_real_escape_string($connect, $_POST ["countryObligor" ]); $amount = mysqli_real_escape_string($connect, $_POST ["amount" ]); $currency = mysqli_real_escape_string($connect, $_POST ["currency" ]); $percent = mysqli_real_escape_string($connect, $_POST ["percent" ]); $tenor = mysqli_real_escape_string($connect, $_POST ["tenor" ]); $type = mysqli_real_escape_string($connect, $_POST ["type" ]); $responseDate = mysqli_real_escape_string($connect, $_POST ["responseDate" ]); $person = mysqli_real_escape_string($connect, $_POST ["person" ]);

Громоздкий код для элементарных операций. Опытный программист напишет блок в одну строку.

if (!empty ($_FILES ["upload" ]["name" ])) { $path_directory = "documents/" ; $filename = $_FILES ["upload" ]["name" ]; if (preg_match ("/[.](doc)|(docx)|(pdf)|(xls)|(jpg)$/" , $_FILES ["upload" ]["name" ])) { $source = $_FILES ["upload" ]["tmp_name" ]; $target = $path_directory . $filename ; $fileName = $moved = move_uploaded_file ($source , $target ); } } else { $filename = $deal ["documents" ]; } $query = "update Deals set name=" $name ", date=" $date ", nameOfTheInsured=" $insured ", nameOfTheObligor=" $obligor ", countryOfTheObligor=" $countryObligor ", amount=" $amount ", currencyOfTheDeal=" $currency ", percentToBeInsured=" $percent ", tenorOfTheExposure=" $tenor ", typeOfTheDeal=" $type ", targetResponseDate=" $responseDate ", nameOfTheContactPerson=" $person ", documents=" $filename " where id="" .$_GET ["dealId" ].""" ;

Подстановка параметра GET-запроса (строки, приходящей от пользователя при открытии страницы в браузере) прямо в SQL-запрос (обращение к базе данных). Потенциальная уязвимость в безопасности (SQL-инъекция).

Mysqli_query($connect , $query ); mysqli_close($connect ); header (.$_GET ["dealId" ]);

Хардкод URL"ов. Адрес страницы приложения может меняться. Для отсылки на новый адрес программисту придется искать и менять данные в коде вхождения старого URL.

else if (isset ($_POST ["addComment" ])) { $connect = mysqli_connect (BAZA_SERVER, BAZA_USER, BAZA_PASSWORD, BAZA_MYSQL);

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

$dealId = mysqli_real_escape_string($connect , $_GET ["dealId" ]); $userId = mysqli_real_escape_string($connect , $user ["id" ]); $comment = mysqli_real_escape_string($connect , $_POST ["comment" ]); $query = "insert into Comments (dealRefer, userRefer, comment) values(" $dealId "," $userId "," $comment ")" ; mysqli_query($connect , $query ); mysqli_close($connect ); header ("location: http://example.com/view.php?dealId=" .$_GET ["dealId" ]); }

Пример кода уровня «Junior».

if (isset ($_GET ["action" ]) && ($_GET ["action" ] == "online" ))

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

{ $document = new Document(); $document -> SetLanguage ($cur_lang ); if ($starter = $db -> GetFByQuery ("SELECT u.login FROM games g LEFT JOIN users u ON g.starter=u.id WHERE g.`invited`= $uid " )) { echo " $starter " . $document -> Translate (17 ) . "
" . $document -> Translate (19 ) . "" ; }

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

else { $rows = $db -> GetByQuery ("SELECT id, login FROM users WHERE `lastping`>" . (time () - 30 ) . " AND `id`<> $uid " ); if (count ($rows )) foreach ($rows as $row ) { echo "$row\")">$row
" ; }

Захардкоденный обработчик события click. Аналогично предыдущему пункту. Весь JS нужно выносить в отдельные файлы.

else { echo $document -> Translate (11 ); } } } elseif (isset ($_GET ["action" ]) && ($_GET ["action" ] == "creategame" )) { ... } elseif (isset ($_GET ["action" ]) && ($_GET ["action" ] == "getfields" )) { ... } ...

Код Middle-разработчика прост для понимания и содержит комментарии для разбора сложных участков. Используется ORM (Object-relational mapping) взамен написания нативных запросов к базе. Значительно снижается риск SQL-инъекций. Применяется ООП и MVC.

public function actionStatistics () { // Получение из БД общего количества игр и количества игроков. $GamesNumber = tableGame::model () -> count (); $PlayersNumber = tableUser::model () -> count (); $GeneralStatistics = array ("GamesNumber" => $GamesNumber , "PlayersNumber" => $PlayersNumber ); $Player = new Player(); // Получение из БД списка игроков с самым высоким рейтингом. $dbModel = tableUser::model () -> findAllByAttributes (array ("Enable" => 1 ), array ("limit" => self::TOP_PLAYERS_LIST_SIZE , "order" => "Rating DESC" )); // Формирование массива сводной информации по лучшим игрокам. foreach ($dbModel as $PlayerData ) { if ($Player -> Load ($PlayerData -> ID )) { $PlayersList = clone $Player ; } } // Загрузка данных авторизованного игрока. $Player -> Load (Yii::app () -> user -> getId ()); // Вывод представления. $this -> render ("statistics" , array ("GeneralStatistics" => $GeneralStatistics , "PlayerData" => $Player , "PlayersList" => $PlayersList )); }

Различия между Middle- и Senior-разработчиком по фрагменту кода прослеживаются слабо и заключаются в выборе верных архитектурных решений.

Обобщенные критерии оценки сведены в таблицу. Список не ограничивается приведенными примерами.

Меня иногда спрашивают, что нужно выучить, чтобы стать программистом. Вопрос несколько наивный, т.к. нормально ответить на него по-моему невозможно. Т.е. для начала нужно выяснить, каким программистом нужно стать. Да и вообще, программистом ли? Кроме того, на рынке востребованы как высококвалифицированные дорогие специалисты, так и “рабочая сила”. Пакет знаний и опыта первых и вторых отличается в значительной степени.

Но, не смотря на такую расплывчатость вопроса, дать ответ на него все же можно. Можно описать примерный максимум знаний, которые так или иначе относятся к программированию. Собственно, этот максимум обычно и стремятся преподать в ВУЗах на специальностях, в названии которых фигурирует слово “программист”.

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

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

В предыдущем абзаце я нарочно ввел термин “инженер-программист”. Как-то получается так, что программист - это не обязательно инженер. Даже из определения Википедии следует, что инженер - это в первую очередь проектировщик. Это тот, кто создает, т.е. проектирует системы. А в практике программирования проектирование нужно не всегда. Иногда достаточно кодирования: используя данный набор технологий, слепить что-то работающее. Типичный пример - стадо корпоративных или маркетинговых сайтов на джумлах, ворпрессах, друпалах и т.д. Это уровень техника, не инженера. Это уровень среднего образования. И работать техником можно даже после окончания курсов какого-либо языка программирования, крепкая теоретическая база там не нужна.

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

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

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

Первый уровень из CS (computer science) - Специальная база . Это стартовая площадка для любого программиста по четырем фронтам:

    арифметические основы ЭВМ (системы счисления и операции с числами, логические операции);

    физические основы ЭВМ (полупроводники, транзисторы, логические элементы, схемы, интегральные микросхемы);

    теория алгоритмов (алгоритмы и структуры данных; сложность, эффективность; способы представления информации в памяти);

    (архитектура ОС, процессы, межпроцессное взаимодействие, потоки, планирование, работы с памятью и переферией, POSIX-системы);

    системный анализ (предметная область, бизнес-процессы, потоки, диаграммы, принципы и теория системного анализа);

    базы данных (теория множеств, виды СУБД, реляционные СУБД, модели данных, SQL, конкретные БД).

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

Уровень 2 включает:

    разработку ПО (жизненный цикл ПО, этапы разработки, основы ведения программных проектов, инструменты);

    анализ данных (Data Mining, OLAP, машинное обучение, нейронные сети, ИИ);

    компьютерные сети (по уровням стеков TCP/IP и/или ISO/OSI “от и до”, протоколы, сетевое программирование на C/C++);

    языки программирования с управляемым кодом (управляемый код, виртуальные машины, сборщики мусора, юнит-тестирование, собственно практика на C# или Java);

Уровень 3 - последний уровень для среднего программиста. Он самый объемный и включает только те дисциплины, которые непосредственно связаны с разработкой ПО. Всего их получилось 6:

    разработка UI и юзабилити (принципы построения интерфейсов пользователя);

    управление командами и проектами (методологии разработки и другие вопросы управления);

    тестирование ПО (обзорно: виды тестирования, инструменты);

    веб-технологии (HTTP-протокол, веб-сервер, CGI, кэширование и проксирование, клиентское программирование);

    распределенные системы (архитектуры распределенных систем, протоколы сетевого взаимодействия компонентов, инструменты, принципы, подходы к построению распределенных систем, отказоустойчивость, большие данные, высокие нагрузки);

    интерпретируемые языки программирования (особенности, основы по двум-трем языкам, практика по одному-двум языкам: JS, PHP, Python, Ruby).

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

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

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

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

Граф - это модель. А хорошая модель как правило дает ответы сразу на множество вопросов. Я поставил перед собой задачу сделать хороший граф, близкий к реальности. Естественно, он основан на моем личном опыте и не претендует на идеал. Я старался сделать его наиболее объективным. И еще раз напоминаю, что это граф для программиста. Т.е. для тестировщика, сисадмина и других близких к программированию профессий он будет более или менее близким, но явно другим.