Category: техника

Category was added automatically. Read all entries about "техника".

tylor

Про тасктрекеры

Много раз обсуждал лично и по скайпу своё видение тасктрекера, как продукта, который мне было бы интересно делать (и приятно пользоваться). В принципе, тасктрекер с открытыми настройками схем данных это основа автоматизации абсолютного большинства информационных процессов. Добавлением новых схем и небольшой бизнес-логики из него получаются CRM, ERP, PLM и многие другие системы. Причём, количество обособленных UI-представлений для них минимально, большинство сценариев работы покрываются общими механизмами таблиц и форм.

Однако, примеров подобных решений мне было известно ноль. Всё либо узконишевое, либо монолитно-хипстерское, либо кое-как настраиваемое через ады бюрократии. А недавно наткнулся на Podio (podio.com), и оно внезапно оказалось вот таким сервисом, наиболее близким к моему видению подобных систем. Причём, уже несколько лет существующим.

Там нет многих вещей, которые я считаю необходимыми. Общих вьюх работы со временем, аутлайнеров, встроенного контроля версий, развитых механизмов прав доступа, etc. Но у других этого (в удобном виде) тоже нет. А вот необходимая многопредметность, которая есть в Podio, это уже круто. Мне бы больше понравился отдельный продукт (а ещё больше продукт с исходниками), но большинство людей готовы доверить свою информацию сервисам, так что с точки зрения бизнеса такая модель более удачна.

Что мне особо приятно наблюдать, так это подтверждение жизнеспособности идеи универсального тасктрекера. А что непонятно - почему информация о более развитых продуктах/сервисах доходит так долго, в то время как очередные реализации всё той же старой бумажной бюрократии постоянно на слуху?
flow

О специалистах

За последнее время уже столько раз отвечал, что решил вынести из комментариев к http://justy-tylor.livejournal.com/231069.html в отдельный пост:

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

Типы для реальности

Тут последнее время всё всплывает вопрос - как совместить систему типов и сущности реального (или возможного) мира. Спрашиваете - отвечаем.

История.

Системы типов в computer science работают с абстракциями. Есть тип ЦелоеЧисло, есть значение 100500. А если тип ЦентрифужныйНасос, то он суть product type (структурка, класс, ...), который может содержать в себе некие значения в связи с центрифужными насосами. Онтологи это неодобряэ, дескать, надо в системе типов различать индивид Насос№123 (реальный, физический) и структурки, представляющие малый срез его качеств. Поэтому пишут свои системы типов, где всё заведомо правильно и одобрено Аристотелем, прекрасно записывается на слайды PowerPoint и глиняные таблички, но не работает.

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

Решение.

Представьте себе такой product type:
struct vector2d { float x; float y; };
Значения этого типа содержат пару float, а вот сам тип содержит в себе множество геометрических смыслов, с которыми работает непосредственно человеческий разум. Какие-то из этих смыслов можно воплотить в коде функций/методов, другие остаются в реальном мире.

Идём дальше, рассматриваем тип беззнакового целого uint32_t. Чуть ниже уровнем это тоже product type. 4 байта, 32 бита, есть некий побайтовый layout (big-endian или little-endian), который различается между платформами. Таким образом, у vector2d, uint32_t и float есть некий битовый "хвост". Причём, длина этого "хвоста" идентична для float и uint32_t. Разница лишь во вне-битовых смыслах реального мира, которые, опять же, могут быть частично выражены в каких-либо программных аспектах.

Но бывают и unit types, где кроме указания типа ничего нет. Классы и структуры без полей, конструкторы алгебраических типов без параметров, etc. Такой тип содержит исключительно смыслы реального мира. Соответственно, "мистические онтологические индивиды" могут быть представлены обычными unit types. Для типа Насос№123 его "хвост" находится в реальном (или возможном) мире. Этот тип - множество все темпоральных частей данного насоса. Аналогично, тип ГородОдесса - множество темпоральных частей реально существующего города. И описывать качества этих сущностей или какие-либо требования к ним мы можем точно так же, как с обычными типами, используя богатые (или не очень) возможности языка - методы, type classes, etc.

Однако, как нам выразить деятельностное требование, что в каких-то контекстах можно указывать только Город, а в каких-то только Насос? Здесь предлагаются множества, sum types.

Первый случай - variant, экстенсиональное определение.

Во многом похож на реализацию алгебраических типов в Haskell, но с важным отличием - вместо конструкторов типов используются полноценные product types и unit types, поэтому не требуется создавать дубликаты одинаковых смыслов для разных variant.
data CardinalDirection = N | S | W | E
data CompassDirection = N | S | W | E | NW | NE | SW | SE
В Haskell такое повторение не допускается, но при интеграции данных такая возможность необходима. Надо, чтобы в каждом variant, предусматривающем состояние paused, вместо MY_ENUM_BLABLABLA_PAUSED использовался standard_dictionary.paused, с подходящим и хорошо документированным набором смыслов.

Второй случай - tag, интенсиональное определение. Ближайшие аналоги - классификация, type classes, type families. Для сущности Насос№123 ставятся тэги Оборудование, Насос, ЦентрифужныйНасос. В свою очередь, на ЦентрифужныйНасос может быть поставлен тэг ВидНасосов.

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

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

Метаданные

Вот есть у нас бинарный контейнер. С музыкой, например. Очень естественное желание - хранить в нём же метаданные - Artist, Album, etc. Но где-то ещё надо хранить контекстные метаданные - от "пять звёздочек", "три звёздочки" и "количество проигрываний пользователем" до "учитывать этот файл при автоподборе сетов для вечеринок". Вне самого файла. При этом, совпадение формата внешних метаданных с форматом внутренних и наличие однозначного механизма идентификации файла из внешних метаданных это разумные требования для дизайна бинарных контейнеров, надо их учитывать, чем сейчас и занимаюсь.

Тема внешнего хранения метаданных ранее была затронута в комментариях к http://justy-tylor.livejournal.com/189379.html Как и вариант их хранения прямо внутри индексов файловой системы, который мне кажется не самым удачным. А детальное рассмотрение вопроса приводит к такому парадоксальному выводу: даже те метаданные, хранение которых обеспечивается распространёнными файловыми системами, должны находиться вовсе не там.

Метаданные о времени создания/изменения файла практически невозможно использовать для идентификации версий файла, эффективность как у гадания на кофейной гуще. Их автоматическое применение в пайплайне с архиваторами и разными таймзонами ведёт к 100% попаданию на грабли.

Для упорядочивание пришедших файлов необходимы метаданные о времени скачивания/копирования, источнике, тэгах источника по отношению к файлу. Для рабочих файлов - полноценная система контроля версий. Существующие мета типа "какое-то время" бесполезны.

Права доступа файловой системы хороши для нескольких пользователей на удалённом сервере. При наличии физического доступа к нешифрованому диску они фикция. А необходимой на десктопах/ноутах возможности детально расписать права для приложений в файловой системе нет. Так может и не должна файловая система заниматься правами? Есть примеры апачевского .htaccess и других конфигов, где понятным образом описываются достаточно сложные правила доступа/редиректа, и без того ада потеряных идентификаций, который любят показывать механизмы управления доступом NTFS.

Вместо корявых метаданных файловой системы нужны внешние метаданные в файлах. Например:

.access -- определяет права доступа для файлов и поддиректорий, по аналогии с .htaccess

.tracking -- информация о том, что файл "имя" в [дата+время] скачан с [URI], где сопровождался тэгами [fun, english humor], а затем в [дата+время] был с десятком других скопирован сюда из "D:/inbound".

.fts-index -- индекс полнотекстового поиска по документам директории и поддиректорий.

.some-media-tags -- та самая информация про три звёздочки и что учитывать в сетах для вечеринок.

.git -- контроль версий, как сейчас.

При каких-либо действиях в директории операционная система запрашивает и оповещает соответствующие сервисы. Если в задействованных в операции директориях (и над ними) отсутствуют .fts-index и .some-media-tags, то эти сервисы не используются.

А файловая система занимается только своими задачами - идентификация, владение и хранение.
flow

Скобочки

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

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

В ситуациях res = (2+2)*3 или f (a*x+b) содержимое скобок себя идентифицирует. Введение промежуточных этапов вроде sum = 2+2; res = sum*3 не требуется.

В ситуации process_information_using (... полкило матана ...) (... запрос из базы, ад, коровники, джойны ...) получается write-only код в традициях APL. Длинный код в скобках просто не воспринимается. Для читаемости необходимы промежуточные модальности и идентификации.

При дизайне текстового представления это ведёт к такому решению: в каждой строке соблюдается баланс скобок, нельзя поставить открывающую скобку в одной строке, а закрывающую где-то в следующих. А совмещение крупных групп ситуаций с их модальностями (контекстами, уплавляющими конструкциями, см. http://justy-tylor.livejournal.com/191741.html) осуществляется не скобками, а индентацией.

modality1:
  situation1
  situation2
  modality2: situation3
  situation4
  situation5
  modality3:
    situation6
    ...

Индентация в 2 пробела, никаких табов, обязательный баланс скобок в пределах строки. Так максимизируется читаемость, и текстовое представление становится ближе к представлению в виде дерева, что особо удобно для описания данных. Добавим фолдинг лесенкой в редакторе и получится нормальное дерево, в котором можно просматривать и модифицировать инженерные датасеты приличного объёма.

В бинарном представлении (для контейнеров и протоколов) тоже есть свой вопрос скобок. А именно, позволять или не позволять указание каких-то выражений внутри бинарных ситуаций. Когда одним из аргументов ситуации является какой-нибудь vector3f, то такого вопроса нет - нам даже не нужен маркер типа vector3f, мы просто пишем три флота. Однако, если используются не только product types, но и sum types, то либо придётся создавать некий словарь констант, либо надо инлайнить данные прямо в ситуацию с использованием маркера типа, т.е. те же скобочки.

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

Решение находится на уровне системы типов. Например, в словарике для микроконтроллера все ситуации (такие как "изменить значение регистра") идентифицируются одним байтом, регистры также идентифицируются байтами, булевы значения передаются как bool1, а sum types просто отсутствуют. Получается аналог Modbus.

А в словаре управляющей системы, которая с ним работает, идентификация "регистр 7 контроллера 3" уже мэппится на идентификацию boat.navigation_lights, которая при передаче инлайнится непосредственно по месту использования или упоминается ссылкой на словарь констант (смотря какие типы вы установите), а также имеет тип значения bool32. И именно в таком виде информация передаётся на навигационный компьютер яхты.

Один текстовый синтаксис, один бинарный протокол. Разные словари и типы. И сначала надо допиливать именно бинарную часть, систему типов, а текстовый сахар... с ним, в принципе, уже всё ясно.
flow

Как избавиться от динамической типизации

Давно хотел оформить subj в один пост, а сейчас и срачи подоспели в тему:
http://thedeemon.livejournal.com/54732.html
http://belnetmon.livejournal.com/2093044.html
http://metaclass.livejournal.com/735575.html

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

Когда в языке с динамической типизацией пишется obj.width = 132, то мы и так заранее знаем, что width всегда int (или что-то ещё известное, в зависимости от архитектуры системы). Нет ситуаций, когда в width должен содержаться экземпляр какого-нибудь HTTPConnection или иной мусор. Однако, width может отсутствовать, если данный obj не используется в ситуациях заведомо требующих наличия width, а используется только там, где width не требуется, или наличие дополнительно проверяется.

Это типичная ситуация для САПРов, где таких width, которые есть или нет, могут быть сотни и тысячи. Обычных product types и sum types оказывается недостаточно. Поэтому в САПРах всегда своя система типов, отличающаяся от системы типов хост-языка. Можно добавлять пользовательские свойства (как строки), хотя не во всех системах можно регистрировать ограничения на их типы (что значением "mywidth" всегда будет целое число). В языках с динамической типизацией об этом вообще не думают, объект является контейнером Map(строка->хзчто). Бардак.

Системное решение такое: вместо случайных строк ключами в контейнере должны быть полноценные identity, а типы хранимых значений должны однозначно соответствовать им. Назовём такой тип контейнера multidomain.

Далее, для обычных структур (product types) мы используем описание самой структуры при трансляции a = ent.width, а для multidomain придётся добавить описания необходимых свойств:
type physical.width = pair float UoM
type ui.width = int
и использовать как
b = ent physical.width // получить значение или ошибку времени выполнения
c = ent maybe ui.width // получить Just значение или Nothing
со строгим контролем типов.

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

Кроме того, multidomain контейнеры подходят не только для "ад, коровники, энтерпрайз", описаний винтиков и жизненного цикла нефтяной платформы, но и для описаний самих типов данных, включая пользовательские traits.