Низкое качество
Часть 2.
Я бы мог еще рассказать про Silent Hill и Crash Bandicoot на PS1 или про Metal Gear Solid 2 на PS2, но не хочу затягивать пост.
Я привожу примеры из видеоигр, потому что это очень удачная сфера, которая одновременно является так же программным ПО, но и вместе с тем близка рядовому человеку. C 2000 годов, когда гейминг был задротской нишей, он сегодня превратился в универсальное хобби, на примере которого можно увидеть в хронологии в какой упадок мы сегодня пришли.
Эти примеры показывают, что такие подвиги возможны лишь тогда, когда люди действительно любят то, что делают. Такие открытия невозможны при работе из под палки или просто ради зарплаты. Нужен талант. Но в эпоху быстрого заработка на цифровых продуктах талант никому не нужен. Нужная дешевая рабочая сила. Именно поэтому сегодня мы не видим всего этого, а видим усталых разрабов на бесконечном легаси, мечтающих о проекте для души, или стартап-запуски очередной ИИ-помойки, от которой немеет мозг. Сколько раз я слышал от руководов фразы, вроде "Что-то не нравится - можешь уходить" или "ну ты сам виноват, что решил на себя это взять", каждый раз, когда ты пытаешься добавить хоть какой-то жизни в продукт, но сталкиваешься с сопротивлением морально умерщвленных людей, которые уже поняли, что пытаться что-то делать самому - не вариант.
По моему скромному мнению - это глобальный тренд, который касается не то, что профессионального поля смыслов, а человечества в целом. Человеку для смысла жизни надо что-то создавать, но сегодня есть лишь иллюзия строительства. Одни и те же бизнесы, одна и та же музыка, одни и те же цифровые продукты. Творческая муза укрощена и рабствует на благо больших компаний, но интуицию и собственную волю к творчеству подчинить нельзя, об этом уже сказали все, от античных мыслителей до современных.
Но вместе с тем, я надеюсь, что это не повод для отчаянья. Как и у любого растущего процесса, наступает время стагнации и упадка, чтобы потом всё начало расти опять.
Я ставлю на VR, хоть и это игра в долгую. Ready Player One.
#ai #game #article #dev
Часть 2.
Я бы мог еще рассказать про Silent Hill и Crash Bandicoot на PS1 или про Metal Gear Solid 2 на PS2, но не хочу затягивать пост.
Я привожу примеры из видеоигр, потому что это очень удачная сфера, которая одновременно является так же программным ПО, но и вместе с тем близка рядовому человеку. C 2000 годов, когда гейминг был задротской нишей, он сегодня превратился в универсальное хобби, на примере которого можно увидеть в хронологии в какой упадок мы сегодня пришли.
Эти примеры показывают, что такие подвиги возможны лишь тогда, когда люди действительно любят то, что делают. Такие открытия невозможны при работе из под палки или просто ради зарплаты. Нужен талант. Но в эпоху быстрого заработка на цифровых продуктах талант никому не нужен. Нужная дешевая рабочая сила. Именно поэтому сегодня мы не видим всего этого, а видим усталых разрабов на бесконечном легаси, мечтающих о проекте для души, или стартап-запуски очередной ИИ-помойки, от которой немеет мозг. Сколько раз я слышал от руководов фразы, вроде "Что-то не нравится - можешь уходить" или "ну ты сам виноват, что решил на себя это взять", каждый раз, когда ты пытаешься добавить хоть какой-то жизни в продукт, но сталкиваешься с сопротивлением морально умерщвленных людей, которые уже поняли, что пытаться что-то делать самому - не вариант.
По моему скромному мнению - это глобальный тренд, который касается не то, что профессионального поля смыслов, а человечества в целом. Человеку для смысла жизни надо что-то создавать, но сегодня есть лишь иллюзия строительства. Одни и те же бизнесы, одна и та же музыка, одни и те же цифровые продукты. Творческая муза укрощена и рабствует на благо больших компаний, но интуицию и собственную волю к творчеству подчинить нельзя, об этом уже сказали все, от античных мыслителей до современных.
Но вместе с тем, я надеюсь, что это не повод для отчаянья. Как и у любого растущего процесса, наступает время стагнации и упадка, чтобы потом всё начало расти опять.
Я ставлю на VR, хоть и это игра в долгую. Ready Player One.
#ai #game #article #dev
setka.ru
Коллапс качества программного обеспечения | Сетка — социальная сеть от hh.ru
Прочитал (и вам рекомендую) статью от сентября 2025, в которой говорится о серьёзном падении качества программного обеспечения. Началось оно ещё до массового распространения ИИ, а с его появлением в...
🔥2
На одном из прежних мест работы, когда в команде появился второй фронтенд-разработчик, довольно быстро встал вопрос о единообразности кода, а следовательно о линтере и форматтере. Для многих разработчиков, кто не особо вдается в глубину, особенно на начальном этапе, линтер и форматтер может зачастую означать одно и тоже. Особенно, когда до определенного момента в некотором смысле так и было.
Всем известный ESLint заведовал всеми правилами, но JavaScript продолжал усложняться: вышел ES6, появилась деструктуризация, стрелочные функции, async/await. Правила линтера для этих сложных вещей конфликтовали с правилами их оформления, это становилось сложно поддерживать.
Проблему решил Prettier в 2017 году. Он забрал на себя всё форматирование и сказал: "Мы придумали лучшие правила, берите и пользуйтесь, хватит спорить из-за стилей.". Действительно, спорить будет ли два таба или четыре пробела в начале строки - контрпродуктивно.
Таким образом, произошло разделение обязанностей. И если правила линтера продолжают быть темой споров, разные команды выкатывают свои конфиги в npm, какие-то наборы правил обрастают фанбазой, то с Prettier договариваться стало проще. Поставил и забыл.
В 2023 году команда ESLint официально перевела все правила форматтинга в "устаревшие" и прямо заявила, что поддерживать их было болью, потому предлагают пользоваться Prettier или ESLint Stylistic.
В моем личном случае мне пришлось это всё разобрать, так как мы стали настраивать линтер для команды. Какие-то наборы правил взяли готовые, что-то написали сами. Пока этой необходимости не возникло, я просто пользовался расширением ESLint в VSCode с какими-то дефолтными правилами, которые шли с CRA, но потом для меня открылся целый мир.
Еще интересный факт, касательно линтера: когда правил много и кодовая база большая, это начинает сказываться на производительности. Редактор кода может тупить, медленнее сохранять файлы, не сразу обрабатывать код и давать подсказки. Один из способов, которым это пытаются решить - переписать линтер и его правила на Rust. Например, Oxlint. Скорость работы в десятки раз выше, но на тот момент, когда я в этом разбирался, не было переписано еще очень большого количества правил, потому мы использовать не стали. Но может кому-то будет интересно.
#javascript #eslint #formatter #linter #Oxlint #Prettier
Всем известный ESLint заведовал всеми правилами, но JavaScript продолжал усложняться: вышел ES6, появилась деструктуризация, стрелочные функции, async/await. Правила линтера для этих сложных вещей конфликтовали с правилами их оформления, это становилось сложно поддерживать.
Проблему решил Prettier в 2017 году. Он забрал на себя всё форматирование и сказал: "Мы придумали лучшие правила, берите и пользуйтесь, хватит спорить из-за стилей.". Действительно, спорить будет ли два таба или четыре пробела в начале строки - контрпродуктивно.
Таким образом, произошло разделение обязанностей. И если правила линтера продолжают быть темой споров, разные команды выкатывают свои конфиги в npm, какие-то наборы правил обрастают фанбазой, то с Prettier договариваться стало проще. Поставил и забыл.
В 2023 году команда ESLint официально перевела все правила форматтинга в "устаревшие" и прямо заявила, что поддерживать их было болью, потому предлагают пользоваться Prettier или ESLint Stylistic.
В моем личном случае мне пришлось это всё разобрать, так как мы стали настраивать линтер для команды. Какие-то наборы правил взяли готовые, что-то написали сами. Пока этой необходимости не возникло, я просто пользовался расширением ESLint в VSCode с какими-то дефолтными правилами, которые шли с CRA, но потом для меня открылся целый мир.
Еще интересный факт, касательно линтера: когда правил много и кодовая база большая, это начинает сказываться на производительности. Редактор кода может тупить, медленнее сохранять файлы, не сразу обрабатывать код и давать подсказки. Один из способов, которым это пытаются решить - переписать линтер и его правила на Rust. Например, Oxlint. Скорость работы в десятки раз выше, но на тот момент, когда я в этом разбирался, не было переписано еще очень большого количества правил, потому мы использовать не стали. Но может кому-то будет интересно.
#javascript #eslint #formatter #linter #Oxlint #Prettier
🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Пользуюсь ИИ-чатом на Arena AI.
Очень нравится как визуально выполнена кнопка копирования.
Вроде бы ничего особенного, но именно это сочетание цветов, переходящих друг в друга, скорость и вид анимации вместе создают очень плавное ощущение. Хочется постоянно нажимать на эту кнопку.
#frontend #webdev #ux
Очень нравится как визуально выполнена кнопка копирования.
Вроде бы ничего особенного, но именно это сочетание цветов, переходящих друг в друга, скорость и вид анимации вместе создают очень плавное ощущение. Хочется постоянно нажимать на эту кнопку.
#frontend #webdev #ux
🔥2👍1👏1
Сейчас будет задротская тема.
Я питаю определенную любовь к нишевым инди-играм. В них зачастую есть та душа творчества, которая сегодня уже полностью вымылась системой подписок и лутбоксов от ААА-компаний. Одна из таких игр The Textorcist: The Story of Ray Bibbia.
Прикольный буллет-хелл, который завязан на том, чтобы печатать слова на клавиатуре для нанесения атак по врагу. Очень сильно точит слепую печать, а еще вызывает взрывы пукана невероятной мощности.
Короч. Суть в чем, я хотел как-то переустановить ОС (бог пойми зачем опять 🤦🏻♂️), но прежде, чем это делать, решил проверить, что сейвы с этой игры перенесутся, так как я очень не хотел терять прогресс, доставшийся мне неоправданно тяжелым для видеоигры трудом. Накатил игру на ноуте. Запустил. Steam Cloud нет, перетащил папку сейвов с компа на ноут. На старте игры сейвов нет, закрываю игру, смотрю сейвы - они потерты, созданы новые.
Простите, что?
Может быть я дурак, копирую опять. Смотрю, файлы изменились только что, захожу опять, на запуске файлы трутся на новые.
ПРОСТИТЕ, ЧТО?
Чтобы я не делал, игра при запуске затирает мои сейвы и создает свои. Первым делом я пошел на форумы стима, пообщался с ребятами, никто ничего толком не сказал. Нашел тред с разрабами, написал им. Игнор. Прошел год. Написал им на почту. Прошел год. На форуме стиме тоже никаких комментов на тему. Оставил негативный отзыв. Пошел ковырять файлы. Обнаружил, что содержимое файлов сохранений выглядит интересно:
У меня была мысль, что это какая-то кодировка, но на тот момент я не сообразил, потому пошел искать форумы в инете, где люди занимаются взломом игровых процессов и прочего и набрел сюда.
Я питаю определенную любовь к нишевым инди-играм. В них зачастую есть та душа творчества, которая сегодня уже полностью вымылась системой подписок и лутбоксов от ААА-компаний. Одна из таких игр The Textorcist: The Story of Ray Bibbia.
Прикольный буллет-хелл, который завязан на том, чтобы печатать слова на клавиатуре для нанесения атак по врагу. Очень сильно точит слепую печать, а еще вызывает взрывы пукана невероятной мощности.
Короч. Суть в чем, я хотел как-то переустановить ОС (бог пойми зачем опять 🤦🏻♂️), но прежде, чем это делать, решил проверить, что сейвы с этой игры перенесутся, так как я очень не хотел терять прогресс, доставшийся мне неоправданно тяжелым для видеоигры трудом. Накатил игру на ноуте. Запустил. Steam Cloud нет, перетащил папку сейвов с компа на ноут. На старте игры сейвов нет, закрываю игру, смотрю сейвы - они потерты, созданы новые.
Простите, что?
Может быть я дурак, копирую опять. Смотрю, файлы изменились только что, захожу опять, на запуске файлы трутся на новые.
ПРОСТИТЕ, ЧТО?
Чтобы я не делал, игра при запуске затирает мои сейвы и создает свои. Первым делом я пошел на форумы стима, пообщался с ребятами, никто ничего толком не сказал. Нашел тред с разрабами, написал им. Игнор. Прошел год. Написал им на почту. Прошел год. На форуме стиме тоже никаких комментов на тему. Оставил негативный отзыв. Пошел ковырять файлы. Обнаружил, что содержимое файлов сохранений выглядит интересно:
f27624b7b4c469c2d33b38c6bb833e4ab9b93dc0ef4073705b26c98017d32a5cc4c31c74be1a924eeyAiaWQxMGJldGEiOiAtMS4wLCAic2NvcmU1IjogOTg3MzQ1LjAsICJzY29yZTViZXRhIjogMC4wLCAic2NvcmU5YmV0YSI6IDAuMCwgImlkZGxjMSI6IC0xLjAsICJzY29yZXJ1c2giOiAwLjAsICJpZDdiZXRhIjogLTEuMCwgInNjb3JlZGxjMiI6IDAuMCwgInNjb3JlMmJldGEiOiAwLjAsICJzY29yZTEiOiA1OTE1ODcuMCwgImlkZGxjMyI6IC0xLjAsICJzY29yZTciOiAxNDU4Nzk5LjAsICJzY29yZTkiOiAxNjg1MDczLjAsICJzY29yZTMiOiAxMDUxNjE0LjAsICJpZGJldGEiOiAtMS4wLCAic2NvcmVrcmFtcHVzIjogMC4wLCAiaWR0ZXN0IjogLTEuMCwgImlkNCI6IDEwMDk2My4wLCAiaWQyIjogMjkwOTM4LjAsICJpZDJiZXRhIjogLTEuMCwgImlkcnVzaGJldGEiOiAtMS4wLCAic2NvcmU3YmV0YSI6IDAuMCwgImlkNWJldGEiOiAtMS4wLCAiaWQ5YmV0YSI6IC0xLjAsICJpZDYiOiA0MTU5MS4wLCAiaWQ4IjogMjMzNDguMCwgInNjb3JlZGxjMyI6IDAuMCwgInNjb3JlcnVzaGJldGEiOiAwLjAsICJpZDEwIjogMTMyMzkuMCwgInVzZXJuYW1lIjogIkFJVyIsICJzY29yZTQiOiAxNzA2MjkyLjAsICJzY29yZTEwIjogNTY5NTM2LjAsICJpZDZiZXRhIjogLTEuMCwgInNjb3JlM2JldGEiOiAwLjAsICJzY29yZTIiOiAxMDk5NjMyLjAsICJzY29yZWRsYzEiOiAwLjAsICJpZCI6IDM3NjkzNy4wLCAiaWRydXNoIjogLTEuMCwgInNjb3JlNGJldGEiOiAwLjAsICJpZGRsYzIiOiAtMS4wLCAic2NvcmU4YmV0YSI6IDAuMCwgInNjb3JlOCI6IDEzMTI5MjUuMCwgInNjb3JlMTBiZXRhIjogMC4wLCAic2NvcmU2IjogMjIwMDQ3MC4wLCAiaWQ1IjogNjI0MjguMCwgImlkNGJldGEiOiAtMS4wLCAiaWQ4YmV0YSI6IC0xLjAsICJzY29yZTFiZXRhIjogMC4wLCAic2NvcmVoYyI6IDAuMCwgImlkM2JldGEiOiAtMS4wLCAic2NvcmU2YmV0YSI6IDAuMCwgImlkOSI6IDE0NDIxLjAsICJpZDciOiAyNzA4NS4wLCAic2NvcmV0ZXN0IjogMTA1MTYxNC4wLCAiaWQzIjogMTc1ODg2LjAgfQA=
У меня была мысль, что это какая-то кодировка, но на тот момент я не сообразил, потому пошел искать форумы в инете, где люди занимаются взломом игровых процессов и прочего и набрел сюда.
🤯2
В общем, мне подсказали, что это base64. И после расшифровки данные выглядят так:
Как мы видим, это таблица рекордов из моего сохранения. Логика такая:
В начале всей строки есть рандомный кусочек, назовем его ID —
На старте игры проверяется ID. Если он совпадает - игра загружает сейвы, если нет, то всё трётся, делаются новые файлы. Таким образом мы можем взять старые сейвы, в них после расшифровки заменить ID на новый и добавить в игру, не теряя, таким образом, свой прогресс.
Понравилось ли мне тратить время на то, чтобы в этом разобраться? Безусловно. Хотел ли бы я этим заняться опять? Конечно, нет.
Сказать честно, я не понял для чего разрабы так запарились и не позволили просто менять файлы сейвов, как в любой другой человеческой игре, но было прикольно узнать, что такое бывает. Я даже запилил гайд в стим.
#steam #textorcist #guide #base64
nۆo86w}:m7 o4y4~彺s4wٮ\s7mZn { "id10beta": -1.0, "score5": 987345.0, "score5beta": 0.0, "score9beta": 0.0, "iddlc1": -1.0, "scorerush": 0.0, "id7beta": -1.0, "scoredlc2": 0.0, "score2beta": 0.0, "score1": 591587.0, "iddlc3": -1.0, "score7": 1458799.0, "score9": 1685073.0, "score3": 1051614.0, "idbeta": -1.0, "scorekrampus": 0.0, "idtest": -1.0, "id4": 100963.0, "id2": 290938.0, "id2beta": -1.0, "idrushbeta": -1.0, "score7beta": 0.0, "id5beta": -1.0, "id9beta": -1.0, "id6": 41591.0, "id8": 23348.0, "scoredlc3": 0.0, "scorerushbeta": 0.0, "id10": 13239.0, "username": "AIW", "score4": 1706292.0, "score10": 569536.0, "id6beta": -1.0, "score3beta": 0.0, "score2": 1099632.0, "scoredlc1": 0.0, "id": 376937.0, "idrush": -1.0, "score4beta": 0.0, "iddlc2": -1.0, "score8beta": 0.0, "score8": 1312925.0, "score10beta": 0.0, "score6": 2200470.0, "id5": 62428.0, "id4beta": -1.0, "id8beta": -1.0, "score1beta": 0.0, "scorehc": 0.0, "id3beta": -1.0, "score6beta": 0.0, "id9": 14421.0, "id7": 27085.0, "scoretest": 1051614.0, "id3": 175886.0 }�Как мы видим, это таблица рекордов из моего сохранения. Логика такая:
В начале всей строки есть рандомный кусочек, назовем его ID —
nۆo86w}:m7 o4y4~彺s4wٮ\s7mZn . Затем идет JSON с данными сохранения, в данном случае количество очков. Все это шифруется в base64. На старте игры проверяется ID. Если он совпадает - игра загружает сейвы, если нет, то всё трётся, делаются новые файлы. Таким образом мы можем взять старые сейвы, в них после расшифровки заменить ID на новый и добавить в игру, не теряя, таким образом, свой прогресс.
Понравилось ли мне тратить время на то, чтобы в этом разобраться? Безусловно. Хотел ли бы я этим заняться опять? Конечно, нет.
Сказать честно, я не понял для чего разрабы так запарились и не позволили просто менять файлы сейвов, как в любой другой человеческой игре, но было прикольно узнать, что такое бывает. Я даже запилил гайд в стим.
#steam #textorcist #guide #base64
Steampowered
The Textorcist: The Story of Ray Bibbia on Steam
Dodge bullets while typing exorcisms at the very same time: Get ready for an electrifying mix between bullet hell and typing game! Turn on both sides of your brain and jump into the adventure of private exorcist Ray Bibbia!
👍1🔥1😁1
Был у меня давным-давно красивый инстаграм. Я в него заливал только самые эстетичные, на мой взгляд, фотки. Вел я его довольно давно, лет с 20, там была целая хронология становления моей персоны. К сожалению, с наступлением 2022 года то ли активизировались боты в инсте, то ли еще какой-то блудняк произошел, и в инсте стали блочить аккаунты, особенно с РФ, направо и налево.
Мой аккаунт не стал исключением. Я отправил, наверное, десяток фоток своей хари с листиком с написанным от руки 6-значным кодом, чтобы меня пустили в мой же аккаунт. Всё было бестолку и в течение года я наблюдал за своим аккаунтом со стороны учеток друзей, неспособный дотронуться до того, что было раньше моим...
По истечению года мой аккаунт окончательно удалили с серверов. Я зарегался под своей почтой, будто в первый раз, но больше никогда туда ничего не постил.
Потому я решил, что буду, может, по воскресеньям какие-то фотки тут выкидывать, чтобы показать миру как классно я живу.
#instagram
Мой аккаунт не стал исключением. Я отправил, наверное, десяток фоток своей хари с листиком с написанным от руки 6-значным кодом, чтобы меня пустили в мой же аккаунт. Всё было бестолку и в течение года я наблюдал за своим аккаунтом со стороны учеток друзей, неспособный дотронуться до того, что было раньше моим...
По истечению года мой аккаунт окончательно удалили с серверов. Я зарегался под своей почтой, будто в первый раз, но больше никогда туда ничего не постил.
Потому я решил, что буду, может, по воскресеньям какие-то фотки тут выкидывать, чтобы показать миру как классно я живу.
❤4👏2🥰1
К лучшему или нет, но зима заканчивается, а рабочие обороты увеличиваются. Времени на посты становится меньше, но я приготовил кое-что прикольное.
Я купил себе как-то часы Mi Band 8 на смену своим пожилым Mi Band 2, доставшимся мне от жены. Хотелось просто добавить цвета с кастомными циферблатами к подсчету шагов и калорий. На них нашелся циферблат, который мне невероятно сильно понравился. От картинки чувствовался такой осенний, немного хеллоуинский вайб с примесью какой-то диснеевской сказки. Но был у них баг один, дни недели отставали на один. В понедельник показывали воскресенье.
У восьмой версии часов оказался какой-то совершенно непонятный алгоритм счета калорий, который насчитывал мне по сожженных 400 ккал пока я просто сижу за компом. Решил вернуть. Взял 7 версию, на которой старый алгоритм подсчета, меня это устроило, но того циферблата на них не было. Ну что ж, полез курить форумы.
Накурился и узнал такую вещь:
Файлы циферблатов идут в формате .bin, но по сути они открываются обычным ZIP-архиватором. А внутри...
🎉 JavaScript 🎉
Вы не ослышались, ребята! Внутри .json-файлы манифестов, куча ассетов в видео картинок и javascript-код.
Потому, смачно похрустев пальцами, я полез исправлять циферблат и пересобирать его для 7 версии Mi Band. Обратно всё собирается программой ZMake, точнее, адаптируются картинки под ZeppOS.
Такие вот дела.
#javascript #zeppos #miband
Я купил себе как-то часы Mi Band 8 на смену своим пожилым Mi Band 2, доставшимся мне от жены. Хотелось просто добавить цвета с кастомными циферблатами к подсчету шагов и калорий. На них нашелся циферблат, который мне невероятно сильно понравился. От картинки чувствовался такой осенний, немного хеллоуинский вайб с примесью какой-то диснеевской сказки. Но был у них баг один, дни недели отставали на один. В понедельник показывали воскресенье.
У восьмой версии часов оказался какой-то совершенно непонятный алгоритм счета калорий, который насчитывал мне по сожженных 400 ккал пока я просто сижу за компом. Решил вернуть. Взял 7 версию, на которой старый алгоритм подсчета, меня это устроило, но того циферблата на них не было. Ну что ж, полез курить форумы.
Накурился и узнал такую вещь:
Файлы циферблатов идут в формате .bin, но по сути они открываются обычным ZIP-архиватором. А внутри...
🎉 JavaScript 🎉
Вы не ослышались, ребята! Внутри .json-файлы манифестов, куча ассетов в видео картинок и javascript-код.
Потому, смачно похрустев пальцами, я полез исправлять циферблат и пересобирать его для 7 версии Mi Band. Обратно всё собирается программой ZMake, точнее, адаптируются картинки под ZeppOS.
Такие вот дела.
#javascript #zeppos #miband
🔥4
Про баланс работа-жизнь.
В 23 года мне ударила в голову идея, что мне кровь из носу нужно заработать гору бабок. В момент, когда мне пришло это осознание, я устроился на вторую работу и еще, когда успевал, на Авито чинил компы и чистил аквариумы.
Все последующие 10 лет, в ходе которых трансформировался мой профессиональный путь, я смотрел на жизнь, по большей части, через призму работы и количества зарабатываемых денег.
Так случилось, во-первых, потому что кроме работы я ничем не занимался, а, во-вторых, потому что интенсивность такой рабочей жизни свела на нет почти всё беззаботное дружеское взаимодействие и стало своеобразным фильтром общения, оставив меня наедине с моими амбициями.
К 30 годам я сделал что хотел, но очень быстро понял, что самый главный урок, который был упущен, заключался в том, что главное - это не конечная цель, а путешествие к ней. Положив весь свой праймтайм на работу, я только последние пару лет стал обращать внимание на смену сезонов. На то, как приятно чувствовать ослабевающую хватку зимы, и на то, с каким ожиданием я жду пожелтение листвы осенью. В 2024 году я ездил в Выборг посмотреть на осенний Монрепо, и мне очень жаль, что я не замечал всего этого раньше.
Всё хорошо в меру, ребятки.
#personal
В 23 года мне ударила в голову идея, что мне кровь из носу нужно заработать гору бабок. В момент, когда мне пришло это осознание, я устроился на вторую работу и еще, когда успевал, на Авито чинил компы и чистил аквариумы.
Все последующие 10 лет, в ходе которых трансформировался мой профессиональный путь, я смотрел на жизнь, по большей части, через призму работы и количества зарабатываемых денег.
Так случилось, во-первых, потому что кроме работы я ничем не занимался, а, во-вторых, потому что интенсивность такой рабочей жизни свела на нет почти всё беззаботное дружеское взаимодействие и стало своеобразным фильтром общения, оставив меня наедине с моими амбициями.
К 30 годам я сделал что хотел, но очень быстро понял, что самый главный урок, который был упущен, заключался в том, что главное - это не конечная цель, а путешествие к ней. Положив весь свой праймтайм на работу, я только последние пару лет стал обращать внимание на смену сезонов. На то, как приятно чувствовать ослабевающую хватку зимы, и на то, с каким ожиданием я жду пожелтение листвы осенью. В 2024 году я ездил в Выборг посмотреть на осенний Монрепо, и мне очень жаль, что я не замечал всего этого раньше.
Всё хорошо в меру, ребятки.
#personal
❤2
Я придумал аудиосообщения в телеграм
Когда я учился в 7-8 классе школы, я оооочень активно переписывался смсками. Тогда у Теле2 был классный тариф, в котором смски стоили то ли 5, то ли 10 копеек, что позволяло продолжительно чатиться.
Одни вечером я гостил у соседа, общался и пил чай. Телефон без конца вибрировал сообщениями, отвечая на которые можно было бы потратить кучу времени (все помнят клавиатуры с Т9?).
И мне тогда пришла в голову мысль, которую я озвучил вслух. Мне показалось, что было бы классно иметь возможность записать голос и отправить его как сообщение. Сосед посмотрел на меня как дебила и сказал: "Так просто позвони..."
И где мы сейчас находимся? 😲
Не знаю, как Паша выудил у меня из ума эту мысль, но жаль, что я не запатентовал ее тогда.
А лет 5 назад, кстати, я подумал о том, как меня достали проводные мышки, клавы и наушники. Как было бы круто сделать все беспроводным, но при этом не иметь необходимости это всё заряжать. Например, мышки и клавиатуры могли бы заряжаться от коврика (типа MagSafe). То есть, пока периферия на коврике - она заряжается, не надо пихать в нее никакие провода. В любой момент можно ее взять с коврика и работать уже от аккумулятора.
Подобным образом с наушниками. Представим, что на мониторе закреплен специальный крюк, на который они вешаются и начинают заряжаться.
Прикольно было увидеть, что идею с ковриком реализовали. Про наушники не знаю, но раз я об этом подумал, значит скоро появится. 😎
А вас посещали передовые идеи?
#telegram #wireless #idea
Когда я учился в 7-8 классе школы, я оооочень активно переписывался смсками. Тогда у Теле2 был классный тариф, в котором смски стоили то ли 5, то ли 10 копеек, что позволяло продолжительно чатиться.
Одни вечером я гостил у соседа, общался и пил чай. Телефон без конца вибрировал сообщениями, отвечая на которые можно было бы потратить кучу времени (все помнят клавиатуры с Т9?).
И мне тогда пришла в голову мысль, которую я озвучил вслух. Мне показалось, что было бы классно иметь возможность записать голос и отправить его как сообщение. Сосед посмотрел на меня как дебила и сказал: "Так просто позвони..."
И где мы сейчас находимся? 😲
Не знаю, как Паша выудил у меня из ума эту мысль, но жаль, что я не запатентовал ее тогда.
А лет 5 назад, кстати, я подумал о том, как меня достали проводные мышки, клавы и наушники. Как было бы круто сделать все беспроводным, но при этом не иметь необходимости это всё заряжать. Например, мышки и клавиатуры могли бы заряжаться от коврика (типа MagSafe). То есть, пока периферия на коврике - она заряжается, не надо пихать в нее никакие провода. В любой момент можно ее взять с коврика и работать уже от аккумулятора.
Подобным образом с наушниками. Представим, что на мониторе закреплен специальный крюк, на который они вешаются и начинают заряжаться.
Прикольно было увидеть, что идею с ковриком реализовали. Про наушники не знаю, но раз я об этом подумал, значит скоро появится. 😎
А вас посещали передовые идеи?
#telegram #wireless #idea
❤🔥1🔥1🤯1
Важность понимания сложности алгоритмов
Сейчас на проекте поддерживаем ужасное легаси, доставшееся от бывшего подрядчика. Баги валятся со всех сторон, а в контексте расширения бизнеса и появления новых требований к продукту зачастую валится и базовый функционал. На выходных столкнулись с хрестоматийной проблемой неэффективности алгоритма.
В какой-то момент стали поступать жалобы от пользователей на то, что приложение вылетает на андроид-устройствах. Сами устройства довольно старые: RFID-считыватели на Android 6 и Android 14. После диагностики поняли, что суть в том, что тупо кончается оперативная память и приложение падает. Сразу оговорюсь, что к падению приложения причастен был и ряд других проблем, но в рамках темы рассмотрим только алгоритм.
Суть: в приложении есть функционал выгрузки части базы данных на устройство для оффлайн работы. При выгрузке из БД (у нас couchdb 1.7.2 😢) тянется 130000 документов. Пару секунд приложение пыжится, потом ломается. Предлагаю рассмотреть изначальный код:
Как мы видим, внутри цикла forEach на каждой итерации вызывается filter, который проходит по тому же массиву. У нас квадратичная сложность вычисления O(n²).
Для тех, кто не в теме, приведу пример: представим, что у нас есть массив, в котором 1000 элементов. Проходя по нему одним циклом мы имеем линейную сложность вычисления O(n), потому что мы пройдем по всем элементам без исключения один раз. В данном случае n - количество элементов в массиве (1000). Количество операций равно количеству элементов.
А теперь представим, что проходя по одному элементу, мы вызываем еще один цикл, который проходится по тому же массиву (цикл в цикле). Сколько будет операций? На каждую операцию будет тоже O(n) вычислений. То есть, 1000 * 1000 = 1000000 операций. То есть, O(n * n) = O(n²).
Однако, если мы не будем вызывать цикл в цикле, а найдем способ вытащить один цикл из другого (а еще лучше, воспользуемся хеш-таблицами 😉), то наша сложность снова станет линейной. И вместо миллиона операций на массив мы вернемся к 1000, что является тысячекратным упрощением.
В общем, решили мы это так:
По сути, разбили одну операции на две, но в сумме своей они дают более эффективную работу. Мы в одном цикле проходимся по данным, делаем подсчет, к примеру, а потом в новом цикле уже с данными что-то делаем. В результате даже хиленький девайс на андроиде 6 справляется с повторяемой выгрузкой данных, ничего не падает, пользователи довольны. Конечно, скорее всего можно сделать это еще более эффективно, как мы знаем, предел редко виден в причесывании кода, но самое главное, что мы решили проблему.
#javascript #algo #android
Сейчас на проекте поддерживаем ужасное легаси, доставшееся от бывшего подрядчика. Баги валятся со всех сторон, а в контексте расширения бизнеса и появления новых требований к продукту зачастую валится и базовый функционал. На выходных столкнулись с хрестоматийной проблемой неэффективности алгоритма.
В какой-то момент стали поступать жалобы от пользователей на то, что приложение вылетает на андроид-устройствах. Сами устройства довольно старые: RFID-считыватели на Android 6 и Android 14. После диагностики поняли, что суть в том, что тупо кончается оперативная память и приложение падает. Сразу оговорюсь, что к падению приложения причастен был и ряд других проблем, но в рамках темы рассмотрим только алгоритм.
Суть: в приложении есть функционал выгрузки части базы данных на устройство для оффлайн работы. При выгрузке из БД (у нас couchdb 1.7.2 😢) тянется 130000 документов. Пару секунд приложение пыжится, потом ломается. Предлагаю рассмотреть изначальный код:
obj_arr.forEach(obj => {
if (obj.m_type === OT_BAG) {
obj.art_count = obj_arr
.filter(x => (x.m_type === OT_ART) && (x.container === obj.id))
.length;
}
});Как мы видим, внутри цикла forEach на каждой итерации вызывается filter, который проходит по тому же массиву. У нас квадратичная сложность вычисления O(n²).
Для тех, кто не в теме, приведу пример: представим, что у нас есть массив, в котором 1000 элементов. Проходя по нему одним циклом мы имеем линейную сложность вычисления O(n), потому что мы пройдем по всем элементам без исключения один раз. В данном случае n - количество элементов в массиве (1000). Количество операций равно количеству элементов.
А теперь представим, что проходя по одному элементу, мы вызываем еще один цикл, который проходится по тому же массиву (цикл в цикле). Сколько будет операций? На каждую операцию будет тоже O(n) вычислений. То есть, 1000 * 1000 = 1000000 операций. То есть, O(n * n) = O(n²).
Однако, если мы не будем вызывать цикл в цикле, а найдем способ вытащить один цикл из другого (а еще лучше, воспользуемся хеш-таблицами 😉), то наша сложность снова станет линейной. И вместо миллиона операций на массив мы вернемся к 1000, что является тысячекратным упрощением.
В общем, решили мы это так:
let bag_art_count = {};
rows.forEach(r => {
const value = r.value || {};
if (value.m_type === OT_ART && value.container) {
bag_art_count[value.container] =
(bag_art_count[value.container] || 0) + 1;
}
});
let obj_arr = rows.map(r => {
const obj = Object.assign(
{ _id: r.value.tag.substr(0, 24), id: r.id },
r.value
);
if (obj.m_type === OT_BAG) {
obj.art_count = bag_art_count[obj.id] || 0;
obj.is_suited = (obj.art_count === 0);
}
return obj;
});По сути, разбили одну операции на две, но в сумме своей они дают более эффективную работу. Мы в одном цикле проходимся по данным, делаем подсчет, к примеру, а потом в новом цикле уже с данными что-то делаем. В результате даже хиленький девайс на андроиде 6 справляется с повторяемой выгрузкой данных, ничего не падает, пользователи довольны. Конечно, скорее всего можно сделать это еще более эффективно, как мы знаем, предел редко виден в причесывании кода, но самое главное, что мы решили проблему.
#javascript #algo #android
🔥3❤1
У нас довольно непростая история с доступами во внешнюю сеть на работе. Если еще в рамках ежедневной работы что-то можно погуглить, но если нужно посветить виртуалкой в инет для простоты работы, то тут начинаются разнообразные этапы согласований, которые могут отнять время и желание вообще что-либо делать.
Очередная такая ситуация возникла, когда мы запустили виртуальную машину, чтобы развернуть на ней копию прода для тестов. У нас очень много чего завязано на SSL-сертификатах, но в нашей ситуации получать домен и светить айпишником в инет не было реализуемым вариантом. Я до этого с подобным не сталкивался, потому начал думать, как решить, чем сейчас и поделюсь.
Если кратко, то мы выпустили самописный сертификат на айпи адрес в локальной сети. По сути, работает точно так же, как сертификат от Let's Encrypt. Отличие лишь в том, что нужно вручную устанавливать этот сертификат в операционную систему. Вот процедура:
1) Создаем чистую папку для работы, чтобы не запутаться в файлах.
2) Создаем «Главный ключ» и «Главный сертификат». Этим сертификатом мы будем подписывать все остальные.
Итог: Появятся
3) Создается файл настройки с расширением .conf примерно такого содержания:
В
4) Генерим ключ сервера и запрос на подпись:
Появятся файлы
5) Подписываем запрос нашим корневым сертификатом:
Появится
6) На этом этапе я добавил созданные сертификаты
По сути с сертификатами всё. Теперь просто берем
#ssl #dev #debian
Очередная такая ситуация возникла, когда мы запустили виртуальную машину, чтобы развернуть на ней копию прода для тестов. У нас очень много чего завязано на SSL-сертификатах, но в нашей ситуации получать домен и светить айпишником в инет не было реализуемым вариантом. Я до этого с подобным не сталкивался, потому начал думать, как решить, чем сейчас и поделюсь.
Если кратко, то мы выпустили самописный сертификат на айпи адрес в локальной сети. По сути, работает точно так же, как сертификат от Let's Encrypt. Отличие лишь в том, что нужно вручную устанавливать этот сертификат в операционную систему. Вот процедура:
1) Создаем чистую папку для работы, чтобы не запутаться в файлах.
mkdir -p /root/certs
cd /root/certs
2) Создаем «Главный ключ» и «Главный сертификат». Этим сертификатом мы будем подписывать все остальные.
openssl genrsa -aes256 -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt
Итог: Появятся
rootCA.key (секретный, никому не давать) и rootCA.crt (публичный, его будем ставить на устройства, которые будут ходить на наш сервер).3) Создается файл настройки с расширением .conf примерно такого содержания:
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_req
[req_distinguished_name]
C = RU
ST = Moscow
L = Moscow
O = CompanyGroup
CN = 101.148.223.60
[req_ext]
subjectAltName = @alt_names
[v3_req]
subjectAltName = @alt_names
[alt_names]
# List all DNS names and IPs here
DNS.1 = app.mycompany.ru
IP.1 = 101.148.223.60
IP.2 = 190.118.127.12
IP.3 = 127.0.0.1
В
[alt_names] мы прописываем адреса, по которым будем ходить на сервер, для которого выпускается сертификат. Нас интересует IP.1 - адрес сервера в локальной сети.4) Генерим ключ сервера и запрос на подпись:
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/server.key \
-out /etc/nginx/ssl/server.crt \
-config cert_config.cnf
Появятся файлы
server.key (секретный ключ) и server.csr (запрос).5) Подписываем запрос нашим корневым сертификатом:
openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial \
-out server.crt -days 3650 -sha256 -extfile server.conf -extensions req_ext
Появится
server.crt.6) На этом этапе я добавил созданные сертификаты
server.crt и server.key в nginx и перезапустил службу.По сути с сертификатами всё. Теперь просто берем
rootCA.crt и устанавливаем его на устройства, с которых планируется работа с сервером. Я устанавливал на Android и на Windows 11. #ssl #dev #debian
👏3🔥2❤🔥1💯1
Сегодня расскажу про проброс портов в VScode. Удобная фишка, когда разрабатываешь сайт и его нужно показать кому-то. Позволяет не делать никакой деплой, все делается в рамках среды разработки.
Через сервера Microsoft Azure делается туннель, который ведет на вашу машину и ваша разработка становится доступны из внешней сети.
Делается просто:
Например, допустим, у нас просто вёрстка HTML-файлов с помощью встроенного Live Server на порту 5500.
В VScode в терминале жмем Порты. Если терминал закрыт, можно открыть с помощью
Жмем Перенаправить порт. Вводим порт 5500. Расширение попросит залогиниться - делаем.
После того, как служба отработает, вы увидите ссылку на вашу разработку, которой можно делиться.
Видимость проброса может быть частной и общедоступной. Частная - каждый, кто заходит, должен будет проходить авторизацию, а общедоступный - ссылка напрямую проксирует на вашу машину, потому держим в уме безопасность.
На скринах можно посмотреть как это все выглядит.
#vscode #portforwarding
Через сервера Microsoft Azure делается туннель, который ведет на вашу машину и ваша разработка становится доступны из внешней сети.
Делается просто:
Например, допустим, у нас просто вёрстка HTML-файлов с помощью встроенного Live Server на порту 5500.
В VScode в терминале жмем Порты. Если терминал закрыт, можно открыть с помощью
Ctrl + `, либо Вид - Терминал.Жмем Перенаправить порт. Вводим порт 5500. Расширение попросит залогиниться - делаем.
После того, как служба отработает, вы увидите ссылку на вашу разработку, которой можно делиться.
Видимость проброса может быть частной и общедоступной. Частная - каждый, кто заходит, должен будет проходить авторизацию, а общедоступный - ссылка напрямую проксирует на вашу машину, потому держим в уме безопасность.
На скринах можно посмотреть как это все выглядит.
#vscode #portforwarding
❤2
Когда я был молод, 10 лет назад, я уехал работать преподом английского в Таиланд. Такой поворот судьбы стал результатом хронической усталости от работы, на которой количество получаемого не совпадает с количеством отданного. То был, пожалуй, один из первых важных уроков, предоставленных мне жизнью.
Урок заключался в том, что изменения, которые мы ждем увидеть, находятся гораздо ближе, чем нам кажется, и вся сложность лишь в том, чтобы договориться с самим с собой оставить проигрышные условия и начать заново. В своем отчаянии я бросился в гугл искать все частные школы Таиланда и закидывать их имейлами со своим резюме. Через месяц я нашел школу. Через 2 месяца я уже был там. Настолько сильно я хотел поменять что-то, лишь бы было не так, как сейчас.
Из Таиланда я вернулся полным решимости вносить изменения дальше и, как только получил диплом, собрал вещи и уехал в Москву, откуда начался весь мой профессиональный рост.
#personal #thailand
Урок заключался в том, что изменения, которые мы ждем увидеть, находятся гораздо ближе, чем нам кажется, и вся сложность лишь в том, чтобы договориться с самим с собой оставить проигрышные условия и начать заново. В своем отчаянии я бросился в гугл искать все частные школы Таиланда и закидывать их имейлами со своим резюме. Через месяц я нашел школу. Через 2 месяца я уже был там. Настолько сильно я хотел поменять что-то, лишь бы было не так, как сейчас.
Из Таиланда я вернулся полным решимости вносить изменения дальше и, как только получил диплом, собрал вещи и уехал в Москву, откуда начался весь мой профессиональный рост.
#personal #thailand
❤3