• Такое

    В интернете модно говорить “это такое…” с томной затяжкой на конце.

    • Ездить через всю Москву — это такое…
    • Писать под мобилу на Джаваскрипте — это такое…
    • Косплеить Соню Блейд без сисек — это такое…

    Что это, откуда пришло? Такое — что именно? Говно? Ну так договаривай!

    Говорить “это такое” — это такое…

  • I will never let monads be in a Clojure project

    Sounds a bit aggressive, doesn’t it? Well, let me explain. Monads are fine until you play with them in Haskell. But don’t bring them to Clojure. They are completely foreign beings to Clojure ecosystem. Besides the technical issues, there is a problem with sharing monads across the team. Read the following, and I hope you’ll get into what I’m worried about.

    Nobody uses monads in libraries

    So, why you’d better not to ship monads into Clojure code? First, they are used quite rarely in production. Let me open my recent project which is just another two-in-one boring stuff. An HTTP server plus a single page application. I’ve got plenty of dependencies here in my project.clj file. There are about 40 of them just to cover basic stuff. Database, oAuth, UI… I don’t want to dump the whole list here. Check this gist for the reference.

    The full tree of dependencies expands into multiple screens. Their children libraries, and their children, and so forth. There are about 100 packages in total.

    Now guess how many of them use monads? You know that, it’s zero. None of the libraries needs monads to bear their functionality. I’d like to stress that. Some of them provide a really tough stuff: database access, template system, HTTP communication, etc. Yet they work without monadic operations. Why? Just because Clojure is powerful enough. It brings everything you need for convenient development. The authors of those libraries didn’t use monads not because they are not aware of them but because they just don’t need them.

    I don’t believe you are experiencing a trouble which is much more series then something mentioned above and thus craves for monads. There is definitely a plain way for doing this.

    Railway Programming is a toy

    Moving on, most of the people who are using monads told me, they are fascinated with the idea of Railway Programming. I believe you are aware of this site and their mental model in general. Several years ago I fell into it completely thinking I’ve found the ultimate solution. It didn’t work, I regret to say.

    The problem with it is, it’s just a mock. A toy model which looks nice on the screen. At first glance, it reminds a holy grail that you’ve been looking for years and got it finally. So simple: just cut your code into a set of same looking chunks and then build a pipeline.

    I’ve been praying for that picture for months.

    Suddenly, it becomes clumsy and tough once you try to fit it into a real project. You’ve got to write more code. As I mentioned, none of the libraries really use it. All the functions should be wrapped to return monadic values rather than plain ones.

    The standard let, cond, when, and dozens of useful core functions don’t work with monadic values. You’ll lose a huge stuff for no reason. Instead, you’ll have to implement monadic versions of let, if, etc. Then test them, write documentation. Why? It’s clear to me, the more code you’ve brought on board, the less the project is maintainable.

    We are already there

    The Railway Programming proposes a happy path where each step leads either to the next happy step or to the negative outcome. This is fine, but we’ve already got the same stuff, indeed. These are exceptions. They act the same way.

    Take a look at the standard Railway example. They query the database, send email, write a file, etc. Surely, each of these steps is dangerous, whoever argues. But I don’t see a reason for why not to wrap the whole code with a simple try-catch statement? It acts exactly the same. For example, when an error occurs on the third step which is sending email, the entire pipeline terminates so we end up in the catch clause.

    Here, we’ve got an exception instance with most of the data we need. What to do next is up to us. We can log the error and fail silently. Or rise another exception with a high-detailed message plus the source exception attached for a cause. That’s is sufficient for maintaining the business logic.

    The main reason people turn to monads is, they’ve got lack of knowledge of using exceptions. There is no common rule for handling exceptions and thus it might be tricky sometimes. Some of them must be caught right here, others should flow up. For example, when iterating through the list, I wouldn’t like to stop the whole program once failing on a certain item. I just log the detailed message and go on. Or if I found a user doesn’t have enough permission for that endpoint, I throw an exception so it called by the top-level middleware. It does know how to turn in into a proper HTTP response.

    I know this is just an extended version of the GOTO operator. It looks completely imperative but I don’t care. This is a business problem, not a Haskell tutorial.

    Monads are built upon strict types

    In fact, I don’t see any reason for using monads with a language of dynamic typing system. Don’t see at all. In Clojure, we’ve got nice collections for storing either data or a nil value. Since nil is treated as an empty collection and we mostly process collections in Clojure, there is no reason to worry about whether it was a map or just nil.

    When I doubt if a value I’ve got might be nil, I just wrap the top-level form with (when value ...) which prevents me from dealing with nil. In addition, it returns nil and thus is compatible with threading macros as well.

    The very need for monads comes when you’ve got an honest typing system. An honest system is such a one that doesn’t allow to pass empty values (nil, NULL, None, etc) for an arbitrary object like one does in Java. When you are out of this trick, you’ve got to compose a complex type with a bunch of special operations upon it.

    A good example might a language with a strict typing system and algebraic types, say Scala. They haven’t got a Nil type at all. You cannot just pass an dummy value instead of a DateTime parameter. Instead, there is an Option<T> type which is a composition of either an instance of <T> class or a None value. This is only because of their type system’s limitations.

    But this is not our case! In Clojure, we are not suffering from such things. It’s much easier to check the value for its completeness with the standard if form rather than wrapping it into a monad. You overcomplicate things, and that’s the problem.

    By the way, talking about complexity. In Clojure, we don’t like complex things, we’d rather take simple ones. The entire language is about simplicity, you know. You either have got some data represented with a map or nil. That is simple. That is something you can always check within REPL out from your editor. Instead, a monad is a wrapper what obscures the original value and forces me to recover it with special macro. That’s too complex.

    Leave other languages alone

    That situation with monads in Clojure reminds me something from Python. Since it has map and reduce functions as well as flexible syntax, one believes it’s possible to program with Python in a functional way. The Internet is full of tutorials about higher order functions, functors and even monads. My shame, I used to write my own “functional” library for Python with all that stuff. It was an mess stiched from chunks of Scala and Clojure. I was really proud of it being sure this is really a great stuff. So do other authors, I suppose.

    One minor detail is, nobody uses those “functional” libraries. I’ve seen a lot of Python code before switching to Clojure. Let me assure you, a functional way in Python is a myth. There is no a chance to deliver a Django project in functional terms. Put map and reduce here and there, it won’t affect the whole picture. After all, the very language is completely imperative so you end up with changing objects through their lifetime. This is not because Python sucks, no. I love it. It’s just a matter of different design.

    Clojure also has got other design. It doesn’t know anything about monads. Talking in a more broad way, the idea of fetching foreign ideas from other languages doesn’t work. If a language is entirely imperative, functional way won’t apply here. When it has got dynamic types, the idea of adding strict type checks manually neither applies. Otherwise, you get something that we call Chimera. A strange mix of foreign elements that do not match each other. This is subject to break.

    What would you do with the team?

    One other note is, think for a while about not yourself but the whole team. Look, not everyone is as smart as you. We know you’ve been drilling Haskell by nights but know what? Nobody cares. You’ve been hired to solve business problems, not to tickle your arrogance.

    With monads, we’ve got to teach the team first. Some of my friends are really great developers yet they know nothing about monads. I don’t see any reason to violate their brains. For what? To force them to know monads? They are already capable of solving any possible business problem. Live them alone.

    I’m not against one-man-band use cases when you are the only one person responsible for everything. Use monads, monoids, do what you want. Yet it’s still an amateur way. You won’t go far as a single developer.

    Wrapping up

    Using monads is fine when you’ve got a language which is monad-friendly. They should be a part of the language’s design. Haskell or Scala would be a great choice for that.

    Railway programming looks fine right until you put that gizmo into a real project. Dull exceptions would be enough.

    Don’t borrow too much from other languages. What has been in Haskell should be left behind. It’s Clojure time! Shifting your mind between paradigms is really fun. But not sticking around the only “truthful” way!

  • Сложный выбор

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

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

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

    Поработать на выходных? Полно семейных дел, а два часа ничего не решат.

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

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

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

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

    Пользователи слышат наплевательское отношение к коду. Может показаться, что сопли на бекенде спрятаны за интерфейсом, но это не так. Кривое поведение нет-нет, но прорвется сквозь щели. Пользователю покажут идиотскую ошибку, пришлют “[Object object]” в смс, оборвут сессию в важный момент.

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

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

    1) Это ухудшает код, а плохой код значит плохой продукт. Код – это материал разработчика. За буквами на экране стоит его архитектура, ментальная модель. Ее нельзя ломать. Код подобен башне из кубиков. По мере роста она становится нестабильной. Башня не монолит, а набор блоков. Даже если класть кубики с хирургической точностью, она все равно упадет. Вопрос в том, успеет ли она подняться на нужную высоту. Нельзя вносить помехи в и без того хрупкую сущность.

    2) Вы учите плохому новичков. К вам приходят молодые ребята, они чисты и впитывают все, что видят в проекте. Нельзя поощрять плохие практики, это дурно и с практической, и моральной стороны. Новички утащат костыли в соседний проект, потом в другой отдел. Плохая практика приживется в компании. Со временем она укрепится чужим авторитетом. На вопрос “почему так?” вам ответят “так писал сам Василий”. С полной уверенностью, что это исчерпывающий ответ.

    3) Вы заметаете проблемы под ковер. Грубое решение все равно придется исправлять. Часто об этом не ставят в известность менеджеров и старших разработчиков. Иногда якобы по уважительной причине – они были в отпуске или болели. А выпиливать костыль еще труднее, чем добавить, поэтому легче махнуть рукой.

    4) Замедление проекта. Проблему легче решить, когда в голове полный контекст о ней. Будет трудно вернуться к багу, который мигнул год назад. Разработчик, который знал все о нем, ушел. Комментарии в задаче скудные, воспроизвести не получается. Теперь, чтобы вновь наполнить голову контекстом, потребуется больше времени, чем когда проблема стояла в полный рост. Но никто не хочет этого делать. Задачу закрывают. Может, только каждый тысячный пользователь ловит этот баг, но им лень писать разработчикам. Сигнал не доходит до команды, всем наплевать.

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

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

    6) Менеджмент не позволит. Если в проекте хоть как-то считают часы, то починить последствия вам не дадут. Проектному менеджеру платят за нововведения и продвижение продукта, но никогда — за оптимизации. Менеджер не лазит в код, он оценивает глазами и метриками. Если бага не видно, значит, его нет. И плевать, что разработчик патчит классы в рантайме.

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

    Потом означает никогда.

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

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

    Я вижу две стратегии: краткосрочную и долгосрочную.

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

    Цель краткосрочной стратегии в том, чтобы найти наименее болезненное решение. Акцент на том, что такое решение будет легче всего исправить. Мы оставляем задел на то, чтобы с наименьшими проблемами выкинуть этот код. Он должен быть написан с пониманием, его удалят. А не с мантрой “я же писал в два ночи, страдал, не трожьте, сволочи!!1”.

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

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

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

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

    Потом я раскидываю вопрос по нескольким чатам: рабочий, нерабочий, профильный канал в Телеграме, Слака. На грамотно составленный вопрос отвечают, как правило, за 5-10 минут.

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

    Это была краткосрочная стратегия. Ее недостаток в том, что решение все же может оказаться недостаточно хорошим. Как мы помним, слабые решения — лишний груз в проекте. Это тот случай, когда остается признать – мы оказались бессильны перед задачей. Поможет долгосрочная стратегия.

    Долгосрочная состоит в том, чтобы научиться делать и быстро, и качественно одновременно. Это совершенно другая планка. Если краткосрочная стратегия обусловлена соглашениями в команде, то долгосрочная – это скорее внутреннее. Это про личный рост и путь.

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

    В школе это называется работа над ошибками. Делайте ее хотя бы мысленно.

    Не позволяйте себе больше одного костыля на проблему. Это должно стать мантрой. Если вы встретили проблему в первый раз, решить ее костылем не так уж постыдно. Может быть, все будет не так плохо.

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

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

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

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

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

    Хотя бы один такой вопрос. Тогда статья написана не зря.

  • История одного провала

    Самый дурацкий вопрос на собеседованиях — расскажите о вашей неудаче. What was your biggest failure. Никчемней этого вопроса ничего не может быть. Для меня это своего рода маркер. Нормальный человек не станет такое спрашивать. Это либо глупость, либо дурь в голове.

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

    Это как при знакомстве с девушкой спросить: слушай, а расскажи-ка мне о своих самых неудачных отношениях?

    — Больной ублюдок.

    Я искренне не понимаю, зачем это спрашивают. Что хотят услышать? Очевидно же, к этому вопросу готовятся. У каждого девелопера заготовлена сказочка о том, как он уронил прод, но потом все поднял, и этого довольно. Обязательно должен быть хеппи-энд.

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

    Я работал с некоторыми разработчиками и знаю: этого, например, выперли из фирмы за банальное хамство. Другой ни хера не делал и его тоже выперли. Это и есть их the biggest failure. При устройстве в очередной стартап оба навешают, что один раз сломали миграции, но потом починили, и ладушки.

    Лет пять назад я работал в условной фирме Art of Data, и там были подготовки к собеседованиям. Меня не просто долбили этим вопросом, а натурально ЕБЛИ: какой у тебя был провал, каковы твои слабости. И когда я отвечал, что ничего такого не было, это никого не устраивало. Нет, должен быть провал! Не бывает так, чтобы не было!

    Все это протекало с откровенным троллингом на фоне моего неуверенного английского. Что я мог тогда возразить?

    Я никогда не мог вспомнить за собой откровенного провала. Не потому что память короткая, а потому что всегда относился к работе ответственно. Не кидал, не пропадал с деньгами, всех обо всем уведомлял. Чувствовал приближение пиздеца заранее и все исправлял. Уходил достойно, приводил замену.

    То же самое с технической частью: проды не ронял, миграции проверял. Так что мне правда нечего ответить на вопрос про the biggest failure, уж извините.

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

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

    Итак, это случилось в Чите, где я родился и вырос. Мне было 17 или около того, и я страстно хотел работать. Я уже поступил в институт на очный факультет и тратил первую половину дня на учебу. Во вторую половину хотелось где-то работать, а на домашнее задание я плевал. Когда спишу, когда ночью сделаю, когда и не спросят.

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

    Параллельно я занимался 3Д-Максом. Случилось так, что мне попалась книжка по третьей версии Макса, и я зависал в нем часами, надувая сферы и бублики. Один знакомый узнал об этом и пригласил в рекламный отдел на местный телеканал. Будешь фигачить рекламу. Я без раздумий согласился: мне было все равно, где работать, а тут что-то связанное с компами и ЗД.

    Региональный телеканал — это вещь в себе, отдельный мир. Балаган, где не прекращается возня. Все действие замкнуто на себе. Актеры сами же себе зрители и критики. После записи вечернего эфира все едут домой и сами же его смотрят, а утром обсуждают.

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

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

    Ничего этого я тогда не знал, да и не хотел знать.

    Рекламному отделу меня представили как гуру 3Д-Макса, но это их мало волновало. Они искали ответственного человека под тяжелую задачу, о которой я и не подозревал. Мои ответы их удовлетворили, и вот она, моя первая работа — инженер рекламного отдела.

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

    Выглядит это так. На каждый день составляется список роликов, которые будут в эфире. В отдел приходит девушка с БЛОКНОТИКОМ. В блокнотике написаны ролики. Я открываю Adobe Premiere, программу видеомонтажа. По тайм-линии разбросаны сотни роликов, когда-либо бывших в эфире. Моя задача — собрать несколько блоков их этих роликов и записать их на ленту.

    Сделать это не так просто, как кажется. На блоки действуют ограничения. Должно быть пять одноминутных блоков, три двухминутных и два трехминутных, например. Отклонение по времени — максимум плюс-минус пять секунд, иначе не поместится в региональное окно, которое выделяет Москва.

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

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

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

    В те годы все было автоматизировано чуть менее, чем никак. В соседнем отделе работал парень, который тратил по два часа в день на тупейшее занятие. Он открывал Ворд-файл с программой телепередач, присланной из Москвы, и заменял московское время на местное с разницей в шесть часов. Например, исправлял 15:45 на 21:45. Как-то он признался мне, что мечтает о программе, которая могла бы это делать автоматом, а он бы дольше тупил в интернете.

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

    Однажды, чтобы упростить себе жизнь, схитрил. Если ролик в каждом блоке, я ставил его первым, чтобы не забыть. За что опять получил, ведь по сути это была халявная услуга “первый в блоке”.

    Бывали клиенты-маньяки: они буквально ВЕСЬ ДЕНЬ смотрели эфир и записывали на бумажку: какая реклама шла, во сколько и в каком порядке. Потом ехали в офис и устраивали скандал.

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

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

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

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

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

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

    Минута видео в телевизионном DV-качестве занимает один гигабайт. То есть час — 60 гигабайт. На какой-нибудь клип могут наснимать три часа, а на этом компе уже куча других проектов. Жесткие диски не долговечны. Малейший дефект, и все гигабайты пропадут. Восстановить их можно будет только в мастерской, и то не всегда. А лента может осыпаться где-то на середине, на этом месте появятся артефакты-кубики, но все остальное не пострадает. Я всецело за ленточное хранение.

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

    Дают мне ленту, я ее вставляю в DV-Cam — такой цифровой проигрыватель, подсоединенный к компу — и начинаю гнать рекламу. А коллеги по кабинету уже закончили и играют в Контер-Страйк 1.6. Кричат, убивают, азарт зашкаливает. У меня аж подгорает, потому что я играл лучше всех, и не терпится к ним присоединиться. Обычно мы играли так: я против всех остальных. Они толпой вместе ходят, я вылечу, троих убью, сам помру, но денег на следующий раунд заработаю.

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

    Я затер рекламой все под ноль.

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

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

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

    Я смутно помню, чем все закончилось, настолько меня накрыло от масштаба косяка. Вроде бы нашли журналистку, подававшую надежды стать ведущей, и записали ее. Открыли “консервы” — так называют материал, который смонтировали, но оставили на будущее. Подняли какие-то архивы с мэром, слепили из говна конфету и на такси отвезли не телебашню. Утром отбрехались перед директрисой, получили выговор.

    С тех пор я всегда проверял, куда смотана лента, перед тем как писать на нее.

    Это и был the biggest failure. Как я его исправил? Никак! И это самое худшее. Коллеги, конечно, сохранили лицо и сработали дружно. Сделали скидку на неопытность и возраст, но глубоко внутри, наверное, кипели. Пятница, вечер, праздник, мэр — и так обосраться!

    С телеканала меня не уволили. Я отработал там четыре года и ушел сам. Много чего там случилось, что ни день — то приключение. Бывало всякое, и хорошее, и плохое. Но даже воспоминания о плохом приносят приятные чувства.

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

    Славное было время. Мне очень повезло повариться на этой кухне. После регионального телеканала я уже ничего не боялся.

  • Авто-буллиты

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

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

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

    Поэтому я придумал обратный буллит — не цифра-скобка, а скобка-цифра, вот так:

    (1 подготовить документы
    (2 создать учетку
    (3 написать в блог
    

    Аналогично с точкой:

    .1 подготовить документы
    .2 создать учетку
    .3 написать в блог
    

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

  • Новые правила деловой переписки

    Прочитал “Новые правила деловой переписки” Ильяхова и Сарычевой. Это продолжение их первой книги “Пиши, сокращай”. На этот раз авторы пишут о том, как составлять и отвечать на письма.

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

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

    Проблема в том, что многие ребята уверены: если писать “вы” с большой буквы, лепить “с уважением” и “заранее благодарю”, то уважение получится само собой. Увы, не получится. Сейчас так пишут все кому не лень — секретарши, сотрудники поддержки, менеджеры низшего звена. Эти приемчики превратились в шелуху, шум, который мы автоматически отсекаем.

    В самом деле, неужели кто-то обращает внимание, было ли в конце письма “с уважением” и “вы” с прописной? Читая письмо, адресат интересуется только одним — решили его проблему или нет. Он и не заметит этих приемчиков, потому что в день получает по десять писем, усыпанных “уважительными” эпитетами. А вот общий тон письма, его структуру, отношение автора он почувствует и запомнит навсегда.

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

    Вот что нужно сделать, чтобы получатель почувствовал заботу.

    Четко донести мысль. Письмо не должно быть потоком сознания с финалом “ну ты разберись как-то теперь”. Должны быть четкие вопросы. Ответ на такой вопрос подразумевает дату, человека или документ.

    Вопросы в письме должны быть на одну тему. Если у вас сразу два вопроса на разные темы, например, обсуждение задачи и проведение корпоратива, нужно послать два письма.

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

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

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

    У меня было такое сотни раз, да и у вас тоже. Отправляешь код на ревью, в ответ прилетает сотня комментариев. Все они преисполнены “уважения”: гротескно вежливы, слащавы, со смайликами на конце. Но почему-то хочется разбить автору лицо. Цедишь сквозь зубы “сука ты пидорас” и отвечаешь в том же духе: на каждый его комент — твой комент. Такой же вежливый, со смайликом, конечно-конечно, но переделывать я не буду. Он, подумав то же самое, отвечает опять и так без конца. Утром вы встречаетесь на стендапе, жмете руки, расходитесь по комнатам и все повторяется.

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

    Всего этого можно было избежать. Как именно — читайте “Новые правила деловой переписки”.

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


    См. эту и другие книги в разделе “книжная полка”.

  • Этаоин Шрдлу

    В детстве у меня был сборник фантастических рассказов. Я до сих пор помню многие из них: названия, героев, сюжеты. Например, там я впервые прочитал культовый киберпанковый рассказ “Нажмите ввод” и прямо офигел с него. Но сейчас хочу рассказать про другой, не менее крутой рассказ. Это “Этаоин Шрдлу”.

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

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

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

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

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

    Все это я пишу к тому, что некоторые ребята напоминают Этаоинов — слепо верят в то, что читают.

    Начали учить Хаскелл — теперь ООП говно, чистые функции спасут мир. Читать файл только из монады. На каждую сущность — алгебраический тип. Чем это лучше идеи, что на каждую сущность по классу? Класс коннектор, класс коннекшен, класс эксепшен. Да то же самое.

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

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

    Не надо так. Все прочитанное нужно проверять практикой. Тогда выяснится, что Хаскелл вымораживает мозг хуже Джаваскрипта. Что простейший классификатор по Байесу или Фишеру работает лучше, чем нейросеть. Что база Биткоина требует 180 гигабайт и 3 дня на выкачивание, и если хранить кошелек на удаленном сервере, то это ничем не отличается от Вебмани. Еще на них ничего не купишь.

    Критичнее надо, критичнее. И побольше практики.

  • User-Agent parser for Clojure

    Today, I detached another chunk of my codebase into a separate library. This time, it is for parsing User-Agent headers with Clojure. For a long time, I’ve been copying it from project to project, but now I decided to keep it aside from the code because it is not connected to the business logic. All the technical stuff that is not related to the very problem we are trying to solve should be kept as a separate library, I believe. The main code is all about the business problem.

    The library ships only one function, which is parse. It takes a string and returns a detailed map with information about the browser’s type, its version, manufacturer, operating system, etc. The library relies on good old Java UA Detector with the latest set of patterns. I know, there are already some solutions for that. But they either do not provide full information about a user or maintainers do not accept pull requests.

    Add it to your project:

    :dependencies [[user-agent "0.1.0-SNAPSHOT"]]
    

    Usage:

    (ns some.ns
      (:require [user-agent :as ua]))
    
    (def ua-sample
      "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36")
    
    (ua/parse ua-sample)
    
    {:producer "Google Inc."
     :family :CHROME
     :name "Chrome"
     :type :BROWSER
     :icon "chrome.png"
     :producer-url "http://www.google.com/"
     :url "http://www.google.com/chrome"
     :device {:category :PERSONAL_COMPUTER
              :name "Personal computer"}
     :os
     {:family :OS_X
      :family-name "OS X"
      :name "OS X"
      :producer "Apple Computer, Inc."
      :producer-url "http://www.apple.com/"
      :url "http://en.wikipedia.org/wiki/Mac_OS_X"
      :version
      {:bug-fix "6"
       :extension ""
       :groups ["10" "11" "6"]
       :major "10"
       :minor "11"
       :version "10.11.6"}}
     :type-name "Browser"
     :version
     {:bug-fix "3396"
      :extension ""
      :groups ["67" "0" "3396" "99"]
      :major "67"
      :minor "0"
      :version "67.0.3396.99"}}
    

    It supports plenty of desktop and mobile browsers as well as unusual ones like bots, crawlers or TVs. Hope you’ll enjoy it, your suggestions and PR’s are welcome.

  • Раньше было лучше

    Думаю, вы уже видели этот твит:

    I have a Python program I run every day, it takes 1.5 seconds. I spent six hours re-writing it in rust, now it takes 0.06 seconds. That efficiency improvement means I’ll make my time back in 41 years, 24 days :-)

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

    Поговорим об этом.

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

    Если ты хорошо знаешь Питон, то пусть программа на нем работает дольше, чем на Расте. Все дело в том, как человек воспринимает время. Если скрипт работает меньше какого-то порога, например, двух секунд, то для человека нет разницы, сколько это конкретно. В самом деле, кто может отличить 50 мс и 500 мс? Если это не система торможения в автомобиле, а обработка логов, то какая разница?

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

    На старой работе я с помощью Питона автоматизировл все что возможно. Сделал загрузку платежей из всех банков и платежных систем. Улучшил документооборот. Добавил прием заявок от населения. Запилил личный кабинет, сбор показаний счетчиков по смс и миллион других штук. Это был буквально информационный взрыв. Годами фирма делала вялые попытки как-то навести порядок, а тут такое. Было ли интересно пользователям, что Питон в 30 раз медленней Раста? Да наплевать.

    Кстати, никто их трех гигантов — Гугл, Эпл, МС — не использует С и С++ на мобилах как основной язык. У Гугла это доработанная напильником Джава. У Эпла был Obj-C, попытка нарастить старый Си до уровня Лиспа или Smalltalk. В итоге его заменили на Свифт, который по своей простоте напоминает скриптовый язык. У МС это .Net и Си-шарп, скучный ООП-язык, по сути продвинутая Джава. Во всех случаях к C/C++ прибегают только в крайнем случае, когда образуется горлышко.

    Это же справедливо и для десктопа. Виндовый софт пишут на Дотнете, для Мака на Свифте или Obj-C.

    Все нормально, жизнь идет своим чередом. Но все спорят про этот твит, натыкаешься и не понимаешь. Сижу в ступоре: о чем они спорят? Опровергни делом, а не словом! Портируй все, что хочешь на чистый Си под Винду 98, тогда и поговорим.

    На качественное ПО люди тратят треть жизни. Разработчик Total Commander пилит файловый менеджер уже 25 лет на Дельфи 2. Гвидо занимался Питоном 30 лет. Линус своей операционкой 20 лет. Емаксу Столлмана уже 40 лет. Тут каждый выбирает сам. Хочешь качественный софт – садись и пили. Может, после первого десятилетия получится что-то надежное.

    Разговоры о том, что теперь все плохо, а раньше было норм напоминают эту картинку:

    Конечно, с высоты опыта легко говорить, что раньше было лучше. Я читал воспоминания одного девелопера. Он пишет, что разрабатывал сайт в девяностых для крупной фирмы. Главное требование было читать прайс-лист из CSV-файла и показывать пользователю. По тем временам это было неслыханно. Все делалось на Си через CGI, шаблонизаторов не было, HTML собирался по кусочкам вперемешку с if-else. Делали несколько месяцев.

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

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

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

    Можно же поставить Винду XP, Фотошоп 9, Дельфи 7, Оперу 10. Вместо Андроида — кнопочная Нокия со Змейкой и Оперой-мини. Да, в Твиттер с Нокии уже не напишешь, в Инстаграм не запостишь. Технически возможно написать Джава-аплет под Нокию для постинга в Твиттер, но кто этим будет заниматься? Или можно взять последний 3D-Max и портировать его на Винду XP. А заодно все видео-драйверы и утилиты к нему. Но из-за разницы архитектур получится два 3D-Макса. Сколько пользователей будет у версии под XP? Зарплаты разработчиков будут неизмеримо больше продаж этой версии.

    Вот публика и потребляет новейший софт, Маки, Айфоны, беспроводные устройства, Что-Угодно-Script, и при этом раньше было лучше.

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

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

    А жизнь продолжается.

  • Интернет для юрлиц

    Особая жесть — это интернет для юрлиц. Вы когда-нибудь подключали интернет как ИП? Так послушайте.

    Он стоит примерно в двадцать раз дороже. Например, вы сидите на бизнес-этаже и платите 6000 рублей в месяц, а Вася из жилой квартиры выше — 350 рублей. Разница на порядок.

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

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

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

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

    Цены для юрлиц — банальный развод по принципу “есть деньги, значит, плати больше”.

Страница 1 из 42