Обновить

Бэкенд

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

Читаемость Си-кода: грустный ликбез, чтобы жить стало веселее

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

И всему виной (ожидаемо) выражения препроцессора и, как следствие, макросы. Да, вы правильно подумали. Именно те части кода, в которых вызываются такие легенды как:

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

#if defined // вместо #ifdef
#if !defined // вместо #ifndef

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

Чего далеко ходить - все open source проекты пестрят именно сокращенными вариантами этих выражений и с этим уже ничего не поделаешь.

А вот первое выражение из первой тройки игроков иногда вообще открывает врата ада, когда используется многострочный макрос с бэкслэш-символами (\) на концах строк.

Конечно же выражения препроцессора - это очень гибкий и полезный инструмент, позволяющий делать всё:

  • условную компиляцию;

  • выравнивание структур;

  • предотвращать повторные включения файла;

  • работать со строками;

  • грамотно оборачивать повторяющийся код и т.д. и т.п.

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

struct {
  const char *name;
  const char *value;
#define _SPECIAL(x) { .name = #x, .value = b->x, }
} specials[] = {
  { .name = "object", .value = b->object_string, },
  _SPECIAL(host),
  _SPECIAL(endpoint),
#undef _SPECIAL
};

*ну все, можно начинать грустить*

Чтобы разобраться, давайте очистим код от макросов, но сохраним суть:

struct {
  const char *name;
  const char *value;
} specials[] = {
  { .name = "object", .value = b->object_string, },
  { .name = "host", .value = host, },
  { .name = "endpoint", .value = endpoint, },
};

Что понятно из очищенного варианта:

  • инициализируется массив specials[];

  • типом данных этого массива является структура с полями *name и *value;

  • поля элементов массива задаются вручную.

Но как можно этот процесс немного автоматизировать и не прописывать вручную одинаковые строки?

Правильно, с помощью макроса:

#define _SPECIAL(x) { .name = #x, .value = b->x, }

который определяется после объявления полей структуры.

Как обрабатывается аргумент x:

  • имя аргумента преобразуется в строку с помощью макроса "#x" и присваивается полю *name;

  • полю *value присваивается значение поля структуры b с названием аргумента x (тут нужно убедиться, что поле с именем x действительно существует в структуре b).

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

{ .name = "host", .value = host, },
{ .name = "endpoint", .value = endpoint, }

можно вызвать выражение _SPECIALS:

_SPECIAL(host),
_SPECIAL(endpoint),

Ну и в самом конце вызываем удаление созданного макроса, чтобы оно не было использовано в коде в дальнейшем:

#undef _SPECIAL

Теперь после прочтения этого небольшого ликбеза вы можете смело пользоваться макросами и создавать более сложные и нечитаемые шедевры наконец-то разобрались в том, насколько гибкими могут оказаться выражения препроцессора ( вообще не понимаю, как вы жили без них раньше...)

А какие выражения и макросы в Си видели вы?

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

🗯️ Про метрики на отдельном порту.

Далее про то как сделать выделенный порт и http-пулл для promitheus-метрик, так вот докладываю👇

Мы используем embedded tomcat как и великое множество других Java-проектов(остальным сил и терпения), по этому этот пост применительно к нему.

📍Для создания выделенного порта достаточно создать отдельный коннектор спринговой java-конфигурацией и проинициализировать его через TomcatServletWebServerFactory.

❕Стоит обратить внимание что на данном порту будут доступны вообще все сервлеты доступные и на стандартном порту, но при наличии разграничения доступа обычно это не является проблемой.

P.S. Не хочу быть злом по этому в комменты в свою телегу выложу класс в текстовом варианте😁

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

Опасности Apache POI 📍

Наверняка многие из вас юзают Apache POI. Для тех, кто не знает: это джаванская либа для работы с файлами Microsoft Office и OOXML — всякие Excel, Word и прочее.

А в чём опасность?

При генерации Excel-файла эта библиотека позволяет включить отслеживание ширины данных в колонках и автоподгонку ширины столбцов под содержимое (чтобы данные не скрывались из-за маленькой ширины столбца по умолчанию).

Включается это так:
// Отслеживаем ширину для автосайзинга
sheet.trackAllColumnsForAutoSizing();
// ... генерируем строки Excel-файла
// Автосайзим столбцы
sheet.autoSizeColumn(columnIndex);

Проблема: эта тема крайне ресурсоёмкая на больших объёмах данных. На тесте с 100 строками — всё быстро. На проде с 600К строк — 20 минут превращаются в 4 часа. 4 часа, Карл! Чего оно там делает вообще?!)

У нас такое не раз уезжало в прод и штука эта совсем неприятная я вам скажу:

  • Отчёт не собирается вовремя;

  • Заказчик негодует;

  • Паника, крики — в общем, ну его этот трекинг! 😅

Что делать?

В 99% случаев: достаточно автосайзинга только для заголовков:

// Включаем автосайзинг
sheet.trackAllColumnsForAutoSizing();
// Генерируем заголовки
//...
// Автосайзим колонки
sheet.autoSizeColumn(columnIndex);
// Выключаем трекинг
sheet.untrackAllColumnsForAutoSizing();
//... продолжаем генерацию

В 1% случаев: нужно отавтосайзить 1-2 столбца из сотен. Тогда делаем точечный трекинг:

// Трекинг только нужных колонок
sheet.trackColumnForAutoSizing(columnIndex);
// ... генерация данных
// Автосайзим
sheet.autoSizeColumn(columnIndex);

Ну и можно конечно вручную задавать ширину столбцов, но это не всегда удобно.

P.S. Метод autoSizeColumn() очень тяжёлый. Выдержка из джавадоки:

Этот процесс может быть медленным на больших листах, поэтому его стоит вызывать только один раз для каждого столбца в конце обработки.

P.S.S. Еще кстати поя умеют не буферизовать весь excel’ник в память при генерации, надеюсь вы все этим пользуетесь ибо обратное дико некармическая тема)) Знаете ж как?

Приходите к телегу, там обсуждаем наши кровавые энтерпрайзы: https://t.me/umenyarabotaet

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

В 2ГИС мы пишем на Go и помогаем инженерам перейти на него с других языков. Знакомство с Go открывает возможность контрибьютить в одну из самых востребованных технологий современности. На Go написаны проекты, без которых сложно представить мир распределённых систем: K8s, CockroachDB, Badger, Prometheus, VictoriaMetrics, Jaeger, NATS, Temporal. 

Переход на Go — реальность! В карточках рассказываем, как это получилось у Саши

Хочешь так же? Прямо сейчас ищем ребят с Java и C#.

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

Доброго дня. В этом посте хочу описать способ развертывания приложений в Docker на Linux сервере без использования реестра. Для этого нужно:

  1. Сохранение образа docker save -o myimage.tar myimagename

  2. Передача файл myimage.tar на сервер по FTP или любым другим способом

  3. Загрузка образа docker load -i myimage.tar или podman load -i myimage.tar

Такой способ позволяет разворачивать Docker‑образы без использования реестра — просто, удобно и быстро. Если у вас по любой причине нет реестра, но хочется использовать Docker, вы можете найти это полезным. Надеюсь, кому‑то пригодится в реальной практике. Если вы используете другие подходы или автоматизируете процесс — поделитесь в комментариях. Спасибо за внимание!

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

Привет, Хабр. Делимся подборкой ближайших открытых уроков. Это вебинары с преподавателями-практиками, где можно разобраться в теме и задать вопросы экспертам. Участие бесплатное, требуется регистрация.

29 апреля, вторник:

30 апреля, среда:

5 мая, понедельник:

6 мая, вторник:

Список всех открытых уроков по всем ИТ-направлениям можно посмотреть в календаре.

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

PEP 750: t-строки в 3.14

Недавно ревьюил один интересный PR в CPython: в питон добавили еще один способ форматировать строки. Теперь – со специальным АПИ для внешних интеграций. Расскажу: как и зачем.

Основная причина: использовать f строки удобно, но нет никакого АПИ для перехвата момента "вставки" или интерполяции значений. Например, при форматировании html или sql – требуется специальным образом делать escape для значений. И раньше код вида f"{template}" представлял собой дыру в безопасности и потенциальное место для XSS.

string.templatelib.Template

Новый префикс t не будет создавать объект str, он будет создавать объект класса string.templatelib.Template:

>>> user = 'sobolevn'
>>> template = t"Hi, {user}"
>>> template
Template(strings=('Hi, ', ''), interpolations=(Interpolation('sobolevn', 'user', None, ''),))

>>> from string.templatelib import Template
>>> isinstance(template, Template)
True

Обратите внимание, что при создании template – у нас не произошло форматирование сразу. Мы создали объект, у которого есть свойства strings и interpolations, из которых можно собрать финальную отформатированную строку.

Давайте посмотрим на примере. Допустим, мы хотим формировать URL из наших данных:

>>> domain = 'example.com'
>>> query = 'python string formatting is too complex'
>>> template = t'https://{domain}?q={query}'

И сам код логики форматирования, где мы будем вставлять значения разным способом. Если у нас шаблон query, то мы будем использовать quote_plus для его форматирования. Остальные значения – будем вставлять как есть:

>>> from string.templatelib import Template, Interpolation
>>> from urllib.parse import quote_plus

>>> def format_url(template: Template) -> str:
...     parts = []
...     for part in template:
...         match part:
...             case str() as s:  # regular string
...                 parts.append(s)
...             case Interpolation(value, expression='query'):
...                 parts.append(quote_plus(value))
...             case Interpolation(value):
...                 parts.append(value)
...     return ''.join(parts)

И вот результат:

>>> format_url(template)
'https://example.com?q=python+string+formatting+is+too+complex'

Только теперь наш Template был отформатирован. Нами. Ручками.
У нас есть полный контроль за процессом форматирования. Вот в чем суть данного ПЕПа.

Фичи одной строкой

  • Работает = как обычно в f строках: t'{user=}'

  • Есть привычные определители формата: !r, !s, .2f, тд

  • t строки можно конкатенировать: t'Hello' + t' , world!' и t'Hello, ' + 'world'

  • Поддерживается режим raw строк: rt"Hi \n!"

Как устроено внутри?

Интересные места имплементации:

>>> import dis
>>> user = 'sobolevn'
>>> dis.dis('t"Hi, {user}"')
  0           RESUME                   0

  1           LOAD_CONST               2 (('Hi, ', ''))
              LOAD_NAME                0 (user)
              LOAD_CONST               1 ('user')
              BUILD_INTERPOLATION      2
              BUILD_TUPLE              1
              BUILD_TEMPLATE
              RETURN_VALUE

Обсуждение: как вам еще один способ форматирования строк?

Если понравилось – заходи в тг, где я рассказываю, как я делаю CPython.

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

Для себя я определил архитектуру так:

Архитектура программной системы - это набор ограничений, которые формируют и направляют реализацию системы в сторону максимизации её ценности

Архитектура - это набор ограничений
Архитектура - это набор ограничений
  • Это набор ограничений: архитектура задаёт рамки/правила по которым должна строиться система

  • Архитектура формирует и направляет реализацию: у разработчиков должна быть свобода в реализации, но архитектура задаёт для них ограничения

  • Архитектура максимизирует ценность: ограничения поставлены так, чтобы вписываясь в них система принесла больше ценности. Именно архитектура определяет: какими паттернами реализовывать бизнес-логику, как связываться со сторонними сервисами, из каких категорий будет состоять программный код

И я придумал для этого метафору. Представьте, что мы строим дом. Тогда:

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

Системный дизайнер:
Он как дизайнер интерьеров. Определяет назначение каждой комнаты, учитывая уже наложенные архитектурные ограничения. Где будет гостиная, где спальня, где рабочий кабинет и т.п. И расставляет мебель (структурные ограничения), руководствуясь назначением каждой комнаты (поведенческие ограничения). И всё это так, чтобы живущим в квартире людям было удобно.

Программист:
Это рабочий, который по чертежам дизайнера положит паркет, подключит фурнитуру и соберёт мебель.

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

  • Системный архитектор - senior (опытный программист, способный спроектировать кластер контейнеров)

  • Системный дизайнер - middle (программист, способный спроектировать один контейнер)

  • Программист - junior (любой программист, способный работать внутри контейнера по готовым ограничениям)

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

Работаем в лоб: Прямое редактирование XML форм Joomla

Используя событие onContentPrepareForm можно изменять почти любую форму Joomla, но методов класса Joomla\CMS\Form\Form обычно не хватает для работы со сложными формами (например с полями типа subform).

Но есть простое решение - работать с формой как c экземпляром SimpleXMLElement.

Получаем XML формы.

echo $form->getXml()->asXMl();
die;

Отправляем его в ChatGPT с описанием что и как надо изменить в форме, и просим написать PHP-код.

Например у меня такая форма:

<?xml version="1.0"?>
<form>
	<config>
		<fieldset label="PLG_CONTENT_WISHBOXRADICALMARTCDEKORDERREGISTRATOR_FIELDSET_LABEL" name="wishboxradicalmartcdekorderregistrator"
                  addfieldprefix="Joomla\Component\Wishboxradicalmartcdek\Administrator\Field">
			<field name="wishboxradicalmartcdekorderregistrator" type="subform"
                   label="PLG_CONTENT_WISHBOXRADICALMARTCDEKORDERREGISTRATOR_FIELD_REGISTRATOR_LABEL"
                   buttons="add,remove,move"
                   multiple="false"
                   hiddenLabel="true">
				<form>
					<fieldset>
						<field name="order_number_prefix" type="text"
                               label="COM_WISHBOXRADICALMARTCDEK_FIELD_ORDER_NUMBER_PREFIX_LABEL"
                               default="test_" />
					</fieldset>
				</form>
			</field>
		</fieldset>
	</config>
</form>

И для изменения атрибута default поля order_number_prefix получаем следующий код:

$fields = $xml->xpath('//field[@name="wishboxradicalmartcdekorderregistrator"]/form/fieldset/field[@name="order_number_prefix"]');

$fields[0]['default'] = 'Test ';

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

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

Coding Game. Mad Pod Racing. Игра для программистов.

Coding Game — это онлайн-платформа, которая помогает изучать программирование. В ней вы будете решать различные задачи и головоломки и игры, используя разные языки программирования. Игра доступна бесплатно и подходит для начинающих программистов.

Mad Pod Racing

Mad Pod Racing - это многопользовательская игра (соревнование) для программистов.

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

Вы можете использовать методы оптимизации, нейронные сети и многое другое для решения поставленной задачи.

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

Что такое чистая архитектура: основные особенности

Чистая архитектура — это подход к проектированию систем, который предполагает независимость от фреймворка и вообще от внешних компонентов. Выделяем слой use-кейсов, слой сущностей, UI и презентер — и теперь эти слои и есть наши фреймворки. Поэтому реальный фреймворк в чистой архитектуре можно использовать как инструмент, а не перестраивать весь проект под его ограничения.

Как, по сути, работает чистая архитектура
Как, по сути, работает чистая архитектура

Какие еще свойства чистой архитектуры важны:

  1. Тестируемость. Это значит, что бизнес-правила могут быть протестированы без UI, без баз данных, без веб-сервера и без любого другого внешнего компонента. Например, у нас может быть фронтенд на React и мобилка на Flutter — и мы при этом всё равно можем менять контракты, не меняя бизнес-правила.

  2. Чистая архитектура независима от информационных хранилищ. Можно поменять PostgreSQL на MongoDB или на любую другую СУБД. При этом работа бизнес-правил не изменится. 

  3. Чистая архитектура — это независимость от внешнего сервиса. По факту слой use-кейсов изолирован от внешнего мира, ничего о нем не знает. А знает только о том, как работать в рамках бизнес-системы.

Большой материал о том, на каком проекте была внедрен этот подход и почему выбрали именно его, читайте в блоге.

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

Когда нельзя доверять даже себе

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

В такой среде доверие к собственному коду становится условным. Разработчик ещё способен более-менее контролировать точку входа — HTML-страницу или Node.js-скрипт. Он может доверять тому, что написал сам и вызывает сам. До тех пор, пока не подключит стороннюю библиотеку. А дальше — возможны любые сценарии.

Чтобы можно было доверять своему коду хоть немного больше, я пошёл на эксперимент и по умолчанию встроил "заморозку" всех объектов, создаваемых моим DI-контейнером:

let res = await _composer.create(key, module, stack, this);
if (canBeFrozen(res)) Object.freeze(res);

При запуске node-приложения (или при загрузке кода на веб-страницу) я создаю контейнер и через него получаю нужный объект со всеми зависимостями:

import Container from '@teqfw/di';

const container = new Container();
const resolver = container.getResolver();
resolver.addNamespaceRoot('App_', '/home/user/project/src');
const app = await container.get('App_Main');
app.run();

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

Разумеется, такой подход не делает JS-среду абсолютно безопасной. Но он позволяет немного повысить уровень доверия к тому, что происходит внутри.

Эта идея родилась после прений с коллегой @nin-jin — так что спасибо ему за подброшенную мысль ;) Я реализовал её в коде, опробовал на своих приложениях и вот теперь делюсь результатом.

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

Хотите разобраться, как работает Docker и зачем он нужен?

Тогда новый бесплатный курс — для вас!

Docker — это open source-платформа для создания контейнеров — окружений, где приложения работают независимо от ОС или среды. Технология упрощает перенос приложений между окружениями и ускоряет разработку.

В новом бесплатном курсе мы расскажем, с чего начать: как установить Docker, собрать образ, создать и запустить контейнер. Также познакомимся с Docker Compose и обсудим, чем Kubernetes отличается от Docker Swarm.

Несколько материалов для начала

Приступить к изучению курса →

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

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

Поздравляем с 0x8 марта девушек в IT!

В этом году мы решили не просто на словах поздравить девушек с праздником. Мы сделали видео с девушками и о девушках в IT. На то есть несколько причин:

  • Мы хотим сказать: коллеги, мы вам благодарны за ваш труд! Мы гордимся вами!

  • Мы хотим показать вам реальных людей из разных сфер IT, а не просто цифры в статистике.

  • Надеемся, примеры участниц покажут, что IT — это не для избранных. Здесь есть место каждой, если ей интересно и она этого захочет.

Смотрите видео по ссылкам:

Вдохновляйтесь, делитесь своими историями и отправляйте своим друзьям, коллегам, знакомым и всем, кто имеет отношение к IT!

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

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

Ещё раз о количестве способов набрать сдачу в n рублей из заданного набора монет/купюр

 Вот известная задача: «Имеется неограниченное количество монет достоинством 1, 2, 5 и 10 рублей. Определить, сколькими способами можно ими выдать сдачу в n рублей».

 Я, бывший преподаватель информатики, хочу рассказать профессионалам, экспертам, знатокам и гуру о придуманной мной (если это не «изобретение велосипеда») идее решения задачи без перебора всех возможных вариантов (без четырёх вложенных циклов).

Возможно, эта идея будет полезна в других задачах.

Итак.

При n = 7 все варианты следующие:

1 + 1 + 1 + 1 + 1 + 1 + 1

1 + 1 + 1 + 1 + 1 + 2

1 + 1 + 1 + 2 + 2

1 + 2 + 2 + 2

1 + 1 + 5

2 + 5

 Среди них можно выделить те, в которых минимальным слагаемым является 1. Их – 5. В оставшемся шестом варианте минимальным слагаемым является 2. Вариантов, в которых минимальным слагаемым является 5 и 10, в данном случае нет.

При n = 10 все варианты следующие (без знака +):

1111111111, 111111112, 11111122, 1111222, 112222, 111115, 11125, 1225, 22222, 55, 10,

то есть

количество вариантов с минимальным слагаемым 1 равно 8;

количество вариантов с минимальным слагаемым 2 равно 1;

количество вариантов с минимальным слагаемым 5 равно 1;

количество вариантов с минимальным слагаемым 10 равно 1.

 Подумав (😊), можем сказать, что при n = 11:

· количество вариантов с минимальным слагаемым 1 будет таким же, как общее число всех вариантов для n = 10 (так как разность 11 – 10 не превышает 1);

· количество вариантов с минимальным слагаемым 2 будет равно сумме количеств с минимальными слагаемыми 2, 5 и 10 для n = 9 (так как разность 11 – 9 не превышает 2);

· количество вариантов с минимальным слагаемым 5 будет равно сумме количеств с минимальными слагаемыми 5 и 10 для n = 6  (так как разность 11 – 6 не превышает 5);

· количество вариантов с минимальным слагаемым 10 будет равно такому же количеству для n = 1 (так как разность 11 – 1 не превышает 10).

 Приведённые рекуррентные зависимости применимы для всех значений n, но с некоторыми исключениями – при n = 1 количество вариантов с минимальным слагаемым 1, при n = 2 количество вариантов с минимальным слагаемым 2, при n = 5 количество вариантов с минимальным слагаемым 5 и при n = 10 количество вариантов с минимальным слагаемым 10 будет равно 1 (в перечисленных случаях соответствующие слагаемые появляются впервые).

Допустим, что максимальное значение n равно 99.

В программе, реализующей описанную идею для такого случая, можно использовать двумерный массив из 109 строк и пяти столбцов (10 начальных строк массива являются условными для рекуррентного расчёта значений при n = 1..99).

Вся программа на так называемом «школьном алгоритмическом языке» (система программирования КуМир):

алг
нач цел таб м[-9:99, 1:5], цел n, j
  | Нули, в том числе в фиктивных строках   

нц для n от -9 до 99
    нц для j от 1 до 5
      м[n, j] := 0
    кц
  кц

  | Расчёты
  нц для n от 1 до 99
    если n = 1
      то
        м[n, 1] := 1
      иначе | Рекуррентная зависимость
        м[n, 1] := м[n - 1, 5]
    все
    если n = 2
      то
        м[n, 2] := 1       иначе
        м[n, 2] := м[n - 2, 2] + м[n - 2, 3] + м[n - 2, 4]
    все
    если n = 5
      то
        м[n, 3] := 1
      иначе
        м[n, 3] := м[n - 5, 3] + м[n - 5, 4]
    все
    если n = 10
      то
        м[n, 4] := 1
      иначе
        м[n, 4] := м[n - 10, 4]
    все
    | Последний столбец
    м[n, 5] := м[n, 1] + м[n, 2] + м[n, 3] + м[n, 4]    
  кц
  | Вывод всех значений
  нц для n от 1 до 99
    вывод нс, n, " | ", м[n, 5]
  кц
кон

 Конечно, вместо массива из 109 строк можно использовать 10-строковый массив и после расчёта значений для очередной строки переписать массив, отбросив «хвостовую» строку.

 Спасибо.

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

Вклад инженеров Axiom JDK в развитие OpenIDE

На текущий момент среди разработчиков Java в качестве основной среды разработки применяется IntelliJ IDEA. Однако, коммерческая версия этого и других продуктов JetBrains, включая IDE, Code With Me, Upsource, TeamCity и Space, а также техническая поддержка теперь не доступны в России. Это побудило нас на создание продукта OpenIDE с открытым исходным кодом и всей инфраструктурой, размещенной на территории РФ.

Как было анонсировано ранее, OpenIDE создается на базе исходного кода IntelliJ IDEA CE и будет развиваться в рамках некоммерческого партнерства Axiom JDK, «Группы Астра» и Haulmont. В этом посте мы расскажем о вкладе команды Axiom JDK в проект.

Рантайм Axiom JDK будет предоставляться в качестве выбора по умолчанию для разработки на Java/Kotlin в OpenIDE. Дополнительно будет возможна установка Axiom JDK из интерфейса OpenIDE. При этом релизный цикл Axiom JDK синхронизирован с OpenJDK и регулярными обновлениями.

Команда Axiom JDK будет выпускать и поддерживать рантайм, используемый для запуска OpenIDE, с набором улучшений. Это, например, расширенное переопределение классов c помощью DCEVM и поддержка JCEF фреймворка для встраивания браузера на базе Chromium. Также планируется ряд улучшений для рендеринга шрифтов, поддержка режимов HiDPI, что обеспечит лучшее масштабирование интерфейса пользователя. А еще это позволит исправлять специфичные для работы IDE ошибки, исправлений для которых еще нет в OpenJDK.

Несмотря на то, что исходный код IntelliJ IDEA CE открыт, в процессе работы IDEA обращается к серверам JetBrains для обновлений, поддержки маркетплейса плагинов, а также других нужд. Этот функционал сейчас перерабатывается с участием инженеров Axiom JDK, что позволит создать локальную российскую библиотеку плагинов, локализованный (и отключаемый) сбор статистики и механизм обновления OpenIDE.

Наконец, команда Axiom JDK занимается настройкой сборочного конвейера OpenIDE, и со временем произведет анализ всех OSS зависимостей OpenIDE и будет обеспечивать оперативное исправлений уязвимостей в ОSS зависимостях в рамках релизного цикла OpenIDE.

Релиз продукта намечен на март 2025 года.

Axiom JDK — единственный российский разработчик JDK. Инженеры команды стояли у истоков Java в России и развивают платформу более 25 лет.

OpenIDE можно использовать взамен IntelliJ IDEA CE. По данным нашего исследования, 78% Java разработчиков используют IntelliJ IDEA Ultimate, а 47% - работают на Community Edition. Мы хотим предоставить сотням тысяч разработчиков открытый инструмент, не уступающий по удобству привычным IDE, чтобы они могли быстро и эффективно работать.

Читайте также у нас на сайте и у партнеров на хабре.

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

Готов пример приложения для https://pypi.org/project/targeting-platform/ (библиотека с общим интерфейсом к разным DSP (те которые "A demand-side platform")).

Это в продолжение https://habr.com/ru/posts/829114/

Пример тут: https://gitlab.com/dsp6802915/targeting_platform_example_simple (https://github.com/iSINUS/targeting_platform_example_simple) - в реадми описано все что есть сказать - не буду здесь повторяться.

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

Готова реализация для The Trade Desk (TDD) — как и обещал. Актуальная версия. (https://github.com/iSINUS/targeting_platform)

Пока это «классическая» реализация (с новым подходом что‑то у TTD не задалось). Когда и если они сделают рабочим новый подход (задание локации и времени в парах через BidLists) я обновлю код.

Теперь библиотека умеет вычитывать, устанавливать, очищать и валидировать таргетинг для трех платформ (DV360, Meta, TTD) с единым интерфейсом. При установке опций будут создаваться дубликаты в системах DV360 и Meta — это необходимо когда вы задаете много географических точек (лимиты платформ на объем информации). Внутри методов реализовано кэширование для операций чтения (get_...) и установка блокировок для операций изменения (set_..., clear_... и т. д.). Кэширование актуально для Meta — чтобы не словить Rate Limit на частых операциях получение информации. Блокировки более актуальны для DV360 и TTD — там операции по созданию дубликатов и установке таргетинг опций относительно длительные (но блокировка только внутри библиотеки работает — внешние системы все еще могут изменить тот же элемент системы — для этого у вас есть интерфейс валидации, который поможет проверить что в системе сохранено то, что вы хотели установить).

Базовый набор операций — как вызывать и что возвращает можно посмотреть в интегрейшен тестах — ссылка.

Пользуйтесь, задавайте вопросы.

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

Возможно кому-то пригодится библиотека с общим интерфейсом к разным DSP (те которые "A demand-side platform"). PyPi - https://pypi.org/project/targeting-platform/ (https://github.com/iSINUS/targeting_platform)

Пока реализовано только для Google DV360, Meta и The Trade Desk (TTD) получение каталогов плейсментов. В ближайшее время будет и непосредственно управление targeting на основе геоинформации (Uber H3 и lat/lng). Библиотека не решает проблемы выбора аудитории, она только поможет универсально выставлять таргетирование по локации и времени.

Библиотека это переосмысление более чем года работы на коммерческом проекте (код для всех операций уже есть - вопрос переноса в Open Source только вопрос времени). Будет дополнена документации и возможно пример приложения, но на данном этапе как это использовать можно увидеть в интеграционных тестах.

Область применения достаточно специфическая и требует наличия доступов к платформам. Получить самим (индивидуально) такие доступы можно только к Meta; DV360 и TTD только через Technical Account Manager платформ (только если вы уже такие имеете - сможете их использовать).

Пока комментарии и пожелания не принимаются :), но будут учитываться. (Сейчас это полностью синхронная библиотека, реализация максимально ориентировано на работоспособность, а не показать "как я пишу идеальный код". Если будет кем-либо использоваться библиотека, то реализация получит развитие и улучшения, и возможно новые DSP.)

Продолжение: https://habr.com/ru/posts/827828/ https://habr.com/ru/posts/829114/

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

Возвращение в будущее.

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

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