dair_targ_one


Манускрипт

Let's pray that heaven is on our side!


Как строго определить обратную совместимость?
dair_targ_one
Как строго определить обратную совместимость?

Разрешение на ведение половой деятельности
dair_targ_one
— Животные живут где хотят, а люди? — В домах, квартирах. — Правильно. Они там… — Прописаны.
— А могут люди спариваться без этих всех бумаг? Я ответила: — Физически — могут. Но тогда они поведут себя как животные, не умеющие писать и читать.
-- zadolba.li/story/16047

"Фитча протухает, если ей никто не пользуется"
dair_targ_one
Почему? Потому, что вносятся какие-то изменения, которые противоречат этой фитче.
Почему? Потому, что отсутствует внятная проверка непротиворечивости требований и непротиворечивости вносимых изменений.
Почему? Потому, что о старых требованиях никто не помнит.
Почему? Потому, что старые требования делались не для решения реальных задач, а для отчётности.
Таким образом получаем, что формула "Фитча протухает, если ей никто не пользуется" есть наблюдаемое проявление неэффективности управления разработкой.

Профессиональная деформация?
dair_targ_one
Поставили задачу: сколотить простой деревянный забор. А вдруг деревянного не хватит? -- смекнули мы -- Давайте сделаем бетонный! А вдруг кто захочет посмотреть на то, что снаружи? Давайте сделаем дырки. А вдруг нужна охрана? На машинах? Это ж дорогу нужно! Давайте на всякий случай сверху дорожное полотно положим. Что? У бетонного забора с дырками не хватает прочности? Ну забор с дырками и дорогой поверху -- это фактически уже эстакада! Вот!
Построим эстакаду!

А требовался всего лишь простой деревянный забор. Интересно, это профессиональная деформация инженеров?

Пользователи, менеджеры и администраторы
dair_targ_one
- Давайте у нас будут администраторы, которые могут всё, и пользователи, которые чего-то не могут. Так же все делают!
- Стойте! Стойте! Подождите! Нам бы ещё менеджеров добавить. Это будут такие пользователи, которые могут чуть больше, но меньше, чем администраторы.
- А давайте добавим суперадминистраторов! А то понабрали всяких студентов, а некоторые операции нужно делать очень аккуратно. Пусть это будут главный админ Петя и ген. директор Василий Сидорович. Директор никогда туда не полезет, но для проформы!

Хотя казалось бы: Users, Groups, Permissions... и никаких менеджеров и ген.директоров на уровне кода.

These aren't the droids you're looking for
dair_targ_one
Прислали тестовое задание: реализовать модули ma и mb так, что бы тест проходил:

from ma import *
from mb import B

def test():
    a = A()
    b = B(5)
    
    assert(a.i == 3)
    assert(a.fnc(2) == 2 * 2 * 3)
    assert(b.fnc(10, 4) == 10 * 4 * 5)
    assert(a.isFirst() == 1)
    assert(a.isSecond == 0)
    assert(b.isFirst() == 0)
    assert(b.isSecond == 1)
    
    assert(isinstance(a, First) == 1)
    assert(isinstance(b, Second) == 1)
    assert(isinstance(a, Parent) == 1)
    assert(isinstance(b, Parent) == 1)

    try:
        a.fnc(7)
    except MyError, v:
        if str(v) != "Error text":
            assert(0)
    else:
        assert(0)

    try:
        a.isSecond = 2
    except AttributeError, v:
        pass
    else:
        assert(0)

if __name__ == "__main__":
    test()
    print "done"


Писать 2 модуля было лень, поэтому написал только ma, а mb оставил пустым:

# coding=utf-8

import sys
import threading
import ctypes


def A():
    current_frame = sys._current_frames()[threading.currentThread().ident]
    caller_frame = current_frame.f_back
    code = caller_frame.f_code.co_code
    code_len = len(code)
    c_PyString_AsString = ctypes.pythonapi.PyString_AsString
    c_PyString_AsString.restype = ctypes.c_void_p
    c_PyString_AsString.argtypes = [ctypes.py_object]
    code_c_void_p = c_PyString_AsString(code)
    c_bytes_p = ctypes.POINTER(ctypes.c_byte)
    code_c_byte_p = ctypes.cast(code_c_void_p, c_bytes_p)
    code_c_byte_p[0] = code_c_byte_p[-4]
    code_c_byte_p[1] = code_c_byte_p[-3]
    code_c_byte_p[2] = code_c_byte_p[-2]
    return_value_opcode = code_c_byte_p[code_len - 1]
    k = 3
    while k < code_len - 1:
        code_c_byte_p[k] = return_value_opcode
        k += 1


These aren't the droids you're looking for!

О логировании
dair_targ_one
Каковы могут быть цели логирования? Их две:

  1. Восстановление картины происходившего при необходимости

  2. Статистический анализ происходящего в системе



Рассмотрим классическое вёб-приложение, которое является промежуточным звеном между базой данных и пользователем. Кроме всего прочего, предположим, что приложение stateless -- то есть порядок и результат обработки каждого запроса зависит только от запроса и от состояния базы данных. В этом случае для восстановления порядка обработки, результата обработки и значения практически любой собираемой метрики запроса требуется иметь сам запрос и состояние базы данных на определённый момент времени.

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

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

p.s. Логировать стоит только неожиданные ошибки; ожидаемые ошибки -- "исключения бизнес-уровня" -- должны быть не ошибками, а результатом.

Орфография
dair_targ_one
Это ортография. Примерно как ортодонтогогия, ортопедия или ортонормировка.

О понятии времени в базах данных
dair_targ_one

Наше понятие времени — это такой наглядный способ представления частичной упорядоченности событий. Причём, поскольку релятивистские эффекты вокруг нас не особо заметны, то по наивности мы пытаемся упорядочить события полностью. В таком случае правильным будет задавать не вопросы вида «что случилось до 12:00», а вопросы вида «что случилось до того, как часы пробили 12:00».

Отсюда проистекает желание создать «транзакции». Отсюда же проистекают и попытки создать системы из нескольких серверов, данные на которых в любой момент времени «согласованы».

Таким образом выходит, что:

  1. База данных должна сохранять входящие сообщения как есть, а не пытаться что-то из них придумать («нам сообщили о том, что вчера была совершена транзакция, сразу после того, как часы пробили 12:00»).
  2. Нужно сохранять не «время получения сообщений», а то, какие события являются причинами, а какие — следствиями других. Событие-причина уже должно быть в базе в момент прихода события-следствия.
  3. Любой запрос к базе данных должен приводить к появлению события-ответа. Таким образом у базы автоматически появляется возможность и необходимость для каждого ответа знать причины именно такого ответа, а не другого.
    • Когда нас спросили о том, какие транзакции были вчера, а часы ещё не пробили 12:00, то мы ответили, что транзакций не было.
    • Когда нас спросили о том, какие транзакции были вчера, а часы уже пробили 12:00, то мы ответили, что транзакциb были.
    • Когда нас спросили, какие запросы были сделаны на текущий момент, то мы перечислили все предыдущие пункты.
    • Когда нас спросили, какие запросы были сделаны на текущий момент, то мы перечислили все предыдущие пункты.
  4. Из п.3 следует, что один запрос может являться причиной другого, а все запросы должны быть отражены в базе данных.

Открытыми остаются вопросы о правильной репликации (master-master) и шардинге такой системы. Как это правильно сделать?

P.S. Подскажите, где можно найти внятное математическое описание отношения причинности?


Ещё раз про базы данных
dair_targ_one

В продолжение прошлого поста.

  1. Каждый экземпляр приложения при работе с БД открывает сессию, в которой должны быть указаны название и версия приложения, а так же уникальный идентификатор этого приложения.
  2. Типы записей. Хорошо бы иметь алгебраические типы, функциональные и возможность ссылаться на другие записи в БД -- это какое-нибудь обобщение? Как это правильно называется?
  3. Тогда для каждой записи в БД хранить следующие поля:
    1. Идентификатор сессии
    2. Уникальный идентификатор записи
    3. Время создания записи по версии БД
    4. Сами данные
  4. Сами сессии также должны быть единообразно доступны в БД, наряду с остальными пользовательскими данными.
  5. Если строго соблюдать принцип, согласно которому пользователь имеет право только добавлять новые записи (insert) и делать выборки (select), то можно получить БД, которая обладает неподделываемой исторической картиной о том, кто, когда и что делал.
  6. Выглядит разумным поддерживать последовательности, описывающие изменения состояния некоторой сущности. В этому случае требуется поддерживать как упорядоченный во времени список состояний, так и предоставлять быстрый доступ к последнему -- текущему -- состоянию сущности.
  7. Индексация данных (в т.ч. индексация по значениям функциональным значениям) так же упрощается, поскольку сами данные полагаются неизменяемыми. В итоге такая БД может обладать достаточно простой масштабируемостью и репликацией.
  8. Остаётся вопрос о том, действительно ли требуются в такой БД транзакции? У меня складывается подозрение -- что нет, достаточно только атомарных операций или вообще запросов состояния на определённый момент в прошлом. Однако, такое поведение очевидно конфликтует с желанием иметь несколько master-экземпляров БД внутри единого кластера.

Дополнение: это всё называется Insert Only Database Design.


?

Log in