Hacker Newsnew | past | comments | ask | show | jobs | submit | Retozi's commentslogin

we use jooq extensively it's probably the most valuable tech in our backend.

Also among various other tech stacks I've never seen something that hits the sweet spot between "plain sql" and "advantages of ORM-stuff" as well as jooq


Also, props to the primary developer Lucas, who directly replied to my questions within a day, twice


I have never understood why typed languages make you slower at any point in time (early, late etc.).

Because you have to hit more keystrokes to write your program?

That doesn't compute. typing is the thing you do the least amount of when programming. In all best practices we are taught to not save keystrokes. Name your variables expressively. write small functions. document code. Write tests. All ""excess"" keystrokes nobody questions. But when you have to type " ... : number" it's slow velocity?

In my opinion people vastly over-estimate productivity boosts of saving keystrokes. It's the tedious, boring part of the work that you would like to skip entirely, hence excess keystrokes feel way more "slowing you down" than they acutally are.

Although it doesn't matter, you actualy save keystrokes: autocomplete, auto-refactors and less low level unit-tests compensate the couple of type annotations easily.


I completely agree with you, but the criticism isn't usually with typing number, it's typing complex higher-order functions or this kind of things. Where the time lost isn't in typing out the code, but in understanding what the type should be or (worse) what does this cryptic typing error means


I don’t tend to write or encounter many complex higher order functions in other languages. Are they common in JS?


It is not the typing per se. Anecdotally, I started adding types to my python code and it is somewhat useful.

That usefulness is diminished when you are fighting the type system instead of getting things done.

Like when you have to make exceptions in typescript by using Any. Like when an interface for a js library is missing and you don't want to do all that work.

Or when an API returns a field with a different type in between two calls and you have to make exceptions in the code when parsing with jackson in java.


Python’s type system is a particularly bad example. It’s not ergonomic and the type checking is immature.


Not sure what immature or ergonomic means in this context, but I'm pretty sure handling of "private" variables (self._foo) is abysmal.


Though you have a point, writing down type annotations can seriously slow you down when you are doing exploratory (prototyping) programming. It can also make your code less readable as the annotations can get in the way of the logic you really care about (easily fixed in an IDE, but people want to still use notepad to edit/read code). Then there is figuring out what the annotation should be in the first place, again easily enough automated in an IDE but the notepad problem remains.


What usually slows me down about dynamically typed code is you have some variable returned by a function only denoted by var myVariable = myFunction(); and I'm sitting there staring at thinking... "what are the contents of that variable? what properties do I have access to on that object? what can I do with it?"

And figuring that out becomes a massive time suck when that's a constant across an entire code base. Statically typed stuff means I can very quickly find that out even if it's the first time i'm exploring that particular area of the code.


I agree, in a type inferred language or a language where annotations can be supressed, this is just another matter of IDE affordable.

Some dynamically typed languages support type annotations that are only enforced dynamically; Julia is the primary example of such a language ATM.


A well designed dynamic language like clojure can have explosive velocity. Stuff just fits together smoothly: a predicate can be a function or a set or a map or a regex, but most importantly, libraries are built of these mutually compatible blocks. Reminds me of (Sussman's?) description of lisp codebases as organic.. of course, "explosive" can be very literal when type mistakes propagate and the data model goes to bizarroworld. In clojure, you can defend yourself with spec, which catches these things at the site of the mistake. It's a tradeoff I often like (velocity vs. compile time checks). It all depends on the domain.


Yes. Extra typing is not a huge drain, I agree, but it is a minor one. Shorter is better until it impacts readability. Visual noise is a thing.

Code is read much more often of course. You may argue you can read a fifteen-page book as fast as a ten-pager, but it's pretty clear that's not the case.

Of course tools and inference change the balance, but even so I avoid putting code into the the kiln until the design is fully understood and at least satisfactory. And that can take a few revisions.


Frontend: (vanilla) React with TypeScript.

- TypeScript is more important than React, static typing is such a productivity boost, even for projects of all sizes.

- Start with vanilla React and create-react-app, monitor for painpoints and look for solutions for these pain points in the community, don't look at the whole ecosystem before you start building stuff.

Backend: Kotlin on the JVM.

Kotlin is a really nice language for either functional or object oriented programming. Static typing with strict null checks are again a huge productivity boost. Standard library is very complete

Beeing on the JVM without beeing stuck with Java is a big win:

- unlocks a huge ecosystem and Java interoperability of Kotlin is superb.There are a lot of lightweight frameworks for stuff around here, enterprise Java is a myth if you are free to choose what to use.

- special shoutout to the JOOQ library, the golden middleground between an ORM and raw SQL Strings.

- JVM is fast

- fat jars are somewhat like containers, can be run everywhere with minimal setup (yeah I'm looking at you python-uwsgi black magic)

Database: Postgresql. Everything you need (relational, JSON), fast, rocksolid


Wanted to look into Kotlin on the backend for a while now. Do you use any framework or do you just assemble individual libraries for whatever you need?

I am not sure I find Spring an attractive proposition and Ktor seems rather young, slow and not that well documented.

What do you think is the best option?


I'm personally in the "functional handler" way of doing HTTP Request camp.

We have a very small Ktor service in Production, and it works nice, for legacy reasons, we're using http://sparkjava.com/ for the heavy lifting. An alternative would be https://javalin.io/

I would not start with Sparkjava anymore. The way you write handlers is quite okey (compared to other frameworks), but there are issues with how it's connected to Jetty and relies on singletons that will be painful if you would like to do advanced stuff. It's on our todolist to swap Sparkjava with Ktor somewhere down the road.

To be honest, Ktor seems to have come a long way, the docs improved a lot last year and it seems well thought out. I would give it a try. It's quite easy do decouple your application Handlers from the underlying framework via functional composition, so there is no big lock-in Risk.

In my experience, all three Frameworks are way better than the regular Java-like approach with annotating classes. Request-Context specific information ("The user making the request") is very hard to get to this way and it's usually untyped. On top of it, you are locked in HARD to the Framework. Swapping out a Framework that just mounts Functional Handlers is way easier...


Thanks for the writeup, Javalin looks like what I was looking for honestly, but I'd check out Ktor again as well.

EDIT: Ktor does look a lot better today and now that Kotlin coroutines are actually stable, I'd definitely check it out.


Has anyone used both Ktor and Javalin and have any advice for choosing between the two?


Just use any Java framework or library, Kotlin can adapt to them quite easily.. We've used Ratpack with great success, we had to do a tiny bit of plumbing but it's great now and we open sourced our coroutine adapter (it was around 10 lines of code).

Vert.x already did the Kotlin plumbing on their own so you can use coroutines and similar goodies out of the box, Spring Boot supports Kotlin natively AFAIK, and something like Dropwizard should be easy to use as well..

Seriously, don't limit yourself, part of Kotlin's beauty is how easy it is to use it with Java products and reap immediate gains!


I haven't used it yet, but I like the look of this guy: http://micronaut.io/


At this point this would prolly be my advice as well.

From React/TS, to Kotlin, to PG, to the JOOQ shout out.

I hoped a strongly(ish) language that spans from BE to FE, like ReasonML, would be ready by now, but it isn't.

Kotlin to JS is not there I'm afraid:

https://kotlinlang.org/docs/tutorials/javascript/kotlin-to-j...


What's not there about Kotlin/JS for you, out of curiosity?


Interop with other JS libraries for example - Vue in our case. We switched to Typescript mid-project and never looked back. Server is still Kotlin and we just export the data transfer classes as Typescript definitions (using a library we found on GitHub that works well enough).


I .. cannot upvote this enough :) We're using an almost identical stack (Vue instead of React, but that's about it) and we love it!

Going back to old projects using various ORM products makes me cringe nowadays, JOOQ + Postgres are such a powerful combo!


Curious to know if you tried React with Flow before choosing to go with React and Typescript.


I agree. I exlusively write React Frontends since 2014, and very minor things have changed.

It feels a lot more stable than before, where every project had homegrown framework stuff on top of backbone.js or jquery, or then using ember.js. There was just an awful lot of difficult discussion on how to design event-bus abstractions, global state management and general architecture

To me it feels like the frontend ecosystem has stabilized a lot, since the react paradigm is very robust and versatile. For most difficult problems, the solution is somewhat clear. Sometimes more, sometimes less elegant, but at least the timeconsuming disussions have become less frequent within a team


This is a quite common myth that is factually wrong. It's the main way for a private wealth advisors to talk somebody into a unecessary mortage.

The interest rate on mortages is always higher compared to the interest rate on leverage for stock (by using the stock itself as collateral).

You can get close to the yield on swiss confederation bonds if you buy well priced, leveraged ETFs.

Obviously that interest rate is as stable if not more stable than the interest rates on mortages.

Please DO NOT buy stocks with money from a mortage. you're just giving up at least 1% yield.


> leverage for stock

Please note that with leverage (stocks or real estate) is is possible to lose more money than you invest.


I agree 100%.

TypeScript is an invaluable, mature technology that provides large productivity boosts to any team that maintains a mid-sized code base.

It plays extremely well with React too, and it's benefits are independent of the tech stack. If you are used to typed components/templates, you will NEVER want to go back.

I would argue that is more important to have static typing in the front-end compared to the back-end in a web-application context. There is more state, lot's of shared entities and unit tests are expensive to write and maintain.


> There is more state, lot's of shared entities and unit tests are expensive to write and maintain.

Good point, but only to an extent: Unit tests boilerplate in dynamic languages that is redundant with static typing is only a (minor) subset of unit tests that you should be writing for your code. Static typing is not an excuse to skip unit tests altogether. I've unfortunately met people claiming exactly that...


In 2014 I used Typescript on a four month long project. I liked it alot compared to using just JS, however compiling was slow.

I retried using Typescript 1 month ago. Compiling took 6-7 seconds for about 8 files. I could not find a solution and gave up using TS. I hope that's just me doing not good enough research.


Definitely something up with your environment. We compile hundreds of .ts files at my job each build and it only takes a few seconds


Must be something with your setup, tsc is known to be quite fast. Maybe try using it with the watcher? "tsc -w" and you'll never need to compile more than one file at a time.


I'm using a MacBook Pro with Windows on it as my main development environment except for iOS native stuff obviously.

1. install chocolatey https://chocolatey.org/, and install everything with it

2. install conEmu for a decent command line

3. install git for windows, which comes with a bash shell that brings you all the linux commands, inlcuding ssh.

This brings a Windows PC relatively far. You can even get ssh-agent working with an according .bashrc script (along the lines of https://github.com/joaotavora/holy/blob/master/share/zsh/ssh...)

This does it for me to do node / web-dev / java/ android centered development, I prefer it over macOS and Linux.

Things I do not use:

1) Cywgin. Quite the behemoth, and I get by with git bash just fine

2) The Ubuntu Subsystem. I tried it, had trouble with ssh stuff, seems not ready yet...

3) putty. the open-ssh that comes with git is better and closer to linux.


  >> 3. install git for windows, which comes with a bash shell that brings you all the linux commands, including ssh.
Thank you!

I often wished that each HN user got one '10x upvote' a week. I would give it to you this week.


I like it as well. I have yet to see tech stack that has comparable potential but is less complicated and can be stripped down as low as the web stack if your requirements permit it.

I mean yeah, if you have a big app, complex requirements, there is a bunch of stuff you need to take care of.

However, I would like to see the tech stack that allows you to do the same with less complexity.

It's not like Android (gradle?!, java 6?!, the android api!?) or iOS development is a walk in the park if you want to do anything with production quality.


TypeScript is the one technology I would discard last of the entire web stack.

Using TypeScript instead of JavaScript is such a productivity boost for a team developing a sizeable single page application, any other technical decision (which Framework, tooling decisions) is almost irrelevant relative to this major improvement.

TypeScript has ALL the properties that should make adoption a no-brainer:

1) Increases developer productivity, especially over long term maintenance timeframes. (My non-scientific, ymmv estimate is at least 30%)

2) Reduces production exception rate significantly

3) Can be adopted gradually

4) Full JavaScript ecosystem still at disposal

People seem to massively underestimate the benefit of a typed language in a frontend codebase. At gunpoint, I would rather have the backend in a dynamically typed language and keep TypeScript for the frontend. Chances are that the distance between your database and the API is not far, so static typing is not that useful.

However, if you have decided for a client side rendered application, your app is stateful, dynamic and probably quite big. Static typing really helps to avoid mistakes and increases the ability to refactor quickly and correctly by order of magnitude.

There are too many hardly ever visited code branches, and tests are very costly to write for an application where users can click a lot of things.


It's not even the fact that JS is dynamically typed it's that it's the worst of dynamic typing - magic strings, monkey-patching, retarded scoping rules coupled with callback pyramids all over the place, no proper modules - you just get no meaningful help from tooling as soon as your code base grows to even medium complexity. ES6 helps but TS brings all that + more.

Python IDEs like PyCharm offer far superior tooling even without static typing, and Clojure is so nice I don't usually even need the tools.


I get your point, but while I am a big advocate of typescript, I think that the topology of the javascript language is perfectly suited for front-end development.

There are a lot of impedance mismatches to deal with in the front end, (javascript to DOM, json to javascript, diversity of execution environments etc...), and I feel that when correctly used, dynamism the way javascript does it is a god-send.

All my core developments are in typescript, but in many situations it feels so magic to just do : myprop.undeclared = value and encapsulate the stuff in a knockout component written in typescript, while the situation would have caused a drama / major redesign in a back-end static language (C#, Java etc...). There are many valid scenarios (not resulting from a wrong OOP design) where this is very useful.

I'm actually amazed that people who designed Javascript got it so right. Static languages are great in the backend, typescript is great for the front-end and solved a real maintenance and Q&A issue by providing a level of typing and popularizing OOP in the front-end, but javacript is great for the web browser in general. Typescript is the piece that was missing, but this doesn't mean that javascript is broken, the elasticity of the language is a very powerful and elegant solution for the problems specific to the front-end.


>myprop.unDeclared = value and encapsulate the stuff in a knockout component written in typescript

And when I need to read this code later on and figure out what the shape of myprop is what do I do ? When I come across a function in a different file that touches that "unDeclared" property how the hell do I figure out what type it is, where it was assigned, etc. How do I find all references to that if "unDeclared" is a common word or is used on multiple types as a property name ?

JavaScript is just a nightmare to maintain - sure it might be easier to bang out the code initially - but good luck finding someone who will maintain that stuff once the author moves on. Hell - good luck coming back to your code base a year later and finding your way around that. From my experience most of non-trivial JS ends up being write only.


> I think that the topology [emphasis mine] of the javascript language is perfectly suited for front-end development.

What exactly does “topology” mean in the context of programming languages? Are you trying to pull a Derrida (using fancy words without any actual meaning)?

> I'm actually amazed that people who designed Javascript got it so right.

Are you assuming that, even with a better language, the DOM's crappiness was inevitable, and thus we need a loosey-goosey language like JavaScript to deal with it? I doubt this is the case. Good languages make it easier to design good programs and APIs.


3 & 4 in your list are so key. I was very skeptical of it until I started using it and realized that javascript is always valid typescript. So it never gets in your way. It only helps, and only if you want it to.


I agree.

One benefit I've seen a lot is typing external services. A lot of code (both the frontend and the backend in say Node.js) tends to deal with calling external APIs, which would be dynamic in JavaScript and end up being quite loosely documented in the code.

With TypeScript, however, you can type in the JSON responses, which makes reading any code dealing with external services so much quicker. And these days with literal types you can even document that a particular property is either "magic_string_1" or "magic_string_2".


Although, dynamic languages force extra incentive to unit-test the shit out of the codebase. Compilers certainly catch a lot of syntax mistakes and whatnot, but it also relaxes the requirement to add extra code coverage. The onus is more on the developer with dynamic typing but I'd take more-accurate code coverage over static types any day!

EDIT:

If you have static-typing and good unit-test coverage it's the best of both worlds I suppose. I tend to prefer duck-typing though which is sort of wedged in-between dynamic and static-typing in a sense. This however then becomes not a question of static vs. dynamic typing but of the language implementation of the type system.

In C++ for instance, the over-object-orientation is a pet peeve of mine when people define so many types and interfaces for this-and-that. I tend to prefer the "looseness" of template functions since you can pass whatever type in there so long as it contains the appropriate methods on the passed-in object. Such is static typing though so I'm digging myself into a hole from my original post :)

Now, a good static-analysis tool could catch issues on a dynamically-typed language in the same sense. Then I suppose the dynamic language becomes a pseudo-static language since a static-analysis algorithm is executed on the codebase. Since most build systems are set up to do: compile codebase; run static analysis to detect issues; run unit tests; run integration tests, it could theoretically be redundant step at compile-time doing static analysis when it's also done by an external tool. Just some stream-of-consciousness thoughts :)


The only tests you have to discard when using a statically typed language are some of the tests validating your input data. I don't see how static typing leads to less test coverage...


These are a lot of tedious to write tests in a frontend codebase that mainly renders a lot of state into HTML.

Additionally, these are tests that you will have to tediously adjust every refactor since HTML frontends and it's data APIs behind it tend to change often over the lifecycle of a product.

From my experience, "only those tests" save you hours and hours of programming time.


> The only tests you have to discard (...) are some of the tests validating your input data.

That's not true. You can safely discard anything that tests something you've proven. A good type system doesn't only prove things for you - it also makes it easier to manually prove what the type system can't prove.


A good type system, yes. Something like TypeScript though? Only checks that variable types match. We're a far cry from ML/Elm/Scala/Haskell here.

So the only thing it helps is get rid of bad tests (eg: tests that check a function return any string...tests you shouldn't write even in a purely dynamic language).


> Something like TypeScript though? Only checks that variable types match.

TypeScript's type system is unsound, so you can't rely on the type checker alone to prove anything useful. However, manually proving things about TypeScript programs is still easier than doing so with JavaScript programs.

I don't believe it's practical to rely on type checkers to prove absolutely everything. There are mathematically proven upper bounds on how much you can automate reasoning. For instance, global type inference only works with first-order type languages. Higher-order anything flies out of the window, yet higher-order properties of programs need to be proven!

What we ought to do is find the optimal division of labor between automated and manual proving, always keeping in mind that the optimal case isn't being able to prove something. The optimal case is not having to prove it because it's obviously true. How do we design a programming language so that more interesting things are obviously true?


Sound type systems help you prove things. In other words, a type system is a tool that partially discharges part of the programmer's proof obligation. Of course, what you can't prove, you still need to test. This isn't news to anyone.

The problem is when the programmer doesn't know how much of his proof obligation is actually discharged by his use of the type system. (Hint: Not all of it!) And the solution is educating programmers, not replacing types with tests.


And that's why I prefer static typing. All those trivial unit tests get in the way.


You really shouldn't have a "trivial" test that a type system like TypeScript makes redundant, when doing pure JavaScript either.

If you have a function, eg: (a, b) => a + b The only thing TypeScript will help you enforce here is that a and b should be numbers, and the function should return a number.

Except, the test for this will be something such: "given 10 and 21, return 31". So you're testing the return type already. TypeScript will ensure that you never pass a string to a or b, for sure, but you should not have a test for that (unless you literred your code with type guards and wanted to test those. Don't do that).

Now, unless the function above is your final, public API (where TypeScript/Flow will have the biggest bang for the buck and have the most value add), you're probably calling that function somewhere. That somewhere will be tested too, and the full test harness will make sure strings never end up there.

You'll never actually need to write a test: "Make sure this is a string", and the only vulnerable area is the top level API, and that is a responsibility of the caller.


> Chances are that the distance between your database and the API is not far, so static typing is not that useful.

For me, this mostly brings up the question of why the distance between data sources and front-end code apparently seems so big these days, and whether or not that's really an asset.


I believe what he is trying to say is this:

It will take a person a couple of days to "grok" Redux, and a quite a bit longer to fully understand the ins and outs so one can make informed, confident decisions on how to solve problems "the Redux way".

Now you gain "cool" things by doing it, but here is the catch: Is the benefit worth the time investment to get there?

His argument is that for a lot of simple apps it isn't. You get very far with plain React, and a project has to have significant complexity to pay back the costs of fully understanding Redux.

I would argue a lot of people picking the React ecosystem make the mistake of choosing too much architectural complexity, not too little.

The extreme pluggability helps to broaden usage of Redux. But it is overkill for many projects. Decoupling is important, but it is not free (see parts of the Java ecosystem).

Devs should consciously decide what to introduce, and leave out stuff that simply doesn't increase development efficiency given the nature of their project.


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

Search: