Наткнулся на интересный манифест, который последнее время много где упоминается, и хотел бы его разобрать. Много кто писал, что бьет прямо в сердце, а мне кажется, его как будто писал подросток-максималист, за все хорошее против всего плохого. Погнали:
👉 Мы убиваем программы, когда добавляем новые фичи, не учитывая вносимой ими дополнительной сложности.
✏️ Согласен, любая новая фича увеличивает когнитивную нагрузку. Сейчас каждая корпорация пытается сделать суперапп, которая на эту нагрузку кладет хер. У меня неделя ушла, чтобы в инсте найти, где мои лайки.
👉 Мы убиваем программы сложными билд-системами.
✏️ Вообще не понял, как это связано. Пользователям вообще похую, ты хоть на make собирай. Сложные билд-системы убивают разве что желание разрабов жить в трезвом мире...
👉 Мы разрушаем программы абсурдной цепочкой зависимостей, делая всё раздутым и хрупким.
✏️ Я так понял, это пункт про проблему транзитивных зависимостей. Ну тут охота процитировать того деда из сериала: "Ну почему мы не можем жить без сторонних зависимостей? Да потому что блять не можем..."
👉 Мы разрушаем программы, говоря новым разработчикам: «Не изобретай велосипед!».
✏️ Потому что, изобретая велосипед, в большинстве случаев они внесут кучу уязвимостей, которые уже давно поправлены, или уничтожат перформанс. Нет ничего плохого в велосипедах, но только когда ты уже не начинающий.
👉 Мы разрушаем программы, не заботясь о обратной совместимости API.
✏️ Согласен, это отсутствие инженерной культуры.
👉 Мы разрушаем программы, заставляя переписывать то, что уже работает.
✏️ Кто их заставляет? Покажите мне хоть одного менеджера, который в восторге, когда к нему приносят задачу на рефакторинг?
👉 Мы разрушаем программы, бросаясь на каждый новый язык, парадигму и фреймворк.
✏️ По мне так нет ничего плохого в изучении новых языков и парадигм. Плохо, если ты на работе каждую новую систему или фичу делаешь на новом языке или с новым подходом.
👉 Мы разрушаем программы, постоянно недооценивая, насколько сложно работать с существующими сложными библиотеками по сравнению с созданием собственных решений.
✏️ В подавляющем большинстве случаев в разы проще использовать готовые библиотеки. Ты заранее не знаешь всего пиздеца, который уже пофиксили в готовом решении.
👉 Мы разрушаем программы, всегда считая, что стандарт де-факто для XYZ лучше, чем то, что мы можем создать, специально адаптированное под наш случай.
✏️ По моему опыту, это имеет смысл только когда проект уже приносит деньги и есть прям конкретная причина, почему нам нужно свое решение. Часто бывает, что свое решение делают просто из-за того, что есть толпа разрабов, которым нечего делать.
👉 Мы разрушаем программы, утверждая, что комментарии в коде бесполезны.
✏️ Большинство да, однако в сложных местах это может сэкономить часы. Лучше всего руководствоваться правилом наименьшего удивления.
👉 Мы разрушаем программы, ошибочно принимая разработку за чисто инженерную дисциплину.
✏️ Странный пункт. Что это тогда, наука, писательство?
👉 Мы убиваем программы, проектируя их таким образом, что вносить простые изменения становится сложно.
✏️ Потому что заранее ты не сможешь никак предсказать, в какую сторону будет двигаться твой проект. Однако есть архитектурные паттерны, которые могут сгладить этот фактор.
👉 Мы разрушаем программы, стремясь писать код как можно быстрее, а не как можно лучше.
✏️ Бизнесу как-то похуй, к сожалению, с этим приходится мириться.
👉 Мы разрушаем программы, и то, что останется, больше не будет приносить нам радость хакерства.
✏️ Подразумевается, что разработчикам нет никакой радости от работы. Ну совсем сомнительный пункт, не понимаю почему и как это прокомментировать…
👉 Мы убиваем программы, когда добавляем новые фичи, не учитывая вносимой ими дополнительной сложности.
✏️ Согласен, любая новая фича увеличивает когнитивную нагрузку. Сейчас каждая корпорация пытается сделать суперапп, которая на эту нагрузку кладет хер. У меня неделя ушла, чтобы в инсте найти, где мои лайки.
👉 Мы убиваем программы сложными билд-системами.
✏️ Вообще не понял, как это связано. Пользователям вообще похую, ты хоть на make собирай. Сложные билд-системы убивают разве что желание разрабов жить в трезвом мире...
👉 Мы разрушаем программы абсурдной цепочкой зависимостей, делая всё раздутым и хрупким.
✏️ Я так понял, это пункт про проблему транзитивных зависимостей. Ну тут охота процитировать того деда из сериала: "Ну почему мы не можем жить без сторонних зависимостей? Да потому что блять не можем..."
👉 Мы разрушаем программы, говоря новым разработчикам: «Не изобретай велосипед!».
✏️ Потому что, изобретая велосипед, в большинстве случаев они внесут кучу уязвимостей, которые уже давно поправлены, или уничтожат перформанс. Нет ничего плохого в велосипедах, но только когда ты уже не начинающий.
👉 Мы разрушаем программы, не заботясь о обратной совместимости API.
✏️ Согласен, это отсутствие инженерной культуры.
👉 Мы разрушаем программы, заставляя переписывать то, что уже работает.
✏️ Кто их заставляет? Покажите мне хоть одного менеджера, который в восторге, когда к нему приносят задачу на рефакторинг?
👉 Мы разрушаем программы, бросаясь на каждый новый язык, парадигму и фреймворк.
✏️ По мне так нет ничего плохого в изучении новых языков и парадигм. Плохо, если ты на работе каждую новую систему или фичу делаешь на новом языке или с новым подходом.
👉 Мы разрушаем программы, постоянно недооценивая, насколько сложно работать с существующими сложными библиотеками по сравнению с созданием собственных решений.
✏️ В подавляющем большинстве случаев в разы проще использовать готовые библиотеки. Ты заранее не знаешь всего пиздеца, который уже пофиксили в готовом решении.
👉 Мы разрушаем программы, всегда считая, что стандарт де-факто для XYZ лучше, чем то, что мы можем создать, специально адаптированное под наш случай.
✏️ По моему опыту, это имеет смысл только когда проект уже приносит деньги и есть прям конкретная причина, почему нам нужно свое решение. Часто бывает, что свое решение делают просто из-за того, что есть толпа разрабов, которым нечего делать.
👉 Мы разрушаем программы, утверждая, что комментарии в коде бесполезны.
✏️ Большинство да, однако в сложных местах это может сэкономить часы. Лучше всего руководствоваться правилом наименьшего удивления.
👉 Мы разрушаем программы, ошибочно принимая разработку за чисто инженерную дисциплину.
✏️ Странный пункт. Что это тогда, наука, писательство?
👉 Мы убиваем программы, проектируя их таким образом, что вносить простые изменения становится сложно.
✏️ Потому что заранее ты не сможешь никак предсказать, в какую сторону будет двигаться твой проект. Однако есть архитектурные паттерны, которые могут сгладить этот фактор.
👉 Мы разрушаем программы, стремясь писать код как можно быстрее, а не как можно лучше.
✏️ Бизнесу как-то похуй, к сожалению, с этим приходится мириться.
👉 Мы разрушаем программы, и то, что останется, больше не будет приносить нам радость хакерства.
✏️ Подразумевается, что разработчикам нет никакой радости от работы. Ну совсем сомнительный пункт, не понимаю почему и как это прокомментировать…
👍21🤔4😁3❤2👎2
{1/3} TypeScript переписали на Go. Последнее время эта новость пронеслась на волне хайпа. Даже если вы рот топтали TypeScript и Go тут есть кое-что интересное.
Для начала, в чем суть новости. В любом языке есть две части — Транслятор и Рантайм. Трансляторы реализуются в виде компиляторов или интерпретаторов. Чем они отличаются, я надеюсь, вы знаете. Транслятор преобразует текст в команды нужного формата, которые затем исполняет Рантайм. Так вот, TypeScript транслятор теперь реализован на Go вместо JS.
Сделали это с одной целью – ускорить работу компилятора. Тестирование показало, что сборка крупных проектов, типа VS Code с кодовой базой около 1,5 млн строк, с новым компилятором на Go занимает 7,5 секунд против 77,8 секунд ранее. С одной стороны, десятикратное ускорение — весьма неплохо, с другой стороны, компиляция в минуту — это не чтобы big deal. В Gradle у нас столько одна только конфигурация занимает. Другое дело, если бы речь была о сокращении времени с нескольких часов до пары минут.
Самое интересное тут то, как они всё переписали. У команды было 4 претендента на переписывание: C#, Go, Rust и F#. Им хотелось попробовать все 4 варианта. Разумеется, взять и перелопатить такую огромную кодовую базу вручную, да еще и 4 раза, нереально.
Поэтому что они сделали? Они написали автопереводчик с JS языка на каждый из вариантов. Как я понял, из всех вариантов проще всего было перевести на Go. С C# и F# не получилось потому как это чисто объектные и функциональные языки. С Rust не пошло, так как модель памяти в нем запрещает цикличные ссылки, поэтому это имело бы смысл только если на нем бы разрабатывали изначально. С Go не было особых проблем, потому как он ближе всего стоял по подходам, поэтому в результате выбрали его.
Разумеется код там теперь вообще не лучшего качества. Это не удивительно ведь код на JS по определению не может быть качественным, а тут еще и переведен автоматикой на другой язык. При этом по метрикам, даже с таким качеством кода все стало быстрее. Потенциально они еще могут ускорить раз в 5 как говорят матерые Go разрабы.
Казалось бы, разрабам стоит только порадоваться — теперь компиляция кода будет "блейзингли фаст". Однако тут не учитывается психология разработчиков и философия языков программирования.
Для начала, в чем суть новости. В любом языке есть две части — Транслятор и Рантайм. Трансляторы реализуются в виде компиляторов или интерпретаторов. Чем они отличаются, я надеюсь, вы знаете. Транслятор преобразует текст в команды нужного формата, которые затем исполняет Рантайм. Так вот, TypeScript транслятор теперь реализован на Go вместо JS.
Сделали это с одной целью – ускорить работу компилятора. Тестирование показало, что сборка крупных проектов, типа VS Code с кодовой базой около 1,5 млн строк, с новым компилятором на Go занимает 7,5 секунд против 77,8 секунд ранее. С одной стороны, десятикратное ускорение — весьма неплохо, с другой стороны, компиляция в минуту — это не чтобы big deal. В Gradle у нас столько одна только конфигурация занимает. Другое дело, если бы речь была о сокращении времени с нескольких часов до пары минут.
Самое интересное тут то, как они всё переписали. У команды было 4 претендента на переписывание: C#, Go, Rust и F#. Им хотелось попробовать все 4 варианта. Разумеется, взять и перелопатить такую огромную кодовую базу вручную, да еще и 4 раза, нереально.
Поэтому что они сделали? Они написали автопереводчик с JS языка на каждый из вариантов. Как я понял, из всех вариантов проще всего было перевести на Go. С C# и F# не получилось потому как это чисто объектные и функциональные языки. С Rust не пошло, так как модель памяти в нем запрещает цикличные ссылки, поэтому это имело бы смысл только если на нем бы разрабатывали изначально. С Go не было особых проблем, потому как он ближе всего стоял по подходам, поэтому в результате выбрали его.
Разумеется код там теперь вообще не лучшего качества. Это не удивительно ведь код на JS по определению не может быть качественным, а тут еще и переведен автоматикой на другой язык. При этом по метрикам, даже с таким качеством кода все стало быстрее. Потенциально они еще могут ускорить раз в 5 как говорят матерые Go разрабы.
Казалось бы, разрабам стоит только порадоваться — теперь компиляция кода будет "блейзингли фаст". Однако тут не учитывается психология разработчиков и философия языков программирования.
👍23🤔5
{2/3} В мире языков есть такое понятие как самокомпилируемость (self-hosting). Компиляторы «взрослых» языков написаны на них же самих — C компилируется C-компилятором, Java использует компилятор на Java, даже Go изначально был на C, но потом его переписали на Go и т.д.
Почему это так важно?
1️⃣ Это показывает, что язык достаточно мощный и выразительный, чтобы реализовать функционал собственного компилятора. Если же компилятор переписывается на другой язык, многие могут воспринять это как увядание языка.
2️⃣ Компилятор должен быть независим от других технологий. Вот например: компилятор языка X написан на языке Y. Что случится, если язык Y перестанут поддерживать? У компилятора X будут большие проблемы. Ведь язык, на котором написан компилятор, не развивается, а значит никто не улучшает производительность, никто не добавляет новые фичи для ускорения. Так еще попробуй теперь найти разрабов на устаревающем языке.
3️⃣ Корпоративный аспект: TypeScript поддерживает Microsoft, а Go разрабатывает Google. Получается, что Microsoft в некотором смысле становится зависимым от решений Google. По идее было бы в разы меньше рисков если бы они выбрали С#. Что сказать, у команды TypeScript железные яйца.
С точки зрения рациональности, было бы логично, чтобы компилятор каждого языка был написан на каком-то низкоуровневом языке — это объективно сделает его быстрее. Однако психология восприятия технологий и доверие сообщества разработчиков часто становятся важнее чистой рациональности.
Почему это так важно?
1️⃣ Это показывает, что язык достаточно мощный и выразительный, чтобы реализовать функционал собственного компилятора. Если же компилятор переписывается на другой язык, многие могут воспринять это как увядание языка.
2️⃣ Компилятор должен быть независим от других технологий. Вот например: компилятор языка X написан на языке Y. Что случится, если язык Y перестанут поддерживать? У компилятора X будут большие проблемы. Ведь язык, на котором написан компилятор, не развивается, а значит никто не улучшает производительность, никто не добавляет новые фичи для ускорения. Так еще попробуй теперь найти разрабов на устаревающем языке.
3️⃣ Корпоративный аспект: TypeScript поддерживает Microsoft, а Go разрабатывает Google. Получается, что Microsoft в некотором смысле становится зависимым от решений Google. По идее было бы в разы меньше рисков если бы они выбрали С#. Что сказать, у команды TypeScript железные яйца.
С точки зрения рациональности, было бы логично, чтобы компилятор каждого языка был написан на каком-то низкоуровневом языке — это объективно сделает его быстрее. Однако психология восприятия технологий и доверие сообщества разработчиков часто становятся важнее чистой рациональности.
👍26
{3/3} Базу прошли, теперь поговорим про kotlin и gradle.
Важно разделять: есть компилятор языка и есть система сборки, в которой компиляция это лишь одна из фичей. Исходя из прошлых постов я думаю очевидно, что компилятор kotlin всегда будет на kotlin, и в целом это хорошо. JetBrains не настолько психи, чтобы создавать зависимость на другую компанию или технологический стек.
Теперь про систему сборки. В обязанности сборщика помимо компиляции кода входит:
👉 Управление зависимостями
👉 Тестирование
👉 Упаковка приложения
👉 Работа с кешами
👉 И еще дохера всего
Нужно ли для этих задач использовать тот же язык, на котором мы пишем код или на котором написан компилятор? Однозначно нельзя ответить на этот вопрос.
Говоря откровенно, когда я садился писать этот пост, мне казалось что я сейчас быстро найду кучу примеров сборщиков, написанных на других языках. Иии оказалось их почти нет, только один Bazel написан на java и может компилировать C++.
Если пройтись по всем 3-м пунктам которые я привел для компилятора вот что получим:
👉 Если мы не можем написать сборщик на том же языке, то нужно ли вообще такой язык использовать?
👉 Если же другой язык перестанут поддерживать, нам придется переписывать систему сборки на другой, а это затраты
👉 Корпоративный аспект в система сборки кстати не работает, почти всегда сборщики делают сторонние компании, тут конечно минус
Давайте на примере. Допустим у нас есть язык Java и система сборки для нее например на C++ . Кого ты хочешь в команду для разработки сборщика? Человека который всю жизнь писал на Java, знает все ее тонкости и проблемы или человека на C++ который всю жизнь решал другие проблемы?
Как бы мне не хотелось, чтобы гребанный Gradle был написан на шустром Rust, в реальном мире это не сработает. Несмотря на то, что объективно все системы сборки должны быть написаны на низкоуровневых языках, все равно работает идеология. Если тулза для языка не написана на нем самом, на язык смотрят с опасением.
Решение команды TypeScript это интересный прецидент: практическая производительность становится важнее вот этих опасений. Если у них все выгорит, то кто знает, возможно мы когда-нибудь получим аналог Gradle на Rust.
Важно разделять: есть компилятор языка и есть система сборки, в которой компиляция это лишь одна из фичей. Исходя из прошлых постов я думаю очевидно, что компилятор kotlin всегда будет на kotlin, и в целом это хорошо. JetBrains не настолько психи, чтобы создавать зависимость на другую компанию или технологический стек.
Теперь про систему сборки. В обязанности сборщика помимо компиляции кода входит:
👉 Управление зависимостями
👉 Тестирование
👉 Упаковка приложения
👉 Работа с кешами
👉 И еще дохера всего
Нужно ли для этих задач использовать тот же язык, на котором мы пишем код или на котором написан компилятор? Однозначно нельзя ответить на этот вопрос.
Говоря откровенно, когда я садился писать этот пост, мне казалось что я сейчас быстро найду кучу примеров сборщиков, написанных на других языках. Иии оказалось их почти нет, только один Bazel написан на java и может компилировать C++.
Если пройтись по всем 3-м пунктам которые я привел для компилятора вот что получим:
👉 Если мы не можем написать сборщик на том же языке, то нужно ли вообще такой язык использовать?
👉 Если же другой язык перестанут поддерживать, нам придется переписывать систему сборки на другой, а это затраты
👉 Корпоративный аспект в система сборки кстати не работает, почти всегда сборщики делают сторонние компании, тут конечно минус
Давайте на примере. Допустим у нас есть язык Java и система сборки для нее например на C++ . Кого ты хочешь в команду для разработки сборщика? Человека который всю жизнь писал на Java, знает все ее тонкости и проблемы или человека на C++ который всю жизнь решал другие проблемы?
Как бы мне не хотелось, чтобы гребанный Gradle был написан на шустром Rust, в реальном мире это не сработает. Несмотря на то, что объективно все системы сборки должны быть написаны на низкоуровневых языках, все равно работает идеология. Если тулза для языка не написана на нем самом, на язык смотрят с опасением.
Решение команды TypeScript это интересный прецидент: практическая производительность становится важнее вот этих опасений. Если у них все выгорит, то кто знает, возможно мы когда-нибудь получим аналог Gradle на Rust.
👍21
Итак, снепшот тесты. Тесты когда мы отрисовываем интерфейс, сравниваем его по пикселям с эталоном и падаем, если картинка сильно отличается.
Я на практике много раз убеждался, что такие тесты нужны иссключительно командам, которые занимаются дизайн-системами. В таких командах действительно важно, чтобы при изменениях в кнопке всё не поехало. Если они выпустят новую версию UI Kit с таким багом, кривая кнопка появится во всех приложениях компании. В таких командах снепшот-тесты реально приносят пользу и экономят деньги.
Но я вижу тенденцию, что эти тесты пытаются затащить в само приложение. Ведь они так просто внедряются, всего пара аннотаций на Compose функцию. По мне, так в приложении в снепшотах столько же смысла, как в сюжете порно. Они очень хрупкие, дорогие в поддержке, и непонятно, какая от них реальная польза.
Что такого вы можете сделать в коде, от чего вас спасут эти тесты? Я просто не понимаю, как можно накосячить в верстке так, чтобы всё сломалось. Compose позволяет даже сложные экраны верстать в полмозга, левой пяткой. В верстке нет сложной логики, которую мы можем сломать изменениями. Или вы падинги рассчитываете по сложной формуле?
Я понимаю, можно накосячить со сложными анимациями, но анимации снепшотами не протестируешь – вообще никак не протестируешь.
Команды, которые внедрили себе снепшот тесты, постоянно страдают. Недавно показывают две идентичные картинки, в которых автоматика находит пару отличающихся пикселей. Причина в том, что эталон снимался на устройстве с одним разрешением, а на ферме эмуляторов сейчас другое. И теперь нужно перелопатить все тесты, чтобы это починить. Бессмысленная дрочь….
Может, у вас есть истории успеха, где такие тесты реально спасли релиз?
Я на практике много раз убеждался, что такие тесты нужны иссключительно командам, которые занимаются дизайн-системами. В таких командах действительно важно, чтобы при изменениях в кнопке всё не поехало. Если они выпустят новую версию UI Kit с таким багом, кривая кнопка появится во всех приложениях компании. В таких командах снепшот-тесты реально приносят пользу и экономят деньги.
Но я вижу тенденцию, что эти тесты пытаются затащить в само приложение. Ведь они так просто внедряются, всего пара аннотаций на Compose функцию. По мне, так в приложении в снепшотах столько же смысла, как в сюжете порно. Они очень хрупкие, дорогие в поддержке, и непонятно, какая от них реальная польза.
Что такого вы можете сделать в коде, от чего вас спасут эти тесты? Я просто не понимаю, как можно накосячить в верстке так, чтобы всё сломалось. Compose позволяет даже сложные экраны верстать в полмозга, левой пяткой. В верстке нет сложной логики, которую мы можем сломать изменениями. Или вы падинги рассчитываете по сложной формуле?
Я понимаю, можно накосячить со сложными анимациями, но анимации снепшотами не протестируешь – вообще никак не протестируешь.
Команды, которые внедрили себе снепшот тесты, постоянно страдают. Недавно показывают две идентичные картинки, в которых автоматика находит пару отличающихся пикселей. Причина в том, что эталон снимался на устройстве с одним разрешением, а на ферме эмуляторов сейчас другое. И теперь нужно перелопатить все тесты, чтобы это починить. Бессмысленная дрочь….
Может, у вас есть истории успеха, где такие тесты реально спасли релиз?
🔥21👎5
Давайте подытожим, что у нас со снепшотами. Соберем все плюсы и минусы:
✅ Плюсы:
👉 Нет эмуляторов – довольно жирный плюс
👉 Легко написать проверку вместо вызова кучи функций в espresso
👉 Позволяет отследить баги SDK
🚫Минусы:
👉 Нужно думать как хранить и обновлять скриншоты
👉 Могут начать флакать из-за пары пикселей, нужно подбирать параметры
👉 Не проверяют логику – это пункт, который вообще перекрывает все плюсы
Может у меня это старческое, но я все чаще пытаюсь понять профит в бабках от использования технологии. Тесты имеют смысл тогда, когда затраты на их написание и поддержку окупаются за счет багов, которые они ловят. Вот на конкретном примере, есть два бага:
👉 Поехал текст на кнопке, но сама кнопка работает
👉 Запрос отправляет не на тот endpoint, из-за чего у клиента не работает оплата
Знатоки, внимание вопрос, за какой из этих багов форма вашего стула станет похожа на бутылку?
Если у вас поехала верстка, ну похихикают над вами в твитере и забудут через 5 секунд. В прошлом комменте был кейс про тени. Вы прям потеряли бы кучу клиентов из-за теней, да? При этом если вы потеряете хотя бы рубль при переводе, вас просто уничтожат.
Да, снепшот тесты отлично проверяют внешний вид приложения, а толку то от этого? В тестах важно чтобы не было регресса в логике. Вы тут можете возразить, ведь в таких тестах можно ходить в сеть. Если под капотом снепшотов нет robolecric, вы сходите лесом, а не в сеть. Что если замокать network и проверять на фейковых данных? В этом случае вы проверите как ваше приложение работает в мире феечек с единорогами.
Поэтому я и говорю, что снепшоты приносят профит только для команды дизайн системы. В таких командах вся логика направлена именно на внешний вид, у этих ребят снепшоты реально помогают с регрессом.
Что касается того, что есть какие-то легаси экраны, где верстка не консистентная? Вы просто берете пару дизайнеров или пару QA, отдаете им прилу на полный регресс и все, вам нагенерят задачи на исправление. Это в разы дешевле тысячи человекочасов на создание и поддержку тестов, которые тестируют целое нифига.
✅ Плюсы:
👉 Нет эмуляторов – довольно жирный плюс
👉 Легко написать проверку вместо вызова кучи функций в espresso
👉 Позволяет отследить баги SDK
🚫Минусы:
👉 Нужно думать как хранить и обновлять скриншоты
👉 Могут начать флакать из-за пары пикселей, нужно подбирать параметры
👉 Не проверяют логику – это пункт, который вообще перекрывает все плюсы
Может у меня это старческое, но я все чаще пытаюсь понять профит в бабках от использования технологии. Тесты имеют смысл тогда, когда затраты на их написание и поддержку окупаются за счет багов, которые они ловят. Вот на конкретном примере, есть два бага:
👉 Поехал текст на кнопке, но сама кнопка работает
👉 Запрос отправляет не на тот endpoint, из-за чего у клиента не работает оплата
Знатоки, внимание вопрос, за какой из этих багов форма вашего стула станет похожа на бутылку?
Если у вас поехала верстка, ну похихикают над вами в твитере и забудут через 5 секунд. В прошлом комменте был кейс про тени. Вы прям потеряли бы кучу клиентов из-за теней, да? При этом если вы потеряете хотя бы рубль при переводе, вас просто уничтожат.
Да, снепшот тесты отлично проверяют внешний вид приложения, а толку то от этого? В тестах важно чтобы не было регресса в логике. Вы тут можете возразить, ведь в таких тестах можно ходить в сеть. Если под капотом снепшотов нет robolecric, вы сходите лесом, а не в сеть. Что если замокать network и проверять на фейковых данных? В этом случае вы проверите как ваше приложение работает в мире феечек с единорогами.
Поэтому я и говорю, что снепшоты приносят профит только для команды дизайн системы. В таких командах вся логика направлена именно на внешний вид, у этих ребят снепшоты реально помогают с регрессом.
Что касается того, что есть какие-то легаси экраны, где верстка не консистентная? Вы просто берете пару дизайнеров или пару QA, отдаете им прилу на полный регресс и все, вам нагенерят задачи на исправление. Это в разы дешевле тысячи человекочасов на создание и поддержку тестов, которые тестируют целое нифига.
👍31👎7❤2
В канале моего тёзки был недавно пост про Пирамиду Маслова (да, именно Маслова) в интерфейсах. Крутая идея, которая базируется на том, что интерфейс в самую первую очередь должен решать проблему, и быть удобным, и только в самую последнюю очередь красивым.
Это действительно так, есть много невероятно красивых приложений, которые решают выдуманную проблему, и ими никто не пользуется. В противовес есть куча приложений, которые решают проблему, но у них просто вырвиглазный интерфейс.
Разумеется, в идеальном мире у нас должны быть только красивые приложения, которые решают проблему. Правда, вот какое дело: чем выше по пирамиде, тем субъективнее оценка. То, что один считает красивым, другой увидит говно.
И я подумал, что если поразгонять с этой точки зрения, то снепшоты тестируют именно красоту. Ведь снепшотами вы не тестируете логику, а значит, вы не можете быть уверены, что ваше приложение решает проблему. При этом вы можете протестировать, что не сломалась красота, которая субьективная и если сломается не факт что станет хуже)))
Поэтому если у компании прям дофига денег, и она капец как волнуется о том, что не дай бог на наше приложение ни у кого не встанет, то да, снепшоты прям тема. Правда, история где снепшоты выбирают с целью отказаться от UI тестов, крайне странная.
Это действительно так, есть много невероятно красивых приложений, которые решают выдуманную проблему, и ими никто не пользуется. В противовес есть куча приложений, которые решают проблему, но у них просто вырвиглазный интерфейс.
Разумеется, в идеальном мире у нас должны быть только красивые приложения, которые решают проблему. Правда, вот какое дело: чем выше по пирамиде, тем субъективнее оценка. То, что один считает красивым, другой увидит говно.
И я подумал, что если поразгонять с этой точки зрения, то снепшоты тестируют именно красоту. Ведь снепшотами вы не тестируете логику, а значит, вы не можете быть уверены, что ваше приложение решает проблему. При этом вы можете протестировать, что не сломалась красота, которая субьективная и если сломается не факт что станет хуже)))
Поэтому если у компании прям дофига денег, и она капец как волнуется о том, что не дай бог на наше приложение ни у кого не встанет, то да, снепшоты прям тема. Правда, история где снепшоты выбирают с целью отказаться от UI тестов, крайне странная.
👍11😁2
Смотрите, есть два основных подхода в архитектуре.
Первый — когда мы в самом начале пытаемся все продумать, подсунуть абстракции куда нужно, чтобы можно было быстро поменять поведение.
Второй — эволюционный подход, который базируется на идее: "давай сейчас нафигачим быстрее, а после уже поправим где нужно".
Недостаток первого подхода в том, что мы плохо предвидим будущее и можем подсунуть абстракцию не туда, куда нужно, а куда нужно — не подсунуть.
Недостаток второго подхода в том, что эволюционным путём мы тупо можем упереться в локальный минимум и застрять в нем что приведет к повторению плохих решений.
Если соединить эти два подхода, то ведь получается, что мы обречены писать говнокод, подумал я, не может же быть все так плохо. Потом вспоминаешь всё современное ПО, ах да, точно…
Первый — когда мы в самом начале пытаемся все продумать, подсунуть абстракции куда нужно, чтобы можно было быстро поменять поведение.
Второй — эволюционный подход, который базируется на идее: "давай сейчас нафигачим быстрее, а после уже поправим где нужно".
Недостаток первого подхода в том, что мы плохо предвидим будущее и можем подсунуть абстракцию не туда, куда нужно, а куда нужно — не подсунуть.
Недостаток второго подхода в том, что эволюционным путём мы тупо можем упереться в локальный минимум и застрять в нем что приведет к повторению плохих решений.
Если соединить эти два подхода, то ведь получается, что мы обречены писать говнокод, подумал я, не может же быть все так плохо. Потом вспоминаешь всё современное ПО, ах да, точно…
😁34👍6👏3🔥1
Итак, собесы. Собесов я проходил много, и в закромах уже давно лежит идея рассказать про некоторые из них.
Компания AliExpress Russia, собес на позицию Android-разработчика. Было несколько этапов, насколько помню, три: скрининг, Android-секция и техническая. Скрининг и Android-секцию я слабо помню, видимо, вопросы были максимально банальные в стиле: "расскажите про все основные компоненты". Техническая сессия оказалась алгоритмической.
Первым вопросом у меня была задача на обнаружение циклов в связном списке. Это буквально самый нелепый вопрос на собеседовании, потому как я вообще не понимаю, что он проверяет. Ты либо знаешь алгоритм, либо нет, если ты никогда не задротил LeetCode, ты скорее всего завалишь его сразу. Ну, они, разумеется, не на того напали, ведь я эту задачу прикола ради поизучал буквально за пару дней до собеса.
Вторым вопросом был flatten array. Нужно было написать кастомный iterator, который из такого списка [1, 2, 3, [4, [5, 6]]], делает такой [1, 2, 3, 4, 5, 6]. Задача была прикольная, с натяжкой можно представить, где такое можно применить.
Знаете, что было самое забавное в этих собесах? Собес в AliExpress, по ощущениям, был самым сложным по сравнению с другими, а оффер в итоге был самый маленький…
Если вдруг вам интересно узнать, как решаются эти задачи в моей подаче с иллюстрациями, накидайте огоньков, я про это сделаю посты.
Компания AliExpress Russia, собес на позицию Android-разработчика. Было несколько этапов, насколько помню, три: скрининг, Android-секция и техническая. Скрининг и Android-секцию я слабо помню, видимо, вопросы были максимально банальные в стиле: "расскажите про все основные компоненты". Техническая сессия оказалась алгоритмической.
Первым вопросом у меня была задача на обнаружение циклов в связном списке. Это буквально самый нелепый вопрос на собеседовании, потому как я вообще не понимаю, что он проверяет. Ты либо знаешь алгоритм, либо нет, если ты никогда не задротил LeetCode, ты скорее всего завалишь его сразу. Ну, они, разумеется, не на того напали, ведь я эту задачу прикола ради поизучал буквально за пару дней до собеса.
Вторым вопросом был flatten array. Нужно было написать кастомный iterator, который из такого списка [1, 2, 3, [4, [5, 6]]], делает такой [1, 2, 3, 4, 5, 6]. Задача была прикольная, с натяжкой можно представить, где такое можно применить.
Знаете, что было самое забавное в этих собесах? Собес в AliExpress, по ощущениям, был самым сложным по сравнению с другими, а оффер в итоге был самый маленький…
Если вдруг вам интересно узнать, как решаются эти задачи в моей подаче с иллюстрациями, накидайте огоньков, я про это сделаю посты.
🔥198🗿13❤2👍2
Знаете, я тут подумал и кажется осознал:
👉 покрывать все интерфейсами это единственно верное решение, чтобы ваша кодовая база не развалилась.
👉 npm и gradle это лучшие системы сборки, которые существуют на рынке.
👉 снепшоты это отличная замена UI тестам, в целом можно только их использовать!
👉 llm от лукавого и нужно писать весь код самостоятельно
👉 чтобы быть востребованным на рынке важно, чтобы у вас был красивый github
UPD: лучшая тема в IDE – светлая
👉 покрывать все интерфейсами это единственно верное решение, чтобы ваша кодовая база не развалилась.
👉 npm и gradle это лучшие системы сборки, которые существуют на рынке.
👉 снепшоты это отличная замена UI тестам, в целом можно только их использовать!
👉 llm от лукавого и нужно писать весь код самостоятельно
👉 чтобы быть востребованным на рынке важно, чтобы у вас был красивый github
UPD: лучшая тема в IDE – светлая
🤡63😁37👍16🔥5🗿2🥰1
Вы накидали много огоньков (кажется ни один пост столько не набирал), а это значит, что придется делать разбор задачи. Ну что ж, погнали, поиск цикла в связном списке.
Условия задачи: есть связный список, и нужно понять, есть ли в нем цикл. Цикл — это когда у нас последний элемент списка ссылается не на null, а на какой-то из элементов этого самого списка, короче, смотрите картинку.
Начну с того, что я вообще не ебу, где такое можно применять. Я понимаю алгоритм поиска цикла в графе, который применяется повсеместно, но в связном списке... Цикл в связном списке — это баг реализации, но да ладно.
Сложность тут в том, что его не решишь обычными способами вроде "запомнить все элементы в set и потом проверять по нему". В этом списке нет индексов, элементы могут повторяться, и мы заранее не знаем, где его конец.
Поэтому поступаем изящнее – два указателя. Один нормальный, который идет по элементам, второй в жопу ужаленный, который скачет через элемент. Если запустить два этих указателя, то у нас может быть два кейса:
👉 быстрый указатель упрется в null – цикла нет
👉 они встретятся на каком-то из элементов – цикл есть
Это собственно все... Код решения на python:
В некоторых случаях могут попросить вернуть ссылку на начало цикла, в этом случае вам нужно будет подвигать ссылку head до нужного места.
Условия задачи: есть связный список, и нужно понять, есть ли в нем цикл. Цикл — это когда у нас последний элемент списка ссылается не на null, а на какой-то из элементов этого самого списка, короче, смотрите картинку.
Начну с того, что я вообще не ебу, где такое можно применять. Я понимаю алгоритм поиска цикла в графе, который применяется повсеместно, но в связном списке... Цикл в связном списке — это баг реализации, но да ладно.
Сложность тут в том, что его не решишь обычными способами вроде "запомнить все элементы в set и потом проверять по нему". В этом списке нет индексов, элементы могут повторяться, и мы заранее не знаем, где его конец.
Поэтому поступаем изящнее – два указателя. Один нормальный, который идет по элементам, второй в жопу ужаленный, который скачет через элемент. Если запустить два этих указателя, то у нас может быть два кейса:
👉 быстрый указатель упрется в null – цикла нет
👉 они встретятся на каком-то из элементов – цикл есть
Это собственно все... Код решения на python:
class ListNode:
def __init__(self, x, next):
self.val = x
self.next = next
def detect_cycle(head: ListNode) -> bool:
fast = slow = head
circle_detected = False
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
circle_detected = True
break
return circle_detected
В некоторых случаях могут попросить вернуть ссылку на начало цикла, в этом случае вам нужно будет подвигать ссылку head до нужного места.
🗿20👍12🔥1
Удивительно, но даже на решении базовой задачи умудрились придраться. Смотрите, было несколько комментов касательно решения с использованием set.
Это один из вариантов наивного решения, которое заключается в том, что мы всё кладем в set, и если обнаружили копию, значит есть цикл. Решение рабочее, более простое, но менее эффективное, и на интервью вероятнее всего не примут. Вот почему:
Во-первых, вам нужно сравнивать именно ссылки, по значению не получится, так как в списке могут быть дубликаты — список это не set.
Во-вторых, оба решения имеют временную сложность O(n), однако при использовании set вы получаете расход по памяти O(n), тогда как в решении с двумя указателями расходов на дополнительную память нет.
Это один из вариантов наивного решения, которое заключается в том, что мы всё кладем в set, и если обнаружили копию, значит есть цикл. Решение рабочее, более простое, но менее эффективное, и на интервью вероятнее всего не примут. Вот почему:
Во-первых, вам нужно сравнивать именно ссылки, по значению не получится, так как в списке могут быть дубликаты — список это не set.
Во-вторых, оба решения имеют временную сложность O(n), однако при использовании set вы получаете расход по памяти O(n), тогда как в решении с двумя указателями расходов на дополнительную память нет.
👍17🔥2😁1
Небольшой совет, если вдруг заведете канал, аккуратнее протирайте клавиатуру на компе с включенной телегой. Есть тут один дурачок, который об это обжегся, не буду расскрывать его личность
😁41🗿6🤡5❤3
Вот, я все ждал когда уже начнут появлятся первые новости о гонке вооружений в области собеседований.
Не представляю как изменятся собеседования в индустрии в следующие 5 лет. Мало того, что волков становится все больше, так еще теперь любой школьник может сделать систему, которая будет перехватывать аудиопоток, вычленять вопросы и отправлять в LLM генерирующую подробный ответ.
По тому, что я сейчас вижу, есть ощущение, что происходит более сильный перевес в найме через рефералку и знакомых, нежели через отклики в HH.
Не представляю как изменятся собеседования в индустрии в следующие 5 лет. Мало того, что волков становится все больше, так еще теперь любой школьник может сделать систему, которая будет перехватывать аудиопоток, вычленять вопросы и отправлять в LLM генерирующую подробный ответ.
По тому, что я сейчас вижу, есть ощущение, что происходит более сильный перевес в найме через рефералку и знакомых, нежели через отклики в HH.
😁10👍5🔥1
Последнюю неделю выпал из ведения канала, пытаюсь закончить рабочий проект до конца апреля. Поэтому пока поразгоняем более простые темы.
Самая противоречивая тема в разработке — это сроки. Есть куча аргументов от сторонников и противников. Я лично считаю, что точно рассчитать сроки вы можете только на функционал, который реализовали несколько раз. В противном случае попытка рассчитать точный срок равносильна консультации таролога — примерно одинаковая эффективность будет. Потому что тут работает базовый принцип: мы очень плохо предсказываем будущее, и может всплыть очень много неочевидных проблем.
При этом мы все работаем на бизнес. Бизнесу всегда так или иначе нужны какие-то сроки, например, для маркетинговой кампании. Есть очень интересный метод, который я услышал от Бобука, как можно прикинуть сроки для проекта, чтобы свести промахи к минимуму.
Работает следующая формула. В начале мы рассчитываем срок, исходя из нашего прошлого, на глазок. Затем мы умножаем это число на π и добавляем две недели. Почему на π, спросите вы? Исходим из того, что мы двигаемся от начала проекта к его концу.
Оптимистичное мышление подсказывает нам, что мы двигаемся по прямой. Однако в реальности, даже в лучшем случае, мы будем двигаться по окружности из-за разного рода проблем. Длина окружности у нас — это 2πr. Нам нужно пройти половину окружности, значит, πr, где r — это срок, который мы насчитали в начале.
Две недели нужно добавить вот для чего: даже если мы максимально проебались и ничего не делали весь срок, двух недель хватит, чтобы создать хоть какой-то MVP, который можно показать заказчику.
UPD: меня в комментах ткнули носом что формула: πr/2 - ведь срок у нас это не радиус а диаметр
Самая противоречивая тема в разработке — это сроки. Есть куча аргументов от сторонников и противников. Я лично считаю, что точно рассчитать сроки вы можете только на функционал, который реализовали несколько раз. В противном случае попытка рассчитать точный срок равносильна консультации таролога — примерно одинаковая эффективность будет. Потому что тут работает базовый принцип: мы очень плохо предсказываем будущее, и может всплыть очень много неочевидных проблем.
При этом мы все работаем на бизнес. Бизнесу всегда так или иначе нужны какие-то сроки, например, для маркетинговой кампании. Есть очень интересный метод, который я услышал от Бобука, как можно прикинуть сроки для проекта, чтобы свести промахи к минимуму.
Работает следующая формула. В начале мы рассчитываем срок, исходя из нашего прошлого, на глазок. Затем мы умножаем это число на π и добавляем две недели. Почему на π, спросите вы? Исходим из того, что мы двигаемся от начала проекта к его концу.
Оптимистичное мышление подсказывает нам, что мы двигаемся по прямой. Однако в реальности, даже в лучшем случае, мы будем двигаться по окружности из-за разного рода проблем. Длина окружности у нас — это 2πr. Нам нужно пройти половину окружности, значит, πr, где r — это срок, который мы насчитали в начале.
Две недели нужно добавить вот для чего: даже если мы максимально проебались и ничего не делали весь срок, двух недель хватит, чтобы создать хоть какой-то MVP, который можно показать заказчику.
UPD: меня в комментах ткнули носом что формула: πr/2 - ведь срок у нас это не радиус а диаметр
👍27😁21👏5🗿4🥰1
Наконец-то опубликовали мою статью про robolectric, немного вернулся к темам android.
Я кстати начал понимать, почему большая часть статьей корпоративных блогов такие пресные. Редактор порезала все мои агрессивные шутки и даже запретили мне обращаться к читателю на "ты", ведь не дай бог мы заденем чьи то чувства.
Благо пока канал мой не трогают. Короче вот статья, старался писать не душно https://habr.com/ru/companies/tbank/articles/902180/
Я кстати начал понимать, почему большая часть статьей корпоративных блогов такие пресные. Редактор порезала все мои агрессивные шутки и даже запретили мне обращаться к читателю на "ты", ведь не дай бог мы заденем чьи то чувства.
Благо пока канал мой не трогают. Короче вот статья, старался писать не душно https://habr.com/ru/companies/tbank/articles/902180/
Хабр
Что скрывает Robolectric и почему это важно знать?
Представьте, что можно тестировать android-код без эмулятора, запуская тесты за секунды вместо минут. Именно это обещает Robolectric — библиотека, которую либо любят, либо ненавидят, но точно не...
👍17❤11🥰1
На этапах системного дизайна любят задавать вопрос: "Что такое архитектура?" Вопрос интересный и сразу показывает, насколько кандидат широко мыслит при ответе.
Если кандидат отвечает, что архитектура позволяет проще изменять код, то это показывает, что он мыслит исключительно на уровне кода, а это значит, что он максимум мидл. Поэтому я постараюсь дать ответ на этот вопрос, который, как показывает практика, нравится всем интервьюерам.
База такая: архитектура — это инструмент, который позволяет быстрее доносить ценность как для пользователя, так и для заказчика. Хорошая архитектура дешевле и быстрее доносит ценность, плохая — медленнее и дороже.
Из этой базы исходит то, что архитектура должна решать следующие задачи:
• 💰 Сохраняет стоимость внедрения фичей. Бизнесу важно, чтобы стоимость внедрения новых фичей, которые по сложности не отличаются от предыдущих, не росла в цене. Если в начале проекта стоимость внедрения фичи X, а через полгода 2X — это проёб архитектуры, который реально может сильно ударить.
• 👥 Параллелизация работы. Представьте, что на проекте один разработчик, и у него весь проект в нескольких основных файлах. Пока он один, он, возможно, даже хорошо справляется и делает всё в срок. Однако с ростом бизнеса вам нужно открывать новые направления, и одного разраба уже не хватит. Вам нужно нанять ещё 2-3. В этом случае параллелизация работы практически невозможна, вы умрёте в конфликтах. Поэтому важная часть архитектуры в том, что она должна обеспечивать разделение работы.
• 🧪 Тестирование. Это может проявляться на уровне кода, когда вы забили на DI, и нельзя никак подменить зависимость для тестов, и никак нельзя протестировать отдельную фичу, не задев ничего другого. Также может проявляться на уровне всей системы, когда у вас нет возможности поменять конфиги для QA контура, и тестировать можно исключительно на проде — это, кстати, проблема как бэка, так и фронта.
• 🚀 Развёртывание. Не актуальный пункт для мобилок, но очень важный для бэка. Архитектура должна помогать в поднятии новой версии приложения. Если у вас приложение спроектировано так, что может работать только один инстанс и при этом много пользователей, то у вас проблемы. Ведь про zero downtime можно забыть.
• 🔄 Деградация. Хорошая архитектура должна отвечать на вопрос: "А что будет, если у нас отъебнёт база?" или, если мы говорим про мобилку: "Что будет, если инет пропадёт?"
• 👁 Observability. Это уже больше про SRE, однако каждому важно понимать, что архитектура должна давать возможность трекать состояние каждого элемента системы, чтобы быстро понимать, где именно проблема.
Мне очень нравится выражение Иванова: не бывает плохих архитектур, бывают дорогие.
Если кандидат отвечает, что архитектура позволяет проще изменять код, то это показывает, что он мыслит исключительно на уровне кода, а это значит, что он максимум мидл. Поэтому я постараюсь дать ответ на этот вопрос, который, как показывает практика, нравится всем интервьюерам.
База такая: архитектура — это инструмент, который позволяет быстрее доносить ценность как для пользователя, так и для заказчика. Хорошая архитектура дешевле и быстрее доносит ценность, плохая — медленнее и дороже.
Из этой базы исходит то, что архитектура должна решать следующие задачи:
• 💰 Сохраняет стоимость внедрения фичей. Бизнесу важно, чтобы стоимость внедрения новых фичей, которые по сложности не отличаются от предыдущих, не росла в цене. Если в начале проекта стоимость внедрения фичи X, а через полгода 2X — это проёб архитектуры, который реально может сильно ударить.
• 👥 Параллелизация работы. Представьте, что на проекте один разработчик, и у него весь проект в нескольких основных файлах. Пока он один, он, возможно, даже хорошо справляется и делает всё в срок. Однако с ростом бизнеса вам нужно открывать новые направления, и одного разраба уже не хватит. Вам нужно нанять ещё 2-3. В этом случае параллелизация работы практически невозможна, вы умрёте в конфликтах. Поэтому важная часть архитектуры в том, что она должна обеспечивать разделение работы.
• 🧪 Тестирование. Это может проявляться на уровне кода, когда вы забили на DI, и нельзя никак подменить зависимость для тестов, и никак нельзя протестировать отдельную фичу, не задев ничего другого. Также может проявляться на уровне всей системы, когда у вас нет возможности поменять конфиги для QA контура, и тестировать можно исключительно на проде — это, кстати, проблема как бэка, так и фронта.
• 🚀 Развёртывание. Не актуальный пункт для мобилок, но очень важный для бэка. Архитектура должна помогать в поднятии новой версии приложения. Если у вас приложение спроектировано так, что может работать только один инстанс и при этом много пользователей, то у вас проблемы. Ведь про zero downtime можно забыть.
• 🔄 Деградация. Хорошая архитектура должна отвечать на вопрос: "А что будет, если у нас отъебнёт база?" или, если мы говорим про мобилку: "Что будет, если инет пропадёт?"
• 👁 Observability. Это уже больше про SRE, однако каждому важно понимать, что архитектура должна давать возможность трекать состояние каждого элемента системы, чтобы быстро понимать, где именно проблема.
Мне очень нравится выражение Иванова: не бывает плохих архитектур, бывают дорогие.
👍27❤11😁5🗿3🤡1
Почему все так хейтят Сбер последнее время? В некоторых каналах заметил тенденцию, что HR к работникам Сбера относятся с таким же пренебрежением, как Яндекс к ребятам, которые долго сидели на php.
При этом речь не только про Сбер, а про любой крупный банк или компанию. С одной стороны можно понять, действительно в крупной компании, есть много команд где за тебя уже все сделано, и работаешь в полмозга. С другой, есть команды в которых ты работаешь в режиме семирукий-восьмихуй, где нужно и код пописать, и разрабов опросить, и идею продвинуть и свой небольшой сервис написать.
Наверное стоит каждого в отдельности рассматривать, а не клеймить разработчика исключительно за компанию, в которой он работал.
При этом речь не только про Сбер, а про любой крупный банк или компанию. С одной стороны можно понять, действительно в крупной компании, есть много команд где за тебя уже все сделано, и работаешь в полмозга. С другой, есть команды в которых ты работаешь в режиме семирукий-восьмихуй, где нужно и код пописать, и разрабов опросить, и идею продвинуть и свой небольшой сервис написать.
Наверное стоит каждого в отдельности рассматривать, а не клеймить разработчика исключительно за компанию, в которой он работал.
👍45👎3❤1
Последнее время от знакомых слышу, что на рынке все стало гораздо сложнее.
Вакансий гораздо меньше, вопросы стали сложнее и поиск новых мест может затянутся на несколько месяцев, против того, что раньше уходило пару недель. Какие у вас ощущения?
Вакансий гораздо меньше, вопросы стали сложнее и поиск новых мест может затянутся на несколько месяцев, против того, что раньше уходило пару недель. Какие у вас ощущения?
Final Results
30%
Искал недавно, да все правда сложнее
8%
Искал недавно, все также как и пару лет назад
1%
Искал недавно, все стало проще
61%
Не искал уже пару лет
Основная идея, вокруг которой строится успешный продукт, — это взять одну проблему, сосредоточиться только на ней и решить её лучше всех конкурентов. Яркий пример — Telegram, который зашёл на рынок мессенджеров и вытеснил всех просто потому, что был удобнее и быстрее.
Однако после того, как компания разрастается, все начинают добавлять фичи, о которых никто не просил. Тот же Telegram в какой-то момент сказал: "Я теперь не просто мессенджер — я теперь социальная сеть нахуй, держи сторисы, ну а ещё я криптокошелёк, звезды брать будешь?".
Среди таких компаний верх неадекватности — казахстанские банки. В Казахстане два основных крупных банка — это Kaspi и Halyk. Открыв приложения этих банков, ты обнаружишь, что это не банки с функцией маркетплейса, а маркетплейсы с функцией банка. Причём доходит до абсурда — в рандомный момент тебе приходит пуш от банка с текстом: "Брат, корм для кошек будешь брать?"
Это пост без какой-то умной мысли, просто крик души.
Однако после того, как компания разрастается, все начинают добавлять фичи, о которых никто не просил. Тот же Telegram в какой-то момент сказал: "Я теперь не просто мессенджер — я теперь социальная сеть нахуй, держи сторисы, ну а ещё я криптокошелёк, звезды брать будешь?".
Среди таких компаний верх неадекватности — казахстанские банки. В Казахстане два основных крупных банка — это Kaspi и Halyk. Открыв приложения этих банков, ты обнаружишь, что это не банки с функцией маркетплейса, а маркетплейсы с функцией банка. Причём доходит до абсурда — в рандомный момент тебе приходит пуш от банка с текстом: "Брат, корм для кошек будешь брать?"
Это пост без какой-то умной мысли, просто крик души.
👍34🤡19😁17❤6🔥1