Cross Join - канал о разработке
3.69K subscribers
92 photos
8 videos
3 files
288 links
Канал о разработке Антона Околелова. Разрабочик/ex-тимлид Go, живу в Чехии. Мысли, новости, вопросы.

По вопросам рекламы @antonokolelov
Download Telegram
Я принес. Гуманизм против «эффективного менеджмента». Почему заботиться о людях выгодно

Вы знаете, что я тот еще гуманист 🙂 Поэтому не мог пройти мимо этого лонгрида https://habr.com/ru/articles/816545/
Текст большой, так что наливайте чай-кофе, заводите один таймер pomodoro и погружайтесь.

Я хоть и гуманист, но не идеалист. Понимаю, что во взрослой капиталистической жизни на высоком уровне управления почти всегда будет то, на что статья ругается. Однако, мы же в тимлидском канале. А позиция тимлида как раз может себе позволить обеспечивать гуманизм и комфорт в своей команде. На уровне руководителей тимлидов я подобного видел реже, а еще выше, так и зачастую – деньги, ресурсы, безобразно, но однообразно.

Так что, граждане тимлиды, этот контент вам точно будет полезен.
👍83🔥2
Вышел PostgreSQL 17

Производительность:

Существенно улучшена работа с памятью. Вакуум теперь потребляет до 20 раз меньше памяти, что ускоряет его работу и снижает нагрузку на систему.
Запись при высокой конкурентной нагрузке стала быстрее в 2 раза благодаря оптимизации обработки WAL.
Улучшена производительность запросов с использованием условий IN для B-tree индексов.
Добавлена поддержка SIMD-инструкций (в том числе AVX-512) для ускорения вычислений.
Оптимизирована производительность COPY для экспорта больших объемов данных.

Для разработчиков:

Расширена поддержка JSON: добавлен JSON_TABLE для конвертации json в обычные таблицы PostgreSQL.
Появились новые конструкторы и функции для работы с json: JSON, JSON_SCALAR, JSON_SERIALIZE, JSON_EXISTS, JSON_QUERY, JSON_VALUE.
Улучшена команда MERGE: добавлена поддержка RETURNING и возможность обновления представлений.
EXPLAIN теперь показывает время, затраченное на локальное чтение и запись блоков, а также использование памяти.

Репликация и обновление:

Упрощен процесс обновления между мажорными версиями при использовании логической репликации. Теперь не нужно удалять слоты репликации при обновлении.
Добавлен контроль отказоустойчивости для логической репликации.
Представлен инструмент pg_createsubscriber для конвертации физической реплики в логическую.

Безопасность и управление:

Новые опции TLS для более гибкой настройки безопасности соединений.
Добавлена предопределенная роль pg_maintain для выполнения задач обслуживания.
Улучшены возможности резервного копирования: поддержка инкрементальных бэкапов в pg_basebackup.

Мониторинг и анализ:

Добавлено отображение прогресса при вакууме индексов.
Новое системное представление pg_wait_events для более детального анализа ожидающих сессий.
🔥36👍4😍1
Я наверно слоупок, только сейчас узнал о программе dust, замене du

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

Запустил в папке с проектами, сразу нашел гигабайтные node_modules в старых проектах, прикольно.

подробнее тут (там куча полезных параметров)

Ставится просто brew install dust
❤‍🔥22🔥7👍3
Forwarded from Shit books (Maxi Frolof)
#непрокниги

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

Эти вопросы я собрал при помощи коллег, когда проходил интервью в Яндекс 360. Дополняйте своими вопросами в комментариях.
👍27🔥5👎2💩2🤮1
Давайте пофантазируем.

Что, если сделать свой отдельный Go, который бы транспилировался в обычный? как TS -> JS

Я бы добавил туда как минимум две вещи, которые точно никогда не появятся в Go, и половине людей там и не нужны:

1. Сахар для обработки ошибок (как-нибудь как в Расте, чтобы обработка была всё еще явной, но синтаксически попроще). Плюс синтаксис для ловли паник тоже попроще.

2. Добавил бы немного structured concurrency: запретил бы голый вызов команды go. Синтаксически заставить дожидаться завершения горутины в той же функции, где она была запущена.

Может, еще с каналами что-то намутить, чтобы заставить их закрывать примерно там же, где в них шла запись (в том же пакете?)

Тогда это получится язык в 10 раз более читаемый и в 10 раз менее запутанный в вопросах concurrency
👍13🥱4👎3🌚1
Очень интересный документ на github, который на различных примерах утверждает, что при программировании во главу угла нужно ставить когнитивную нагрузку от твоего кода и всегда это держать в голове.

Как делить на модули, когда нужно или не нужно использовать микросервисы, гексагональную архитектуру и т.д. Что важнее: гибкость/универсальность кода или простота.

TLDR: используйте сложные трюки только там, где они действительно нужны.

https://github.com/zakirullin/cognitive-load
👍40🔥9👏21
В догонку к предыдущему посту про гибкость vs простота. В языке Go очень интересно сделаны интерфейсы.

Например, есть какой-то класс (точнее структура с методами) с методом getWeather(city), который является обёрткой над внешним сервисом погоды.



type WeatherService struct {
apiKey string
}

func (w *WeatherService) GetWeather(city string) (string, error) {
// http вызов внешнего API
return "Sunny", nil
}


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



type WeatherAnalyzer struct {
weatherService *WeatherService // конкретный класс
}

func (wa *WeatherAnalyzer) AnalyzeWeather(city string) string {
weather, err := wa.weatherService.GetWeather(city)
if err != nil {
return "Unable to analyze weather"
}
if weather == "Sunny" {
return "Great day for a picnic!"
}
return "Maybe stay indoors"
}

// Использование
func main() {
ws := &WeatherService{apiKey: "some-api-key"}
wa := &WeatherAnalyzer{weatherService: ws}
result := wa.AnalyzeWeather("New York")
fmt.Println(result)
}


И тут мы ВНЕЗАПНО поняли, что покрывать тестами это неудобно (ибо внешние вызовы), и лучше бы написать интерфейс, чтобы потом его замокать. Или у нас вдруг появился еще один сервис погоды, и нужен интерфейс. Так вот, в Go достаточно просто ПО МЕСТУ добавить интерфейс с описанием нужных в этом месте методов, а сам класс погоды останется неизменным.

Вот как это будет выглядеть:


// WeatherService остается без изменений

type WeatherProvider interface {
GetWeather(city string) (string, error)
}

type WeatherAnalyzer struct {
weatherProvider WeatherProvider
}

func (wa *WeatherAnalyzer) AnalyzeWeather(city string) string {
weather, err := wa.weatherProvider.GetWeather(city)
if err != nil {
return "Unable to analyze weather"
}
if weather == "Sunny" {
return "Great day for a picnic!"
}
return "Maybe stay indoors"
}


Потому что в отличие от Java/PHP/etc не нужно писать что класс имплементирует что-то там. Если у класса есть методы такие же как в интерфейсе, то он подходит под сигнатуру

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

Теперь мы можем легко создать мок для тестирования (упрощенный пример)



type MockWeatherProvider struct {
MockWeather string
}

func (m *MockWeatherProvider) GetWeather(city string) (string, error) {
return m.MockWeather, nil
}

func TestWeatherAnalyzer(t *testing.T) {
mockProvider := &MockWeatherProvider{MockWeather: "Sunny"}
analyzer := &WeatherAnalyzer{weatherProvider: mockProvider}

result := analyzer.AnalyzeWeather("Test City")
expected := "Great day for a picnic!"

if result != expected {
t.Errorf("Expected %s, but got %s", expected, result)
}
}


У этого конечно есть и недостатки.
👍19🌚5👎1
Ну и неустаревающая классика. Для тех, кто любит делать код максимально гибким на всякий случай под неизвестные требования:

FizzBuzz Enterprise Edition

Думаю, все знают задачку Fizz Buzz (выведи Fizz, если число делится на 3, Buzz, если на 5, FizzBuzz если на 3 и на 5). Посмотрите, как делают эту задачу серьёзные люди. Для серьёзного бизнеса. Какие стратегии, фабрики, интерфейсы и всё такое.

Это настоящее пособие по паттернам, а паттерны - это язык, облегчающий общение разработчиков
😁29🥴2🔥1
Гоферы, пройдите опрос 2024

Прошлогодний опрос показал, что гошники в основном бывшие пыхари, и от языка хотят они одного: улучшения обработки ошибок :)
😁9👍4🤯1
иногда комментарии в коде очень важны
😁58👍3
Devjobscanner пропарсил 12 миллионов вакансий (за 1.5 года) и составил топ самых востребованных языков. Из интересного - Ruby и PHP, про смерть которых я слышу уже лет 10, по прежнему хорошо себя чувствуют и всех нас еще переживут. С++ че-то немного пошел вниз
🔥14
Если нужно с помощью ChatGPT сделать сразу несколько файлов с кодом, например целый проект, то это неудобно, надо копировать каждый файл отдельно и хз как это организовать, в общем тупо как-то. Вчера я увидел интересный лайфхак (здесь): можно гопчат попросить сделать bash-файл, который создаст тебе проект со всеми файлами, env переменными и т.д.

Например, такой промт:

"Создай проект на Go 1.23, который делает API для todo list. Данные хранить в Postgres. Создай проект со всеми необходимыми файлами, docker-compose и env переменными. Сделай это в виде bash файла, который сразу всё правильно создаст. Проект назови proverka"

в итоге реально был создан bash файл, который при запуске создал проект. Этот проект сбилдился (я сделал только одну правочку в импортах), запустился через docker-compose, всё ок. Правда, версия Go была не такая, зачем-то туда приделался Gorm, но не суть, это мелочи и можно поиграться с промтом
🔥39👍12💩21👏1🌚1