I've experimented with both Home Assistant, Domoticz and OpenHab. They're all pretty good in different ways, but in the end in decided to roll my own.
They all have built-in scripting, but it's pretty common to send events to mqtt and use some external tools for scripting. In ended up using node-red, because it looked interesting and was really easy to get going.
After a while it seemed like the only reason for using any of those 3 systems was the device support, and since I was just using z-wave, for which there is a nice node-red library, I decided to do it all on my own. It only took a couple of week nights before I had most of the things I needed.
It did feel kinda silly to do drag and drop programming, and I did en up using the function node a whole lot, but in the end I stuck with it because it allowed me to show the family what it does and how it works.
I hope it's clear from my previous comments that I don't actually disagree with you on most things, I've just had to make compromises that makes things more accessible to my clientele.
>> "Some other people might write code that does things incorrectly and then their software might break
Welcome to my world :)
>> is something you can say about any API style, it's nothing special to media type versioning
True, but mimetype versioning still makes things more complicated for my average user.
>> If many of your customers are writing code that integrates with your API incorrectly, you don't have an API design problem, you have a poor communication problem, and that's going to hurt you in all kinds of ways.
Sorry, but no. We have full Swagger interface, examples for all major operations in 4 different languages, many pages of documentation and tutorials, and very clear and informative error messages for most situations. Still people will write and say it doesn't work, without having read any docs or even looked at the response.
>> This is not designing for maximum simplicity. Designing for maximum simplicity is to have an API that says "here's a link; follow it", not an API that says "here's an ID, generate a URI from it according to these rules we set out in our documentation, that are different for every type of resource". The latter is more work and more error prone.
I'll reiterate, we're probably designing for different clientele. I'd wager my old Amstrad that most of my users would strip any url'y parts of ids I'd return and just store, what they'd perceive to be, the "true" id in their database, because they only have 20 cloumns allocated in their weird mainframe system, named info1-10 and extra1-10, and the latter only allows 32 chars.
But also consider this: A user uploads a resource through the perfect HATEOAS api, he get's back a big object with a unique url id, and links to all the actions he can perform. It doesn't really makes sense for him to store anything other than the URI though, because I might add more actions later, so he'd have to requery the URI to get links to the latest actions anyway. So for any operation he wants to perform, he should GET URI, parse and follow link with appropriate parameters. Also, in that scenario my system gets hit twice for any operation.
Compare that to: Replace parameters into https://example.com/people/{id}/poke and fire request.
I'd argue that the latter is conceptually simple.
Very soon we'll start on a new api for our ui, and on that there will be no compromise :)
>> I guess you're using something like HTTP digest auth with usernames and passwords?
Basic auth (over https only) actually, I'm even advocating it. We support expirable tokens as well.
>> requests without a specific version get the latest version, or requests without a specific version get version 1, or requests without a specific version get the latest stable version that changes from time to time
The only way for me to go would be option 2: requests without a specific version get version 1. Any other choice and I'd have customers API integrations breaking, because many of them would not have specified their version mimetypes correctly and would therefore get the default version, which would at some point diverge from their expectations.
>> URIs are meant to be the primary keys of the web, and you're going against the grain of the medium when you break that.
In that context your example makes sense, I just don't see that as realistic problem. In real life URI aren't as static as we pretend. How many companies would make sure the resource urls are still valid after changing the company and domain name?
The real identifier in your case is "foo" and "people" is the type. Accepting that sets you free to do versioning as you please and to save 90% characters in all ids :)
In the end we should design apis for our users, not for our selves. My clients are always non-IT departments, often in enterprisy environments, and if they can get 2-4 hours allocated from IT in the next 6 months to do some API integration, they are lucky. So I design my api for maximum simplicity, and maximum longevity of the using scripts, because if I wanted to make a breaking change, I'd have to wait 6 months before all customers could be expected to have transitioned.
Most of my api users couldn't tell you what a mimetype is btw., but a v2 in the url would make complete sense.
I get where you're coming from, on our latest api version I started out wanting to do full HATEOAS (Bought and read this great book http://www.designinghypermediaapis.com/), but in the end I had too much trouble getting my test customers migrated, so I had to scale back on the desgin goals. Scaling back to what worked for everybody was very informative and the api is now, imo, the better for it.
If I need to bump the vesion it'll be with a vx in the url. An id is a simple non-globally unique thing, that you use to build a url etc.
I suspect that we are designing for different clientele.
I'm currently in charge of a pretty classic, GET things out, and POST things in API. If my API supports that some non-IT office guy can get his daily report through the browser, and the API at the same time has the power and flexibility needed for someone with IT skills to do more then I've won. Both me and my users gain by me taking extra steps to make it as accessible as possible.
I also fail to see how versioning through urls break anything, except if the newer client no longer has support for v1. In both versioning schemes you specify which version of a resource you're sending/wants to receive, in one scheme you do it through a header, in the other through the url.
>> If a client using v1 communicates with a client using v2, then they will see two separate sets of resources and they would never have the same identifiers for (what should be) the same resources.
Maybe we're defining versioning differently. I strive to make resource types backwards compatible, but if I can't then it's either a new version or a creating a new more specialized resource type for the specific problem.
I should probably have moderated that statement, but mostly I think it's bad because it makes the versioning aspect inaccessible from the lowest common denominator, the browser address bar.
Versioning through the url and versioning through mimetypes requires the same amount of work from the user, but the former is a lot simpler. If you then also take into account, that many http clients have poor support for manipulating headers (SAP and PowerShell (earlier version) for instance), then choosing mimetype versioning makes it harder (impossible) for your users.
Yes, an additional 4xx code to help differentiate between api endpoints and resources would be nice.
I didn't mean to imply that HTTP status codes could stand alone as error messages, so for a 404 error I'd also respond with more data, to help the user identify the issue.
HTTP has some very useful status codes, which convey standard conditions found in most apis: 200, 201, 400, 401, 404, 403, 406, 429, 500
Also note that not all APIs will be used be developers. Often it's someone less proficient with programming, and you can't rely on them to check the content of the return message. Help them help themselves by making curl (or whatever) bitch when there is an error.
It takes a bit more work to design an API that works over multiple transports, but a good framework, such as Servicestack.net if your in .Net land, mostly does it for you. By advocating 200 for all responses you're basically reverting to SOAP and WCF (Windows Communication Foundation).
Each to his own though, and for internal stuff, it might make a lot more sense.
Code can follow links as well, as long as the semantics doesn't change.
Aside from versioning through mimetypes, which I believe is a really bad idea, I find HATEOAS to be a beautiful concept, although not very useful in practice.
It's a good place to start though. Trying to design for that can help you shape your API properly, just like SOLID or TDD can do for code.
I'm currently looking into what our next client side framework should be and I have a really good feeling about Aurelia. It feels like someone finally got it right. It's the same feeling I had about ServiceStack, which is by far the best web framework I've ever used.
My main criteria is ease of use by backend devs and going by the tutorials I've done so far, that certainly seems to be the case. I am however myself a backend guy and it's quite likely that Aurelia is missing something important or that the niceness breaks down once you cross some complexity threshold, and I can't see that due to my limited experience in that field.
Kilns biggest omission, which is what made me choose Bitbucket, is the lack of branch pull requests. Kilns commit-based PRs are useless in a feature branch workflow.
Bitbuckets code review implementation doesn't handle big changes gracefully though, so I primarily inspect the changes in Beyond Compare.
I bought new certificates, for a new set of domains, through AlphaSSL today. One hour later customers starts calling, complaining about revoked certificates. Initially I assumed they had screwed up somehow and revoked our old certs, but after reports saying that it worked with some browsers and failed on others I started googling for recent related issues, and found out about GlobalSign.
Man, do they suck at communication. We're now 14 hours into the incident. 6-7 hours ago they posted a trouble shooting guid, promising new intermediate certificates for AlphaSSL and I've just been informed by their support that it'll be another hour before they're ready.
It's now 02:00 in dk, so I can expect the new certs at 3 and be done by 4.
Fun night.
Thanks GlobalSign.
P.S. Also thanks to the guy who made their marketing department stop tweeting iot crap while this is going on.
That pissed me off.
As a Citizen of Denmark and a father of two (4 & 1), I absolutely love the danish stuff on Ramasjang and hate most of the American (foreign) stuff. The programs produced in DK are rude and fun and slow and scary, while the foreign stuff is mostly lame attempts at education (Dora the explorer is a particularly nasty example of this) or over the top animations with too much moral crap, too pretty characters and backed by toy franchises and whatnot.
I seems to me that the author actually enjoyed the shows and I mostly agree with his assessment, but he can't have been watching too much because he missed some important shows that are in fact educational.
Most prominent of the educational shows is Mr. Beard, who teaches numbers, counting, simple math, letters and simple spelling. The show is weird and quirky, but also features some great songs. The whole thing is backed by some pretty great apps, which expand on the educational stuff.
There's also a great show about kids helping animals in trouble. They don't pretend that the kids do most of the work, it's a professional that does the heavy lifting, but the kids get involved as much as possible.
I don't mind watching these shows with my kids, but I'll leave as soon as Dora or Thomas the tank engine or Chuggington starts.
If you're interested in watching some completely outrageous danish childrens TV, go watch "Carsten og Gittes vennevilla". It's created by the duo "Wulf Morgenthaler", who have produced some the weirdest stuff on danish TV. Particularly the one where Carsten creates a fox is a hoot.
They all have built-in scripting, but it's pretty common to send events to mqtt and use some external tools for scripting. In ended up using node-red, because it looked interesting and was really easy to get going.
After a while it seemed like the only reason for using any of those 3 systems was the device support, and since I was just using z-wave, for which there is a nice node-red library, I decided to do it all on my own. It only took a couple of week nights before I had most of the things I needed.
It did feel kinda silly to do drag and drop programming, and I did en up using the function node a whole lot, but in the end I stuck with it because it allowed me to show the family what it does and how it works.