Что такое moc файлы
Я часто встречаю критику фреймворка Qt, в которой ему пеняют использованием мета-объектного компилятора (утилиты moc). Как один из разработчиков moc, я решил написать данную статью с целью развенчать некоторые связанные с этим мифы.
На примере внешнего API
Давайте рассмотрим стандартный пример из реальной жизни: внешнее API.
Представьте, что вы хотите использовать Twitter API в веб-приложении на фреймворке Phoenix или Rails. В приложение приходит запрос, который перенаправляется в контроллер, который, в свою очередь, делает запрос к внешнему API. Вызов внешнего API происходит прямо в контроллере:
Далее вы используете такой же подход в других частях приложения и добиваетесь прохождения юнит и интеграционных тестов. Время двигаться дальше?
Кроме того, так как мок, показанный выше, изменяет модуль глобально, вы больше не сможете запустить эти тесты в Elixir параллельно.
Шаблоны, вложенные классы или классы, используемые множественное наследование, не могут быть QObject-ами
Хотя это и является правдой, но эти возможности просто пока не поддерживаются QObject, хотя и вполне могут быть реализованы в moc, если мы этого захотим. Проект Qt в данный момент не считает данные фичи приоритетными.
Я однажды добавил поддержку шаблонных QObjects в moc, но это изменение не вошло в основную ветку разработки, поскольку никто больше не выразил интереса к данной функциональности.
Ещё нужно отметить поддержку шаблонных и вложенных классов в moc-ng.
Множественное наследование уже само по себе является очень неоднозначным. Чаще всего оно указывает на проблемы с архитектурой приложения и многие современные языки напрямую его запрещают. Вы всё ещё можете использовать множественное наследование с Qt, если если QObject является первым базовым классом в цепочке наследования. Это небольшое ограничение позволяет нам применять полезные оптимизации. Когда-нибудь задумывались почему qobject_cast настолько быстрее, чем dynamic_cast?
Что такое мок?
Воспользуемся определением из англоязычной википедии: мок — настраиваемый объект, который имитирует поведение реального объекта. Я сделаю акцент на этом позже, но для меня мок — это всегда существительное, а не глагол [для наглядности, глагол mock везде будет переводиться как "замокать" — прим. перев.].
Программы, обслуживающие файл MOC
Windows
Вступление
Moc — это один из инструментов разработчика и часть библиотеки Qt. Его задача — поддерживать расширение языка С++, необходимое для интроспекции и рефлексии в Qt (сюда относятся сигналы, слоты и QML). Для более детального объяснение вы можете почитать о том, как работают сигналы и слоты в Qt.
Необходимость использования moc является одним из главных объектов критики Qt. Это даже привело к появлению форков Qt, принципиально отказавшихся от moc (например, CopperSpice). Но всё-же большинство приписываемых moc так называемых недостатков не обоснованы.
Отказ от moc улучшает производительность на этапе выполнения кода
Это прямая цитата с главной страницы CopperSpice, и, вероятно, самая большая их ложь. Код, генерируемый moc, старается избегать динамических аллокаций и уменьшить количество реаллокаций памяти. Генерируемые moc таблицы являют собой константные массивы и хранятся в read-only сегменте данных. CopperSpice же регистрирует свои QMetaObject (информацию о сигналах, слотах и свойствах) на рантайме.
Milian Wolff проделал некоторые сравнения производительности Qt и CopperSpice в его докладе на CppCon2015. Вот скриншот одного из его слайдов (меньше — лучше).
Также нужно отметить, что код на Qt даже с учётом запуска moc компилируется быстрее, чем код на CopperSpice.
Используя Qt, вы не пишете на настоящем С++
Я слышал этот довод много раз, но он попросту неверен. Макросы, используемые moc для аннотации кода — это стандартные макросы С++. Они должны быть корректно распознаны любым инструментом, способным анализировать код на С++. Когда вы добавляете в код Q_OBJECT, то просто дописываете объявление нескольких функций. Когда вы пишете «signals:», то просто добавляете макрос, который превратится в «public:». Многие другие макросы Qt вообще ни во что не раскрываются. Moc просто находит их и генерирует код эмиттеров сигналов и таблиц интроспекции.
Тот факт, что ваш код теперь может быть прочитан ещё одним инструментом, не делает его «менее соответствующим стандарту С++». Вы же не считаете код, написанный с расчётом на использование gettext или doxygen каким-то «менее правильным С++»?
Локальные моки
Хотя мы и использовали конфигурацию приложения для решения проблемы с внешним API, иногда проще передать зависимость как аргумент. Например, некоторая функция выполняет долгие вычисления, которые вы хотите изолировать в тестах:
Можно избавиться от зависимости, передав её как аргумент. В данном случае будет достаточно передачи анонимной функции:
Тест будет выглядеть следующим образом:
Или, как было описано ранее, можно определить контракт и передать модуль целиком:
Вы также можете представить зависимость в виде data structure и определить контракт с помощью protocol.
Передать зависимость как аргумент намного проще, поэтому, если возможно, такой способ должен быть предпочтительнее использования конфигурационного файла и Application.get_env/3 .
Moc усложняет процесс сборки кода
Если вы используете любую промышленную систему сборки кода, вроде CMake или qmake, то получаете нативную поддержку Qt. Даже с какой-то собственной системой сборки речь идёт о всего-лишь одном дополнительном запуске команды обработки заголовочных файлов. Все известные мне системы сборки позволяют добавлять шаги по запуску дополнительных команд перед запуском компилятора, поскольку многие проекты в том или ином виде используют генерацию кода при сборке проекта. Вспомните, например, инструменты вроде yacc/bison, gperf, llvm/TableGen.
Решение
В Elixir все приложения имеют конфигурационные файлы и механизм для их чтения. Используем этот механизм, чтобы настроить клиент Twitter'a для различных окружений. Код контроллера теперь будет выглядеть следующим образом:
Соответствующие настройки для различных окружений:
Moc делает отладку сложнее
Поскольку moc генерирует код на чистом С++, то отладчики не должны иметь никаких проблем с ним. Мы стараемся поддерживать сгенерированный код в таком состоянии, чтобы он не вызывал предупреждений компиляторов или инструментов статического или динамического анализа кода. Да, иногда при отладке вы будете видеть в колстеке следы сгенерированного moc кода. В некоторых редких случаях вы можете получить ошибку, связанную с кодом, созданным moc, но обычно причины достаточно легко обнаружить. Код, сгенерированный moc, достаточно человекочитаем. Также его, вероятно, понимать и отлаживать даже проще, чем те печально известные ошибки некоторых библиотек, построенных на продвинутом использовании шаблонов.
Другая критика
Макрос не может быть использован при объявлении сигнала, слота, базового класса объекта, а также .
До выхода Qt5 утилита moc действительно не раскрывала макросы. Но начиная с Qt 5.0 moc полностью поддерживает макросы во всех вышеперечисленных местах, так что это больше совершенно не является проблемой.
Q_PROPERTY не позволяет использовать запятые в типах
Заключение
Одна из задач тестирования системы — нахождение правильных контрактов и границ между компонентами. Использование моков только в случае наличия явного контракта позволит вам:
Явные контракты позволяют увидеть сложность зависимостей в вашем приложении. Сложность присутствует в каждом приложении, поэтому всегда старайтесь делать её настолько явной, насколько это возможно.
Программы, которые поддерживают MOC расширение файла
Программы, которые могут обрабатывать MOC файлы, следующие. Файлы с расширением MOC, как и любые другие форматы файлов, можно найти в любой операционной системе. Указанные файлы могут быть переданы на другие устройства, будь то мобильные или стационарные, но не все системы могут быть способны правильно обрабатывать такие файлы.
Moc переписывает ваш код перед тем, как передать его компилятору
Это распространённое заблуждение. Moc не модифицирует и не переписывает ваш код. Он просто парсит часть кода для того, чтобы сгенерировать дополнительные С++ файлы, которые потом будут компилироваться независимо. Это не очень большое отличие, но всё-же важное техническое недопонимание.
Moc просто автоматически генерирует шаблонный код, который можно было бы долго и нудно писать вручную, если бы moc не существовало. Если вы мазохист, то и сейчас вполне возможно взять и написать самостоятельно все таблицы для интроспекции и реализации сигналов. Ну или положиться на надёжный инструмент, который сделает это за вас.
How to open file with MOC extension?
Problems with accessing MOC may be due to various reasons. On the bright side, the most encountered issues pertaining to MOCHA Java Script files aren’t complex. In most cases they can be addressed swiftly and effectively without assistance from a specialist. The list below will guide you through the process of addressing the encountered problem.
Step 1. Install Mocha software
The most common reason for such problems is the lack of proper applications that supports MOC files installed on the system. To address this issue, go to the Mocha developer website, download the tool, and install it. It is that easy Above you will find a complete listing of programs that support MOC files, classified according to system platforms for which they are available. If you want to download Mocha installer in the most secured manner, we suggest you visit Imagineer Systems Limited website and download from their official repositories.
Step 2. Check the version of Mocha and update if needed
If the problems with opening MOC files still occur even after installing Mocha, it is possible that you have an outdated version of the software. Check the developer’s website whether a newer version of Mocha is available. Sometimes software developers introduce new formats in place of that already supports along with newer versions of their applications. If you have an older version of Mocha installed, it may not support MOC format. All of the file formats that were handled just fine by the previous versions of given program should be also possible to open using Mocha.
Step 3. Set the default application to open MOC files to Mocha
After installing Mocha (the most recent version) make sure that it is set as the default application to open MOC files. The method is quite simple and varies little across operating systems.
Selecting the first-choice application in Windows
- Right-click the MOC file and choose Open with option
- Select Choose another app → More apps
- The last step is to select Look for another app on this PC option supply the directory path to the folder where Mocha is installed. Now all that is left is to confirm your choice by selecting Always use this app to open MOC files and clicking OK .
Selecting the first-choice application in Mac OS
- By clicking right mouse button on the selected MOC file open the file menu and choose Information
- Open the Open with section by clicking its name
- Select Mocha and click Change for all.
- If you followed the previous steps a message should appear: This change will be applied to all files with MOC extension. Next, click the Continue button to finalize the process.
Step 4. Verify that the MOC is not faulty
Should the problem still occur after following steps 1-3, check if the MOC file is valid. Problems with opening the file may arise due to various reasons.
1. Check the MOC file for viruses or malware
If the MOC is indeed infected, it is possible that the malware is blocking it from opening. Scan the MOC file as well as your computer for malware or viruses. If the scanner detected that the MOC file is unsafe, proceed as instructed by the antivirus program to neutralize the threat.
2. Ensure the file with MOC extension is complete and error-free
Did you receive the MOC file in question from a different person? Ask him/her to send it one more time. The file might have been copied erroneously and the data lost integrity, which precludes from accessing the file. It could happen the the download process of file with MOC extension was interrupted and the file data is defective. Download the file again from the same source.
3. Verify whether your account has administrative rights
Some files require elevated access rights to open them. Log out of your current account and log in to an account with sufficient access privileges. Then open the MOCHA Java Script file.
4. Make sure that the system has sufficient resources to run Mocha
The operating systems may note enough free resources to run the application that support MOC files. Close all running programs and try opening the MOC file.
5. Verify that your operating system and drivers are up to date
Regularly updated system, drivers, and programs keep your computer secure. This may also prevent problems with MOCHA Java Script files. It is possible that one of the available system or driver updates may solve the problems with MOC files affecting older versions of given software.
Do you want to help?
If you have additional information about the MOC file, we will be grateful if you share it with our users. To do this, use the form here and send us your information on MOC file.
Выводы
Я не думаю, что moc — это проблема. Макросы Qt действительно помогают реализовать необходимую Qt функциональность. Сравнивая их с подходом CopperSpice мы можем заметить в последнем значительную избыточность служебного кода, а также недружелюбный синтаксис макросов (не говоря уже о потерях производительности на рантайме). Синтаксис сигналов и слотов, который существует в Qt с 90-ых годов — одна из фундаментальных вещей, обеспечивших успех фреймворка.
Вам может быть также интересно изучить некоторые эксперименты, связанные с moc, вроде moc-ng (это moc, переписанный с использованием библиотек clang). Также есть вот это исследование замены moc с помощью инструментов рефлексии С++. Ну и библиотека Verdigris, с макросами, создающими QMetaObject без moc.
Qt хорошо известен своим механизмом сигналов и слотов. Но как это работает? В этом посте мы исследуем внутренности QObject и QMetaObject и раскроем их работу за кадром. Я буду давать примеры Qt5 кода, иногда отредактированные для краткости и добавления форматирования.
Сигналы и слоты
Для начала, вспомним, как выглядят сигналы и слоты, заглянув в официальный пример. Заголовочный файл выглядит так:
Где-то, в .cpp файле, мы реализуем setValue():
Затем, можем использовать объект Counter таким образом:
Это оригинальный синаксис, который почти не изменялся с начала Qt в 1992 году. Но даже если базовое API не было изменено, реализация же менялась несколько раз. Под капотом добавлялись новые возможности и происходили другие вещи. Тут нет никакой магии и я покажу как это работает.
MOC или метаобъектный компилятор
Сигналы и слоты, а также система свойств Qt, основываются на возможностях самоанализа объектов во время выполнения программы. Самоанализ означает способность перечислить методы и свойства объекта и иметь всю информацию про них, в частности, о типах их аргументов. QtScript и QML вряд ли был бы возможны без этого.
C++ не предоставляет родной поддержки самоанализа, поэтому Qt поставляется с инструментом, который это обеспечивает. Этот инструмент называется MOC. Это кодогенератор (но не препроцессор, как думают некоторые люди).
Он парсит заголовочные файлы и генерирует дополнительный C++ файл, который компилируется с остальной частью программы. Этот сгенерированный C++ файл содержит всю информацию, необходимую для самоанализа.
Qt иногда подвергается критике со стороны языковых пуристов, так как это дополнительный генератор кода. Я позволю документации Qt ответить на эту критику. Нет ничего плохого в кодогенераторе и MOC является превосходным помощником.
Магические макросы
Сможете ли вы заметить ключевые слова, которые не являются ключевыми словами C++? signals, slots, Q_OBJECT, emit, SIGNAL, SLOT. Они известны как Qt-расширение для C++. На самом деле это простые макросы, которые определены в qobjectdefs.h.
Это правда, сигналы и слоты являются простыми функциями: компилятор обрабатывает их как и любые другие функции. Макросы еще служат определённой цели: MOC видит их. Сигналы были в секции protected в Qt4 и ранее. Но в Qt5 они уже открыты, для поддержки нового синтаксиса.
Q_OBJECT определяет связку функций и статический QMetaObject. Эти функции реализованы в файле, сгенерированном MOC.
emit – пустой макрос. Он даже не парсится MOC. Другими словами, emit опционален и ничего не значит (за исключением подсказки для разработчика).
Эти макросы просто используются препроцессором для конвертации параметра в строку и добавления кода в начале. В режиме отладки мы также дополняем строку с расположением файла предупреждением, если соединение с сигналом не работает. Это было добавлено в Qt 4.5 для совместимости. Для того, чтобы узнать, какие строки содержат информацию о строке, мы используем qFlagLocation, которая регистрирует адрес строки в таблице, с двумя включениями.
Теперь перейдём к коду, сгенерированному MOC.
QMetaObject
Тут мы видим реализацию Counter::metaObject() и Counter::staticMetaObject. Они объявленный в макросе Q_OBJECT. QObject::d_ptr->metaObject используется только для динамических метаобъектов (QML объекты), поэтому, в общем случае, виртуальная функция metaObject() просто возвращает staticMetaObject класса. staticMetaObject построен с данными только для чтения. QMetaObject определён в qobjectdefs.h в виде:
d косвенно символизирует, что все члены должны быть сокрыты, но они не сокрыты для сохранение POD и возможности статической инициализации.
QMetaObject инициализируется с помощью метаобъекта родительского класса superdata (QObject::staticMetaObject в данном случае). stringdata и data инициализируются некоторыми данными, которые будут рассмотрены далее. static_metacall это указатель на функцию, инициализируемый Counter::qt_static_metacall.
Таблицы самоанализа
Во-первых, давайте посмотрим на основные данные QMetaObject.
Первые 13 int составляют заголовок. Он предоставляет собой две колонки, первая колонка – это количество, а вторая – индекс массива, где начинается описание. В текущем случае мы имеем два метода, и описание методов начинается с индекса 14.
Описание метода состоит из 5 int. Первый – это имя, индекс в таблице строк (мы детально рассмотрим её позднее). Второе целое – количество параметров, вслед за которым идёт индекс, где мы может найти их описание. Сейчас мы будет игнорировать тег и флаги. Для каждой функции MOC также сохраняет возвращаемый тип каждого параметра, их тип и индекс имени.
Таблица строк
В основном, это статический массив QByteArray (создаваемый макросом QT_MOC_LITERAL), который ссылается на конкретный индекс в строке ниже.
Сигналы
MOC также реализует сигналы. Они являются функциями, которые просто создают массив указателей на аргументы и передают их QMetaObject::activate. Первый элемент массива это возвращаемое значение. В нашем примере это 0, потому что возвращаемое значение void. Третий аргумент, передаваемый функции для активации, это индекс сигнала (0 в данном случае).
Вызов слота
Также возможно вызвать слот по его индексу, используя функцию qt_static_metacall:
Массив указателей на аргументы в таком же формате, как и в сигналах. _a[0] не тронут, потому что везде тут возвращается void.
Примечание по поводу индексов
Для каждого QMetaObject, сигналам, слотам и прочим вызываемым методам объекта, даются индексы, начинающиеся с 0. Они упорядочены так, что на первом месте сигналы, затем слоты и затем уже прочие методы. Эти индексы внутри называется относительными индексами. Они не включают индексы родителей. Но в общем, мы не хотим знать более глобальный индекс, который не относится к конкретному классу, но включает все прочие методы в цепочке наследования. Поэтому, мы просто добавляем смещение к относительному индексу и получаем абсолютный индекс. Этот индекс, используемый в публичном API, возвращается функциями вида QMetaObject::indexOf.
Механизм соединения использует массив, индексированный для сигналов. Но все слоты занимают место в этом массиве и обычно слотов больше чем сигналов. Так что, с Qt 4.6, появляется новый внутренний индекс для сигналов, который включает только индексы, используемые для сигналов. Если вы разрабатываете с Qt, вам нужно знать только про абсолютный индекс для методов. Но пока вы просматриваете исходный код QObject, вы должны знать разницу между этими тремя индексами.
Как работает соединение
Первое, что делает Qt при соединении, это ищет индексы сигнала и слота. Qt будет просматривать таблицы строк метаобъекта в поисках соответствующих индексов. Затем, создается и добавляется во внутренние списки объект QObjectPrivate::Connection.
Какая информация необходима для хранения каждого соединения? Нам нужен способ быстрого доступа к соединению для данного индекса сигнала. Так как могут быть несколько слотов, присоединённых к одному и тому же сигналу, нам нужно для каждого сигнала иметь список присоединённых слотов. Каждое соединение должно содержать объект-получатель и индекс слота. Мы также хотим, чтобы соединения автоматически удалялись, при удалении получателя, поэтому каждый объект-получатель должен знать, кто соединён с ним, чтобы он мог удалить соединение.
Вот QObjectPrivate::Connection, определённый в qobject_p.h:
Каждый объект имеет массив соединений: это массив, который связывает каждого сигнала списки QObjectPrivate::Connection. Каждый объект также имеет обратные списки соединений объектов, подключённых для автоматического удаления. Это двусвязный список.
Связные списки используются для возможности быстрого добавления и удаления объектов. Они реализованы с наличием указателей на следующий/предыдущий узел внутри QObjectPrivate::Connection. Заметьте, что указатель prev из senderList это указатель на указатель. Это потому что мы действительно не указываем на предыдущий узел, а, скорее, на следующий, в предыдущем узле. Этот указатель используется только когда соединение разрушается. Это позволяет не иметь специальный случай для первого элемента.
Эмиссия сигнала
Когда мы вызываем сигнал, мы видели, что он вызывает код, сгенерированный MOC, который уже вызывает QMetaObject::activate. Вот реализация (с примечаниями) этого метода в qobject.cpp:
Наверное каждый, кто начинал писать юнит и интеграционные тесты, сталкивался с проблемой злоупотребления моками, которая приводит к хрупким тестам. Последние, в свою очередь, создают у программиста неверное убеждение в том, что тесты только мешают работать.
Ниже представлен вольный перевод статьи, в которой José Valim — создатель языка Elixir — высказал своё мнение на проблему использования моков, с которым я полностью согласен.
Несколько дней назад я поделился своими мыслями по поводу моков в Twitter:
Мок — полезный инструмент в тестировании, но имеющиеся тестовые библиотеки и фреймворки зачастую приводят к злоупотреблению этим инструментом. Ниже мы рассмотрим лучший способ использования моков.
Библиотеки для создания моков
После прочитанного у вас может возникнуть вопрос: "Нужно ли отказываться от библиотек для создания моков?"
Все зависит от ситуации. Если библиотека подталкивает вас на подмену глобальных объектов (или на использование моков в качестве глаголов), изменение статических методов в объектно-ориентированном или замену модулей в функциональном программировании, то есть на нарушение описанных выше правил создания моков, то вам лучше отказаться от неё.
Однако, есть библиотеки для создания моков, которые не подталкивают вас на использование описанных выше анти-паттернов. Такие библиотеки предоставляют "мок-объекты" или "мок-модули", которые передаются в тестируемую систему в качестве аргумента и собирают информацию о количестве вызовов мока и о том, с какими аргументами он был вызван.
Мок — это существительное
Лучше думать о моках как о существительных. Вместо того, чтобы мокать API (мокать — глагол), нужно создать мок (мок — существительное), который реализует необходимый API.
Большинство проблем от использования моков возникают, когда они используются как глаголы. Если вы мокаете что-то, вы изменяете уже существующие объекты, и зачастую эти изменения являются глобальными. Например, когда мы мокаем модуль SomeDependency , он изменится глобально:
При использовании мока как существительного, вам необходимо создать что-то новое, и, естественно, это не может быть уже существующий модуль SomeDependency . Правило "мок — это существительное, а не глагол" помогает находить "плохие" моки. Но ваш опыт может отличаться от моего.
Примечания
Я бы хотел закончить эту статью разбором нескольких общих проблем, которые всплывают практически в каждом обсуждении моков.
Programs that support MOC file
Windows
Создание "тестируемого" кода
Получается, предложенное решение делает production-код более "тестируемым", но создает необходимость ходить в конфигурацию приложения на каждый вызов функции? Наличие ненужного оверхэда, чтобы сделать что-то "тестируемым", не похоже на хорошее решение.
Я бы сказал, что речь идет не о создании "тестируемого" кода, а об улучшении дизайна [от англ. design of your code — прим. перев.].
Тест — это пользователь вашего API, как и любой другой код, который вы пишите. Одна из идей TDD заключается в том, что тесты — это код и ничем не отличаются от кода. Если вы говорите: "Я не хочу делать мой код тестируемым", это означает "Я не хочу уменьшать зависимость между компонентами" или "Я не хочу думать о контракте (интерфейсе) этих компонентов".
Нет ничего плохого в нежелании уменьшать зависимость между компонентами. Например, если речь идет о модуле работы с URI [имеется ввиду модуль URI для Elixir — прим. перев.]. Но если мы говорим о чем-то таком же сложном, как внешнее API, определение явного контракта и наличие возможности заменять реализацию этого контракта сделает ваш код удобным и простым в сопровождении.
Кроме того, оверхэд минимален, так как конфигурация Elixir-приложения хранится в ETS, а значит вычитывается прямо из памяти.
Тестирование границ
Сначала, когда явные контракты отсутствовали, границы приложения выглядели так:
[MyApp] -> [MyApp.Twitter (contract)]
Сложность тестирования больших систем заключается в определение четких границ между компонентами. Слишком высокий уровень изоляции при отсутствии интеграционных тестов сделает тесты хрупкими, а большинство проблем будут обнаруживаться только на production. С другой стороны, низкий уровень изоляции увеличит время прохождения тестов и сделает тесты сложными в сопровождении. Единственного верного решения нет, и уровень изоляции будет изменяться в зависимости от уверенности команды и прочих факторов.
Исключим тесты с Twitter API:
При необходимости включим их в общий тестовый прогон:
mix test --include twitter_api
Также можно запустить их отдельно:
mix test --only twitter_api
Перечисления (enums) и переопределения типов (typedefs) должны строго соответствовать при использовании их в качестве параметров сигналов и слотов
Это является проблемой только если вы всё ещё хотите использовать синтаксис соединений, основанный на строках (поскольку там действительно используется прямое сравнение названий типов). С выходом Qt5 и новым синтаксисом это больше не препятствие.
Устаревшие мифы
Некоторая критика когда-то была справедливой, но более таковой не является.
Как открыть файл MOC?
Проблемы с доступом к MOC могут быть вызваны разными причинами. С другой стороны, наиболее часто встречающиеся проблемы, связанные с файлами MOCHA Java Script, не являются сложными. В большинстве случаев они могут быть решены быстро и эффективно без помощи специалиста. Приведенный ниже список проведет вас через процесс решения возникшей проблемы.
Шаг 1. Установите Mocha программное обеспечение
Наиболее распространенной причиной таких проблем является отсутствие соответствующих приложений, поддерживающих файлы MOC, установленные в системе. Чтобы решить эту проблему, перейдите на веб-сайт разработчика Mocha, загрузите инструмент и установите его. Это так просто Выше вы найдете полный список программ, которые поддерживают MOC файлы, классифицированные в соответствии с системными платформами, для которых они доступны. Если вы хотите загрузить установщик Mocha наиболее безопасным способом, мы рекомендуем вам посетить сайт Imagineer Systems Limited и загрузить его из официальных репозиториев.
Шаг 2. Проверьте версию Mocha и обновите при необходимости
Если проблемы с открытием файлов MOC по-прежнему возникают даже после установки Mocha, возможно, у вас устаревшая версия программного обеспечения. Проверьте веб-сайт разработчика, доступна ли более новая версия Mocha. Иногда разработчики программного обеспечения вводят новые форматы вместо уже поддерживаемых вместе с новыми версиями своих приложений. Если у вас установлена более старая версия Mocha, она может не поддерживать формат MOC. Все форматы файлов, которые прекрасно обрабатывались предыдущими версиями данной программы, также должны быть открыты с помощью Mocha.
Шаг 3. Настройте приложение по умолчанию для открытия MOC файлов на Mocha
После установки Mocha (самой последней версии) убедитесь, что он установлен в качестве приложения по умолчанию для открытия MOC файлов. Метод довольно прост и мало меняется в разных операционных системах.
Выбор приложения первого выбора в Windows
- Щелкните правой кнопкой мыши на файле MOC и выберите « Открыть с помощью опцией».
- Выберите Выбрать другое приложение → Еще приложения
- Последний шаг - выбрать опцию Найти другое приложение на этом. указать путь к папке, в которой установлен Mocha. Теперь осталось только подтвердить свой выбор, выбрав Всегда использовать это приложение для открытия MOC файлы и нажав ОК .
Выбор приложения первого выбора в Mac OS
Шаг 4. Убедитесь, что MOC не неисправен
Если проблема по-прежнему возникает после выполнения шагов 1-3, проверьте, является ли файл MOC действительным. Проблемы с открытием файла могут возникнуть по разным причинам.
1. Проверьте MOC файл на наличие вирусов или вредоносных программ.
Если MOC действительно заражен, возможно, вредоносное ПО блокирует его открытие. Сканируйте файл MOC и ваш компьютер на наличие вредоносных программ или вирусов. Если сканер обнаружил, что файл MOC небезопасен, действуйте в соответствии с инструкциями антивирусной программы для нейтрализации угрозы.
2. Убедитесь, что файл с расширением MOC завершен и не содержит ошибок
3. Проверьте, есть ли у вашей учетной записи административные права
Некоторые файлы требуют повышенных прав доступа для их открытия. Выйдите из своей текущей учетной записи и войдите в учетную запись с достаточными правами доступа. Затем откройте файл MOCHA Java Script.
4. Убедитесь, что в системе достаточно ресурсов для запуска Mocha
Операционные системы могут иметь достаточно свободных ресурсов для запуска приложения, поддерживающего файлы MOC. Закройте все работающие программы и попробуйте открыть файл MOC.
5. Убедитесь, что ваша операционная система и драйверы обновлены
Регулярно обновляемая система, драйверы и программы обеспечивают безопасность вашего компьютера. Это также может предотвратить проблемы с файлами MOCHA Java Script. Возможно, что одно из доступных обновлений системы или драйверов может решить проблемы с файлами MOC, влияющими на более старые версии данного программного обеспечения.
Вы хотите помочь?
Если у Вас есть дополнительная информация о расширение файла MOC мы будем признательны, если Вы поделитесь ею с пользователями нашего сайта. Воспользуйтесь формуляром, находящимся здесь и отправьте нам свою информацию о файле MOC.
Full format name of files that use MOC extension is MOCHA Java Script. MOC files are supported by software applications available for devices running Windows. Files with MOC extension are categorized as Developer Files files. The Developer Files subset comprises 1205 various file formats. Mocha is by far the most used program for working with MOC files. Mocha software was developed by Imagineer Systems Limited, and on its official website you may find more information about MOC files or the Mocha software program.
Programs which support MOC file extension
Programs that can handle MOC files are as follows. Files with MOC extension, just like any other file formats, can be found on any operating system. The files in question may be transferred to other devices, be it mobile or stationary, yet not all systems may be capable of properly handling such files.
Необходимость явных контрактов
Мок предназначен для замены реального объекта, а значит будет эффективен только в том случае, когда поведение реального объекта определено явно. Иначе, вы можете оказаться в ситуации, когда мок начнет становиться все сложнее, увеличивая зависимость между тестируемыми компонентами. Без явного контракта заметить это будет сложно.
Мы уже имеем три реализации Twitter API и лучше сделать их контракты явными. В Elixir описать явный контракт можно с помощью behaviour:
Теперь добавьте @behaviour MyApp.Twitter в каждый модуль, который реализует этот контракт, и Elixir поможет вам создать ожидаемый API.
В Elixir мы полагаемся на такие behaviours постоянно: когда используем Plug, когда работаем с базой данных в Ecto, когда тестируем Phoenix channels и так далее.
Читайте также: