Melhores práticas na construção e implantação de aplicações de clojure: Bons tutoriais?
-
25-09-2019 - |
Pergunta
Sou novo no Clojure e estou começando a experimentar a construção de uma aplicação.
Até agora, tudo o que vi sobre os tutoriais sobre a compilação de programas de clojure envolve interatividade. Por exemplo, "Carregue o REPL e TIPE (FALHO DE LOAD" isto ou isso "para ser executado. Tudo bem, mas não é suficiente.
Estou tão acostumado com os idiomas de edição-compilada de idiomas como C ou Delphi, que sou instintivamente conduzido a fazer edições e depois clicar em "MX Compile".
O problema é que "Lein Uberjar", que eu entendo que é equivalente a "fazer", é dolorosamente lento para executar mesmo para um mundo olá. Então, vou ter que descobrir como esse material de "desenvolvimento interativo" funciona, pare de usar o Uberjar como é uma marca rápida e salvá -lo apenas para o final do dia.
Outra coisa que notei durante a construção (usando Lein Uberjar) é que o pequeno aplicativo da GUI que estou trabalhando em quadros pop -up no processo de compilação, como se estivessem executando durante a compilação. Parece um pouco contra -intuitivo para mim; Não é tão análogo a "fazer" como eu pensava.
Sei que a maneira Lisp de desenvolver as coisas está trabalhando interativamente na REPL, e não estou tentando mudar isso: gostaria de me adaptar a esse modo de vida. Infelizmente, vi pouco na forma de documentação sobre como fazê -lo. Por exemplo, como redefinir o estado atual da máquina. Parece meio confuso continuar compilando trechos individuais em tempo real sem poder fazer algum tipo de redefinição.
A maioria dos tutoriais que eu vi no Clojure (e Lisp) em geral parece se concentrar em invadir o REPL. As melhores práticas sobre a implantação de aplicativos continuam sendo um mistério para mim. Meus usuários vão ser usuários; Eles não serão desenvolvedores que carregarão arquivos em um REPL.
Então, aqui está a minha pergunta: algum recurso para obter boas informações ou tutoriais sobre todo o processo de criação de uma aplicação de clojure, incluindo a implantação?
(Nota: tenho todos os pré -requisitos instalados e funcionando (por exemplo, emacs, lodo, leiningen etc.), então isso não é uma pergunta sobre isso).
Solução
Algumas dicas rápidas, depois alguns links:
Não use lein uberjar
durante o desenvolvimento; preferir lein jar
. A diferença é que lein uberjar
coloca todas as suas dependências no gerado jar
(incluindo a própria clojure), para que seu frasco único seja um pacote totalmente independente com seu aplicativo dentro; lein jar
Apenas diminua seu próprio código. o uberjar
A abordagem tem benefícios óbvios para a implantação, mas para o desenvolvimento, você poderá usar apenas o caminho de classe apropriado ao executar seu aplicativo, economizando o tempo necessário para preparar um Uberjar. Se você não quiser gerenciar manutenção à mão para as execuções de teste, confira o lein run
plugar.
Além disso, provavelmente a maioria do seu código não deve ser compilada aot. O AOT é necessário em alguns cenários de interope Java, mas na maioria das vezes traz um leve impulso na velocidade de inicialização e problemas irritantes com compatibilidade binária com diferentes liberações de clojure. Suponho que a última questão não é relevante para um uberjar
-Ed App independente tipo de projeto, mas qualquer código da biblioteca pelo menos deve ser deixado para ser possível, se possível. Com Leiningen, você pode colocar um :namespaces
Cláusula no defproject
forma em project.clj
para determinar quais espaços de nome devem ser compilados; O que você deixar de fora será atualmente Jit-Ed por padrão. Versões mais antigas de Leiningen costumavam compilar tudo por padrão, o que é realmente um bom motivo para atualizar!
Quanto às janelas que surgem durante a compilação, eu acho que você está executando o código de cappagem de janelas durante o tempo de expansão da macro ou fora de qualquer definição de função ou construto semelhante. (Algo como um (println "Foo!")
no nível superior.) Isso é algo que você não deve fazer, suponho - a menos que você esteja planejando executar seu código como um script. Para evitar o problema, envolva o código de efeito colateral nas definições de função e forneça um ponto de entrada para o seu aplicativo usando o :main
Cláusula em project.clj
. (Se você diz :main foo
, então o -main
função do foo
O namespace será usado como ponto de entrada para o seu aplicativo. Esse é o padrão, de qualquer maneira, e pelo menos o acima mencionado lein run
Parece ter o nome codificado - não tenho certeza sobre o próprio Lein.)
Quanto à redefinição do estado do Repl - você pode apenas reiniciá -lo. Com o Slime, o MX Slime-Restart-Inferior-Lisp fará exatamente isso, mantendo todo o outro estado da sua sessão do EMACS.
Veja também essas discussões sobre o grupo Clojure Google:
Outras dicas
Não, você não insere funções no REPL.
Você edita seus arquivos de origem, como sempre. A vantagem do LISP é que você tem o sistema em execução em segundo plano ao mesmo tempo, para que você possa compilar funções individuais do seu arquivo de origem e colocá -las no sistema em execução ou até substituí -las lá.
Se você usa lodo, você pressiona C-c C-c
no seu arquivo de origem para compilar e carregar a função no ponto. Em seguida, você pode mudar para o repl para testar e explorar, mas tudo o que deseja persistir como fonte, você coloca seus arquivos de origem.
Os tutoriais geralmente começam digitando coisas no REPL, porque não há muito que você precisa configurar para isso, mas o desenvolvimento sério integra o sistema em execução e o gerenciamento de arquivos de origem.
Só para ilustrar, meu fluxo de trabalho usual (estou usando o Lisp comum, mas o clojure é semelhante) é assim:
- Inicie emacs
M-x slime
Para começar o slime, o sistema Lisp e conectar os dois via Swank,
(comando)load-system
foo
para carregar o projeto atual (compilando apenas se necessário) na imagemC-x b
Mude para um buffer de origemC-c ~
Faça do diretório de origem o diretório atual e o pacote de origem, o pacote atual do REPL
Agora, estou configurado com meu sistema em segundo plano. Trabalhar é então:
- Alterar ou adicionar uma função ou definição de classe
C-c C-c
Para compilar e carregá -lo na imagem- mudar para repl, teste
- depurar
Não há pausas de compilação significativas, porque eu nunca compilei tudo de uma só vez, apenas definições individuais.