Обновить
41
ETC.Dema@ETCDema

Пользователь

1
Подписчики
Отправить сообщение

Краткое содержание статьи и каментов автора: "крокодил эффективнее отвертки потому что окно и все несогласные адепты ктулху".


Если много раз и из разных источников слышите фразу "разберитесь сначала", то наверно это не просто так.


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


А вообще, когда начинают приплетать чувства, религию и прочие абстракции, то явно впаривают какую-то дичь.


Обратите внимание на моменты, которые являются однозначными индикаторами понимания, что тут что-то не так:


  1. Движение в двух направлениях — либо нужно всю строку держать в памяти либо делать хитрую буферизацию.
  2. Минимум 4 разнонаправленных прохода по одним и тем же местам строки с произвольной дистанцией:
    1. Найти скобку ->
    2. Найти другую скобку <-
    3. Найти оператор ->
    4. Найти операнд слева <-
  3. Модификация строки: предлагается заменять фрагмент (операции копирования, выделение памяти и прочие радости), плюс для этого нужно число сконвертировать в строку и потом опять парсить
  4. Подмена понятий: использование регулярного выражения это не избавление от посимвольного прохода, это использование чего-то готового.

И коллеги должны поверить, что это эффективнее однонаправленного прохода + использование стэка с числами (сортировочная станция + дерево расчета)?

  1. Расчет чисел фибоначи. Тест из библиотеки fast-memoize
  2. base line x 123.592
  3. fast-memoize x 203.342.420
  4. lodash x 25.877.616
  5. underscore x 20.518.294
  6. memoize-state x 16.834.719
  7. ramda x 1.274.908


Ну — не самый худший вариант.

Хотелось бы уточнить единицу измерения и какое значение (min/max) считается лучшим + не самый худший вариант для кого?

Те, кто делал ремонт дома, знакомы с лазерным дальномером, который вешается на стенку. Внутри секундомер, который считает, за сколько свет туда-обратно слетал, и мы меряем расстояние.

Это с какой же скоростью нужно считывать данные для измерения времени полета фотонов от излучателя к приемнику с учетом точности измерения до 30 000 мм ± 1 мм при скорости света в вакууме 299 792 458 ± 1,2 м/с?


https://ru.wikipedia.org/wiki/Лазерный_дальномер: строительные дальномеры — фазовые.

А топологическая сортировка для определения порядка и логирование измененных полей в цикле пересчета для уменьшения количества вычислений не проще будет?

Хорошее начало, но я бы рекомендовал при усложнении логики бота вместо реализации на контроллерах использовать State Machine т.к. в этом случае можно будет делать более сложную логику общения, реагировать на inline buttons в сообщениях и изменять/дополнять отдельные сообщения, хранить состояние не только в рамках чата/отдельного пользователя, но и отдельных сообщений и работать как через вебхуки, так и через опрос обновлений (отделить способ доставки обновлений от логики обработки).

Тут на самом деле есть один тонкий момент — никто не запрещает написать так:


{
    "StackPanel": 
    {
        "TextBlock": "Hello world",
        "Button":
        {
            "Text": "Click me"
        }
    }
}

но тут встает вопрос с повторением свойств, например:


{
    "StackPanel": 
    {
        "TextBlock": "Hello world",
        "Button":
        {
            "Text": "Click me"
        },
        "Button":
        {
            "Text": "And me!"
        }
    }
}

Парсеры, тот же JSON.parse, при повторении свойства вернет значение именно последнего свойства (работает аналогично инициализации объекта), а вот при потоковом парсинге (например с помощью JsonTextReader из Json.NET) мы увидим все свойства, даже повторяющиеся и можем их корректно обработать. Но это очень холиварный момент. Очень.

Скоро этот пост превратиться в "пост увольнений" судя по тенденции.


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


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


Но каменты забавно почитать — интересно чем закончится.

Косяки с первых же строк. Толсто или максимализм неофита.

Насколько я понимаю вы абсолютно не воспринимаете, что вам пытаются объяснить практически все комментирующие тут люди и подозреваю, что у вас впереди еще много открытий типа промисов, async, замыканий.


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

Ужас-ужас! Ну почему не сделать проще:


...dialog(msg, {
    'Ok':           function(){...},
    'И еще кнопка': function(){...},
    'И еще':        function(){...},
    'и еще!':       function(){...}
},
function() // А вот отмену лучше сделать отдельно и всегда добавлять кнопку
           // + эту функцию можно повесить на другие контролы,
           // например на закрытие окна или клик на placeholder  диалога...
{
    ...
});
Имеющиеся разработки мне не подошли, т.к. хотелось по максимум сохранить синтаксис вызова…
if(confirm('') ) {...}

Выбранное решение сильно модифицирует код:


  1. Требует DOM элемент
  2. Самый ужас-ужас — многократное выполнение скрипта до confirm

Логичней, проще и правильнее перевести код на callback:


confirm = function(msg, onok, oncancel)
{
    if (!ok && !oncancel) throw new Error('Пропустили что-то'); 
    ...тут использование либо готового решения, либо свое решение с вызовом onok|oncancel...
};

// Изменения в коде:

// if(confirm('') ) {...} заменяется на
      confirm('', function(){...});

// if(confirm('') ) {...} else {...} заменяется на
      confirm('', function(){...}, function(){...});

Естественно, что код после if(confirm('') ) тоже нужно внести в функцию onok|oncancel или добавить еще одну:


confirm = function(msg, onok, oncancel, always)
{
    if (!ok && !oncancel) throw new Error('Пропустили что-то'); 
    ...тут использование либо готового решения, либо свое решение с вызовом onok|oncancel 
    ...и последующем вызовом always
};
// if(confirm('') ) {...code on ok...} ...code after confirm... заменяется на
      confirm('', function(){...code on ok...}, null, function(){...code after confirm...});
Да, посмотрим как он будет вести себя в течении недели после изменений.

Спасибо за помощь.
Поддержки у нас нет, основная деятельность у меня — разработка на C# и оракл мне более интересен с точки зрения разработчика (с этой стороны тоже не все гладко).

Насчет помощи — спасибо за предложение, попробую собрать нужное.
1321 таблица, 2 самые толстые по миллиону записей и занимают чуть более 400Мб.
419 пустых таблиц.
Сервер HP 12 ядер, 128Гб память, RAID5 SAS диски, тестовая БД, активности на сервере нет, используем expdp.

`
;;;
Export: Release 12.1.0.1.0 — Production on Tue Mar 15 17:01:09 2016

Copyright © 1982, 2013, Oracle and/or its affiliates. All rights reserved.
;;;
Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 — 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
Starting "SYSTEM"."SYS_EXPORT_SCHEMA_01": system/****@TESTDB SCHEMAS=TEST032 EXCLUDE=STATISTICS DIRECTORY=DATA_PUMP_DIR DUMPFILE=TEST032-2016.03.15.DMP LOGFILE=TEST032-2016.03.15.DMP.LOG
Estimate in progress using BLOCKS method…
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 1.921 GB

...

Job "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully completed at Tue Mar 15 17:57:21 2016 elapsed 0 00:56:01

`
Да, сторонний. Я ничего категорически не утверждаю и не исключаю человеческий фактор, тем более что тогда 12 версия только вышла.
Однако игнорировать реакцию заказчиков на ценник невозможно по понятным причинам.
Как и игнорирование увеличения время бэкапа в 5 раз: раньше версию обновляли за 20 минут, теперь час при учете того, что непосредственно обновление как было 10 минут, так и осталось, а бэкап перед обновлением выполняется 50 минут вместо 10.
я выступал в качестве стороннего наблюдателя, занимались спеца заказчика.
Хорошая попытка, Oracle, но наши заказчики уже требуют миграции с вашей БД т.к. ценик для них стал за гранью здравого смысла, да и к 12 версии ряд вопросов есть:

  • Один заказчик чуть не потерял свою базу т.к. отказалась запускаться pluggable БД и несколько неплохих специалистов так и не смогли за день ее оживить, бэкапы спасли.
  • Кстати о бэкапах: бэкап в 11 версии идет 10 минут, бэкап 12 версии после переноса из 11 идет 50 минут.
Дэн Маргулис: Photoshop для профессионалов. Классическое руководство по цветокоррекции. Вот там очень много чего интересного можно узнать.
Попробую кратко описать наш подход. Во-первых всегда нужно держать в голове полную цепочку:
  1. Пришел запрос на форму
  2. Сформировалась форма с учетом прав и WF и ушла пользователю
  3. Пользователь что-то сделал с формой (он может сделать что угодно — браузеры позволяют и поля добавить и скрипты отключить) и послал данные на сохранение
  4. Данные раскладываются с учетом прав и WF
  5. Происходит валидация и если все плохо, то нужно просто вернуть отрисованную форму обратно с сообщениями о проблемах
  6. Сохраняем модель и если все плохо, то нужно просто вернуть отрисованную форму обратно с сообщениями о проблемах
  7. Перенаправить пользователя на страницу исходя из сценария работы

На этапах 2, 4, 5 и 6 форма и правила обработки должны быть одинаковые.

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

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

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

Такой единой точкой у нас сделана одна модель — коллекция элементов (назову ее FormModel, коротко — FM), которые представляют собой Expression к модели данных + атрибуты (наименование, параметры отрисовки и т.п.). Строится эта коллекция на основе информации в ModelMetadata и далее может быть модифицирована исходя из прав, WF или данных в моделе. Так же можно эту коллекцию собрать полностью руками.

Для этой модели есть один базовый шаблон, который понимает как разместить элементы коллекции (применяется размещение в сетке с соответствующими параметрами) + шаблоны на типы свойств (строка, число, дата, файл, HTML, enum и т.п.) — всего таких шаблонов чуть более 10. В особо тяжелых случаях можно нарисовать кастомный шаблон для этой коллекции, остальная кухня (видимость полей и т.п.) остается за пределами отрисовки HTML.

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

Первый — самый простой:
  1. В действии контроллера по его параметрам получаем модель данных
  2. Строим FM по ModelMetadata (элементы с видимостью, обязательностью, расположением и т.п. + кнопки, их может быть несколько)
  3. Возвращаем отрисованный стандартной view FM
  4. В действии сохранения контроллера по его параметрам получаем модель данных
  5. Строим FM по ModelMetadata
  6. Строим список полей, которые можно bindить
  7. Выполняем платформенный биндинг
  8. Есть ошибки? — добавляем сообщения и возвращаем отрисованный стандартной view FM
  9. Выполняем комплексную валидацию (у нас есть все данные — часть пришла при зачитке, часть из биндинга, но модель получилась полная)
  10. Есть ошибки? — добавляем сообщения и возвращаем отрисованный стандартной view FM
  11. Сохраняем модель данных
  12. Есть ошибки? — добавляем сообщения и возвращаем отрисованный стандартной view FM
  13. Редирект


Посложнее:
На втором шаге FM получаем из фабрики, при этом там уже задана функция комплексной проверки, остальное аналогично.

Самый сложный:
На втором шаге полностью готовую FM получаем из WF, который смотрит на модель данных и ее состояние + пользователя, который хочет что-то сделать.
Для сохранения на шаге 11 опять же передаем обработанную bindингом модель WF для решения, что же с ней делать.

Примерный код контроллера в простейшем случае:
private _dmf - Фабрика моделей данных, получаем из IoC

[HttpGet]
public ActionResult Default(...параметры...)
{
    return StandardView(_getFM(...параметры...));
}

[HttpPost]
public ActionResult Default(...параметры.., FormCollection form)
{
    var fm = _getFM(...параметры...);
    if (fm.Bind(ControllerContext, form)) // разложит данные, разложит ошибки по элементам, добавит сообщения
    {
        if(_dmf.TryPut(..., fm.Model, fm.Messages) // попытка сохранить, если есть ошибки, то будут положены в fm.Messages
        {
            return RedirectToAction(...); // Если все Ок
        }
    }
    return StandardView(fm); // Все плохо - выводим все, что есть и смогли разложить
}

private FormModel<TDataModel> _getFM(...параметры...)
{
    var dm = _dmf.Get(User, ...параметры...);
    var fm = new FormModel<TDataModel>();
    fm.Model = dm;
    fm.Validate = () => {....}; // <-- комплексная проверка dm
    fm.Buttons.Add(...);

    // Тут можно изменить элементы fm.Elements[..] - скрыть, показать, проставить обязательность, изменить расположение и т.п.

    return fm;
}


В сложных случаях метод _getFM(… параметры...) выносится в фабрику или в WF.

В ходе разработки было сказано очень много «тёплых» и «ласковых» слов в адрес разработчиков платформенных ModelMetadata и Bind — пришлось искать обходные пути для нормальной работы.

Как результат: для over 2000 классов моделей данных и 3000+ действий контроллеров сделано всего чуть более 10 базовых шаблонов и пара десятков кастомных. + хитрые пользователи не смогут сохранить то, что запрещено сохранять + контроллеры просты, основная логика в сервисах и WF, view не перегружены.
Так же такая схема позволила добавлять не только элементы — свойства модели, но и статику (просто HTML) и ActionResult в единое отображение.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность

Специализация

Фулстек разработчик, Архитектор программного обеспечения
Ведущий
Веб-разработка
Vue.js
HTML
CSS
JavaScript
.NET Core
ASP.NET MVC
PostgreSQL
Linux