2013-10-13 5 views
44

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

Как вы структурируете свои проекты?

Какие функции OCaml следует использовать и не должны использовать для упрощения управления кодом? Исключения? Первоклассные модули? GADTs? Типы объектов?

Система сборки? Тестирование? Стек библиотеки?

Я нашел отличный recommendations для haskell, и я думаю, было бы хорошо иметь что-то подобное для OCaml.

ответ

57

Я собираюсь ответить за проект среднего размера в условиях, с которыми я знаком, между 100K и 1M строк исходного кода и до 10 разработчиков. Это то, что мы используем сейчас, для проекта началась два месяца назад, в августе 2013 г.

сборки системы и организации код:

  • один источник-состоянии сценарий оболочки определяет PATH и другие переменные для нашего проекта
  • один файл .ocamlinit в корне нашего проекта загружает кучу библиотек при запуске сеанса верхнего уровня
  • omake, который является быстрым (с опцией -j для параллельных построений); но мы избегаем делать сумасшедшие пользовательские Бонус-байку плагин
  • один корень Makefile содержит все необходимые цели (настройки, сборки, испытание, чистые и более)
  • один уровень подкаталогов, а не два
  • большинства подкаталогов построить в OCaml библиотека
  • некоторые подкатегории содержат другие предметы (setup, scripts и т. д.)
  • OCAMLPATH содержит корень проекта; каждый подкаталог библиотеки создает META-файл, делая все части проектов OCaml доступными из верхнего уровня, используя # require.
  • только один OCaml исполняемый построен для всего проекта (экономит много времени, соединяющее; до сих пор не знает, почему)
  • библиотеки устанавливается с помощью сценария установки с помощью opam
  • локальных пакетов opam сделаны для программного обеспечения, его не в официальном репозитории opam
  • мы используем переключатель opam, который является псевдонимом имени нашего проекта, избегая конфликтов с другими проектами на той же машине

редактирование исходного кода:

  • Emacs с opam пакетов OCP-отступ и OCP-индекс

контроля источника и управление:

  • мы используем мерзавец и GitHub
  • все новый код является пэром с помощью выдвижных запросов GitHub
  • tarballs для библиотек non-github non-opam хранятся в отдельном хранилище git (который может быть удален, если история становится слишком большой)
  • bleeding -Станок библиотека, существующая на GitHub раздваивается в нашем GitHub счет и устанавливаются с помощью нашего местного opam пакета

Использования OCaml:

  • OCaml не компенсирует плохую практику программирования; преподавание хорошего вкуса выходит за рамки этого ответа. http://ocaml.org/learn/tutorials/guidelines.html - хорошая отправная точка.
  • OCaml 4.01.0 делает это намного проще, чем раньше, чтобы повторно использовать записи меток полех и вариантные конструктор (т.е. type t1 = {x:int} type t2 = {x:int;y:int} let t1_of_t2 ({x}:t2) : t1 = {x} теперь работает)
  • мы стараемся не использовать расширение синтаксиса camlp4 в нашем собственном коде
  • мы не используем классы и объектами, если не предусмотрено какой-либо внешней библиотекой
  • в теории с OCaml 4.01.0, мы должны предпочесть классические варианты над полиморфными вариантами
  • мы используем исключения, чтобы указывать на ошибки и позволять им проходить счастливо до тех пор, пока наша основная петля сервера не поймает их и не интерпретирует их как «внутренняя ошибка» (по умолчанию), «плохой запрос» или что-то еще
  • Исключения, такие как Exit или Not_found, могут использоваться локально, если это имеет смысл, но в интерфейсах модулей мы предпочитаем использовать параметры.

библиотеки, протоколы, каркасы:

  • мы используем батареи для всех функций товарных, которые отсутствуют в стандартной библиотеке в OCaml; для остальных у нас есть библиотека «util»
  • мы используем Lwt для асинхронного программирования без расширений синтаксиса, а оператор bind (>> =) - единственный оператор, который мы используем (если вам нужно знать, мы делаем неохотно используют предварительную обработку camlp4 для лучшего отслеживания исключений для точек привязки).
  • мы используем HTTP и JSON для взаимодействия с третьей стороной программного обеспечения, и мы ожидаем, что каждый современный сервис, чтобы предоставить такие интерфейсы
  • для обслуживания HTTP, мы запускаем наш собственный сервер SCGI (OCaml-SCGI) за Nginx
  • как HTTP-клиент мы используем Cohttp
  • для сериализации JSON мы используем atdgen

"Облако" услуги:

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

Тестирование:

  • мы одна делает цель/Бонуса-байки для быстрых испытаний и один для медленных тестов
  • быстрых тестов модульных тестов; каждый модуль может обеспечивать «тестовую» функцию; файл test.ml запускает список тестов
  • медленными тестами являются те, которые включают запуск нескольких служб; они созданы специально для нашего проекта, но они охватывают как можно больше, как производственное обслуживание. Все работает локально либо на Linux, либо на MacOS, за исключением облачных сервисов, для которых мы находим способы не вмешиваться в производство.

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

+0

Почему бы не асинхронно вместо lwt? Тогда нет необходимости в каких-либо камерах4. Кроме того, не использовать ocamlnet в любом месте? – rgrinberg

+0

В двух местах вы говорите, что OCaml 4.01.0 делает что-то возможным. Можете ли вы указать, какая функция 4.01.0 делает это? Это улучшит ваш уже отличный ответ. Благодарю. –

+0

@rginberg OCamlnet является монолитным, и его сетевые библиотеки не хорошо сочетаются с Lwt. Мы используем усеченную версию части Netstring OCamlnet, которая не зависит от кода C OCamlnet. –

5

Это один, вероятно, не ответить на ваш вопрос полностью, но вот мой опыт относительно построения среды:

Я действительно ценю OASIS. Он имеет хороший набор функций, помогая не только создавать проект, но и писать документацию и поддерживать среду тестирования.

система сборки

  • OASIS генерирует setup.ml файл из спецификации (_oasis файл), который работает в основном в качестве строительного сценария. Он принимает -configure, -build, -test, -distclean флаги. Я довольно привык к ним при работе с разными GNU и другими проектами, которые обычно используют Makefiles, и я считаю удобным, что здесь можно использовать все из них автоматически.
  • Makefiles. Вместо генерации setup.ml можно также создать Makefile со всеми описанными выше опциями.

Структура

Обычно мой проект, который построен OASIS имеет, по меньшей мере, три директории: src, _build, scripts и tests.

  • В прежнем каталоге все исходные файлы хранятся в одном каталоге: файлы источника (.ml) и интерфейса (.mli) хранятся вместе. Может быть, если проект слишком велик, стоит добавить дополнительные подкаталоги.
  • Каталог _build находится под воздействием системы сборки OASIS. Здесь хранятся исходные и объектные файлы, и мне нравится, что файлы сборки не мешают исходным файлам, поэтому я могу легко удалить их, если что-то пойдет не так.
  • Я храню несколько сценариев оболочки в каталоге scripts. Некоторые из них предназначены для выполнения тестов и создания файлов интерфейса.
  • Все входные и выходные файлы для тестов, которые я храню в отдельном каталоге.

Интерфейсы/Документация

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

Но главная причина, по которой мне нравятся интерфейсные файлы, - это документация. Я использую ocamldoc для генерации (OASIS поддерживает эту функцию с флагом -doc) html с документацией автоматически. На мой взгляд, достаточно написать комментарии, описывающие каждую функцию в интерфейсе, и не вставлять комментарии в середине кода. В OCaml функции обычно короткие и сжатые, и если есть необходимость вставлять туда дополнительные комментарии, возможно, лучше разделить функцию.

Также обратите внимание на -i flag for ocamlc. Компилятор может автоматически генерировать файл интерфейса для модуля.

Тесты

я не нашел разумное решение для поддержки испытаний (я хотел бы иметь некоторые ocamltest приложения), поэтому я использую свои собственные сценарии для выполнения и проверки случаев использования. К счастью, OASIS поддерживает выполнение пользовательских команд, когда setup.ml запущен с флагом -test.

Я не использую OASIS в течение длительного времени, и если кто-нибудь знает какие-либо другие интересные функции, я хотел бы также узнать о них.

Кроме того, вы не знаете о OPAM, это определенно стоит посмотреть. Без него установка и управление новыми пакетами - это кошмар.

10

OASIS

Чтобы добавить к Павлу ответ:

Отказ от ответственности: Я являюсь автором OASIS.

OASIS также имеет oasis2opam, который может помочь быстро создать пакет OPAM и oasis2debian для создания пакетов Debian. Это крайне полезно, если вы хотите создать цель «выпуска», которая автоматизирует большинство задач для загрузки пакета.

OASIS также поставляется со сценарием под названием oasis-dist.ml, который автоматически создает tarball для загрузки.

Посмотрите все это в https://github.com/ocaml.org.

Тестирование

Я использую OUnit сделать все мои тесты. Это просто и довольно эффективно, если вы привыкли к тестированию xUnit.

Источника управление/Управление

Отказ от ответственности: Я владелец/сопровождающего forge.ocamlcore.org (ака forge.o.o)

Если вы хотите использовать мерзавец, я рекомендую использовать GitHub. Это действительно эффективно для обзора.

Если вы используете darcs или subversion, вы можете создать учетную запись на forge.o.o.

В обоих случаях, когда имеется общедоступный список рассылки, в котором вы отправляете все уведомления о фиксации, необходимо, чтобы каждый мог их видеть и просматривать. Вы можете использовать либо группы Google, либо список рассылки на forge.o.o.

Я рекомендую иметь хорошую веб-страницу (github или forge.o.o) с сборкой документации OCamldoc каждый раз, когда вы совершаете. Если у вас есть огромная база кода, это поможет вам с самого начала использовать документацию, созданную OCamldoc (и быстро ее исправить).

Я рекомендую создавать tarballs, когда вы достигаете стабильной стадии. Не просто полагайтесь на проверку последней версии git/svn. Этот совет спас меня от работы в прошлом. Как сказал Мартин, сохраните все ваши архивы в центральном месте (для этого хорошая идея - git-репозиторий).

+0

Как вы организуете свой проект для включения своих модульных тестов в свою сборку OASIS? Где вы помещаете тестовые файлы и как вы выполняете свои тесты? Пример? – brooks94

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