14 ms·
How porting to TypeScript solved our API woes
- shortstuffsushi 7y agoPorting to a typed language helped prevent type errors in a typeless language. Who woulda thunk? I am currently also working on a project written in a JS backend that's slowly porting to TS, for the same reasons, but I still would prefer to go back to C# and take it a level further. I just don't enjoy the TypeScript language all that much.
- smt88 7y ago> Porting to a typed language helped prevent type errors in a typeless language. Who woulda thunk? You say this sarcastically, but every JS-related thread on HN turns into a flamewar between type lovers and haters. The type haters make exactly the argument you're mocking: that typeless languages do not result in more type errors. Their reasoning is along the lines of, "I don't need a type system because I'm a professional and don't make mistakes." That sounds laughable or like an exaggeration, but it's a surprisingly common line of thinking. The buggiest code I ever worked on was a PHP code base written by someone who had been coding for 20 years and had a Master's in CS. Before I inherited the code, he told me, "I code in the terminal. I don't need IDE features because I don't really make mistakes in PHP anymore." Again, seems satirical, but not uncommon.
- giulianob 7y agoThose people are also missing the point that not having types means you are inherently writing a slow program.
- diggan 7y agoThat's the first time I heard that any language that doesn't have types, is slower than a program with types. I'm unsure if that actually makes sense. You mean slower as in performance? I'm having a hard time understanding how types == performance, so you have to mean something else. I guess assembly would be the language you would use if you really need to squeeze out the maximum amount of performance of a single CPU, and as far as I know, it does not have types. Also languages built on top of LLVM could get by with trading compile times for run time performance. Maybe you meant compiling gets slower without types?
- Arnavion 7y agoStrong typing means that at runtime dynamic behaviors don't need to be accounted for. For a compiled language, the compiler could know that `foo` and `bar` are 32-bit integers, and thus compile `foo + bar` to call the addition function for 32-bit integers. In an interpreted language, the interpreter could do the same thing. Without that typing information, both would have to invoke a generic addition function that detects the types of its arguments at runtime, notices they're both 32-bit integers, and delegates to the corresponding addition function. Of course there are tricks that can be played in the weakly-typed case, like assuming the same call site will always have the same types, so that there can be a short path that assumes that and only branches rarely. That way the first or first few executions might be slow, but eventually they get almost as fast as the statically-typed case. JS engines in particular and JITted runtimes in general usually do this. >I guess assembly would be the language you would use if you really need to squeeze out the maximum amount of performance of a single CPU, and as far as I know, it does not have types. Assembly absolutely does have types. The addition function for 32-bit ints only operates on 32-bit ints, and is distinct from the addition function for 64-bit ints.
- mr_toad 7y ago> Assembly absolutely does have types. The addition function for 32-bit ints only operates on 32-bit ints You can add any bits that will fit in the relevant registers. Assembly cares not whether the programmer thinks they are ints.
- Arnavion 7y agoYou should read the part of the sentence you cut off in your quote.
- jbboehr 7y agoDynamically typed languages still have types internally, they just look like this [0] (imagine it all implemented in assembly, without C's types, if you prefer). [0]: https://github.com/php/php-src/blob/3709e74b5e495e210ada8039ed81fafa9cbadcdb/Zend/zend_types.h#L282-L328 https://github.com/php/php-src/blob/3709e74b5e495e210ada8039...
- dang 7y agoPlease don't post grand unsubstantive claims to flamewar topics. That's bomb-throwing and usually leads to silly explosions.
- giulianob 7y agoReally look at any significant benchmark or what types of projects use which languages. The evidence is extremely clear and makes sense due to how computers work.
- Roboprog 7y agoThat was certainly true in 1990. The use of JITs has changed that to a large extent, as frequently used code paths can be rewritten at runtime in many cases. Static types tend to push people towards copy-pasta code, as well, which can even work against performance.
- smt88 7y agoThe factors affecting program speed are numerous, and I would guess that types do not have nearly the greatest effect. Most of us are not optimizing for program speed. Machine time is cheap. Human time is expensive. The biggest cost-savers for most programmers will be the ergonomics of a language, not the optimizations available to the compiler.
- mr_toad 7y agoSo assembly code is slow?
- diggan 7y ago> Their reasoning is along the lines of Now I'm sure that many feel like that, but I don't think it's the majority, but I also don't know. Here are some more arguments against types (don't necessarily agree with all of them myself, but for reference in the future when you want to write from the perspective of someone who feels more productive without types): - There are other, more flexible ways to solve the same problems you solve with typing, the clojure.spec way is one of them - You lose flexibility when suddenly everything is locked to each other by name. Even if Account and Person both has a first and last name fields, you can't use both of them if the function is expecting a Account and only use the first and last name. Then you need to add an interface, name it something, then make Account and Person be based on that. Now the function is locked to the interface, and so on - Type checking is a very basic form of testing that doesn't solve the most common, annoying and hard-to-track down bugs, logic bugs. - Metaprogramming becomes harder. Not impossible, just harder. - Types (at least in TypeScript and other languages I've been using in the past) disappear in runtime, so you can't really use them. It's just a tool for you to tell the compiler what something is so it can say "no, you did wrong here" Now I'm neither a type lover nor hater. I just want to use the right solution for the right problem, sometimes, that's making a program that will take longer time to write but specification is set in stone and requirements won't change, so types will help you a lot. Other times, it's in a very dynamic and experimental environment where you have to be able to apply changes as quickly as possible and minor errors don't matter as much, as long as you can move forward fast and test theories. Then you can go back and refactor things.
- jakear 7y ago> You lose flexibility when suddenly everything is locked to each other by name. TS uses structural typing.
- diggan 7y agoThat's good, compared to the nominative type systems, on that point at least! I'm just trying to help the person I'm replying to to see more arguments in favor of dynamic systems without types, not necessarily straightly aimed at TypeScript as they mainly mentioned just types.
- woah 7y agoHow can you call yourself a programmer if you need a type system babysitting you? EDIT: my apologies to anyone who did not realize this was satirical
- greglindahl 7y ago> The type haters make exactly the argument you're mocking Funny, I usually see type haters claiming that they don't actually make the kinds of mistakes that are fixed by strong typing. Which is a completely different sentiment.
- netghost 7y agoI think the more nuanced point folks tend to make is that they catch the errors at Run Time instead of Compile Time, and that the cost of strict typing is greater than that of catching it at Run Time. Personally, I'm agnostic (I make mistakes in all phases and fix most of them eventually ;) )
- greglindahl 7y agoI agree that people make that point, and I agree that it's a good one. But it's irrelevant to this sub-thread, which started with me attempting to convince smt88 that they were misrepresenting the opinion of the people they were laughing at.
- nohuhu 7y ago> Funny, I usually see type haters claiming that they don't actually make the kinds of mistakes that are fixed by strong typing. As your typical type hater, my preferred argument is: yes, static typing prevents a certain class of bugs from happening; no, this class of bugs is not nearly as relevant as type lovers seem to be claiming. By an order of magnitude if not more. Source: 6 years of being a core developer of a front end framework consisting of 1,500,000 lines of ES5 JavaScript and SASS.
- dang 7y agoThat of course is not the argument at all. The argument is that the cost of working with static types exceeds the benefits. Finding type errors is obviously a benefit, while not finding them (or finding them only at runtime) is a cost. The question is what other costs and benefits there are, and how to compare them. Nobody agrees on that, nor ever will. This argument will never be resolved because it's dominated by psychological factors. Once you've adapted to environment A, A's costs (e.g. hoops the compiler makes you jump through / time spent tracking down type errors) become habitual and you don't notice them anymore. Meanwhile the costs of unfamiliar environment B are extremely highlighted in your attention. Similarly, if you like and identify with A, its benefits will be top-of-mind for you, while if you don't like B (and nobody likes B), you'll discount its benefits. It gets worse. Sometimes benefits are costs until you make it through a learning curve. An example is parentheses in Lisp. They stick out like a sore thumb until one day they don't. Later you realize that they were a liberating force all along, and you now have anti-gravity powers you never dreamt of. (<-- This is an example of how people talk when they are adapted to an environment whose costs they no longer count and whose benefits are top-of-mind for them.) We can't even agree on what the costs and benefits are, let alone how to measure them. It's no wonder that people feel so strongly about this dispute. When you don't count the costs of your preferred environment, and only count the benefits, it gets obvious pretty quickly that other people are idiots. For some reason the idiots feel the opposite and perversely insist on it. It gets worse. Imagine that you're a decent, fairminded sort and so, magnanimously as is your wont, you decide to give the idiots a fair shake—you know, just to verify that you're being fair and whatnot. You fire up whatever it is (Clojure? OCaml? needless to say, you make a charitable choice) and start programming for a while. What happens? All the costs of unfamiliarity hit you in the face. Not one of the benefits that has lived at the top of your mind for years is anywhere to be seen. This thing doesn't even catch trivial type errors at compile time! / I can't even execute this bit of code in a REPL! This is a painful experience. It can even be an enraging one, for example if you are forced for some extraneous reason to work on a system you didn't create using tools you don't like. Most people who go through that experience once have their views solidified for life. Meanwhile someone else had the opposite experience. Given how passionately people feel about this and the certainty in forum threads about it, it's curious (or maybe to be expected) that the question of published evidence comes up so rarely. HN user luu did the definitive survey on this: https://danluu.com/empirical-pl/ https://danluu.com/empirical-pl/. The short version is that such studies as there are don't address the core question and/or find insignificant effects and/or their designs tip obviously to one side or the other (and I do mean obviously, like comparing Peter Norvig's code to that of random undergrads). Bias dominates every other factor, put together, times at least 10. As long as that's true, we can't say anything rational without genuinely accounting for bias. Do we actually know how to do that? The studies don't seem able to. These debates certainly don't, nor do they try. Maybe the interesting phenomenon here is actually the bias itself. Maybe it's not that we like an environment because we're more productive in it, but that we're more productive because we like it. Maybe we should get better at liking things. The debate about this tends to remain stuck at a low level because once you've been around the block enough times you realize that it hurts to bang your head against a wall so you stop. Thus the vocal population undergoes a perpetual exodus of the experienced, but makes up for it with a fresh supply of enthusiasts, reminding one of the adage, "I arrive at the office late, but make up for it by leaving early."
- beders 7y ago[parent predicts flamewar, starts one with:] > Their reasoning is along the lines of, "I don't need a type system because I'm a professional and don't make mistakes." Nah. Where did you get that? That's so horribly wrong, it's not even funny. Types are one tool in the toolbox to describe a system. It is not the most powerful or expressive one. It just happens to be available at compile-time. It catches trivial bugs, acts as documentation, helps the compiler with memory allocation. It also is static. And that's where the weaknesses begin. A whole class of problems that benefit from domain definitions being available at runtime are clumsy to write in languages that force types on you. Not impossible, of course, but clumsy. (i.e. place-oriented programming) To your point: Everyone makes mistakes. The way to catch them and to prevent them in the future is not by having types. It's by writing tests. Tests > Types > no types at all
- yakshaving_jgt 7y ago> Tests > Types > no types at all You conveniently neglected to include (Types + Tests) at the beginning of your little food-chain there.
- orange8 7y agoDid you miss the part where they said "... at runtime are clumsy to write in languages that force types on you.." That may most likely put "types + tests" at the bottom of their food-chain. And speaking of TS, since it compiles down to JS in production, it can be considered a very basic type of testing, or an advanced type of linting.
- yakshaving_jgt 7y ago> That may most likely put "types + tests" at the bottom of their food-chain. That is totally illogical. If types are better than nothing, and tests are better than nothing, then how could both tests and types together be worse than nothing? > Did you miss the part where they said "... at runtime are clumsy to write in languages that force types on you.." No, I didn't miss it. I just disagree with it. Interpreting values at runtime is called "parsing". The parsing step exists regardless of whether the program is written in a static language or a dynamic language.
- mgkimsal 7y ago> Before I inherited the code, he told me, "I code in the terminal. I don't need IDE features because I don't really make mistakes in PHP anymore." Again, seems satirical, but not uncommon. Went to a tech meetup group hosted at a moderate sized local tech company. The tech company had job openings, and I'd looked at a couple earlier that month. Some of their staff came to the meetup, and I got to talking with one of the 'lead' guys. I'd recently started using IntelliJ, and was talking to some others about how much more productive I was being, and it was the best money I'd spent on anything in year. The lead guy jumped in and basically said IDEs were for wimps (more or less). If you're a good developer, you don't need an IDE - he knew everything about their codebase, was very productive, and had been for years. My experience was the opposite - I do a lot of freelance/consulting/dev stuff - my life is jumping between projects every few months or year or so. Having tooling that helps me understand so much more about a project than I could get just from vim (for example) was so eye-opening and transformative to my way of thinking that it made me re-evaluate a lot of previous notions, habits and assumptions about development. I'd explained that using good IDEs had made me better at my craft in every conceivable way. He just sort of shrugged and said he could understand why some people might need an IDE, but they're mostly just crutches for people who don't want to spend the time to learn a codebase the 'real' way. I'd been interested in applying to that company, but didn't bother after realizing I would be having to work with that attitude daily.
- winrid 7y agoIt's just someone being elitist. Why not learn the codebase AND use nice tooling? Silly argument.
- valuearb 7y agoWhen I first got into Node.js I went to a Node meetup and mentioned I was having trouble getting typescript set up. They admonished me, saying you don’t need that, you just need test coverage. Ok...
- Lio 7y agoAgree with your point but just want to point out that you can have "IDE features" without an IDE and in the terminal if you want them. See either Emacs or any editor using LSP such as Vim/NeoVim.
- seanmcdirmid 7y agoTS has some great typing features that I would miss going back to C#, but I miss the better type error messages I get in a nominal type system.
- protonimitate 7y agoTS errors are my only real complaint about TS. Otherwise it's a joy to work in, imo. Trying to go from TS back to JS is a frustrating experience to say the least.
- karatestomp 7y agoTS can generate such good and natural looking JS that, faced with someone insisting on receiving a JS codebase, I’d consider keeping a shadow-repo in TypeScript and handing them its output. Doesn’t work so well with an existing codebase, but still.
- damidekronik 7y agoYea, the structural typing nature of TS drives me nuts. One thing I like in TS is the ability to reference individual "parts of a type", for example Account["email"] instead of "string" in function signatures. Is there something like that in C#?
- pathartl 7y agoSame. The only JS I have to write anymore is for some customization on top of a CRM platform we use. For that I've decided to go with Bridge.NET. They've build .NET libraries based on typings so it has support for almost everything. The resulting JS is FAT, don't get me wrong, but since this is for internal use and it's heavily cached, I don't mind having our users download a 3MB JS file.
- chowells 7y agoA shockingly large number of people tell you that types don't help in the real world. If those people believed this article, I'm sure they'd find it surprising.
- deleted 7y ago[deleted]
- awinter-py 7y agothis is ruby -> TS was expecting JS -> TS
- swrobel 7y agoIt’s both
- dguo 7y agoNote that Stripe is working on a type checker for Ruby: https://sorbet.org/ https://sorbet.org/ I second the sentiment though. I wouldn't choose to use plain JavaScript over TypeScript for any significant project. You might ask why I wouldn't just use a more fully typed language like Java. My main response is that I love having the flexibility to choose how strict the types should be. Sometimes, typing something out fully is not worth the trouble. Having escape hatches lets me make that choice. While I enjoy using types to turn runtime bugs into compile time errors as much as possible, it's not the right thing to do 100% of the time.
- gregkerzhner 7y agoHaving partial type safety is like having a no peeing section in the pool.
- dguo 7y agoTo your point, I do think it depends on the team and their ability to make good judgment calls. But type safety is a spectrum anyway. One could say that not having dependent types is like having a swimming pool without a lifeguard. Should every swimming pool in the world have a lifeguard? Probably not.
- lmm 7y agoLifeguards are expensive. Basic typing is damn near free. More languages should adopt dependent typing, but for the moment there are languages that lack it and offer enough advantages to make up for that. I don't think you can say the same thing for languages without a true type system (one in which unsoundness is the exception rather than the rule) - there are too many good alternatives for it to be worth compromising on that.
- jjeaff 7y agoThat's not true. There are plenty of cases where certain pieces of software is cordoned off and/or non-critical that would not affect the rest of your stack if they fail.
- gyrgtyn 7y agoI watched them go through this process via twitter, and it sounded like inventing that shared api model was a type puzzle i wouldn't be able to figure out myself. also they're the only people i know of doing it?
- Scarbutt 7y agoThis is more prominent in Haskell and Scala circles.
- xupybd 7y agoWow porting the entire backend in two weeks is impressive. I guess he knew the domain well and both languages well but I'm impressed.
- lmm 7y agoIf you control both ends of an API, there's no reason not to use Thrift or equivalent (gRPC) rather than untyped JS. Even if you don't believe in typing in general, an API boundary is exactly where it's most important to make sure both sides agree on what the interface is.
- nice__two 7y agoAbsolutely! If you don't do this, you're just building the next unmaintainable distributed monolith.
- jpdb 7y agoCalling gRPC endpoints from the browser isn't something that works very well today.
- lmm 7y agoCalling thrift endpoints from the browser works great. I had heard that gRPC was a thrift equivalent but haven't used it myself.
- ledauphin 7y agoGraphQL works well for this also if that's an option in your stack. It advertises lots of benefits but the enforced schema types are worth the price of admission even if you're doing simple CRUD with no graphs.
- cryptica 7y agoThe title is misleading because TypeScript does not implicitly do any kind of runtime type checking on data which was sent by remote clients - If the client and server both happen to be written in TypeScript by the same team, the TypeScript type system can give those developers false confidence that the API endpoints on their server enforces runtime type validation on remote user input (I've seen this too many times), but it does not. To implement API endpoints correctly in TypeScript, you're supposed to assume that the arguments sent by the remote client are of 'unknown' type and then you need to do some explicit schema validation followed by explicit type casting. Some TypeScript libraries can make this easier but it's misleading to say that this is a native feature of TypeScript; in fact, it is no different from doing explicit schema validation with JavaScript (there are also libraries to do this). You should always validate remote user input regardless of what programming language you use. Merely getting the compile-time static type checker to shut up because the types in your client code match the types in your server code is not good enough unfortunately - In fact, it may conceal real issues by giving developers false confidence that runtime type validation is happening when in fact it is not. A hacker could write a client in a different language and intentionally send incorrect input to crash your server unless your server explicitly validates the schema. The reality is that there is no guaranteed type continuity/consistency between the client and the server. Any tool which gives the illusion that there is any kind of continuity is deceptive by design. This is why I like plain JavaScript; it requires real discipline and it doesn't give any sense of false confidence. Developers should always be on their toes. The only way to improve code quality and security is by exercising more caution, not using more tooling. The benefit pointed out by the author of this article is in fact one of the few genuine gaps in TypeScript's type safety capabilities. Praising TypeScript for this fictitious feature is only going to give developers false confidence that TS somehow takes care of input validation for them and this is going to lead them to getting hacked.
- gary_bernhardt 7y ago(I wrote the article.) Our system uses io-ts to dynamically validate all incoming and outgoing API data. The static API types are guaranteed to match the io-ts codecs, so the runtime validation will match the static types. Re: "it's misleading to say that this is a feature of TypeScript": I didn't say that. TypeScript makes this kind of static verification possible. It's impossible in JavaScript. Re: "The benefit pointed out by the author of this article is in fact one of the few genuine gaps in TypeScript's capabilities": yes, it's a gap in TS. Again, TS makes it possible (as opposed to JS). io-ts (mentioned explicitly by name in the article) backfills the type erasure shortcoming for our purposes, at the expense of being more verbose and producing worse error messages when compared to first-class reflection in a non-type-erasing language. Re: "going to lead to them getting hacked": no, io-ts isn't going to lead to that more than any other runtime validation scheme. If someone believes that TS' static types provide runtime guarantees, yes, they could write highly insecure API code. But it's hard for me to imagine someone getting to an experience level where they can write a server-side router that's generic over all possible API endpoint payloads, while at the same time not knowing that TS erases types at runtime. Erasure comes up early in the process of learning TS because it leads to surprising behavior, like objects at runtime having properties that aren't present in their static type.
- cameronfraser 7y agoHow does one deal with remote data in typescript? I really like typescript, but not having any guarantees on the returned data is kind of frustrating.
- andy_ppp 7y agoThere are things like io-ts that do exactly this: http://github.com/gcanti/io-ts http://github.com/gcanti/io-ts
- moltar 7y agoYup plus see other projects in the same vein: https://github.com/moltar/typescript-runtime-type-benchmarks https://github.com/moltar/typescript-runtime-type-benchmarks
- k__ 7y agoAWS Amplify has a code generator that uses GraphQL to generate client side TypeScript and server side APIs
- k__ 7y agoJust found out they're using this: https://graphql-code-generator.com/ https://graphql-code-generator.com/
- postalrat 7y agoLet it fail and make sure you are getting notified.
- a_humean 7y agoIt is actually quite frustrating compared to some other languages, and more often than not you see that its just `JSON.parse` and hope for the best. I wish we had something like Rust's Serde or Haskell's aeson. If you want to validate data coming over IO then your options are data validation libraries such joi, io-ts, and yup. You have to write seperate data validators on top of your types. io-ts has a way of deriving types from validators, but io-ts is often seen as quite intimidating being built on top of fp-ts. No matter how carefully you maintain strict typing within your typscript project the moment you hit IO everything is basically `any`. Some projects like openapi-generator might generate some validators for server respones, but I've not seen any good generators that do actual validation. I'm not sure if apollo-graphql does responses validation? Does anyone know?
- leipert 7y agoDo I read the chart correctly and their whole Codebase (minus dependencies) is less the 15k lines of code? Porting 6.5k likes of ruby in 2 weeks sounds reasonable, but how doing migrations 10x or 100x that size is far more challenging.
- myth_drannon 7y agoI think Gary is the only guy working on the project and it is a new project no wonder he migrated it super fast.
- TheSpiciestDev 7y agoI can't imagine not using class-transformer[0] or class-validator[1] in any TypeScript project that deals with external/third-party APIs, remote or not. [0] https://www.npmjs.com/package/class-transformer https://www.npmjs.com/package/class-transformer [1] https://www.npmjs.com/package/class-validator https://www.npmjs.com/package/class-validator
- exogen 7y agoI don't understand the point of transforming things to class instances, though. All of TypeScript's strengths are available without the need for things to be an actual `instanceof` something, right? Can you elaborate? FWIW, I'm biased against `class-transformer` because we were wondering why some of our (TypeScript-driven) API endpoints were so slow, and `classToPlain` + `plainToClass` were the culprits, comprising 2/3 of the time spent. If you look at the source code for those functions, they're kind of insane.
- eropple 7y agoAgreed that actually doing the transformations is a bit of a mug's game. However, TypeScript's type system treats class definitions interestingly, particularly around metadata. You can attach validation metadata to a class and pass plain objects around that structurally match that class so long as you don't define methods or a constructor. As mentioned in my sibling comment to yours, I do this to define DTOs that are then expressed in JSON Schema and passed through ajv, and it's pretty slick. The objects being used are all just JavaScript objects, the class is just being used as a metadata holder and something you can reference/get via `design:type`/`design:paramtype`/`design:returntype`.
- eropple 7y agoI can, because I use ajv and JSON Schema instead because I can trivially just take those models and use them in OAS3 documents. The web framework I've built on top of Fastify--and will be open-sourcing soonish--uses pretty simple model and property annotations to let you define your systems in those terms, and I find it to be really flexible and pleasant to work with. EDIT: Also, as mentioned elsewhere in this thread, io-ts is a pretty good option too!
- myth_drannon 7y agoHow times are changing. The person who is famous for his amazing Ruby/Rails screencasts rewrote his Ruby backend to TS...
- theonething 7y agoBut Ruby is so much more fun that JS or TypeScript. /opinion
- deleted 7y ago[deleted]
- valuearb 7y agoSwift on the Server!
- eat_veggies 7y ago> That means that when one side of the API changes, the other side won't even compile until it's updated to match. Coupling your front end and back end in this way can give you false confidence in making API changes. If you control both sides of the API on a web app that doesn't have too many users yet, then this can be very productive, but consider this situation: You've made a breaking API change on the back end, and thanks to your type system, you make the corresponding front end changes as well, which is great. You deploy your code, and the back end changes take effect immediately. Visitors who were in the middle of a session are still running the old front end code, and their requests start failing. Cached copies of the front end start failing too. You can engineer around this but it's better to have a system that doesn't make introducing breaking API changes too easy. It should be painful.
- jkaptur 7y agoAnd if you do a gradual rollout, newer clients can connect to older backends! And if clients can talk to each other, there can be THREE versions involved. Also: rollbacks. I’m curious if anyone has a system for managing this that they love. I’ve pretty much only seen painful ways.
- n0w 7y agoI think in an ideal world you would do API changes to a live system in much the same way as you do with a live Database Schema: Carefully, and in a backward compatible manner.
- hamandcheese 7y agoAt <dayjob> we use flow types and graphql, so like OP our frontend will fail to compile if we make a breaking change. To assist with the backward-compatible-during-deploy issue, we additionally have a teensy bit of tooling that comments on our PRs to indicate dangerous API changes. It's not perfect (I've ignored the comments before, thinking I knew better... I didn't), but it seems to help. It wouldn't be difficult to make it more sophisticated, and then completely block PRs it knew weren't backward compatible, but we haven't seen a strong need to do that yet.
- 7y ago
- femto113 7y agoDid it not occur to them to, I don't know, "test" the API when they make changes? A compiler or stricter type system may help prevent certain careless errors, but not all (or even most) of them, while a proper test scheme will catch all such errors.
- yakshaving_jgt 7y agoThe author is one of the world's most prolific publishers of TDD educational material. You shouldn't be so quick to assume that everyone else is clueless.
- femto113 7y agoMy snarky tone was unwarranted but I'm not actually assuming cluelessness here, nor did I come there quickly. I find in practice that TDD and what I think of as "testing" are quite orthogonal. > With the Ruby backend, we sometimes forgot that a particular API property held an array of strings, not a single string. ... These are normal dynamic language problems in any system whose tests don't have 100% test coverage. TDD in general focuses on code-adjacent test strategies like unit tests. In the Ruby TDD world it's a popular strategy to test first, code second at the level of classes or even individual methods. In practice this"tests = code = tests" philosophy produces both more code and a focus on metrics like coverage that only measure "for how much of my code do I have other code that asserts that my code is doing what the other code says it should be doing" rather than ensuring "my code is actually doing what someone else needs it to do". "Testing" as I intend the term means using the software to do whatever it is supposed to. For a server side API that probably means consume it via a client. Any client that relies on the type of a property being an array instead of a string will blow up (except perhaps Python, grr). Any reasonably complete smoke or integration testing regime should expose this problem, but more immediately I think developers should be actively testing the thing they are changing while they are changing it. Personally I dislike compilers and restrictive type systems in large part because they _inhibit_ this sort of rapid, iterative testing and fixing. Partially functional dynamically typed code is far more useful to me as I work through a series of related changes than statically typed code that requires I fix all the issues it perceives as important before I can keep going on what really matters.
- blargmaster33 7y agoBackend in JavaScript... What has the world come to
- orange8 7y agoTypeScript has been on HN for different reasons over the last few days. The main thing that has stood out, from the flame wars erupting over it is that it is a truly divisive idea. To some, it gives the same securities and checks provided when working with a statically typed language. To others, it curtails the power and expressiveness inherent in JS, the dynamic, functional language it compiles down to. TypeScript does provide a lot of benefits, but for it to truly succeed and take over in the JS world would mean it has to truly also reflect, and enable JS's functional and dynamic roots. JS got where it is by being JS.. an extremely flexible and accommodating language. HTML got this far today by doing the same, just google XHTML if you doubt that. So for TypeScript to succeed where CoffeeScript failed, this may be the direction it needs to lean more towards: being less divisive, and inviting all kinds of programming paradigms to the party. That, after-all is how JS succeeded.
- scarface74 7y agoJS got where it is by being JS.. JS got where it is solely by being the language built into browsers.
- orange8 7y agoIs that really all it is though? Cases in point: Java Applets, VB, Flash, Dart ... All of these were at one point or another "built into the browser", but where are they now? Give credit where it is due, the success of the web as a platform lies not in its technical superiority over alternatives, but in its inclusiveness and flexibility. Any tech that is trying to replace HTML, CSS and JS in this regards will seriously have to consider and accommodate this, or suffer the same fate of hundreds of other pretenders to the throne. Long live the king! Long live open, approachable and flexible tech! Exhibit A: List of very different and diverse languages that compile to JS ( https://github.com/jashkenas/coffeescript/wiki/List-of-languages-that-compile-to-JS https://github.com/jashkenas/coffeescript/wiki/List-of-langu... ). If this does not demonstrate the flexibility and malleability of the language, then I do not know what does. Take web assembly for example, which has been around for over five years now, and was specifically designed as a "compile to" language. How many languages compile to web assembly in comparison? Any tech that is as divisive as TS is simply not going to get far. Flash ActionScript was massive 10 years ago compared to any alternative to JS tech today, and where is it now? The creator of TS even quotes ActionScript as one of the main inspirations for TS. ActionScript even had a more powerful version of Reacts JSX (ES4), where is it today? CoffeeScript was all the rage 5 years ago, JS simply absorbed all its good ideas, where is it today? The things that last, that stand the test of time are the things that are flexible and accommodate different ways of doing things. For your beloved TS to stand the test of time, it has got to accommodate the whole JS eco-system, not just those who favor the static object oriented way of doing things.
- deleted 7y ago[deleted]