← Back to context

Comment by bheadmaster

2 years ago

Ok, here are two examples on the top of my head, of fairly trivial programs that are a pain to do right in Java.

1) A program that copies all data from standard input to the standard output. Try to write this without Googling. Simple enough, eh?

2) A program that serves as a middleware between servers and clients, both of which are behind NATs so they connect to your middleware, using gRPC methods. Servers use gRPC streams to maintain a connection, send their ID as the first message, receive request messages, and send reply messages. Clients send ID and request in a message, and receive reply message.

I hope you're willing to show me how wrong I am by writing the code :)

1 is really trivial and took me like 5 seconds to write:

    public class Test {
        public static void main(String[] args) {
            System.in.transferTo(System.out);
        }
    }

2 is anything but trivial in any language, unless it is some kind of a language specifically designed to build gRPC programs.

Never versions of Java are quite pleasant to work with. There are a lots of quality-of-life improvements (switch expression, multi-line string literals, string templates (currently in preview), lots of useful stdlib APIs), as well as quite fundamental additions like Loom.

edit: formatting, explanations

  • > System.in.transferTo(System.out);

    Ok, that's really convenient :) I suppose it would be much harder to do it without the transferTo function, but that would be beyond the point. I'll instead focus on the example 2.

    > 2 is anything but trivial in any language, unless it is some kind of a language specifically designed to build gRPC programs.

    The gRPC protocol here is only an example. Feel free to use any protocol you like. As a counter-example, here's a TCP version in <200 lines of Go: https://gist.github.com/paskozdilar/6871fef7b0b245a0846bd27e...

    > Never versions of Java are quite pleasant to work with

    I know this is a typo, but you accidentally wrote something completely true :')

    • > I suppose it would be much harder to do it without the transferTo function,

      No, it would not:

          public class Test {
              public static void main(String[] args) throws Exception {
                  byte[] buf = new byte[4096];
                  int read;
                  while ((read = System.in.read(buf)) > 0) {
                      System.out.write(buf, 0, read);
                  }
              }
          }
      

      I imagine it will look pretty much the same in the majority of languages which have similar I/O abstractions.

    • So this is a direct reimplementation of your example in Java - https://gist.github.com/netvl/32698cc97b88267fecee9b30f00d16...

      It is under 120 lines, uses Java SE API only, and the complexity is approximately the same. Go does have advantage of built-in selects and channels, which make parts of the logic nicer, but not by much IMO.

      On the other hand, in Java almost no one uses standard library to write network apps like this. If I had to use external libraries, which would be the case in the majority of real-world projects, the implementation would look even better and clearer.

      2 replies →

    • Typo, yeah :( I don’t agree that it is true)

      I can try doing it later today, but I’m 100% sure that TCP example will look pretty much the same in Java, in terms of complexity.

      > The gRPC protocol here is only an example. Feel free to use any protocol you like.

      FWIW, this is a pretty huge change. gRPC is quite complex, as it includes protobuf, http/2 and its own RPC mechanism. A simple TCP protocol is peanuts compared to that.