Clojurians
#clojure-italy
<
2018-04-03
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

mdallastella08:04:30

Buondì, ripresi da pasquetta?

helios08:04:38

@gabriele.carrettoni anvil.works ?

helios08:04:45

(ne ho letto sto weekend)

helios08:04:50

ovviamente io consiglio clj/cljs :smile:

gabriele.carrettoni09:04:28

giorno, @helios non ho provato

gabriele.carrettoni09:04:45

ultimamente ho lavorato ad una "draft" per uno schema per definire api con edn, stile swagger/openapi, so che sarebbe solo un formato in più ma scrivere a mano json o yaml mi fa stare male

gabriele.carrettoni09:04:09

anche perché non supportano casi complessi come tipi generici

gabriele.carrettoni09:04:57

vediamo se riesco ad arrivare a qualcosa di decente, qualcuno ha mai avuto l'esigenza e sarebbe disposto a dare un feedback?

nilrecurring09:04:41

Il mio workflow per tirare su una nuova API: 1. Scrivere la Swagger spec a mano in yaml 2. Da lì generare il server 3. Collegare tutta la logica, db, etc 4. Generare i vari client dalla spec del server (questo lo fa la CI)

nilrecurring09:04:34

Proprio oggi sono alla fase 1 di un nuovo servizio

gabriele.carrettoni09:04:06

disagiante scrivere yaml però

helios09:04:16

anche questo e' vero

gabriele.carrettoni09:04:17

in praticolare se hai casi complessi e mille mila api

gabriele.carrettoni09:04:37

già solo esprimere un tipo di ritorno generico è un esercizio in frustrazione

gabriele.carrettoni09:04:59

esempio: qualcosa del tipo "PaginatedList<BeanGenerico>"

reborg09:04:01

Forse mi sono perso le premesse, ma compojure-api permette di scrivere clojure+spec per descrivere APIs. Inoltre credo che usando spec-tools si possa generare JSON schema per i vari consumers: https://github.com/metosin/spec-tools#generating-json-schemas (non l'ho mai usato pero')

gabriele.carrettoni09:04:21

la premesse è che prima di scrivere una api (a livello di codice) la scrivi in un formato tipo swagger, fai le review con i componenti del team

gabriele.carrettoni09:04:26

e poi inizi a scriverla

gabriele.carrettoni09:04:43

clojure+spec non va bene dato che non posso chiedere ai miei colleghi di impararsi clojure

reborg10:04:24

ed edn invece andrebbe bene?

nilrecurring10:04:10

@reborg ho usato spec-tools per generare json-schema e funziona molto bene. Ma una volta che stai usando compojure-api ha senso generare swagger (anche perchè i modelli swagger sono espressi in json-schema IIRC)

nilrecurring10:04:44

@gabriele.carrettoni le premesse che abbiamo sono le stesse, è molto comodo avere la visualizzazione Swagger dell’API anche se l’API non esiste ancora, per sanity-check e review. Per quanto riguarda i “tipi generici” noi non abbiamo problemi particolari, e abbiamo Swagger su un servizio Haskell (che ha un type system un pelo più potente di Swagger). L’assunzione è che i tipi all’esterno devono essere semplici e concreti: liste di oggetti, no oggetti generici tipo { "key" :: String , "value" :: String } (anche se Swagger è perfettamente capace di esprimerli), etc.

nilrecurring10:04:14

La mia euristica personale è che se è doloroso buttare giù i tipi dell’API a mano, allora probabilmente le data structures che stai passando ai bordi sono troppo complicate, e non saranno simpatiche neanche per i consumer dell’API

bronsa10:04:37

purtroppo per problemi familiari non riusciro` a venire a dcd :white_frowning_face:

bronsa10:04:55

@skuro c'e` da disdire la "prenotazione" in qualche modo?

gabriele.carrettoni10:04:32

@nilrecurring liste di oggetti, se hai una struttura, tipo una lista paginata, è abbastanza ripetitivo dover ogni volta dover ridefinire la parte esterna e poi definire il bean interno, quando magari lo hai già definito da un'altra parte, esempio: GET /requests -> PaginatedList<RequestBean> GET /requests/<uid> -> RequestBean

nilrecurring10:04:31

Ha senso?

GET /request        -> [Request]
GET /request/<uid>  -> Request

gabriele.carrettoni10:04:50

ok ma io non ho una lista in uscita, ho una PaginatedList

gabriele.carrettoni10:04:13

che definisce {"has_more": true|false, "data" : [Request]}

nilrecurring10:04:35

E come chiedi la prossima pagina?

gabriele.carrettoni10:04:58

chiamando GET /requests?starting_after=(campo id dell'ultima request)

manuel10:04:30

@bronsa ah caspita, mi spiace!

mdallastella10:04:55

@bronsa peccato, spero nulla di troppo grave!

bronsa10:04:05

eh purtroppo non e` una situazione neanche troppo simpatica... ma si fa il possibile

mdallastella10:04:40

Non sarebbe più "REST" avere tipo /products/page/1?

mdallastella10:04:30

e /product/<product-id>

mdallastella10:04:06

boh, non c'ho mai capito molto delle sintassi REST a dire il vero :sweat_smile:

gabriele.carrettoni10:04:24

vabbe tanto il punto non è quello, non sono api che posso mettermi a scrivere in un modo diverso anche volendo

gabriele.carrettoni10:04:18

e comunque non credo sarebbe più rest dato che page non è un attributo di un prodotto

mdallastella10:04:43

quindi dici GET /products?page=1

gabriele.carrettoni10:04:25

volendo potresti fare così ma implica sempre l'esistenza di qualcosa chiamato page

gabriele.carrettoni10:04:39

se usi una cosa del tipo GET /requests?starting_after=(campo id dell'ultima request)

gabriele.carrettoni10:04:49

starting_after è tipo un cursore

gabriele.carrettoni10:04:21

combinato con &limit= permette un po' di flessibilità sulla quantità di elementi da estrarre