Пользователь
0,0
рейтинг
5 августа 2010 в 10:16

Разработка → Искусство программирования под Unix (и не только). Часть первая, «правило модульности»

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

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

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

Эрик Реймонд выделяет 17 правил этой «философии». Я буду посвящать по одной заметке на каждое правило. Я постараюсь изложить эти концепции в максимально понятной, упрощенной и популярной форме, насколько это будет возможно.

Начнем с самого первого правила — Правила модульности. Оно звучит так: «Простые блоки связывайте друг с другом ясными и понятными интерфейсами» (Rule of Modularity: Write simple parts connected by clean interfaces).

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

Два примера из реальной жизни: 1) классический домашний ПК из системного блока и монитора 2) ноутбук. К примеру, на обоих погас экран. Причина может быть в чем угодно, как мы понимаем. Но в случае домашнего ПК легко проверить первое предположение: а работает ли монитор на другом компьютере? если не работает — причина в мониторе. Если да — причина в компьютере. Далее можно попробовать видеокарту на другом компьютере — и сразу понять, в ней дело или нет. Аналогично дело обстоит с клавиатурой, мышью…

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

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

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

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

Когда-то давно, после института, я писал систему проектирования воздуховодов для рязанской компании Эковент. Там можно было создавать произвольную модель воздуховодов — труб с разветвлениями во всех трех измерениях. В какой-то момент пришлось полностью переделать всю программную часть, потому что она стала просто слишком сложной. Отдельные компоненты, отвечающие за изменение конструкции — такие как, например, добавление элемента, имели текстовый интерфейс в виде текстовых команд вида «add block width=100 height=100 depth=10». Разумеется, пользователя никто не заставлял набирать такие команды, для этого был отдельный графический оконный интерфейс, где он вводил ширину, высоту, глубину, но далее форма все равно преобразовывалась в команду. Это позволяло очень просто отлаживать сложные ситуации, когда нужно было создать сотню объектов и выполнить их отрисовку.

В UNIX-мире уже давно изобретен один унифицированный интерфейс для командной строки, называется он “каналом” (pipe, |). Через каналы можно очень просто связывать разные программы, выполняющие одну, очень простую задачу. Например, есть утилитка, которая считает число строк, символов (wc), и утилитка, которая показывает на экран содержимое файла (cat). Поставив их друг за другом, мы можем получить, например, число строк в файле (cat file | wc -l). И таких “утилиток” уже разработано очень много. Возможность комбинировать их «на лету» помогает решить довольно сложные задачи буквально за секунды.

В итоге, несколько простых советов — мои следствия правила модульности:
  • Каждый блок, программа, модуль должны делать только одну вещь и делать ее хорошо. Если цель, назначение блока начинает «размазываться», стоит задумываться о ее разделении на части.
  • Если есть возможность, выбирайте интерфейсы из числа промышленных стандартов (XML, HTTP, RPC, CSV, JSON) и ни в коем случае не выходите за их рамки.
  • Если можно упростить интерфейс за счет увеличения количества блоков — упрощайте. Пусть блоков будет больше, зато будет возможность тестировать их отдельно. Разумеется, нормально, когда блоки не сами по себе, а выстроены в иерархию.
  • Если можно упростить функционал блока, разбив его на более мелкие блоки, с более четкой выполняемой задачей, со стандартными интерфейсами, без заметного ущерба в производительности — разбивайте. Даже, если есть ущерб в производительности — тщательно продумайте, иногда им стоит жертвовать. «Железо» сейчас стоит дешевле.


» Продолжение: правило ясности
Рауф Алиев @raliev
карма
130,2
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (50)

  • +1
    немного запутано написано, но правильно всё, конечно же :)
  • +6
    принцип хороший, но насколько я помню книгу, там было очень важное замечание — не забывать про здравый смысл, ибо излишняя мелочность тоже вредит
    • 0
      Да-да, и пример с ноутбуком и десктопом показателен.

      Я вот пользуюсь ноутбуком, и ничуть не жалею, что не могу выдернуть видеокарту из него) Для меня, как потребителя, модульная система компьютера — излишняя мелочность. (я понимаю, что ноутбук тоже модульный. мы же утрируем.)
  • 0
    Жаль, что такой материал (и так) не преподают в большинстве университетов
    • 0
      Просто это никому не нужно:
      — большинство студентов нынче не особо рвутся что-то изучать
      — а те, кто изучают, как правило сами разыскивают необходимую информацию
      — при этом преподаватели в большинстве своем тоже не рвутся что-либо менять в устоявшейся программе
      — а те, кто рвутся, сталкиваются в определенными проблемами соответствия своей программы требованиям
  • +7
    Как раз именно за модульность я и люблю Unix-системы. Вот только при чём тут веб-разработка?
    • 0
      Тоже не понял.
      Предлагаю перенести сюда:
      habrahabr.ru/blogs/nix_coding/
      • 0
        Я тут недавно, не могу в хелпе найти ответ на вопрос — могу ли я опубликовать это сразу в двух блогах? это разрешено? или тут и в персональном блоге? Как-то кажется нелогичным это делать через копи-паст.

        Дата публикации после переноса останется прежней? грубо говоря, если я статью годовой давности перенесу в новый тематический блог, она же останется столь же глубоко, что и раньше, но уже в новом?
        • +2
          Опубликовать можно только в одном блоге.
          А дата публикации при переносе остается прежней, вроде бы.
        • 0
          но вот в веб-разработке оно смотрится слегка не в тему.
          есть просто «разработка»: habrahabr.ru/blogs/development/
          • 0
            перенес, действительно место ему там
            последующие статьи также будут там
        • –2
          В двух блогах — запрещено, это называется «кросс-пост». Надо поэтому делать перенос:

          1) Подписаться на новый блог.

          2) Отредактировать блогозапись, указав ей в качестве места публикации новый блог вместо старого.
          • 0
            перенес.

            а в персональный и тематический — это тоже кросс-пост?

            А в ленте в новом блоге статья ж не должна по логике появиться, так как у нее дата старая? в противном случае можно каждый день туда-сюда переносить, и она всегда будет сверху. Да, вряд ли такое возможно.
    • НЛО прилетело и опубликовало эту надпись здесь
    • +6
      Ага, модульность. Уникальные возможности plaintext-овых пайпов. Do one thing right.

      Есть «модуль», перечисляющий процессы — называется ps
      Есть «модуль», умеющий искать паттерны — называется grep
      Есть «модуль», посылающий процессам сигналы — называется kill

      Прекрасно. Как же нам найти процессы по шаблону и послать им сигнал? Наверное так:
      ps | grep <options> | kill <options>

      Хм, не совсем. Надо густо перемазывать все sed/awk. Но вдруг нам не хочется связываться с парсингом. ОК есть -C cmdlist: ps пытается делать работу grep, но делает это плохо (one thing right, да-да). Поэтому появляется pgrep, который умеет еще и регулярные выражения. Ок, ну дальше то все нормально да?
      pgrep <options> | kill <options>
      Уж это то точно должно работать. Правда, ведь?

      Не так быстро. Теперь нужно обмазываться не только sed/awk, но еще и xargs. А если нам не хочется? Ну придется делать еще одну «one thing» — нам не привыкать. Итак, на сцене…
      pkill — комбайн, включающий в себя целых ТРИ модуля. Просто потому, что не только каждый «модуль» по отдельности не справляется со своими задачами, но даже комбинации два-в-одном — тоже не особо помогают.
      А есть еще killall и skill. А также pstree и top (последний в основном потому, что «модуль» sort хреново справляется с задачей сортировки выхлопа из «модуля» ps).

      «Do as I Say Not as I Do» в чистом виде. А вообще забавно, берется прописная истина (недаром работы одного архитектора по шаблонизации и модуляризации так ценятся в CS с середины прошлого века), и легким движением руки приписываются себе (желательно еще приписать это ТОЛЬКО себе — но это не всегда возможно). Особый шик, если у тебя получается всячески нарушать эту прописную истину, но при этом убедить всех в том, что только ты ее и соблюдаешь.
      • 0
        Это не вполне честная логика, потому что искажается исходный посыл, после чего из искаженного посыла делаются следствия. Никто не говорил, что в мире юникс все идеально. И какой пример ни возьми — пайпы делают чудеса.

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

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

        Ну и последнее: людям свойственно ошибаться, а эволюции — тем более. В юниксе ОЧЕНЬ МНОГО того, что какой-то студент плохо продумал, а потом это «прижилось» и стало стандартом. Особенно эти страдают протоколы. Поэтому я не писал в статье нигде, что там все идеально. Но, в целом средневзвешенный мозг разработчиков юникса был отформатирован правильно и хороших примеров все-таки больше. смотреть лучше на них.
        • +3
          Это был ответ на «Как раз именно за модульность я и люблю Unix-системы». Подразумевается неявное сравнение «с не-Unix-системами». Неоднократно встречал эдакий юникс-снобизм как раз таки в духе «в мире юникс все идеально».

          негативные примеры нужно будет не искать специально, а из них будет построено вообще все
          Самое забавное, что модульность не имеет отношения к юниксу, а имеет к программированию вообще (и не только программированию — модуляризация и использование шаблонов пришли в само программирование извне). Более того, как раз в юниксе такие примеры и не надо искать специально — таких примеров на каждом шагу. Недодумки с безопасностью (даже SUS сейчас стеснительно называет суперпользователя «appropriate privileges», но все равно уши торчат в виде chmod в том же стандарте), недодумки с моделью исполнения (вот список функций, связанных с СОЗДАНИЕМ единицы исполнения: fork, fork1, forkall, pthread_create, pthread_atfork, posix_spawn, posix_spanwp, execl, execle, execlp, execv, execve, execvp, fexecve, system, может еще чего забыл), недодумки с файловыми абстракциями (функции для ОТКРЫТИЯ/СОЗДАНИЯ файла: open, fopen, fdopen, creat, popen, opendir, fdopendir, tmpfile, mkdir, mkdirat, может еще чего — причем для каждой функции из этого зоопарка существует отдельная функция закрытия).

          А ведь это самые базовые вещи, основы которых были заложены наверное еще до появления юникса. Что уж говорить о шелле и текстовых пайпах, настолько неудобных, что люди предпочитают создавать огромные комбайны, которые делают все в один проход (типа ImageMagick), дублировать функционал (как в приведенных выше примерах), создавать на лету «новые скрипты» (xargs, find — последний еще и дублирует функционал кучи утилит типа ls, grep, stat и пр) и используют десятки других ухищрений — все только для того, чтобы избежать использования пайпа.

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

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

          Более того, как раз пример с ноутбуком некорректен. Ноутбук состоит из тех же шин и компонентов, что и «большие» компьютеры — просто они не всегда «user serviceable». Более корректным будет пример SoC.
          • 0
            Исправленные версии UNIX, в которых нет большинства из описываемых Вами недостатков, называются Plan9 и Inferno — но они так и не стали популярны за почти 20 лет. Ибо внутренняя простота и элегантность ОС уже давно никого не волнует. И в любом случае даже уродливый и переусложнённый POSIX будет по-проще надцати вариантов виндового API (впрочем, если Вы с этим не согласны, будем считать что я не прав в этом утверждении — разводить на эту тему флейм смысла нет).

            Что касается sed/awk/xargs — я не вижу в их применении никакой трагедии. ps должен уметь выводить море разной информации, и разным программам дальше, в процессе выполнения канала, нужны разные элементы этой информации (grep-у имя команды, kill-у её pid). И гораздо проще и надёжнее пользоваться маленькими простыми кубиками делающими одну задачу и столь же маленькими и простыми склейками на sed/awk, чем большим, сложным и глючным комбайном. Тем более, что на практике в большинстве случаев в большом конвейере на 4-5 строчек применять sed/awk приходится пару-тройку раз, а не между любыми двумя командами. M$ попыталась решить эту проблему в powershell, передавая в канале объекты, но IMHO от этого легче, проще, лучше и удобнее писать конвейеры не стало.

            Комбайны вроде pgrep/pkill и тонны опций у cat и ls появляются зачастую потому, что многие не пытаются следовать описанным в статье принципам — ибо в мире GNU некому бить по рукам пионерам, которые дорвались до возможности отправлять патчи и делать фичи. А в мире Plan9/Inferno этого нет — там cat -v considered harmful. Сравните, например, cat в Linux (12 опций) и в Inferno (0 опций), ls в Linux (57 опций, если я не сбился со счёта) и в Inferno (12 опций). Кстати, недавно в 9fans было прикольное обсуждение сложности команды cp (начиная с этого поста).
            • 0
              Ну а как по мне, правильные «исправления» пошли по другой ветке: VMS -> NT.
              Ибо внутренняя простота и элегантность ОС уже давно никого не волнует.

              Меня волнует. И именно поэтому я использую Windows.

              И в любом случае даже уродливый и переусложнённый POSIX...

              Ой, вот не нужно подменять понятия. В винде есть несколько унифицированных API для доступа к данным, в юниксах — нет вообще (есть отдельные врапперы для каждого отдельного языка программирования). Техническое поражение — команда не явилась на игру. Если уж сравнивать POSIX с чем нибудь, так это с Native API (которое одновременно и несравнимо полнее и несравнимо «стройнее»). А если говорить о Win32 API, то и сравнивать нужно с зоопарком *никсовых usermode библиотек (разных не только в разных ОС, но зачастую имеющих кучу разных версий под одну ОС).

              Что касается sed/awk/xargs — я не вижу в их применении никакой трагедии

              Сериализация в формат, не допускающий однозначной десериализации и собственный для каждой утилиты? Хм, действительно — никаких проблем.

              Тем более, что на практике в большинстве случаев в большом конвейере на 4-5 строчек применять sed/awk приходится пару-тройку раз, а не между любыми двумя командами

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

              M$

              Сколько еще классов до поступления в институт?

              попыталась решить эту проблему в powershell, передавая в канале объекты, но IMHO от этого легче, проще, лучше и удобнее писать конвейеры не стало.

              Во-первых, компонентизация за счет объектов была в винде ЗАДОЛГО до powershell (лет 15 как минимум), а во-вторых таки стало. Пайп выглядит ИМЕННО как: ps | select | kill

              Комбайны вроде pgrep/pkill и тонны опций у cat и ls появляются зачастую потому, что многие не пытаются следовать описанным в статье принципам

              Ну ОК, давайте Вы приведете пример ps-grep-kill на чистом sh (следуя всем правилам), а мы сравним это с pkill (и с парой вариантов на PS, если захочется). pkill сотоварищи действительно появляются потому, что люди не хотят следовать некоторым юникс правилам, а не не хотят они потому, что не враги себе.
  • 0
    Насчёт последнего категорически не согласен. Одно дело, когда производительностью жертвуют в момент отрисовки экрана для пользователя, другое дело — в момент репликации.

    Буквально недавно матерился на систему real-time репликации данных на ocaml'е. Объём данных, который можно было на 386 прокачать, жрёт гиг памяти и целиком (в один поток!) ядро довольно шустрого зеона.
  • +1
    Использование внутренних DSL — это вообще в мире CAD традиция возрастом в минимум лет 30. Не уверен, что найдется много CAD-ов, устроенных иначе.
  • +5
    Нихрена не понял. Модульность которой сто лет в обед, которая юзается везде, почему-то приплетена к юниксу, да еще и в блоге про веб разработку.
    • +2
      Вот вам не все равно к чему она прикреплена? Статья то не о том)
    • +2
      модульность приклеена к юниксу потому именно в нем она наиболее полно реализована
      • 0
        Вы с чем, простите, сравниваете?
        • +3
          С plan9, вероятно.
        • +6
          с виндой, и программами под нее. В винде каждая программа — сама по себе. Все нужные библиотеки носит с собой. Если программе в винде требуется скачать файл с фтп, или создать архив — ей придется самой это реализовывать.
          В юниксах — программа при установке требует определенных зависимостей, и затем использует их ( вызов архиватора, или же curl для работы с фтп ). Так программы делаются легче, и не паряться решением побочных задач.
          • +2
            Есть разница между «наиболее полно» и «полнее чем в винде».
          • –7
            Я всего ожидал. Но то что вы говорите просто превысило все мои ожидания.

            Если программе необходимо скачать файл с FTP она делает WebClient.DownloadFile(«ftp://example.com/stuff.gif», «c:\\temp.gif»);

            Это .NET да-да. Модуль который распространяется с виндой уже лет восемь.
            Хочется из командной строки? System.Net.WebClient::DownloadFile(«ftp://example.com/stuff.gif», «c:\\temp.gif»); Пля, опять тот же модуль юзается? Хочется из КОМ? Хочется из анменджед? Хочется из SQL Сервер? Все есмь у меня. И все через этот модуль.

            Вы вообще на кого расчитываете чсо своим заявочками?
            • +3
              Модульность есть везде. Просто есть некоторая разница в культуре. Модульность в стиле unix way — это несколько принципов, обычно в мире windows не применяемых: использование текстовых протоколов, большое число маленьких процессов, общающихся друг с другом через пайпы, как можно более простая функциональность каждого из процессов.

              Сложно судить, какой из подходов лучше.
              • –2
                >> Модульность есть везде.

                Собсно я это и хотел сказать. Я привел пример, про модульность в винде. Она есть. Она не хуже (это просто не возможно определить). Она другая.

                Пайпы вообще не причем к модульности. Это не более чем протокол общения между программами. Что делать если в Винде пайпы в понимании юнихов не настолько важны? Ну нема там такого количества консолек. А между десктопными приложухами общаются просто другими протоколами. Месаджи, НеймедПайпы, Сокеты. Кстати в ПоверШел Майкры впедалили юниксоподобные пайпы.
                • +2
                  Простите, но пайпы очень даже относятся к модульности. Это один из механизмов её реализации.

                  Основное свойство пайпа — то, что можно всегда воткнуть что-то между двумя его концами. Например тот же netcat. Соответственно, такого рода модульность получается автоматически очень масштабируемой, и её намного проще отлаживать, поскольку протоколы преимущественно текстовые и понятные человеку.

                  Конечно же у этого есть и обратная сторона — низкая производительность, проблемы с несовместимостью протоколов, сложнее инсталляция и конфигурация. Иными словами, реализацию модульности надо выбирать всегда под конкретную задачу, а не религиозно следовать чему-то одному, будь то Unix Way, [D]COM, CORBA, EJB и что угодно еще.
            • +3
              На секундочку:
              WebClient это класс, мы в программе создаём его экземпляр. Я правильно понимаю? То есть мы к своей программе прикручиваем функциональность фтп клиента (а на самом деле и не только фтп). В то время как мы могли бы использовать отдельную специализированную программу. Да, модульность есть. Но только внутри этакого комбайна. И разница лишь в том, что кучу библиотек за нами таскают другие.

              В никсах несколько иная идеалогия. В них изначально писались отдельные программы для выполнения отдельных функций. То есть была «внешняя» модульность, если это так можно назвать. Связано это с историческими причинами (мне кажется, что такая модульность — развитие идей разделяемых библиотек). Windows преследовал несколько иные цели изначально и его развитие шло несколько другим путём. Хотя, как показывает практика, винда приходит к тем же принципам, по которым никсы работают уже сейчас.
              • +2
                Предположим на юниксах вы пишете программу. Для того что бы скачать чето с ФТП, вы вызываете curl (отдельный бинарник). Что происходит в Винде. Вы вызываете функцию DownloadFile из бибилотеки System.Net (отдельный бинарник).

                Неужели это плохая модульность?
                • +2
                  Не холивара ради, но…
                  … а программа на Perl из-под Windows осилит DownloadFile?
                  • 0
                    Вы не поверите ответу. :)
                    • 0
                      И все же. Я готов проверить пример на своей машине.
                • +5
                  curl в юниксах вы можете вызвать для всех языков, без ограничений: из bash-скриптов, из C и С++, из php/ruby/python, из java, из .net (mono приложений).
                  В винде функцию DownloadFile вы можете вызвать адекватно только из .Net. Как это можно сделать из php/ruby, используя «голый» язык? Как подключить System.Net? А из C++ приложения? В этом и есть различия.
                  • +2
                    >> DownloadFile вы можете вызвать адекватно только из .Net

                    Простите, я конешно понимаю что пост заминусованый сложно читать. Но там на русском языке перечислено, откуда DownloadFile можно вызвать нативно, без оберток. Еще раз PowerShell(прямой вызов любого стафа в .NET), COM(почти вся .NET BCL доступна как COM), SQL и AutoCad или любое другое приложение которое хостит CLR).

                    А теперь рассмотрим PowerShell, имея ее вы можете вызвать .NET из любого места которое может создавать процесы.

                    А теперь рассмотрим COM. Все что может создавать обьеткы (Javascript, VBA, 1C). Любой язык который может создавать обьекты.

                    Phyton, Ruby, тут две опции. Вопервых вы можете пользовать ихнее реализации под .NET. А можете как обычно воспользоваться COM (например поищите про win32ole).

                    Короче, я пока не могу придумать место из которого я не могу вызвать DownloadFile.
                • +1
                  Не плохая и не хорошая — просто другая. Для других задач.
            • 0
              Не кипятитесь, линуксоиды не следят за развитием современных технологий уже лет 10. У них на каждый чих давно по программе написано.
              • 0
                Ну а что ещё остаётся делать, когда «современные технологии» реализуют принципы, которые в юникс-подобных системах были реализованы от самого рождения? ;)
  • +3
    да… Эрик Рейнмонд — это настоящая легенда опен сорс комьюнити!
    • 0
      хоть и без бороды
  • 0
    Все логично, по-моему, название статьи «Искуство программирования под Unix (и не только)....». Это актуально для никс? Актуально! И не только для Никс актуальна? Да, и не только для никс. Предполагаю будет очень интересный цикл статей, жду с нетерпением. Думаю для опен сорс это более значимо в следствии идеологии поддерживоемости кода.
  • 0
    Раз уж мы заговорили о *nix'ах, нельзя не упомянуть www.faqs.org/docs/artu/ch01s06.html. (Хотя что мы при этом делаем в блоге о веб-разработках?...).
  • +3
    wc -l file
    :)
  • –4
    Юникс рулит!
  • 0
    Отличный пример на пальцах с десктопом и ноутом, однако, если переборщить с модульностью можно так же проиграть. Но про перебор — тема для отдельной статьи.

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