Hate SDKs for Web APIs that are nothing more than a glorified shim around a HTTP client? Want type hints and concrete types when dealing with APIs? Find writing functional and meaningful SDKs for your APIs a bore and a nightmare to maintain?
Have a machine write your SDKs for you!
There are two services:
src/python/dataserv
- Our API that serves the contents ofdata.json
andschema.json
. It's the least amount of code and dependencies possible to serve the JSON over HTTP.src/elixir/codegen
- A Webservice that takes a URI for an REST API, and a Schema for that API, then spits out SDK in the form of a python wheel that allows you to talk to said API from python. A fully type-hinted SDK, letting your IDE autocomplete for you. Woo.
- Because bad ideas always (usually) start with the best intentions
- See: "What?"
- Do whatever you need to do to install:
- Docker
- Python3 (and the
wheel
package) - Elixir
mix
mix deps.get
- Start the dependent services
$ docker-compose up
- Run the server
$ mix phx.server
-
Create a new library "CodeTest"
-
Pretend you're a CI server, and submit a new/updated resource
$ curl -X POST http://localhost:4000/api/library/<LIBRARY_ID>/resource \
-H "Content-Type: application/json" \
-d '{"resource": {"uri": "http://localhost:8080/", "schema_uri": "http://localhost:8080/schema.json", "name": "compounds"}}'
-
Download the wheel
-
Install the wheel
python3 -m venv VENV source VENV/bin/activate pip3 install foo-1.0.0-py3-none-any.whl
-
Fetch the API data
$ python3 >>> from code_test.compounds import Endpoint >>> Endpoint.list() Compounds(ALogP=4.686, assay_res....
- First time w/ Elixir. Which in hindsight I feel has made this a poor demonstrator of 'me'.
- While nested dataclasses are defined by the code-generator, the JSON data is not cast to them.
- Don't do this. There's so many reasons why.
- It's missing:
- SDK versioning.
- Authentication. Both with the webservice, and with the SDK's API resources.
- Support for different 'styles' of APIs.
- Support for the full JSONSchema spec.
- Lots more.
The parts of the that didn't touch Phoenix were enjoyable (if not leaving me wishing I was playing with Clojure again). Re-surfacing the functional mindset took a little while, but it's still there and once the functional juices were flowing, I often found myself going back over things and refactoring them to read better. I suspect given another week full-time in Elixir this project and post-mortem would be entirely different.
If I was to redo this, I would have spent more time making the SDK generation better and more functional. Spending less (see: zero) time trying to work out Phoenix. Maybe Phoenix would make more sense if you're coming from Rails (i don't know, I've never touched rails), but I still don't 'get' it.
If this was a real-world project, I wouldn't have gone anywhere near Elixir. It brings nothing to the table and only downsides (hiring, immaturity, complexity, mismatch between target-language to name a few).
If someone asked me to fix or extend in an Elixir project, I'm now pretty confident I could do it. With more real-world examples to lean on and learn from it would be a breeze.
If someone asked me to start a new Elixir project, I would be wary. I've still not seen the full breadth of Elixir's strengths and weaknesses. But for a basic Web service and API, the ecosystems and maturity of other languages would make Elixir a hard sell. Maybe with a bit more immersion my tone would change. It's hard to tell.
-
First time with elixir
-
It's not a bad language, but...
use
is a crime. Import and run code in the global scope? This is a great idea!- Why are there multiple syntaxes for nearly everything? Pick one and commit to it!
foo(bar,baz)
vsfoo bar, baz
[{:foo 1}, {:bar 2}]
vs[foo: 1 bar: 2]
:true
vstrue
if foo do: stuff
vsif foo do stuff end
[:a, :b, :c] ++ [1, 2, 3]
vs"abc" <> "123"
%{"foo" => :bar}
vs%{foo: "bar"}
- Frustrating having /everything/ documented on hexdocs, with /everything/ having the same favicon. Then there's Projects (e.g. Phoenix) split up into multiple documentation scopes, so not even all of the Phoenix project can be searched under the Phoenix banner.
- Sort of feels like A Ruby developer wanted to learn Clojure, but couldn't get past it being a lisp. But then it also feels like Elixir is missing a bunch of things that I feel make Clojure (well, lisps) great.
-
Phoenix is ... not great.
- At the very start of the project,
phx.gen
had pushed the SLOC well past 2k lines. - Generated code didn't really do anything. Sure it looked pretty, but the stuff it did do, it did poorly.
- Still have no idea how some parts work.
- e.g.
render(conn, "index.json", ...)
. Somehow gets linked to the view, but the view just returns a map.- Where's the magical bit that converts the data into an actual JSON response?
- What ties the Controller to the View?
- e.g.
- At the very start of the project,