ПОРТАЛ ПРОГРАММИСТОВ
В чём состоят преимущества языка Си по сравнению с другими языками программирования?


Первое из преимуществ - это хорошая читаемость и модифицируемость кода на языке Си.

Второе - быстрота исполнения кода. Ни программы на Java, ни на C# не работают столь быстро, как на СИ.

Но написание кода - это мелочи. Это 5-10% времени и стоимости разработки. Сотни миллиарды долларов и миллионы человеко-лет (без преувеличения), как в трубу, вылетают на поддержание (тестирование, правку багов) софта. Вот это и есть настоящая проблема. Да еще программисты наповадились с места на место бегать каждые 2-4 года, -- только человек освоится и годик поработает продуктивно, -- глядишь, он уже опять в лес намыливается... И вот тут возникает интересная проблема. В связи с высокой текучестью кадров и большой сложностью реальных проектов читаемость и модифицируемость кода приобретает первостепенное значение!

Чтобы код был читаем и легко модифицируем, крайне желательно, чтобы он был локально понятен. Так, чтобы новый человек, посмотрев на процедуру, смог достаточно быстро понять, что она делает и как. И вот тут, в объектно-ориентированных языках типа Java, C++ и С# начинается веселье с конструкторами, деструкторами, виртуальными функциями, наследованием, монстроидальным шаблонным метапрограммированием, полиморфизмом, исключительными ситуациями и проч. Например, часто ли в Си встречаются указатели на функции? -- исключительно редко, и только по делу. Поэтому, увидев вызов функции в Си, как правило сразу понятно, какая именно функция вызвалась, можно сходить и посмотреть, что она делает. В объектно ориентированных языках, где народ (в особенности вчерашние студенты) любят, ой как любят переоперделять функции, не поймешь, какой из 15 виртуальных методов будет вызван в данном контексте, и читать текст их всех дело утомительное. В результате починка бага занимает в 3-5 раз больше времени.

Перейдем к деструкторам и конструкторам. Видит программист описание локальной переменной, которая нигде не используется, и, не сомневаясь, удаляет его. Программа перестает работать. Что случилось? Оказывается, конструктор этой переменной устанавливает связь с Exchange'ем (реальный пример из программы Outlook). Конечно, за такие фокусы (я имею в виду создание такого конструктора) нужно увольнять, но что написано пером - не вырубишь топором. В результате программист (по-хорошему) вынужден прочитать описания всех конструкторов и деструкторов по всей цепочке наследования всех локальных cтруктурных переменных процедуры. Кому хочется шариться по 40 файлам, чтобы понять, что делается в процедуре? — да никому. Никто этого и не делает, в результате через 3 года в программе, лихо написанной на объектно ориентированном языке, не разберется никто. Посему, и надежность программ, размашисто написанных на таких языках, оставляет желать лучшего. Я уже не говорю про перекрытие операторов, конструкторов копирования и прочее. Творческое пользование темплейтами C++ также сможет доставить потомкам немало приятных минут. А чего стоят исключительные события? Почему-то получается, что код, написанный на языке программирования без скрытого поведения, поддерживать и сопровождать гораздо легче. Просто уже потому, что вероятность наступить на грабли меньше. Описана переменная -- можно быть уверенным, что ничего больше это не означает. Вышли из блока -- значит, вышли, и нечего кроме. Что написано, то и происходит. Когда же приходится докапываться до третьего слоя истины -- это бардак. К сожалению, на объектно ориентированных языках наломать дров проще простого, что мы и наблюдаем изо дня в день.

Как это ни удивительно, при промышленном программировании залогом хорошего здоровья является простота. Чем проще, тем лучше. Код должен быть понятен, иначе человек, который заменит Вас через 2-4 года, не справится. Хотите проинициализировать переменную? Вызовите процедуру. Надо вызвать функцию? Вызовите ее напрямую. Не надо вот этого - посылания сообщения, который исполнит XML (взяв его из registry), который запустит ActiveX контрол, который и сделает, что надо, позвав вашу процедуру через COM-интерфейс.

Очевидно, что чем проще язык программирования, тем трудней сделать на нем семантическую ошибку. Если достаточно полное и предельно краткое описание языка занимает около 1000 страниц, можно ли ожидать, что рядовой программист будет знаком хотя бы с 50% особенностей языка? -- навряд ли. Тогда откуда может быть уверенность, что достаточно навороченная конструкция представляет собой именно то, что хотел сказать программист?

Далее. Стандартные библиотеки. Опять же, с точки зрения промышленного программирования, — чем проще, тем лучше. Если в стандартной библиотеке (к тому же динамически подгружаемоей) есть баг, то это беда. Если программисты его не нашли -- значит, найдут пользователи. Если нашли и обошли, то проблемы начнутся после того, как пользователь обновит библиотеки и в новой версии баг будет починен. Наконец, необходимым требованием является 100% обратная совместимость библиотек. Ну скажите мне, хоть одна библиотека для Java удовлетворяет этому требованию? А есть ли там хоть одна процедура без какого-либо ляпа? Я уже не говорю о вопросах совместимости, инсталляции, стабильности их работы на практике, прожорливости разных версий фреймворков под C# .NET и о том, что на изучение постоянно изменяющихся спецификаций различных новомодных библиотек может уйти полжизни.

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

При создании большинства серьезных проектов предъявляются очень жесткие требования к производительности и надежности.

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

В последние годы вышла масса литературы на тему дизайна software. Авторы книг статей постарались на славу. Были выделены и формализованы основные конструкции в виде паттернов проектирования. Сформированы основные практики и рекомендации. Однако, у этой большой и красивой медали есть обратная сторона – очень редко говорится О РЕАЛЬНОЙ НЕОБХОДИМОСТИ ПРИМЕНЕНИЯ тех или иных методик, а также о трудозатратах при этом. Подавлющая масса молодых программистов из-за отсутсвия опыта воспринимает все подобные материалы совершенно неадекватно, стремясь де-факто реализовать в одном месте практически все то, о чем они когда-либо читали и слышали (а слышали они в силу возраста как раз все последние веяния). Им трудно дифференцировать рациональные зерна от бесполезных "бантиков" и программирование превращается не столько в создание требуемого функционала, сколько в продумывание деталей как это будет написано. Внешнее и второстепенное выдвигается на первое место. Значительную часть времени начинает занимать бесполезный рефакторинг программного текста и мысли о том как же организовать очередное хитрое зацепление классов, в то время как создание полезного функционала уходит на задний план. Например, в игровой индустрии подобные повадки особенно вредны. Нужен функционал, не нужен лишний текст. 99% текста выполняют 100% работы.

Когда-то одному разработчику был дан проект очень незатейливой игры. Предполагалось, что эта игра займет около месяца разработки. Но месяца не хватило. Спустя шесть недель выяснилась причина. Программист попался очень педантичный и вместо того чтобы взять чистый СИ и написать игру, он 80% времени занимался тусовкой классов в сложнейшей иерархии. Когда посчитали – оказалось порядка 210 классов. Движок получился, была написана чудовищная гора текста. В объекты было завернуто все, начиная от объектов межпоточной синхронизации и кончая экранными виджетами со своей собственной системой сообщений. Да только вот беда — сама игра была в совершенно зачаточном состоянии и не работала.

Старые игры для GBA, C64, NES, SNES, Megadrive, ZX Spectrum, Atari, N64 с неизменным постоянством работали как часики. Можно конечно сейчас сказать "ну знаешь ли, не сравнивай сложность продуктов" — а ничего подобного, просто нужно знать как писались эти вещи и на чем писались. Раньше ведь даже не было IDE, и дебаггеров с одним тычком мыши. Не было самих мышей. Загружались с дискет (а еще раньше с кассет!). Писали даже не на Си, а на ассемблере! Иногда не было возможности отлаживаться или даже запускать код на самом устройстве, приходилось писать на сходных системах, а запускать раз в день. Так может быть нужно больше уделять внимание эффективности, задачам которые пытаемся сделать, а средство и этот самый "код" (который к слову сказать, никогда "кодом" не назывался, а был всего лишь "текстом") все-таки вторичны? Кто более эффективен — человек, который применяет ООП и Java, создает гору классов, применяет три паттерна, 10 интерфейсов и... ничего не работает или человек который реализует задачу на СИ и она РАБОТАЕТ с первого раза?

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

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