Часто встречаю такое мнение, что главное то как мы систему проектируем сверху и не очень принципиально, что там внутри. То есть вот у нас есть модули, ответственности и дальше как-то оно реализуется.
И это видно в запросах людей в чатах или у тех кто просит помочь поконсалтить. Мол вот тут в коде такое себе, но это не так важно, хочу научиться делать хорошо глобально.
Логически кажется что все верно, если мы делаем хорошо систему снаружи, то внутренности уже не так страшно. На практике же я вижу ситуацию по другому. Если программист не понимает как правильно организовывать локальный код, что и когда выносить в функцию, как работать с побочными эффектами и состоянием приложения, он не сможет перепрыгнув этот уровень научиться и делать хорошо систему в целом.
Для меня это всегда выглядело как техника в спорте. Сначала мы, упорно и монтонно ставим технику, а уже затем двигаемся дальше. Без техники спортсмен всегда будет проигрывать другим. В программировании мы конечно не соревнуемся друг с другом, но результат будет примерно такой же, на выходе получится такая себе архитектура.
И даже если вы со мной согласитесь, дальше начинается вакханалия. А что является базой, которую надо уметь и знать? Готов поспорить, что больше всего будут кричать про SOLID, чистый код и другое похожее мракобесие. Да, в любых шутках есть какие-то полезные мысли, но это все настолько скрыто за ширмой конкретных кейсов делай раз и делай два, что картинка теряется и все скатывается в срач, одна ответственность у функции или две.
Мой личный топ того, что учит писать грамотный код на высокоуровневых языках, где мы фокусируемся на создании правильных абстракций это SICP/HTDP + попрактиковаться в написании кода на одном из популярных функциональных языков.
За мою довольно длительную карьеру, самый большой сдвиг произошел именно в тот момент, когда от изучения фаулеров, мартинов и банд я взялся за более серьезный фундамент. Было это году в 2013, с тех пор, что бы я не изучал, оно накладывается и дополняет, а не переворачивает мой мир внутри, как было 5 лет до того. Тогда, в первые годы моего программированияб каждый раз смотришь на свой код или читаешь что-то и думаешь, блин, надо проектировать по другому.
И это не только мое наблюдение, почти все ребята с кем мы тогда активно тусили в разных комьюнити, пересекались на конфах и дружили, в целом отмечали как фп (в частности clojure, haskell, ocaml, erlang) значительно сдвигали понимание программирования.
Почему это так? А потому что в остатке мы упираемся в побочные эффекты, барьеры абстракции (тут сикп) и грамотное управление состоянием. Вот такие пироги
Каждую осень/весну разработчики вспоминают о "зловещем" performance review и И...П...Р (Индивидуальный План Развития). Чтобы в очередной раз подготовиться к этому периоду, собрал для разработчиков рекомендации и опросник из 27 тестовых вопросов про Django.
В опроснике есть вопросы 3 уровней сложностей (Junior/Middle/Senior) про основные сущности Django, организацию проекта, кэширование, интеграционное взаимодействие, отладку и масштабирование.
По ответам определяется текущий уровень знаний, раскрываются ожидания рынка на этом уровне, даются рекомендации по дальнейшему развитию, которые можно скопировать в ИПР табличку и забить или предметно обсудить с руководителем ожидания и текущие навыки.
P.S. Пока собирал опрос снова задумался, что Middle разработчики закрывают основную массу сформулированных задач
Топ-5 инструментов для старта в DevOps, которые можно освоить уже сейчас
DevOps — это не только про культуру, но и про инструменты. Вот топ-5 must-have технологий, которые помогут вам стартовать и которые реально освоить в ближайшее время:
Linux
Без него — никуда. 90% серверов работают на Linux, поэтому базовые команды (grep, awk, sed), работа с правами (chmod, chown) и понимание файловой системы — обязательный минимум
А для тех, кто хочет освоить все необходимые hard skills для старта в DevOps, 29 сентября стартует новый поток курса-профессии «DevOps Upgrade». Подробности — по ссылке.
Изучение Python может показаться сложным, но с правильным подходом и пониманием ключевых аспектов процесс станет понятным и увлекательным. Привет, я Иван Чернов, senior system architect, кратко расскажу, как начать вкатываться в Python, с какими проблемами сталкиваются новички и как их преодолеть.
Первые шаги
Определяемся с направлением, в котором вы хотите развиваться. Это может быть веб-разработка, машинное обучение, DevOps и т. д. Каждое направление требует своих знаний и навыков. Поэтому важно понять, что конкретно вам интересно и на какой позиции не будет скучно или слишком сложно.
Начните с изучения базовых понятий, таких как переменные, типы данных, структуры данных и функции. Это заложит фундамент для дальнейшего изучения.
Когда определились с направлением и изучили теорию — проходите курсы с практическим обучением или начинайте работать с кодом сами. Всегда лучше писать, чем читать. Как только вывели “Hello, World!”, переходите к обучающим программам, где первые задачки применимы к жизни. Например, на некоторых курсах учат разрабатывать Telegram-бота под ваши нужды. Это отличная практика для понимания процессов.
Также можете прочитать базу «Питона» — книгу “Automated Boring Stuff with Python”. В ней много практических задач, которые помогут вам освоить язык. А ещё есть полезный курс “Learning How to Learn”, который учит, как правильно учиться, опираясь на достижения нейронауки.
Этап, на котором новички отваливаются
При более глубоком изучении «Питона» новичок столкнётся с первой проблемой — настройкой инфраструктуры. На этом этапе многое пугает: установка редакторов кода, интерпретаторов, пакетных менеджеров и прочее. Даже опытные программисты каждый день ищут подходящие инструменты и пытаются освоить новые.
Чтобы облегчить старт, можно для начала научиться использовать онлайн-среду разработки, например Replit. Можно просто зайти на сайт, выбрать язык Python и сразу приступать к написанию кода.
Replit — это сервис для вайб-кодинга. В нём можно быстро экспериментировать с задачами и сразу видеть результат. Так вы сконцентрируетесь именно на изучении языка, а не на технических сложностях.
Тут есть большое «но»: на вайб-кодинге далеко не уедешь. Использование онлайн-сред — это чит-код, который облегчает старт, но не учит решать реальные проблемы. Так что с комплексной инфраструктурой всё же придётся разобраться.
Концептуальные вопросы
Отдельно стоит отметить концептуальные вопросы, которые могут возникнуть на старте. Новички часто сталкиваются с трудностями в понимании таких понятий, как переменные и функции.
Например, в Python переменная может принимать разные значения, что противоречит математическим представлениям. Это может привести к путанице и неправильному пониманию основ программирования.
Важно понимать, что программирование — это не только про то, как писать код, но и о то, как мыслит как программист. Необходимо развивать критическое мышление и осознавать, что многие концепции, которые мы учили на уроках математики, могут быть неверными в программировании.
Советы начинающим питонщикам
Постоянная практика. Пишите код каждый день, хотя бы немного. Работайте над проектами, которые вас интересуют, и решайте проблемы, которые вас раздражают. Я в 2010-м хотел, чтобы дома лампочка включалась по голосу. С помощью Python удалось сделать это.
Изучайте чужой код. Чтение и понимание чужого кода поможет вам увидеть, как другие решают задачи и какие подходы используют. Однако не стоит изучать рандомный код. Лучше ищите тот, что поможет улучшить ваши проекты.
Go sport, go team. Физическая активность способствует лучшему усвоению информации. Поэтому не забывайте делать перерывы и заниматься спортом.
Заключение
Определитесь с направлением, изучите теорию, но не медлите с практикой. Не пугайтесь сложностей инфраструктуры: всегда можно нагуглить или спросить на форумах. Пользуйтесь онлайн-средами, но не делайте большую ставку на вайб-кодинг. Не бойтесь начинать и ошибаться — и у вас всё получится.
Как триггерить события для плагинов на манер Joomla 5+?
В Joomla 6 должны удалить метод triggerEvent(), с помощью которого раньше вызывались события для плагинов. Теперь чтобы в своём коде вызвать событие для плагина и получить от него результаты нужно:
создать объект класса события
передать в него именованные параметры
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
// Грузим плагины нужных групп
PluginHelper::importPlugin('system');
// Создаём объект события
$event = AbstractEvent::create('onAfterInitUniverse', [
'subject' => $this,
'data' => $data, // какие-то данные
'article' => $article, // ещё материал вдовесок
'product' => $product, // и товаров подвезли
]);
// Триггерим событие
Factory::getApplication()->getDispatcher()->dispatch(
$event->getName(), // Тут можно строку передать 'onAfterInitUniverse'
$event
);
// Получаем результаты
// В случае с AbstractEvent это может быть не 'result',
// а что-то ещё - куда сами отдадите данные.
// 2-й аргумент - значение по умолчанию,
// если не получены результаты
$results = $event->getArgument('result', []);
Плюсы такого подхода - вам не нужно запоминать порядок аргументов и проверять их наличие. Если вы написали свой класс события, то в плагине можно получать аргументы с помощью методов $event->getArticle(), $event->getData(), $event->getProduct() и подобными - реализуете сами под свои нужды.
Если такой класс события написали, то создаёте экземпляр своего класса события и укажите его явно в аргументе eventClass
use Joomla\Component\MyComponent\Administrator\Event\MyCoolEvent;
$event = MyCoolEvent::create('onAfterInitUniverse', [
'subject' => $this,
'eventClass' => MyCoolEvent::class, // ваш класс события
'data' => $data, // какие-то данные
'article' => $article, // ещё материал вдовесок
'product' => $product, // и товаров подвезли
]);
Ожидаемо, что класс вашего события будет расширять AbsractEvent или другие классы событий Joomla.
🙁 Есть неприятный нюанс - нельзя просто так вызывать событие и ничего не передать в аргументы. Аргумент subject обязательный. Но если вы всё-таки не хотите туда ничего передавать - передайте туда пустой stdClass или объект Joomla\registry\Registry.
Совет по Joomla: значение переменной по умолчанию с помощью класса Joomla\Registry\Registry.
Очень часто в Joomla мы видим, что данные приходят не в виде массива или простого объекта (stdClass), а их нужно получать с помощью метода get(). Например, в плагине или модуле:
$option = $this->params->get('my_option');
Это означает, что мы получили данные в виде объекта Joomla\Registry\Registry.
❓ Зачем это?
Возможность указать значение переменной по умолчанию. Лично для меня первое и самое важное - это возможность указать значение переменной по умолчанию, если его (значения) в параметрах нет.
Вы выпускаете новую версию своего мега-плагина и вводите в него новую опцию my_option. Мы используем её везде в PHP коде. Однако, мы же понимаем, что люди обновятся, а обновлять настройки плагина не полезут. Не полезут до тех пор, пока не станет любопытно "а что же там нового?" или что-нибудь не отвалится. И пока они не установят новый параметр и не сохранят настройки плагина - в коде он так и не появится.
Чтобы ничего не отвалилось нам в коде нужно предположить сценарий по умолчанию, которому, соответственно, нужны значения параметров по умолчанию. Вот тут нам и поможет класс Joomla\Registry\Registry.
$myOption = $this->params->get('my_option', 'default_value_if_null_or_not_exists'); // string по умолчанию
И теперь нам не надо писать свои проверки на наличие переменной и её пустоту, а так же вы всегда уверены, что получите вменяемое значение для работы в коде. По умолчанию можно указать что угодно. Чаще всего это какая-нибудь строка, число, массив.
Каждый раз, когда я слышу от кого-то описание или определение полиморфизма, там присутствует слово "наследование".
> Объясните что такое полиморфизм? Ну это когда базовый класс и наследники...
Давайте по порядку. Полиморфизмов вообще существует больше чем один. Но, все таки, когда речь идет про массовое программирование (простите функциональщики), по умолчанию говорят о полиморфизме подтипов (subtyping). Упрощенно, в этом полиморфизме мы заменяем иф на общий метод для разных типов объекта. Таким образом сам объект (его тип) определяет реальное поведение, а вызывающий код про это не знает, он просто дергает метод (или методы):
function doSomething(logger) {
// Где-то снаружи выбирается конкретный логгер
// Разные логгеры могут работать сильно по разному
logger.info('hey');
}
Что мы тут получили? Возможность менять поведение конфигурированием приложения (меняем тип объекта во время настройки), а не тем, что ходим по ифам где выбирается конкретная реализация и меняем там код.
Нужно ли для этого наследование? Вообще не нужно и вообще не подразумевается. Типами и подтипами во всех определениях являются интерфейсы или их аналоги, но не классы. Более того, в динамических языках у вас в принципе сами по себе классы могут быть никак не связаны, главное чтобы в них был реализован один и тот же полиморфный метод.
Кстати, для реализации полиморфизма подтипов классы тоже не нужны. Есть немало языков где он есть, но там нет ни классов ни ооп в привычном варианте.
Столкнулся с проблемой отсутствия простых операций со строками, содержащими символы юникода (например, русские буквы), в стандартной библиотеке Zig.
Конкретно, требовалось привести строку в нижний регистр. И оказалось, впрочем ожидаемо, что методы модуля std.ascii не годятся для этого, прямо совсем. Ибо константа lowercase содержит только латинские символы.
А в модуле std.unicode в принципе нет методов, для реализации приведения к нижнему/верхнему регистру символов. В итоге пришлось городить небольшой костыль:
// Кастомное преобразование строки в нижний регистр, с поддержкой
// обработки русских символов, латиницы и акцентированных знаков.
fn toLowerCustom(allocator: Allocator, str: []const u8) ![]const u8 {
var result = std.ArrayList(u8).init(allocator);
var iter = std.unicode.Utf8Iterator{ .bytes = str, .i = 0 };
while (iter.nextCodepoint()) |cp| {
const lower = blk: {
// Русские символы
if (cp >= 'А' and cp <= 'Я') break :blk cp + ('а' - 'А');
if (cp == 'Ё') break :blk 'ё';
// Базовые латинские символы
if (cp >= 'A' and cp <= 'Z') break :blk cp + 32;
// Обработка акцентированных символов
break :blk switch (cp) {
0xC0...0xD6 => cp + 32, // À-Ö → à-ö
0xD8...0xDE => cp + 32, // Ø-Þ → ø-þ
0x100...0x17F => handleLatinExtended(cp),
else => cp,
};
};
var buf: [4]u8 = undefined;
const len = std.unicode.utf8Encode(lower, &buf) catch unreachable;
try result.appendSlice(buf[0..len]);
}
return result.toOwnedSlice();
}
Знаю про существование библиотек для работы со строками на Zig, но ни одна не завелась, да и ради одного метода, тащить всю библиотеку, ИМХО, избыточно. Возможно, что я что-то пропустил и есть проверенные готовые решения?
easyp – пакетный менеджер, билд-система и линтер для .proto файлов. Хоть easyp и написан на #go 😱, одна из его фишек в том – что вы можете использовать любые плагины для генерации финального кода: он может быть хоть на #python, хоть на #rust.
Если много используете ProtoBuf – обязательно для ознакомления!
Пример конфигурации:
# Секция для правил линтера:
lint:
use:
- DEFAULT
# Секция с зависимостями:
deps:
- github.com/googleapis/googleapis
- github.com/grpc-ecosystem/grpc-gateway@v2.20.0
# Секция для правил сборки и генерации итоговых файлов:
generate:
plugins:
- name: go
out: .
opts:
paths: source_relative
- name: go-grpc
out: .
opts:
paths: source_relative
require_unimplemented_servers: false
Прощайте огромные Makefile с кучей скриптов для сборки.
Рад представить aignal.tech — обещанный API для получения сигналов от обученных ML моделей.
Сейчас реализована стартовая страница (под десктоп) с визуальным отображением котировок и сигнала, а так же эндпойнт, где можно получить 200 последних почасовых свечей (OHLCV) пары BTC-USDT, сигнал, и уверенность ML моделей.
Сигналы — не призыв к действию. Это лишь промежуточный результат эксперимента, предназначенный исключительно для тестирования гипотез и дальнейшего обучения моделей. Информация об их обновлении позже будет тоже выводиться.
Ручек планируется больше, подробнее в документации.
Ну и для тех, кто спрашивал про скринсейвер — он реализован отдельной страницей без интерфейса. Минимальный клиент для работы с этим API тоже будет, но чуть позже. Там, собственно, немного покажу, как работать с этой информацией, и какие стратегии можно строить.
Есть такой вечный спор у костра в лагере айтишников. С одной стороны — бизнес хочет всё «ещё вчера». С другой — инженер внутри нас требует стабильности и предсказуемости.
Так где же истина? Как обычно — посередине, но не совсем. Парадокс в том, что настоящий миддл-разгон начинается именно тогда, когда ты перестаёшь выбирать между «сделать, чтобы работало» и «сделать, чтобы работало завтра».
Правильный вопрос: «Как сделать, чтобы оно работало — и быстро сегодня, и так же стабильно через год?»
Ответ — майндсет. С самого начала выстраивать не костыль для единичного случая, а шаблонизированное, автоматизированное решение. Да, на старте это может занять чуть больше времени. Но это — инвестиция.
27-28 сентября мы проведем воркшоп «С нуля в прод за 2 дня» для DevOps-инженеров, которые готовы за два дня пройти весь путь от идеи до работающего продакшен-решения в команде.
Эти два дня вы не будете слушать теорию (хотя немного ее будет), вы пройдёте путь от проектирования инфраструктуры до продакшен-решения — на реальном приложении SlurmTalks (Next.js + Go)
Спикер — Павел Минкин:
DevOps-инженер в сфере FinTech
Автоматизировал исследования и разработки в области электромобилей
Наставник и автор по направлению DevOps в Слёрме
Изучить программу и занять место на воркшопе — через бота.
А чтобы получить скидку на участие, посмотрите запись вебинара «Инфраструктура под ключ за 4 часа» с Павлом Минкиным и Евгением Федосеевым — в ней есть секретный промокод. Действует до 7 сентября!
Финальный релиз Python 3.14 запланирован на 7 октября 2025. Уже вышел RC2 (14 августа), а финальный кандидат RC3 ожидается 16 сентября. Этот пост — краткая шпаргалка, чтобы помнить, какие изменения стоит протестировать и чего ждать в новой версии.
1. Свободная многопоточность (Free-Threaded Python, без GIL)
Зачем нужно: наконец-то полноценный параллелизм и многопоточность на многоядерных системах без глобальной блокировки интерпретатора.
# Включение free-threaded режима при сборке
# ./configure --disable-gil
import threading
def cpu_bound_task(n):
return sum(i*i for i in range(n))
threads = [threading.Thread(target=cpu_bound_task, args=(10**6,)) for _ in range(4)]
[t.start() for t in threads]
[t.join() for t in threads]
Free-Threaded Python теперь не будет экспериментальным и будет официально поддерживаться, но пока пока будет являться опциональным, по умолчанию остаётся GIL.
2. Отложенная оценка аннотаций типов
Зачем нужно: ускорение работы и избавление от кавычек при forward references. Появился новый модуль annotationlib для работы с аннотациями.
# from __future__ import annotations
import annotationlib
class Node:
def __init__(self, value: int, next: Node | None = None):
self.value = value
self.next = next
print(annotationlib.get_annotations(Node.__init__))
Аннотации больше не обрабатываются при определении функций, классов и модулей. Они сохраняются в специальных функциях аннотирования и обрабатываются при необходимости. Импорт from future import annotations можно удалить при поддержке Python 3.14 и новее.
3. Template-строки (t-строки)
Зачем нужно: безопасное форматирование строк, полезное для веба и DSL, расширение возможностей f-строк.
name = "<script>alert('xss')</script>"
age = 25
tpl = t"Hello {name}, you are {age}"
safe = tpl.format(name=escape_html(name), age=age)
print(safe)
4. Zstandard-сжатие
Зачем нужно: современный алгоритм сжатия, быстрее gzip и удобнее для больших блоков данных.
Зачем нужно: можно подключать отладчик к работающему приложению без перезапуска и накладных расходов.
import sys
import pdb
# Подключение отладчика к работающему процессу
sys.remote_exec("""
import pdb; pdb.set_trace()
""", target_pid=12345)
# Безопасное выполнение кода в удаленном процессе
result = sys.remote_exec("print('Debug info:', some_variable)", target_pid=12345)
6. Экспериментальный JIT-компилятор
Зачем нужно: ускорение выполнения вычислительно интенсивных задач.
# Включается флагом при запуске
# python --jit script.py
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
# JIT автоматически оптимизирует "горячие" функции
result = fibonacci(35) # Заметно быстрее с JIT
7. REPL с подсветкой синтаксиса
Зачем нужно: удобнее писать и отлаживать код прямо в интерактивной оболочке.
Подборка обучающих материалов по языкам программирования от Selectel: Go, Python и JavaScript
Привет, Хабр! Несу вам небольшую подборку материалов, которые помогут новичкам лучше разобраться в трех популярных ЯП. Все статьи доступны бесплатно, регистрироваться нигде не нужно, вообще никаких обязательств с вашей стороны. Итак, поехали.
Go
Эти семь статей составляют практический гайд по работе с Go. Вы научитесь писать простые сервисы вроде сокращателя ссылок и использовать этот язык в некоторых рабочих задачах, а еще получите большую подборку материалов для погружения в тему (да, у нас тут подборка в подборке, так уж вышло). На прочтение всех материалов уйдет примерно два часа.
Python
Если самые базовые вещи в Python вы уже освоили, то эта подборка для вас. Вы узнаете, как настраивать инструменты, работать с базами данных, создавать программы с интерфейсом и использовать Python для парсинга. А еще здесь есть несколько интересных задач, чтобы можно было закрепить знания. Всего в подборке девять материалов, примерно на четыре с небольшим часа чтения.
JavaScript
Эту подборку мы с коллегами собрали для тех, кто только делает свой первый шаг в мир JavaScript. В пяти статьях рассказываем, как работать с переменными, типами данных и функциями, а также как строить логику с условными операторами. Практические примеры помогут освоить создание элементов и взаимодействие с ними через JavaScript, а задача в конце — закрепить знания и испытать навыки.
У ИТ-компании «Криптонит» вышел новый выпуск подкаста — на этот раз про Scala! Там обсудили, почему «скалистов» так мало, что эксперты «Криптонита» ждут от новой версии этого языка и почему «в Scala идут те, кому хочется понять этот мир немного лучше».
В выпуске приняли участие сотрудники «Криптонита»: • Алексей Шуксто, директор департамента разработки; • Ахтям Сакаев, руководитель направления серверной разработки; • Юлия Левченкова, директор департамента по управлению персоналом.
Они также обсудили: • почему «скалисты» живут в Питере; • может ли PySpark вытеснить Scala; • планируется ли тотальный переход со Scala на Java; • советы для тех, кто только открывает для себя Scala и полезные ресурсы для «скалистов».
Заглядывайте к нам на карьерный сайт «Криптонита»! Там как раз есть вакансии в команду Ахтяма.
Мы на Let's Go Conf: расскажем, как приручали старый Gateway, и слетаем в космос
В этом году компания МойОфис стала партнёром конференции для Go-разработчиков Let’s GoConf, которая пройдёт 12 сентября в Москве в лофте «Пространство Весна».
В одном из треков выступит Герман Кравец, техлид модуля Календарь почтового сервиса Mailion. В своём докладе он расскажет о том, как команда Mailion работала с «наследием». Представьте: старый Gateway, застрявший на Go 1.19, сложный в поддержке, с самописными генераторами и C++-зависимостями, а конфигурации напоминают древние свитки... Герман поделится тем, как команда справилась с такими вызовами и как изменилась архитектура продукта.
Но конференция — это не только доклады. Для участников мы приготовили по-настоящему космическую игру: нужно будет спасти колонизаторов далёкой планеты, решать задачи по Go и получать призы. Уверены, это станет отличным дополнением к технической программе и подарит всем гостям отличный настрой.
Раскопал интересный тип поля в Joomla - Groupedlist.
В процессе работы над компонентом нужно разделить опции выпадающего списка на группы. Я писал ранее как это сделать просто в коде тут: статья, пост.
Но как сделать такой список для использования в описаниях форм в xml? Первой мыслью было сделать свой тип поля, расширяющий стандартный \Joomla\CMS\Form\Field\ListField. Однако, в ядре Joomla нашёлся уже готовый класс поля для группированных списков \Joomla\CMS\Form\Field\GroupedlistField. Он расширяет напрямую FormField и имеет 2 метода - getGroups() и getInput().
В getInput() вызывается метод getGroups() для получения массивов с группами опций и его можно было спокойно заменить на getcollectLayoutData(), где этой работе самое и место, но это не слишком принципиально. И там и там работа делается. Поэтому нас интересует именно метод getGroups().
Мы создаём свой класс поля, расширяем GroupedlistField. Делаем обязательно свой $type для поля и реализуем метод getGroups(). Всё.
<?php
use Joomla\CMS\Form\Field\GroupedlistField;
use Joomla\CMS\HTML\HTMLHelper;
class ServerschemelistField extends GroupedlistField
{
// type совпадает с именем файла и класса
// без суффикса 'Field'
protected $type = 'Serverschemelist';
/**
* Method to get the field options.
*
* @return array The field option objects.
*
* @throws Exception
*
* @since 1.0.0
*/
protected function getGroups(): array
{
// наши группы
$group1 = [];
$group2 = [];
// Собираем первую группу опций
foreach ($data as $item) {
$optionattr = [];
// Атрибуты для <option>
if ($something_happend) {
$optionattr['option.attr'] = [
'selected' => 'selected',
'onclick' => 'earthQuake()',
'showon' => 'field1:value1000',
];
}
$group1[] = HTMLHelper::_(
'select.option',
$item->option_value,
$item->option_label_text,
$optionattr
);
}
// Аналогично собираем $group2
// ...
$groups = [
['Имя группы 1'] = $group1,
['Имя группы 2'] = $group2,
];
// В parent::getGroups() будут значения
// из xml-описания формы, если они есть.
// Соединяем их с нашими.
return array_merge(parent::getGroups(), $groups);
}
}
Код может сломаться — и это нормально. Другой вопрос: сколько времени уйдет на исправление багов. Залетайте на нашу витрину курсов по разработке — узнаете как работать с любыми ошибками. Ну, кроме случая, когда на клавиатуру залез кот — тут уж никакое тестирование не поможет.
Лутаем Open Source #24. Они наконец-то починили MongoDB! Перенеся его на PostgreSQL...
DocumentDB – БД от Microsoft, которая состоит из 3-х частей:
PG расширение, добавляющее BSON формат (написанный, на С)
CRUD API поверх него (С)
Сервис трансляции Mongo Query в SQL (Rust)
GitHub - documentdb/documentdb: MongoDB-compatible database engine for cloud-native and open-source workloads. Built for scalability, performance, and developer productivity.
И вроде как: "PG – классная база, а MongoDB Query + BSON популярные технологии" – и можно было бы поразмышлять чем это круто, но сначала важно ответить на один туманный вопрос: "кому такая БД может быть нужна?"
Классический PG
Сначала рассмотрим кейс, когда мы накладываем DocumentDB на обычный PostgreSQL.
Те, кто используют MongoDB если попробуют переехать на такой сэтап столкутся с тем, что:
Там нет шардинга (и насколько бы он не был сложно реализован в MongoDB, он есть и им активно пользуются)
Придется использовать двойной тулинг: Compas, чтобы наблюдать за корректностью данных с MongoDB Query, и SQL если надо посмотреть что там внутри
MongoDB поддерживает Uncommitted Read и Write Majority, что странно накладывается на PG: если разраб достаточно продвинутый и намеренно использовал Uncommitted, то с PG он потеряет скорость и Availability из-за PG Committed, а если он использовал Write Majority, то PG не совсем дает такую гарантию (обвал диска при WAL репликации – менее надежен, чем Write Majority)
А самое главное: когда ты работаешь с MongoDB ты можешь открывать 1000 коннекшенов и он вполне себе все это сожрет, потому что (1) коннекшен это тред, (2) при запросах нет никакой проверки реляционной целостности, да и в целом проверка сильно проще, чем в PG, а значит придется потанцевать с пуллерами и даже менять где-то запросы, чтобы не упасть по скорости
То есть, у mongo-юзеров это заберет все особенные фичи MongoDB и при этом не даст фишки PostgreSQL.
Distributed PG-like
А что, если мы положим DocumentDB на что-нибудь из серии CockroachDB, YugabyteDB, AWS Aurora, Citus или Neon?
Все 3 проблемы решаются:
Шардинг из коробки
Достаточно высокая скорость записи и чтения
Отсутствие проблем с коннектами
В такой ситуации DocumentDB начинает играть новыми красками.
Но если в Neon и Citus (и может YugabyteDB) еще есть шанс добавить текущий DocumentDB BSON плагин, то в для других представителей придется писать его с нуля (причем под каждый свой, потому что они построены каждый на своем KV хранилище).
Переезд в Linux Foundation
А еще они сейчас в процессе переезда из Microsoft в Linux Foundation, из плюсов они будут полностью под MIT лицензией и пейвола, за который будут прятать полезные фичи, из минусов, Microsoft могут и забросить, а никто другой не подхватить.
Итоги
Неоднозначная технология, пока имеет смысл в каких-то тонких кейсах, но в общем и целом, не вижу пока где тут middle-ground, может, вы что-то подскажете?