Hacker News new | past | comments | ask | show | jobs | submit login

There are two that stand out to me:

> Always validate your data server-side; anything that comes from the client is suspect.

At least sanitize in a way that won't break the server but will throw an error. For internal applications and side projects it's ok to just respond with a 40X or a 50X and move on.

> To the developer, “isomorphic” code breaks down the barrier between client and server.

"Breaks down the barrier" sounds great, but it's actually has been rather detrimental. "Isomorphic" is confusing even to the senior developers. Having a very clear delimiter of what runs in the server and what runs in the client is essential, and it makes your application much simpler to reason about. Take `isomorphic-fetch` for example... a request from a server to another API server has very different requirements and nuances than a request from a browser to a server.




> At least sanitize in a way that won't break the server but will throw an error.

If you need to sanitize to avoid breaking the server then the server is already broken. Also, never sanitize, validate on input and escape/encode on output, but sanitization (meaning removing/cleaning invalid input) is the wrong way.


OTOH, if you use Flow or Typescript, it is amazing to be able to share type-safe interfaces across the stack (not code). I suppose you could get this from any compiled-to-JS language too.


I've been using JSON Schema to define shared data structures like request/response data, and QuickType to generate Go structs (back-end) and Typescript interfaces (front-end), it's been great so far.


The realization that this permits end-to-end fullstack type safety and allows some awesome things (like surfacing breakage at compile time in response to changes to the data model) is a quietly brewing revolution.


This is in constant tension with the point that GP is making though.

If you’re not _very_ careful with your software architecture, you can inextricably tie your frontend and backend applications together. Depending on the size of your product, or why the growth plans are for that particular frontend/backend app end up being, this might not be a problem.

If it becomes one, though, then every bad technical design decision made in that `common` set of modules or packages ends up hurting you as it gets unspooled from (at least) two components that likely have very different architectural idioms.


When you really stop and unpack this, you can see that this is a non-issue. Adding an object or a field to the schema (the most common operations in a growing schema) never interfere with dependents and can be performed independently of client adoption.

The remaining coordination issues can be solved by documenting or using e.g. a '@Deprecated' decorator in Typescript. And, of course, you can always just remove a field to see where the code has dependencies on it (where code breaks during compilation).

The concerns about shared code may apply in some cases, but the global schema is not one of them, in my experience. I do agree it takes a bit of extra thinking to do this correctly but it's really not that difficult.


100%




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: