Обновить
1077.98

Программирование *

Искусство создания компьютерных программ

Сначала показывать
Порог рейтинга

MTS AI выпустила Kodify 2 — второе поколение ИИ-ассистента для разработчиков:

  • 7 млрд параметров, 

  • контекст до 32 тыс. токенов, 

  • поддержка 90 языков программирования,

  • OpenAI-совместимый API для простой интеграции с другими системами. 

В отличие от первого поколения Kodify, использующегося c 2024 года лишь в компаниях, входящих в ПАО «МТС», Kodify 2 станет доступен внешним заказчикам.

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

Подробнее на сайте разработчика. Демо на Java и Python здесь.

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии4

Нормальный ли у меня код?

Разработчики часто задаются таким вопросом. Давайте подумаем, как оценить "нормальность" кода. На мой взгляд, важны следующие аспекты:

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

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

Быстрый по скорости и компактный по данным. Другими словами, код должен быть нормальной вычислительной и пространственной сложности. Тут помогают и интуитивные представления (что-то тормозит), и теория вычислительной сложности (О-нотация). Если вы сортируете записи за O(n^3) и требуете O(n^5) оперативной памяти, то вы делаете что-то не так.

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

Если, конечно, не горят сроки

Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии1

Определение переменных и вызов функций в Rust

Взглянем на код:

fn main() {
	let a = 10;
	let b: i32 = 20;
	let c = 30i32;
	let d = 30_i32;
	let e = add(add(a, b), add(c, d));

	println!("(a + b) + (c + d) = {}", e);
}

fn add(i: i32, j: i32) -> i32 {
	i + j;
}

Определение функции начинается с ключевого слова fn. Точка входа в Rust-программы - это функция main. Она не получает никаких аргументов и не возвращает никаких значений.

В следующих строках let используется для привязки переменной. По умолчанию переменные неизменяемые, то есть предназначены только для чтения, а не для чтения-записи.

Также можно указывать конкретный тип данных разными способами:

  1. Через двоеточие

  2. Числовые литералы могут включать аннотации типов

В последней строке вызывается макрос println! для вывода текста.

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

И наконец, функция add имеет аргументы с указанными типами данных и возвращает нужный тип данных. Как вы видите, возврат значения происходит автоматически, для этого не используются ключевые слова по типу return.

Поговорим о создании переменных. В Rust они бывают мутабельными (mutable) или немутабельными (unmutable), то есть изменяемые и неизменяемые. Неизменяемые переменные можно сравнить с константами.

Разберем пример:

fn main() {
	let a = 10;
	a = 15;
}

Если мы скомпилируем данную программу, то получим ошибку:

error[E0384]: cannot assign twice to immutable variable `a`
  --> src\main.rs:25:5
   |
24 |     let a = 10;
   |         - first assignment to `a`
25 |     a = 2;
   |     ^^^^^ cannot assign twice to immutable variable
   |
help: consider making this binding mutable
   |
24 |     let mut a = 10;
   |         +++

Т.к. все переменные в rust изначально неизменяемые, то мы не можем изменить переменную. Компилятор нам подсказывает, что для изменения значений надо добавить ключевое слово mut.

Добавим:

fn main() {
	let mut a = 10;
	a = 15;
	println!(a);
}

Программа успешно скомпилируется и мы получим 15.

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

fn main() {
	const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
}

Имя константы - THREE_HOURS_IN_SECONDS, а её значение устанавливается как результат умножения 60 (количество секунд в минуте) на 60 (количество минут в часе) на 3 (количество часов, которые нужно посчитать в этой программе). Соглашение Rust для именования констант требует использования всех заглавных букв с подчёркиванием между словами. Компилятор может вычислять ограниченный набор операций во время компиляции, позволяющий записать это значение более понятным и простым для проверки способом, чем установка этой константы в значение 10 800.

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

Еще момент - в листингах выше мы не декларировали тип данных переменных.

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

fn main() {
	let mut a = 10;
	a = "hello"; // возникнет ошибка
}

Мы не можем поменять тип данных, которые хранятся в переменной. Обычно типы данных указывают так:

fn main() {
	let mut a: i32 = 10;
	a = 15;
}
Теги:
Всего голосов 2: ↑1 и ↓10
Комментарии1

Область видимости и затенение переменных в Rust

Затенение переменных

В Rust, также как и в большинстве ЯВУ, можно "затенять переменные", то есть создавать вторую переменную с таким же именем, используя значение первой переменной:

fn main() {
    let x = 5;

    let x = x + 1;

    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {x}");
    }

    println!("The value of x is: {x}");
}

Эта программа сначала привязывает x к значению 5. Затем она создаёт новую переменную x, повторяя let x =, беря исходное значение и добавляя 1, чтобы значение x стало равным 6. Затем во внутренней области видимости, созданной с помощью фигурных скобок, третий оператор let также затеняет x и создаёт новую переменную, умножая предыдущее значение на 2, чтобы дать x значение 12. Когда эта область заканчивается, внутреннее затенение заканчивается, и x возвращается к значению 6. Запустив эту программу, она выведет следующее:

The value of x in the inner scope is: 12
The value of x is: 6

Область видимости

Связывание переменных происходит в локальной области видимости — они ограничены существованием внутри блока. Блок — это набор инструкций, заключённый между фигурными скобками {}.

fn main() {
    // Эта переменная живёт в функции main
	let long_lived_binding = 1;  
	let shadowed_variable = 1;  
	  
	// Это блок, он имеет меньшую область видимости, чем функция main  
	{  
	    // Эта переменная существует только в этом блоке  
	    let short_lived_binding = 2;  
	    let shadowed_variable = 2;  
	  
	    println!("shadowed variable: {}", shadowed_variable);  
	  
	    println!("inner short: {}", short_lived_binding);  
	}  
	// Конец блока  
	println!("shadowed variable: {}", shadowed_variable);  
	  
	println!("outer long: {}", long_lived_binding);
}

Теги:
Рейтинг0
Комментарии0

Как писать REST API — 9 правил

REST API (Representational State Transfer Application Programming Interface) — это архитектурный стиль взаимодействия между клиентом и сервером через HTTP. Он определяет принципы построения API, обеспечивая стандартизированный и эффективный обмен данными между различными системами.

  1. GET-запросы не должны что-то сохранять, удалять или изменять. Нельзя менять какие-либо данные на стороне сервера при GET-запросе. Почему? GET-запросы часто кешируются на стороне клиента.

  2. POST запросы для загрузки/создания сущностей, PUT для изменения в сущности, а PATCH - для мелких изменений в сущности.

  3. Наименование эндпоинтов. Должен присутствовать единый стиль, и желательно во множественном числе, ибо это более лаконичнее. Например, эндпоинт /users. Можно и единственное число использовать, но обосновано.

  4. Иерархия. Нужно соблюдать единую иерархию для построения запросов. Конструкции /users/1/friends/3/items/4 будет неудобно использовать разработчикам клиентских приложений. Нужно избегать такую иерархию, нужно конкретно указывать что нам нужно, не перезагружать данными.

  5. Соблюдайте версионирование API. Допустим: /api/v1/get_all_users и /api/v2/get_all_users. При выходе новой версии не всегда разработчики готовы переписать логику клиентских приложений, и для этого нам нужно разделять версии API

  6. Чувствительные данные. Очень важный момент. Например, передача различных паролей в Query-параметрах запрещено, только в теле запроса.

  7. Из 6 вытекает 7е правило: не логируйте персональные и прочие секретные данные. Было несколько случаев, когда из-за логирования параметров утекали данные пользователей.

  8. Расширение ответов. Во-первых, не передавайте массивы в самом верхнем уровне ответа. JSON-ответ от сервера не должен быть массивом, только словарь (ключ-значение). Если мы будем возвращать список, в будущем нам будет неудобно расширить ответ сервера, добавив дополнительные параметры. А также иногда в API разработчики делают обязательные параметры, например помимо самих данных параметр success и error, чтобы клиентское приложение могло понять, что произошла ошибка, или наоборот, успешно выполнилось.

  9. Работа с датой и временем. Есть два метода - использование Unix Timestamp (количество секунд прошедших с 1 января 1970 года). Это в какой-то степени более удобно для машины, но менее удобно для клиентского разработчика. И второй метод как раз делает формат даты и времени более понятным - это ISO 8601 (2025-04-05T12:00:00.100Z). Этот метод более удобный, т.к. мы понимаем дату и часовой пояс, точное время.

  10. Бонусное правило, лично мое. Относится не только к REST API, но и в принципе к программированию. Пишите код так, как будто эта поэма, книга. Попробуйте сами поработать со своим API, будто вы его не писали. Разделение ответственности, единая точка отказа, Don't Repeat Yourself и даже Keep It Simple, Stupid. Все это конечно-же вариативно.

Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии5

Напоминаем, что в Академии Selectel можно пройти бесплатный курс «Изучаем Python: теория, практика, настройка инструментов».

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

Что будем делать:

✅ настроим инструменты разработчика — уделим внимание связке IDE и Python;

✅ поработаем с базами данных и брокерами сообщений — будем писать запросы SQL;

✅ создадим приложения с графическим интерфейсом — нарисуем виджеты, выведем диалоговые окна;

✅ научимся автоматизировать получение данных — попрактикуемся и с Request, и с Selenium.

Без задач для практики тоже не останетесь!

Но и это не все! Поделимся записями докладов Python Meetup. Дадим подборку для дальнейшего изучения.

Все материалы бесплатные. Не требуется даже регистрация.

Изучить курс в Академии Selectel

Теги:
Всего голосов 1: ↑1 и ↓0+2
Комментарии0

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

Если в языке есть управляющие конструкции, по типу if/else, то это НЕ объектно-ориентированный язык. И не важно какие свойства ему приписываются в Wikipedia. В ООП работа с булевыми выражениями выглядит так:

result = request->validate(rules);
result
    ->ifTrue(useCase->execute())
    ->ifFalse(response->unprocessable())

Вот вам и посылка сообщений, и "Tell, don't ask".

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

Вы выстрелите себе в ногу, если попытаетесь смоделировать развёртку docker-контейнеров или взаимодействие между web-компонентами с помощью ФП. И вам будет так же трудно обработать данные запроса на сервере с помощью ООП. Все парадигмы имеют свои преимущества и недостатки, и используются как инструменты для разных задач.

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

Призываю всех улучшать своё понимание парадигм и использовать их по назначению. (b.t.w. нативный "Railway programming" в ФП - это круто)

Теги:
Всего голосов 2: ↑1 и ↓10
Комментарии10

Привет, Habr!

Уже завтра увидимся на JPoint в Москве, где на стенде Explyt представим новую версию Explyt Test плагина, разыграем весеннюю коллекцию мерча и на вечернем докладе обсудим, что болит и где подгорает у разработчика и тестировщика.

В этом релизе killer фичи Explyt Test плагина – интеграция тестов в существующую кодовую базу и подражание стилю проекта – усилены:

  • возможностями для увеличения тестового покрытия кода

  • генерацией интеграционных тестов для Spring разных видов: MockMVC, Spring Boot

  • анализом моргающих тестов (Flaky tests)

  • генерацией кода в строке редактора (Inline code generation)

  • объяснением ошибок, возникших в консоли

В Explyt Test мы поддержали современные языковые модели от провайдеров OpenAI, Anthropic, DeepSeek, Google Gemini, Cerebras, Groq, Ollama, в том числе:

  • Claude 3.7 Sonnet

  • OpenAI o3-mini

  • DeepSeek R1

  • OpenAI GPT-4.5

Возможности генерации тестов:

  • расширение тестового класса новыми тестовыми методами

  • автоматическая генерация тестов

  • исправление ошибок компиляции и runtime-ошибок в любом тестовом классе

  • использование существующего тестового класса в качестве примера для генерации тестов

  • подготовка проекта для интеграции сгенерированных тестов в существующую кодовую базу 

  • генерация тестового кода по пользовательскому тестовому сценарию 

  • автоматическое исправление ошибок компиляции и runtime-ошибок

Возможности интегрированного ассистента:

  • чат с LLM с поддержкой вложений

  • анализ кода на предмет потенциальных ошибок в реализации (Analyze for bugs)

  • объяснение работы кода и нюансов его использования (Explain code fragment)

  • использование локальной модели для генерации тестов и общения с ассистентом

Поддержка совместимости:

  • IntelliJ IDEA 2024.1+

  • Kotlin K2 

  • Android Studio Koala, Ladybug, Meercat

Поддерживаем тестовые фреймворки: JUnit 5, JUnit 4, TestNG, kotlin-test, фреймворки мокирования: Mockito, Mockito-Kotlin, MockK, SpringMockK, системы сборки: Maven, Gradle, IntelliJ Build System.

Вы можете обращаться к языковым моделям как через серверы Explyt, так и с использованием собственных API-ключей.

В личном кабинете добавлена возможность выбирать между Personal и Enterprise версиями.

Explyt Enterprise можно развернуть в виртуальном частном облаке (VPC) или в контуре компании (self-hosting). Код компании не отправляется в интернет и не используется для обучения модели.

Мы очень ценим обратную связь от комьюнити и будем рады пообщаться с вами на стенде Explyt на JPoint и почитать ваши комментарии на Хабре. Скачивайте плагин на сайте, багрепорты и фичреквесты добавляйте в GitHub Issues, узнавать новое – в нашем телеграм.

Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии0

Анализируем размер проекта

Среди метрик качества проекта теоретики выделяют число LOC == lines of code, измеряемое обычно в тысячах.

Для измерения размера проекта в строках кода есть интересный проект cloc, запускаемый в том числе в docker (зачем docker?).

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

Пример для одного легаси проекта
Пример для одного легаси проекта

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

DevFM

Теги:
Всего голосов 5: ↑3 и ↓2+2
Комментарии7

Попробуйте себя в роли этичного хакера на T-CTF 2025

19—20 апреля встречаемся на T-CTF — соревнованиях по кибербезопасности. Вас ждут увлекательные задачи из мира информационной безопасности. Лучшие игроки получат шанс выиграть призы — до 420 000 ₽ на команду.

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

  • Приглашаем скилловых ИТ-специалистов из разных сфер. На соревнованиях будет две лиги: Лига безопасности для опытных игроков и Лига разработки для тех, кто еще ни разу не участвовал в СTF. Ждем backend- и frontend-разработчиков, аналитиков, SRE- и QA-инженеров и других специалистов, которые хорошо разбираются в коде.

  • Участвуйте онлайн или приходите на офлайн-площадки в шести городах России. Для тех, кто хочет погрузиться в атмосферу ИТ-хабов Т-Банка, мы подготовили площадки в Москве, Санкт-Петербурге, Казани, Иннополисе, Екатеринбурге и Новосибирске. На них вас будут ждать рабочие места для выполнения заданий, зоны для отдыха и нетворкинга, вкусная еда и напитки. 

  • В T-CTF участвуют командами — если у вас ее нет, мы поможем найти. После регистрации присоединяйтесь к чату в Телеграме: в нем будут единомышленники, которые тоже ищут команду. Еще есть телеграм-бот, где можно посмотреть анкеты участников и объединиться с желающими. В одной команде может быть от одного до трех человек. Чем больше команда, тем выше шансы на победу.

Выбирайте лигу по скиллам, отправляйте заявку и собирайте команду! Регистрация открыта до 18 апреля 23:59.

Зарегистрироваться

Теги:
Всего голосов 1: ↑1 и ↓0+3
Комментарии0

Конкурентность в Go: просто запустить — сложнее управлять

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

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

Например, в статье Curious Channels Дейв Чени описывает два важных свойства каналов в Go:

  1. Закрытый канал не блокируется. После закрытия в него нельзя отправлять данные, но можно читать. Если данных нет, возвращается нулевое значение. Это удобно при использовании range, который автоматически завершает цикл.

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

В отличие от языков вроде C, где конкурентность управляется через блокировки и разделяемую память, в Go используются более простые и безопасные механизмы. Однако работа с каналами требует понимания нюансов.

Владислав Белогрудов, эксперт по разработке ПО в YADRO, собрал полезные материалы про конкурентность в Go. В статье — блоги, выступления и книги, которые помогут разобраться, как в Go работать с горутинами и каналами без хаоса и дедлоков.

Теги:
Всего голосов 4: ↑4 и ↓0+6
Комментарии0

Напиши мне программу богатства

С выходных каждый день программирую новый сервис для студентов.
Программист я никакой, но очень нравится.
Сидишь, смотришь, как нейронка пишет код за тебя. А ты ей: «Просто хочу быть богатым, напиши мне программу». Магия какая-то.
Так думают все, кто первый раз пробует с нейронкой написать код. А потом, спустя первые 20 минут, чёт, ошибка какая-то, и потом 4 часа пробуешь её поправить с помощью нейронки.

Вторая стадия — это когда ты пишешь ей уже матом, чтобы выплеснуть всю ненависть к роботу, и он извиняется: «Мол, прости брат, не бей, ошибся» — и вроде легче на душе. И ошибается снова и снова.
Моя стадия — 4 нейронки, которые правят ошибки друг друга, долго, муторно, но двигаешься, чуть быстрее, чем сам.

Следующая стадия — это уже сам пишешь код. Надеюсь, не дойду сюда.
Всегда, когда видите, что кто-то по-быстрому разбогател с помощью ИИ, помните, что ИИ сделала 20-30% работы.

Перешли этот пост тому, кто думает, что быстро напишет программу с помощью ИИ.

Теги:
Всего голосов 5: ↑3 и ↓2+1
Комментарии2

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

Вот продукт готов, покупатели и менеджеры довольны... Они твои пользователи.

Вопрос: ты никого не забыл? Кто первым посмотрит на твой продукт еще до выхода его в прод? Кто увидит его в сыром, первозданном виде? Кому придется поддерживать его, исправлять ошибки?

Да, да.... это я, твой коллега, твой первый пользователь, твой продукт - это код, я им пользуюсь.

Почему ты не подумал обо мне: не написал README, не оставил инструкций, не озвучил подводные камни? Почему мне нужно провести реверс-инжинириг, просто что бы запустить или задеплоить проект?

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

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

После этого, ты удивляешься тому, что я не хочу иметь ничего общего с твоим продуктом и с тобой. Почему?

Теги:
Всего голосов 6: ↑5 и ↓1+5
Комментарии4

Ближайшие события

Полезные ссылки и новости в дайджесте за февраль🌨️

📢 Анонсировали программу главной конференцию про облачные технологии и искусственный интеллект — GoCloud 2025. Хотите узнать про глобальные тренды в AI, пополнить список инструментов и сценариев работы в облаке, обменяться опытом с коллегами-экспертами, а также увидеть, какой простор открывают облачные и AI-технологии для ваших IT-проектов? Тогда мы ждем вас 10 апреля онлайн и офлайн в Москве в Цифровом деловом пространстве (ЦДП). Посмотреть программу и зарегистрироваться.

🚀 Запустили Cloud․ru Evolution Stack — платформу для создания частных и гибридных облаков в IT-ландшафте компании. Платформа позволяет построить частное облако в собственном дата-центре, а также развернуть гибридную инфраструктуру, объединяя возможности публичного облака Cloud․ru Evolution, сторонние облачные сервисы на базе OpenStack и виртуализацию VMware vSphere. Узнать больше.

☁️ Расширили возможности облака Cloud.ru Evolution:

  • добавили поддержку Kubernetes версии 1.29

  • в личном кабинете добавили возможность указывать публичную часть SSH-ключа из сервиса SSH-ключи для аутентификации на рабочем узле.

  • добавили поддержку Apache Iceberg в Evolution Managed Trino

  • опубликовали UserGate NGFW в виде образа виртуальной машины по модели BYOL — подробности на странице образа.

  • опубликовали инструкцию — как развернуть UserGate NGFW.

  • добавили ресурсы в Evolution Bare Metal — доступно более 40 мощных серверов в двух зонах доступности.

🦾 Обновили наши облачные платформы — об этом подробно рассказали в дайджесте на сайте

💰 Обновили реферальную программу, чтобы вы могли с большей выгодой рекомендовать сервисы Cloud.ru клиентам, коллегам или друзьям. Теперь можно получить 20% от суммы чеков приведенных пользователей в первый год и 15% — в последующие годы. Регистрируйтесь в программе до 31 мая и приводите новых пользователей в течение трех месяцев. Участвовать могут самозанятые, ИП и юридические лица. Присоединиться.

🧊 Заморозили цены на облачные услуги для новых клиентов на три года. Вы можете выбрать виртуальные машины, GPU-ресурсы, объектные хранилища, базы данных и другие облачные сервисы — тарифы останутся неизменными в течение трех лет. Предложение действует до 31 марта 2025 для юрлиц и индивидуальных предпринимателей. Оставить заявку.

📺 Провели вебинары, и их можно посмотреть в записи:

А также приглашаем на ближайшие вебинары: 

До встречи в следующем выпуске!

Теги:
Рейтинг0
Комментарии0

Внедрили себе gitlint

В один из проектов внедрили себе gitlint и уже несколько месяцев полноценно им пользуемся. По отзывам разработчиков: кому-то понравилось, что теперь коммиты нужно писать более дисциплинированно, кто-то и так их качественно писал, поэтому и не заметил разницы. Кто-то, конечно, воняет до сих пор, но на них не отвлекаемся :)

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

За вдохновением по правилам написания коммитов загляните сюда.

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

Вдогонку посмотрите еще на comimitizen.

Не на каждом проекте нужны такие штуки, но может именно на вашем пригодится.

DevFM

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии0

Как джуну вырасти до мидла, а мидлу — почувствовать уверенность

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

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

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

Мидл фронтенд-разработчик — вас ждёт работа с TypeScript, SSR, современными фреймворками и производительностью веб-приложений. Курс также охватывает CI/CD, архитектуру и паттерны проектирования.

Мидл Android‑разработчик — продвинутая разработка на Android с фокусом на Clean Architecture, Kotlin Coroutines, Jetpack Compose и Unit-тестирование. Подойдёт тем, кто хочет писать масштабируемые и поддерживаемые приложения.

Мидл Java‑разработчик — поможет освоить инструменты и технологии Java-разработчика: Spring, Hibernate, микросервисную архитектуру, Kafka и Kubernetes. Подойдёт желающим глубже разобраться в построении отказоустойчивых систем.

Мидл разработчик С++ — курс для разработчиков, желающих освоить продвинутые возможности C++: многопоточность, шаблонное программирование, оптимизацию под производительность и работу с низкоуровневыми механизмами ОС.

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

Приветствую.

Я пишу облегчённую версию SDL3, с поддержкой старых систем. Проект решил назвать SDL3Lite. Проект пишу на C++ 98, но наружу торчит совместимый С API. Я хочу реализовать базовый функционал, поэтому вполне реально довести проект до конца. Главная идея проекта это сохранить совместимость с оригинальным C API SDL3. В идеале это конечно на уровне бинарной совместимости. Код единожды написанный должен собираться без изменений для всех поддерживаемых систем.

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

На данный момент поддерживается windows 95 и выше, linux начиная с Debian 3.

Запуск примера под windows 95 в 16 цветов.
Запуск примера под windows 95 в 16 цветов.

В будущих версиях планирую добавить поддержу windows 3.1 и ms-dos.

Рад буду советам, критике и предложениям.

Теги:
Всего голосов 10: ↑10 и ↓0+13
Комментарии0

На картинке — код на JavaScript с ошибкой, который написал специально для Хабра руководитель группы разработки интерфейсов компании «Криптонит» Василий Беляев.

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

Где здесь ошибка?
Где здесь ошибка?

Если запустим этот код, то получим ошибку

Uncaught TypeError: this.clearHistory is not a function

Проблема находится на строчках 11-13 (на картинке)

this.timeout = setTimeout (function () {
        this.clearHistory();
    }, 0);

Когда мы вызываем setTimeout, то вызываем метод объекта window, и меняем область видимости с нашего конструктора на window ( window.setTimeout() ).

Именно по этой причине у нас метод clearHistory пытается вызываться у объекта window ( window.clearHistory() )

Как можно решить эту проблему?

Вариант 1

const MyItem = function () {
    this.clearStorage = function () {
        console.log ('Очищаем хранилища...');
    };
    this.clearHistory = function () {
        console.log ('Очищаем историю...');
    };
};
MyItem.prototype.refresh = function () {
    this.clearStorage();
    this.timeout = setTimeout (() => {
        this.clearHistory();
    }, 0);
};
const mуItem = new MyItem();
mуItem.refresh();

Заменить анонимную функцию на стрелочную функцию. У них отсутствует свой контекст, и они работают в контексте области видимости, включающий их самих.

Вариант 2

const MyItem = function () {
    this.clearStorage = function () {
        console.log ('Очищаем хранилища...');
    };
    this.clearHistory = function () {
        console.log ('Очищаем историю...');
    };
};
MyItem.prototype.refresh = function () {
    this.clearStorage();
    this.timeout = setTimeout (
        this.clearHistory.bind(this), 0
    );
};
const mуItem = new MyItem();
mуItem.refresh();

Явно передать контекст через метод .bind()

Вариант 3

const MyItem = function () {
    this.clearStorage = function () {
        console.log ('Очищаем хранилища...');
    };
    this.clearHistory = function () {
        console.log ('Очищаем историю...');
    };
};
MyItem.prototype.refresh = function () {
    this.clearStorage();
    const self = this;
    this.timeout = setTimeout (() => {
        self.clearHistory();
    }, 0);
};
const mуItem = new MyItem();
mуItem.refresh();

Выносим контекст в отдельную переменную и работаем с ней. Этот вариант подойдет для поддержки старых браузеров.

А как бы вы решили эту ошибку?

Теги:
Всего голосов 6: ↑3 и ↓3+2
Комментарии5

Внедрили себе gitlint

В один из проектов внедрили себе gitlint и уже несколько месяцев полноценно им пользуемся. По отзывам разработчиков: кому-то понравилось, что теперь коммиты нужно писать более дисциплинированно, кто-то и так их качественно писал, поэтому и не заметил разницы. Кто-то, конечно, воняет до сих пор, но на них не отвлекаемся :)

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

За вдохновением по правилам написания коммитов загляните сюда.

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

Вдогонку посмотрите еще на comimitizen.

Не на каждом проекте нужны такие штуки, но может именно на вашем пригодится.

DevFM

Теги:
Всего голосов 3: ↑2 и ↓1+1
Комментарии3

Представлен онлайн-ресурс для изучения языков программирования Coddy. Внутри полная геймификация: обучение через игру, квесты и допы за активность. За каждый урок ваш персонаж двигается по карте к финишу. Ежедневные испытания дают дополнительный опыт, а за стрик капают «огоньки». Опыт можно тратить на бустеры, включая премиум подписку на 2 недели. Темы выбираете сами — можно сменить в любой момент.

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии1

Вклад авторов