Pull to refresh

Comments 50

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

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

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

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

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

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

А в ленте в новом блоге статья ж не должна по логике появиться, так как у нее дата старая? в противном случае можно каждый день туда-сюда переносить, и она всегда будет сверху. Да, вряд ли такое возможно.
UFO just landed and posted this here
Ага, модульность. Уникальные возможности 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 с середины прошлого века), и легким движением руки приписываются себе (желательно еще приписать это ТОЛЬКО себе — но это не всегда возможно). Особый шик, если у тебя получается всячески нарушать эту прописную истину, но при этом убедить всех в том, что только ты ее и соблюдаешь.
Это не вполне честная логика, потому что искажается исходный посыл, после чего из искаженного посыла делаются следствия. Никто не говорил, что в мире юникс все идеально. И какой пример ни возьми — пайпы делают чудеса.

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

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

Ну и последнее: людям свойственно ошибаться, а эволюции — тем более. В юниксе ОЧЕНЬ МНОГО того, что какой-то студент плохо продумал, а потом это «прижилось» и стало стандартом. Особенно эти страдают протоколы. Поэтому я не писал в статье нигде, что там все идеально. Но, в целом средневзвешенный мозг разработчиков юникса был отформатирован правильно и хороших примеров все-таки больше. смотреть лучше на них.
Это был ответ на «Как раз именно за модульность я и люблю 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.
Исправленные версии 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 (начиная с этого поста).
Ну а как по мне, правильные «исправления» пошли по другой ветке: 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 сотоварищи действительно появляются потому, что люди не хотят следовать некоторым юникс правилам, а не не хотят они потому, что не враги себе.
Насчёт последнего категорически не согласен. Одно дело, когда производительностью жертвуют в момент отрисовки экрана для пользователя, другое дело — в момент репликации.

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

Если программе необходимо скачать файл с 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 Сервер? Все есмь у меня. И все через этот модуль.

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

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

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

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

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

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

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

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

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

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

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

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

Короче, я пока не могу придумать место из которого я не могу вызвать DownloadFile.
Не плохая и не хорошая — просто другая. Для других задач.
Не кипятитесь, линуксоиды не следят за развитием современных технологий уже лет 10. У них на каждый чих давно по программе написано.
Ну а что ещё остаётся делать, когда «современные технологии» реализуют принципы, которые в юникс-подобных системах были реализованы от самого рождения? ;)
да… Эрик Рейнмонд — это настоящая легенда опен сорс комьюнити!
хоть и без бороды
Все логично, по-моему, название статьи «Искуство программирования под Unix (и не только)....». Это актуально для никс? Актуально! И не только для Никс актуальна? Да, и не только для никс. Предполагаю будет очень интересный цикл статей, жду с нетерпением. Думаю для опен сорс это более значимо в следствии идеологии поддерживоемости кода.
Раз уж мы заговорили о *nix'ах, нельзя не упомянуть www.faqs.org/docs/artu/ch01s06.html. (Хотя что мы при этом делаем в блоге о веб-разработках?...).
Отличный пример на пальцах с десктопом и ноутом, однако, если переборщить с модульностью можно так же проиграть. Но про перебор — тема для отдельной статьи.
Sign up to leave a comment.

Articles