Некоторые мощные методы для быстрого прототипирования новых функций

Внесение изменений в большую кодовую базу, с которой вы не знакомы, может оказаться сложной задачей. Откуда вы знаете, что не нарушаете сознательно разработанную логику? Откуда вы знаете, что вносимые вами изменения не будут иметь побочных эффектов и не сломают что-то еще в коде? Будем надеяться, что кодовая база хорошо спроектирована и хорошо структурирована, с большим охватом модульных тестов и документацией для смягчения этих проблем, но в реальном мире обычно все обстоит иначе. Итак, что мы можем сделать, чтобы облегчить себе жизнь в таких ситуациях? В частности, как F# может помочь нам изучить и лучше понять кодовую базу .NET?

Сценарии F# и интерактивный интерфейс F#

Во-первых, краткое введение в скрипты F# и интерактивный F# (fsi). FSI — супермощный инструмент, который можно (и нужно) использовать для интерактивного тестирования кода в процессе его написания. Но он может сделать гораздо больше, чем просто проверить, что цепочка функций модуля списка, которую вы только что собрали, действительно делает то, что вы хотите, — как бы это ни было полезно.

Написание кода в файле .fsx и отправка его в fsi — это только первый шаг на пути к более продуктивному программированию. Подробнее об этом читайте в блоге Матиаса Брандевиндера (слегка устаревшем, но все же чрезвычайно полезном) 10 советов по продуктивному написанию сценариев на F#. В этом посте я раскрою некоторые моменты…

Импорт вещей, которые вам нужны

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

Загрузка файлов или скриптов F# выполняется с помощью директивы #load, за которой следует относительный путь к вашему скрипту:

#load "MyScript.fsx"
open MyScript

Загрузка внешних библиотек или встроенного кода может быть выполнена с помощью #r (и здесь более явное использование относительных путей с использованием @, чтобы избежать необходимости экранировать символы в пути). Затем вы можете открыть любые модули внутри встроенной dll:

#r @"../src/myproject/bin/debug/myproject.dll"
open MyModule

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

#I @"../src/myproject/bin/debug"
#r "myproject.dll"
#r "somelibrary.dll"
open MyModule
open LibraryModule

Еще более быстрый способ сделать это (если ваши сценарии находятся в том же месте, что и ваши встроенные dll) — использовать встроенное значение __SOURCE_DIRECTORY__:

#I __SOURCE_DIRECTORY__
#r "myproject.dll"
#r "somelibrary.dll"
open MyModule
open LibraryModule

Это позволяет вам получить доступ к любому коду из вашей кодовой базы непосредственно в ваших скриптах, готовых к отправке в fsi. Однако стоит помнить, что после загрузки этих dll в fsi, fsi «заблокирует» сами файлы. Это означает, что любая попытка восстановить их (т. е. скопировать или перезаписать) потерпит неудачу. Поэтому убедитесь, что вы завершили сеанс fsi, прежде чем пытаться перестроить проекты, на которые вы ссылались.

Изучение вашей кодовой базы

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

Изучение данных

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

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

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

Целевая отладка

Можно подключить отладчик Visual Studio (или Visual Studio Code с дополнительной работой) к процессу fsi.exe, а затем установить точки останова и отладить код, как если бы вы запускали приложение.

Бывают ситуации, когда это намного эффективнее или желательнее, чем традиционные методы отладки. Например, если вы хотите проверить, что происходит, когда функция получает ввод, который является необычным или сложным для воспроизведения через пользовательский интерфейс (чтобы проверить, что новая функция, в которой может возникнуть такая ситуация, не нарушит код). Или, если вам нужно было ответить на вопрос типа «что происходит, когда…», просто напишите сценарий, создающий эту ситуацию, и подключите отладчик, чтобы посмотреть, что произойдет.

Проверка работоспособности и специальное интеграционное тестирование

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

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

В целом сценарии F# чрезвычайно эффективны и являются практичным способом повышения производительности, даже если ваша основная кодовая база написана на другом языке .NET.