Что общего между психологом и программистом?
Добра добрым людям! Вот и я открыл своё цифровое представительство на Пикабу.
На пятом десятке захотелось поучаствовать в информационном воздействии на умы соплеменников. В ожидании собственных мыслей, достойных этих страниц, решил рассказать вам в этой серии постов несколько невыдуманных историй из психотерапевтической практики хранительницы моего очага. Эти истории могут кого-то просто развлечь своими удивительными сюжетами, а кого-то - побудят обратить внимание на работу человеческой психики в целом и своей в частности. В последнем случае гуглите ресурсы хорошего психолога по названию этой серии постов:)
Но для начала будет введение в психологию. Сам я, будучи немного инженером и программистом, раньше вообще не понимал, что делают эти психологи. Но однажды в попытке понять своим инженерным мозгом суть их работы я испытал озарение. И с тех пор легко перевожу их птичий язык и образы на правоверные инженерные конструкции, алгоритмы и схемы.
В среде программистов ситуацию, когда программа работает не так, как нужно, называют иноземным словом «баг» (bug - жук). А процесс поиска причины и устранения бага называют дебаггингом (debugging). Наши отечественные программисты, не забывшие ещё русский язык, зовут этот процесс отладкой. Сегодня это ладное слово почти ушло из бытовой речи, но ещё присутствует в словаре технарей. Для отладки программа запускается под управлением отладчика – другой специально обученной программы. Отладчик позволяет пошагово следить за исполнением кода программы, наблюдая за изменением данных в памяти. Таким образом вплоть до строки локализуется участок исходного кода, вызывающий ошибку, в результате чего хорошему программисту становится ясна её причина. Тогда проблемный код переписывается и баг устраняется.
Так вот у психологов всё то же самое. Наша психика, как и компьютерная программа – это прежде всего алгоритмика – последовательность шагов преобразования информации. Всю жизнь мы пишем исходный код нашей психики. И как любой разрастающийся код наша психика наполняется самыми разнообразными багами.
Зачастую мы неосознанно загружаем в свою психику чужие алгоритмы поведения, подобно программисту, копирующему куски чужого исходного кода, не особо задумываясь о его работоспособности и безопасности. Иногда на фоне таких сильных эмоций, как страх, экстренно бессознательно прописываем не самые оптимальные поведенческие программы, подобно разработчику, который в режиме ошпаренной кошки придумывает костыли для работы программы в непредвиденных условиях в последний момент сдачи проекта заказчику. Бывает, запутываемся в хитросплетениях алгоритмов собственной психики, бесполезно тратя энергию на бесконечное прокручивание каких-то мыслей, подобно неопытному программисту, не предусмотревшему выход из бесконечного цикла и нагрузившему процессор до невозможности программы реагировать на действия пользователя.
И вот однажды становится невозможно не замечать неадекватность в определённых условиях результатов работы нашей психики нашим же целям и желаниям. Это мы обнаруживаем у себя душевный баг - психологическую проблему. Как и программисту, который копипастил код или писал его давным-давно, будучи ещё джуном, осознать истинные причины душевных багов непросто. Здесь нужна та самая отладка, воспроизведение бага в контролируемой среде, запуск и исследование алгоритмов обработки чувств, эмоций, мыслей, образов, ощущений в теле для локализации проблемного фрагмента психики и последующего его переписывания – нужна Отладка души. Как вы догадались, отладчиком здесь выступает сознание психолога. Да, теоретически отладчик может быть запущен и в нашем сознании (об этом стоит как-нибудь поговорить подробнее). Но обычно среднестатистическое сознание при воспроизведении забаженных программ бессознательных уровней психики жёстко подвисает и не способно что-либо замечать самостоятельно.
Будьте в ладу с собой и миром! Не допускайте жуков в свою психику и программы.
AI Assistant сглаживает ошибки в лабиринте кода
Программы, приложения и веб-сайты создаются с использованием кода, который сообщает компьютеру, телефону или другому устройству, что и как делать. На самом деле создание такого кода — сложный и сложный процесс, в котором даже малейшая ошибка может привести к сбою всей платформы.
Найти ошибку в строках букв и цифр может быть еще сложнее и отнимать чрезвычайно много времени. На самом деле разработчики программного обеспечения могут тратить до 50 процентов своего рабочего времени на тестирование и отладку кода, согласно авторитетному отраслевому журналу ACM Queue.
Но теперь израильская компания разработала “члена команды” с искусственным интеллектом для тестирования и проверки кода, чтобы убедиться, что все работает должным образом, устраняя любые потенциально катастрофические ошибки.
Соучредитель и генеральный директор Codium Итамар Фридман рассказывает NoCamels, что стартап решил использовать подход “снизу вверх” и прочесать существующий код, чтобы найти ошибку, а не заклеивать какие–либо трещины - то, что стало слишком распространенным явлением, поскольку программисты работают в сжатые сроки и под большим давлением.
Фридман говорит, что Codium подключается к коду, чтобы увидеть, откуда взялась проблема.
“Мы сосредоточены на устранении ошибок и неполадок; мы сосредоточены на тестировании кода”, - объясняет он. “В то время как большинство помощников по программированию пытаются подтолкнуть вас к написанию большего количества строк кода и замене ваших строк кода, мы здесь для того, чтобы расширить ваши возможности и убедиться, что ваши строки кода действительно работают так, как ожидалось”.
Разработчики могут тратить до 50 процентов своего рабочего времени на тестирование и отладку кода (Unsplash).
Фридман и соучредитель Codium и исполнительный директор Деди Кредо считали, что использование искусственного интеллекта в качестве члена команды, способного тестировать и отлаживать код, имеет решающее значение как для поддержки разработчиков, так и для продвижения программирования в будущее.
Они достигли этого с помощью двух разных плагинов искусственного интеллекта (загружаемых расширений к программе), каждый из которых выполняет ряд различных, но жизненно важных задач.
Первый из двух - это Codiumate, плагин для интегрированной среды разработки, своего рода цифровой набор инструментов, содержащий множество функций в помощь разработчикам, таких как отладка, учебные пособия и даже проверка орфографии.
Codiumate может выполнять несколько простых команд для существующего кода, например, запускать его новый тест, улучшать его и даже переписывать, чтобы удалить любые ошибки.
Он также может выполнять более сложные задачи, такие как сканирование кода без его запуска, чтобы сообщить разработчикам, как он будет себя вести. И, по словам Фридмана, это дает разработчику простое и понятное объяснение того, как работает программное обеспечение.
“Вы получаете описание на естественном языке того, что должно делать ваше программное обеспечение, которое легче читать – даже разработчику, а затем вы можете сгенерировать тест для этого”, - говорит он.
Второй из плагинов имеет дело с pull–запросами - когда разработчик готов интегрировать новый код в уже существующую систему и просит сначала проверить его на наличие каких-либо ошибок.
Плагин PR-агента Codium с открытым исходным кодом предназначен для помощи с запросами на получение информации – ознакомления с кодом, его тестирования и обобщения, чтобы обозначить возможные проблемы, которые могут возникнуть.
Codium использует искусственный интеллект в качестве “члена команды”, который может тестировать и отлаживать код (Courtesy)
Основываясь на потребностях каждого клиента, плагин может включать более обширное тестирование для выработки рекомендаций о том, как улучшить код и устранить потенциальные ошибки.
“Мы не говорим о 100-процентном охвате кода в качестве нашего видения. Мы говорим о нулевом количестве ошибок”, - объясняет Фридман.
Все предложения, сделанные ИИ, остаются на усмотрение разработчиков. Платформа, подчеркивает Фридман, автоматически не изменяет и не переписывает ничего.
Высокопоставленный чиновник OpenAI был среди инвесторов компании, которая была основана в 2022 году. Другое финансирование поступило от израильской венчурной компании TLV Partners, нью-йоркской Vine Ventures VCи глобального фонда MyVentures, которые инвестируют в стартапы на ранних стадиях.
В начале 2023 года компания объявила, что привлекла 11 миллионов долларов начального финансирования.
Менее чем через два года после своего создания плагины Codium уже установили более полумиллиона разработчиков по всему миру, и более 1000 команд уже используют лицензионную программу, которая позволяет им сотрудничать в режиме реального времени.
Компания из Тель-Авива недавно получила похвалу за свою исследовательскую работу, в которой описывается, как ИИ может быть интегрирован в процесс генерации кода. Этот всеобъемлющий подход называется AlphaCodium, в честь инструмента для кодирования ИИ с открытым исходным кодом AlphaCode.
“AlphaCodium использует лучшие практики разработчиков в области разработки программного обеспечения и превращает их в искусственный интеллект, способный воспроизвести это”, - говорит Фридман.
Среди тех, кто высоко оценил работу, был Андрей Карпати, один из соучредителей OpenAI и бывший директор по искусственному интеллекту в Tesla.
Оригинал здесь
Для Фридмана будущее – продолжать создавать инструменты, которые облегчили бы жизнь разработчикам, а это означает дальнейшую интеграцию искусственного интеллекта.
“ИИ будет не только дополнять код, вместо этого ИИ может расширить возможности разработки программного обеспечения”, - говорит он.
“Это произойдет и охватит весь жизненный цикл разработки программного обеспечения”.
Перевод с английского
Песня "Отладчик". Кавер на "Кукушку" Цоя
Небольшая предыстория.
Поиском ошибок программисты занимаются часто. И зачастую находят именно свои ошибки. В одном из таких поисков у меня и засела в голове фраза "Ошибка моя взгляни на меня". Да так засела, что спустя месяц трансформировалась в целый припев по мотивам известной песни "Кукушка" Цоя.
Дальше захотелось написать текст всей песни о том как программисты ищут ошибки. Спустя неделю текст был готов. Что дальше? У меня полностью отсутствуют музыкальные способности. Я попросил помощи в одном из сообществ программистов 1С. Откликнулось 3 человека, которые попросили посмотреть текст. И один из них довел дело до конца. Он нашел участницу шоу Голос и вместе они положили текст на музыку.
Получилось очень круто и я не могу не поделиться этим с вами.
Текст мой, музыка Цоя, исполняет Ника Нова
https://drive.google.com/file/d/1PuNgO6dZsp6vGf1ouPYH6anxSGH...
Если нужен текст - напишу в комментариях.
Проверяем работу протоколов и шифров вашего сервера
Если кто-то из читателей данного поста занимается настройкой и отладкой tcp/ip стека, вам может быть полезен данный скрипт, который позволяет проверить службу сервера на любом порту на предмет поддержки шифров, протоколов TLS/SSL, а также выявить какие-то дефолтные проблемы. В Readme подробно все описано, комментарии излишне :)
https://github.com/drwetter/testssl.sh
Как находить и исправлять ошибки
Оригинал: How to debug by Phil Booth
Как инженеры, мы проводим много времени за отладкой проблем, однако этому редко учат, как самостоятельному навыку. Некоторые ошибки настолько сложны, что их решение может показаться практически невозможным, особенно для разработчиков без опыта. Нет худшего чувства, чем застрять на сложной проблеме, не зная, как действовать дальше. Конечно, самое правильное, что нужно сделать, если вы застряли — это попросить помощи: у своей команды, у других инженеров в вашей организации или в вашем кругу общения, у случайных незнакомцев в интернете. Как случайный незнакомец в интернете, этот пост — моя попытка помочь вам выбраться из тупика, если вы оказались в подобной ситуации.
На самом деле это началось с моей попытки написать пост типа “чему я научился за 25 лет работы инженером”, как некоторые другие, которые я видел в последнее время. Но оказалось, что я больше склоняюсь к конкретным, практическим советам, чем к глубокой, философской мудрости. 🤷
Пост написан в виде упорядоченного списка, но не каждая проблема требует выполнения всех шагов. Иногда правильное решение приходит в голову само собой на шаге 1 или, что еще лучше, на шаге 0! В других случаях вы можете пропустить несколько шагов или выполнить их в другом порядке. Но в целом, порядок, приведенный здесь, это основа, на которую я постепенно перешел со времени моей первой работы над модулем обработки ресурсов для контроллера базовой станции GSM в компании Lucent Technologies в 1997 году. За прошедшие годы я работал во многих различных средах: системное программирование, базы данных, настольные приложения, веб-приложения, backend и frontend. Эти шаги обобщены и применимы ко всем этим средам, они не являются специфическими для какого-то конкретного языка или парадигмы.
0. Ваше психическое состояние
Самые сложные проблемы часто возникают в моменты наибольшего напряжения. Что-то сломалось на продакшене и платящие клиенты жалуются на это. Возможно, они требуют возврата денег. Ваш начальник хочет знать, когда вы это пофиксите, а вы еще даже не знаете, в чем дело.
Если все это происходит, вы, вероятно, находитесь в состоянии стресса, а стресс заставит вас решать проблему медленнее, а не быстрее. Поэтому, прежде чем перейти к очевидному шагу 1, нам нужно сначала позаботиться о шаге 0. Убедитесь, что вы находитесь в хорошем расположении духа. Постарайтесь расслабиться, будьте спокойны. Ваш продакшен может не работать в течение часа, но это лучше, чем если бы он простоял много часов из-за того, что вы поспешно предприняли неправильные действия.
Не менее важно быть уверенным и оптимистичным в своих взглядах. Программирование — это не волшебство, системы следуют правилам, даже если эти правила загадочны и неизвестны нам. У каждой проблемы есть рациональная причина и решение, которые вы найдете со временем. Поэтому будьте настойчивы, не сдавайтесь.
Наконец, будьте честны с собой в отношении проблемы. Не обманывайте себя в том, что вы знаете, что что-то является правдой, если это всего лишь предположение. Проверяйте эти предположения, потому что они часто удивляют вас. Это нормально, что вы не всегда понимаете все части проблемы, если только вы признаете те части, которые вам пока непонятны. Держите их в уме, но отделяйте и возвращайтесь к ним позже. Разделяй и властвуй.
1. Воспроизведите проблему
Воспроизведение проблемы кажется настолько очевидным первым шагом, что почти не заслуживает упоминания. Это должен быть первый шаг каждого, но я часто удивлялся в разговоре с инженерами, когда спрашивал, воспроизвели ли они проблему самостоятельно.
Недостаточно работать на основе чужого описания ошибки или того, что вы думаете о проблеме. Помните, что вам нужно проверять свои предположения, и нет более важного предположения, чем то, существует ли проблема в том виде, в котором она описана, или какие шаги нужно предпринять, чтобы ее решить. Сначала докажите, что вы правильно их понимаете.
На моей второй работе в компании Transoft я работал над текстовым редактором и получил отчет об ошибке от команды контроля качества о “бесконечном цикле” при нажатии правой кнопки мыши для вызова контекстного меню. Я не мог воспроизвести это, поэтому попросил их показать мне. Оказалось, что “бесконечный цикл” возникал, когда они щелкали правой кнопкой мыши в другой области экрана и ожидали, что это приведет к закрытию меню. Но программа работала как положено, закрывая первоначальное меню и открывая новое в новом месте щелчка. Таким образом, “ошибка” на самом деле была просто ошибкой в ожиданиях.
2. Воспроизведите ее снова
Отлично, вы воспроизвели проблему. Но действительно ли это так или это было просто совпадение? Ошибки иногда могут быть продуктом многих взаимосвязанных факторов, и если у вас есть только одна точка отсчета, вы не можете быть уверены, что понимаете основную причину (причины).
Повторное воспроизведение может исключить возможность того, что в первый раз вы допустили глупые ошибки, и повысить уверенность в том, что вы на правильном пути. Уверенность, если она подкреплена честностью, — ваш лучший друг в этом процессе. Но уверенность — это нежный цветок, и вы должны защищать его любой ценой. Не позволяйте ничему растоптать вашу уверенность.
3. Не воспроизводите ее
Если вы знаете, как воспроизвести проблему, знаете ли вы также, как ее не воспроизводить? Иными словами, знаете ли вы, какие переменные играют важную роль в определении возникновения проблемы?
Экспериментируйте с этими переменными, изменяйте их и доказывайте их значимость. Это может привести к сокращению шагов по воспроизведению, что абсолютно необходимо сделать на данном этапе. Недостаточно того, что вы можете надежно воспроизвести проблему, вы хотите изолировать ее до наименьшего количества шагов или наименьшего количества данных.
4. Поймите код
Теперь вы находитесь на том этапе, когда можно посмотреть на код и попытаться понять, что не так, потому что теперь вы действительно понимаете суть проблемы.
Примените свои знания о действующих переменных к системе, которая находится перед вами. Какой код управляет этими переменными? Как они взаимодействуют? Если есть код, который вы не понимаете, попробуйте найти человека или команду, которые над ним работали. Они смогут сократить ваш путь к просветлению и, возможно, даже уже сталкивались с проблемами, подобными вашей.
Иногда код поступает из непрозрачных сторонних источников. Если у вас нет доступа к этим источникам, у вас все равно есть пути для расследования. Прочитайте справку по API или другую документацию, поищите в базе данных ошибок, если таковая имеется. Есть ли соответствующие вопросы на Stackoverflow или в других местах?
В начале 2000-х годов я работал над прикладным фреймворком, который был бинарником для Internet Explorer 6. Это означало использование ряда API IE и Windows, которые имели скудную документацию. Всякий раз, когда реальность не совпадала с нашими ожиданиям от этих API, мы прибегали к поиску ответа в Usenet или на других онлайн-форумах. Чаще всего, когда мы в конце концов находили правильный ответ, его размещал таинственный гений с именем “Игорь Тандетник”. Прошло немного времени, прежде чем мы начали по умолчанию добавлять ко всем нашим поисковым запросам “Игорь Тандетник”. В качестве ускорителя отладки это полностью оправдало себя.
5. Наблюдайте за состоянием
После рассуждений о коде в его статической форме, посмотрите на динамическое состояние памяти в момент возникновения проблемы (до, во время и после).
Как вы это сделаете, зависит от вас. В начале своей карьеры я предпочитал использовать отладчик, но в наши дни я чаще всего просто вывожу значения на консоль. Отладчик — это здорово, но для определенных классов проблем (например, параллелизм, события пользовательского интерфейса) они представляют собой наблюдение как взаимодействие; попадание в точку останова может само по себе изменить условия кода, который вы пытаетесь отладить. Ведение журнала может быть более надежным отладчиком в таких условиях. И наоборот, чтение логов быстро надоедает, если ваш проект медленно компилируется. Выбирайте то, что лучше всего подходит для конкретных условий.
Логи также помогут вам на этом этапе, не забывайте обращаться к ним. В идеале ваши логи структурированы и доступны для поиска, поэтому вы можете легко устранить шум, используя соответствующие условия запроса. Если вы не знакомы с инфраструктурой ведения производственных журналов, найдите кого-нибудь, кто знаком с ней, и попросите их ввести вас в курс дела.
Какой бы метод вы ни использовали, есть два типа состояний, которые вас интересуют: пути, по которым следует код, и сохраненные значения. Обязательно посмотрите и то, и другое.
6. Запишите то, что вы (как вам кажется) знаете
Записывание информации на бумаге или в электронном виде может быть удивительно эффективным методом анализа. Он работает на два фронта: заставляет вас активно обдумывать то, о чем вы пишете, а затем служит в качестве памятки при просмотре информации в ваших заметках.
Постарайтесь не поддаваться искушению преждевременно найти решение в этих заметках. Если преждевременная оптимизация — корень всех зол (или, по крайней мере, большинства из них), то преждевременная разработка решений — корень всех неправильно диагностированных ошибок (или, по крайней мере, большинства из них). Сосредоточение внимания только на тех вещах, которые, по вашим наблюдениям, являются безусловно верными, поможет держать под контролем ваши предположения и предубеждения.
Заставляйте себя делать записи, как только вы начинаете исследовать проблему, даже если кажется, что она может быть тривиальной. В худшем случае вы сможете выбросить их, если они не пригодятся. Также может быть полезно записывать их в публичном месте, чтобы другие люди могли воспользоваться тем, что вы узнали, и, возможно, внести свои предложения по проблеме, над которой вы работаете. Прозрачность — это суперсила.
Всякий раз, когда я отлаживаю продакшн-инциденты или просто выполняю рутинное обслуживание прод-инфраструктуры, я начинаю новую тему в Slack в нашем канале #devops и веду там оперативные записи. По крайней мере, эти темы служат публичной записью всего, что я делал или наблюдал, с привязкой к временной метке. В дальнейшем, инженеры могут найти их с помощью поиска и вернуться к ним, если подобные сценарии возникнут снова. Но не раз они также служили толчком для полезного обсуждения того, над чем я работаю. Благодаря этим тредам мы быстрее устраняли проблемы.
7. Исключите некоторые вещи
Иногда полезно удалить куски кода, чтобы доказать, что они не связаны (или нет). Это можно сделать по двум направлениям: по времени и по функциям.
Временной подход означает использование контроля исходного кода для постепенного определения набора изменений, в который была внесена ошибка. Если вы используете git, то git bisect существует именно для этой цели. Это отличное оружие в вашем арсенале, и вам следует ознакомиться с ним, если вы еще не знакомы с ним.
Feature-based означает посмотреть на код и физически удалить его части самостоятельно. Удалите его, закомментируйте, используйте условную компиляцию, что угодно. Это проверка ваших предположений. Убедитесь, что вы делаете маленькие шаги, следуя этому подходу. Слишком легко изменить множество вещей одним махом и потом не знать, какая из них отвечает за наблюдаемые эффекты.
8. Погуляйте с собакой
Если вы слишком долго концентрируетесь на одной и той же проблеме, ваш мозг “затуманивается”, и вы становитесь менее эффективным. В этот момент лучше всего пойти погулять, но часто бывает трудно понять, когда для этого настало время. Старайтесь сознательно анализировать свою работу всякий раз, когда вы отходите от рабочего места. Будьте честны в своей оценке.
Мне повезло, что у меня есть собака Майло, которая заставляет меня прекращать работу через регулярные промежутки времени, чтобы мы могли поиграть или погулять. Эти прогулки иногда являются самой продуктивной частью моего дня, количество случаев, когда во время прогулки приходит свежая идея, просто поразительно. (Самое главное, чтобы вам никто не мешал думать, когда вы гуляете :)) Если это не полное решение, то это может быть какая-то его часть или теория, которая продвигает меня на шаг ближе.
Дело в том, что ваш мозг не перестает работать над проблемой только потому, что вы перестали активно думать о ней. Он все еще там, работает в фоновом режиме. Дайте ему немного передышки, чтобы сделать свое дело.
9. Перепишите компонент
Хотя переписывание целых систем редко бывает хорошей идеей, переписывание небольших фрагментов функциональности может быть эффективным способом выявить факторы, которые часто могут быть скрыты от глаз. Иногда вы можете смотреть на код целую вечность, и он выглядит прекрасно, но как только вы попытаетесь переделать его на свой лад, вы столкнетесь с костылями, на которые пришлось пойти автору. Эти костыли — отличный источник моментов “ага!” для отладки.
Важно отметить, что вы не стремитесь заменить код, который вы переписываете. План состоит в том, чтобы отбросить ваш код после того, как он выполнит свою работу, которая заключается исключительно в том, чтобы помочь вам понять. Иногда вам может повезти, и вы обнаружите, что исправление вашей ошибки скрывается в коде “замены”, но лучше не ставить перед собой такую цель, так как это может отвлечь вас от реальной задачи.
10. Напишите неудачный тест
Если и есть одно замечание, которое бросают мне чаще других, как в качестве комплимента, так и в качестве критики, так это то, что я пишу много тестов (для некоторых людей слишком много). Но есть один вид тестов, в котором я абсолютно не иду на компромисс, и это регрессионные тесты. Они подобны технологическому антидолгу, сложным процентам, которые выплачивают все большие суммы по мере накопления их в вашем проекте.
Каждый раз, когда вы исправляете баг, вы должны добавлять как минимум один новый тест в ваш набор регрессионных тестов. То, что в программных проектах идет не так один раз, часто идет не так и во второй раз. Молния бьет дважды. Самый простой способ справиться с этим — писать регрессионные тесты по ходу работы. А самый простой способ убедиться в том, что ваши регрессионные тесты действительно работают, — это написать сначала неудачный тестовый пример, прежде чем приступить к его исправлению.
Написание подобных тестов также является хорошим способом убедить любых специалистов, не склонных к тестированию, внести свой вклад в тестируемый код. Им будет гораздо труднее отказаться по причине нехватки времени или усилий, если вы попросите всего один тест в их PR. Дюйм за дюймом вы сможете подтолкнуть их в направлении лучших привычек.
11. Исправь это
В конце концов, вы поймете проблему настолько хорошо, что один или несколько способов ее решения откроются вам. Если вы в глубине души знаете, в чем заключается единственное верное решение, то можете смело использовать его, и никаких проблем. Но в других случаях дальнейший путь будет менее ясен, и в таких случаях вам следует проявлять инициативу, собирая больше мнений. Не думайте о неуверенности как о признаке слабости; напротив, ваша готовность обсуждать ее — признак силы. И все эти обсуждения будут направлены на устранение будущих ошибок, делая вас более сильными для решения проблем, которые ждут вас впереди.







