2013-04-01 3 views
8

(Я использую слово «рабочий процесс» - не в смысле асинхронных рабочих процессов, а скорее в смысле «git workflow», то есть как вы используете его как часть своей разработки)F # Workflows/Процесс разработки

Поиграв с F # некоторое время, я начал разработку своего первого приложения F #. Я из C#/vb. Наблюдая за различными демонстрациями/разговорами - правильно или ошибочно, я начал использовать fsi в качестве основного «движка» разработки и работал над материалом в этой области. Если я столкнулся с проблемой, которую мне нужно отлаживать, я, как правило, разбиваю проблемную функцию на более мелкие биты и проверяю эту работу, чтобы попробовать и отладить проблему.

Однако, чтобы сохранить код, управляемый в fsi, как только я доволен тем, что сделал, переместите его в .fs и #load .fs обратно в fsi. По мере того, как приложение становится больше, это может начать чувствовать себя немного неуклюжим, поскольку, когда мне нужно рефакторировать, мне приходится возвращаться к содержимому из файла fs, который он запускает, чтобы заставить что-то снова работать, прежде чем выталкивать код обратно в файл .fs. Далее этот стиль на самом деле не первый подход к тестированию, и поэтому я не получаю выгоды от создания набора тестов. (Я также могу упустить возможность установить контрольные точки/шаг кода, который в некоторых ситуациях, например, рекурсия, может быть быстрее для диагностики ошибок, чем разбить части функции - хотя, возможно, это доступно в VS11, и я не настроен право) .. поэтому я думаю, что, возможно, я не делаю ничего оптимально или не думаю о правильных вещах.

Мне было интересно, смогут ли другие предложить, как они разрабатывают приложения. Вы в основном используете fsi или начинаете с tdd. Если подход tdd является основным транспортным средством dev, а FSI используется более выборочно, чтобы помочь, скажем, реализовать более сложные алгоритмы, исследования данных и т. Д.

Я посмотрел this question и, очевидно, он с готовностью указывает на различные рамки tdd для F #, но мне все равно будет интересно узнать о рабочем процессе опытных разработчиков F #.

Многие ТНХ

S

+0

Вы пробовали [файлы сценариев] (http://blogs.msdn.com/b/carlnol/archive/2011/08/09/creating-f-fsx-script-files- от фс-источник-files.aspx? перенаправлены = истина)? Кажется хорошей возможностью добавить некоторые тесты по пути –

+0

Thx. Есть ли шанс, что вы можете немного расширить его до tdd? Я использовал их просто как «более свободный» способ получить материал, исполняемый в fsi. Я, очевидно, что-то пропустил! –

+0

REPL не заменяет правильные тесты. Они скорее дополняют друг друга. https://twitter.com/missingfaktor/status/314452078682595328 –

ответ

12

Я думаю, что вы на правильном пути.

Процесс разработки - дело вкуса. В любом случае я поделюсь своим подходом.

  • Публикация нескольких файлов fs. Каждый файл представляет собой модуль, который состоит из группы функций, тесно связанных друг с другом. Он не должен быть точным с самого начала; вы часто перемещаете вещи между модулями.
  • Создайте несколько файлов fsx для быстрого тестирования, как только скелет модулей будет готов.
  • Создайте тестовый проект и настройте пакеты NuGet. Я часто использую NUnit и FsUnit вместе.
  • Всякий раз, когда скрипты fsx дают правильные результаты, переместите их в тестовые чехлы. Сделайте это повторно.
  • Включите Program.fs в основной проект и скомпилируйте его в исполняемый файл, чтобы отладить при необходимости.

В общем, F # REPL является основным двигателем разработки. Это дает мне мгновенные обратные связи и позволяет инкрементные изменения, которые очень полезны при прототипировании. В F # TDD менее критичен, поскольку частота ошибок намного ниже, чем на других языках. И я не тестирую все, просто сосредоточусь на основных функциях и обеспечиваю высокий уровень охвата тестированием.Использование testdriven.net надстройки или Visual Studio 2012 Premium and Ultimate может предоставить вам полезную статистику по охвату тестированием.

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

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

+0

Thx. Очень полезно. –

+0

@GuyCoder: Спасибо, просто добавьте предложение о покрытии кода. – pad

3

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

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

В Object Oriented мире один думает, что с объектами и в таких языках, я хотел бы начать с написанием объектами на бумаге и работе с различными схемами, такими как use-case, state transition, sequence diagram и т.д., пока я не чувствовал, что было достаточно, чтобы приступить к созданию объекты в файлах C# cs, обтекание объектов методами, свойствами, событиями и т. д.

В функциональном мире я обычно начинаю с абстрактных понятий и преобразовываю их в discriminated unions (DU) в файл F # fs, пропуская использование REPL, то есть F# Interactive, а затем приступить к добавлению нескольких функций. После того, как у меня есть несколько функций, я создал тестовый проект, используя NUnit и FsUnit через NuGet. Поскольку DU являются абстрактными, тестовые примеры обычно сложнее писать, поэтому я создаю принтеры для DU, а затем вставляю их в тестовый сценарий, где я беру результат вывода из принтера в инструменте NUnit, чтобы вырезать и вставить обратно в при необходимости, при необходимости меняет тестовый пример. См. these для примеров того, почему я не пишу их с нуля вручную.

Как только у меня есть абстрактное DU done, я затем могу перейти на код, чтобы преобразовать человеческую/конкретную форму в абстрактный DU и преобразовать абстрактный DU в человеческую/конкретную форму. В некоторых случаях это будут parsers и pretty printers.

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

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

РЕДАКТИРОВАТЬ

За просьбу Ken для примера.

См: Discriminated Unions (F#) и найдите раздел
Using Discriminated Unions Instead of Object Hierarchies

Так вместо базового типа формы с унаследованными типами круга, EquilateralTriangle, квадрат и прямоугольник можно было бы создать дискриминационный Союз отметил:

type Shape = 
| Circle of float 
| EquilateralTriangle of double 
| Square of double 
| Rectangle of double * double 

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

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

+0

Thx vm. Там немного переварить - особенно примеры! Правильно ли я думаю, что вы создаете DU примерно в том же месте, что вы, например, начинаете создавать иерархии объектов, если работаете на C#, или вы говорите что-то немного другое? Кроме того, есть ли у вас пример того, что вы имеете в виду, когда говорите «создайте принтеры для DU» - StructuredFormatDisplayAttribute? –

+1

«Я прав, думая, что вы создаете DU примерно в том же месте, что вы начнете создавать иерархии объектов, если работаете на C#,« Да, это в основном правильно. С OO вы сначала считаете объекты, но с функциональными функциями вы сначала считаете, но функции нуждаются в некоторых типах, прежде чем вы сможете их написать, и поэтому для чего-либо, кроме основ, вам, вероятно, понадобится DU. Примечание. Можно выполнять проекты, которые не нуждаются в DU, потому что это все функции базовых типов, поэтому не думайте, что DU всегда необходим, так же как вам может не понадобиться объект на языке OO для решения проблемы проблема. –

+1

«Кроме того, у вас есть пример того, что вы имеете в виду, когда говорите« создавайте принтеры для DU ». На самом деле это очень хороший вопрос, который вы должны задать здесь здесь. Я укажу вам кое-что здесь, но серьезно спрошу, как другие может дать больше информации, чем это. Смотрите: [fol.fs] (https://github.com/jack-pappas/fsharp-logic-examples/blob/master/FSharpx.Books.AutomatedReasoning/fol.fs) Вам также нужно чтобы узнать о AddPrinter. См.: [fol.fsx] (https://github.com/jack-pappas/fsharp-logic-examples/blob/master/Examples/fol.fsx) –

Смежные вопросы