Как Вы проверяете внутреннее состояние объекта?

Из-за асинхронной природы Node.js может быть немного сложнее с такими вещами. Это означает, что когда ваш код выполняется, он запускает обработчик rl.on('line') и переходит к следующему вызову, который в нашем случае является console.log. Проблема в вашем фактическом коде заключается не в том, что массив не заполняется, а в том, что вы ожидаете, что он будет заселен раньше. Вот пример того, как вы могли бы исправить свою проблему:

var rl = require('readline').createInterface({
  input: require('fs').createReadStream('small.csv')
});

global.myarray = [];
rl.on('line', function (line) {
  console.log('Line from file:', line);
  global.myarray.push(line);
});

rl.on('close', function () {
    console.log(global.myarray);
});

В этом фрагменте кода, когда больше нет строки для чтения, будет вызываться console.log и будут некоторые отображения данных.

7
задан Johann Gerell 5 December 2008 в 21:52
поделиться

4 ответа

Вопрос лучше всего рассматривают в сочетании с тем, как Вы тестируете свое программное обеспечение.

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

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

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

2
ответ дан 7 December 2019 в 01:28
поделиться

Можно использовать технику под названием NVI ( Non-Virtual-Interface) вместе с template method шаблон. Это, вероятно - то, как я сделал бы это (конечно, только мое личное мнение, действительно спорно):

class Printer {
public:
    // checks invariant, and calls the actual queuing
    void Queue(const PrintJob&);
private:
    virtual void DoQueue(const PringJob&);
};


void Printer::Queue(const PrintJob& job) // not virtual
{
    // Validate the state in both release and debug builds.
    // Never proceed with the queuing in a bad state.
    if(!IsValidState()) {
        throw std::logic_error("Printer not ready");
    }

    // call virtual method DoQueue which does the job
    DoQueue(job);
}

void Printer::DoQueue(const PrintJob& job) // virtual
{
    // Do the actual Queuing. State is guaranteed to be valid.
}

, поскольку Queue является невиртуальным, инвариант все еще проверяется, если производный класс переопределяет DoQueue для специальной обработки.

<час>

К Вашим опциям: Я думаю, что это зависит от условия, которое Вы хотите проверить.

, Если это - внутренний инвариант

, Если это - инвариант, для пользователя Вашего класса не должно быть возможно нарушить его. Класс должен заботиться о его инварианте самом. Для этого я был бы assert(CheckInvariant()); в таком случае.

Это - просто предварительное условие метода

, Если это - просто предварительное условие, которое пользователь класса должен был бы гарантировать (скажите, только печатая после того, как принтер готов), я бросил бы std::logic_error как показано выше.

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

<час>

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

6
ответ дан 7 December 2019 в 01:28
поделиться

Это - прекрасный и очень актуальный вопрос. По моему скромному мнению, любая архитектура приложения должна предоставить стратегию сообщить о поврежденных инвариантах. Можно решить использовать исключения, использовать 'ошибочный объект' реестра или явно проверить результат любого действия. Возможно, существуют даже другие стратегии - это не точка.

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

Интерфейс NonVirtual решением от litb является аккуратный способ проверить инварианты.

1
ответ дан 7 December 2019 в 01:28
поделиться

Сложный вопрос этот:)

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

Мой личный опыт с "Do-some-logging-and-then-don't-do-anything-more" - стратегия состоит в том, что это также возвращается, чтобы укусить Вас - особенно, если это реализовано как в Вашем случае (никакая глобальная стратегия, каждый класс мог бы потенциально сделать это различные пути).

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

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

1
ответ дан 7 December 2019 в 01:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: