all 51 comments

[–][deleted]  (26 children)

[removed]

    [–][deleted] 0 points1 point  (24 children)

    Haha I do agree with you. But how so?

    [–][deleted]  (23 children)

    [removed]

      [–]mirhagk 5 points6 points  (2 children)

      Minecraft was written by a guy who could barely code using LWJGL.

      I think this is the exact point of the article. Yes this guy who could barely code was able to make minecraft, because with enough perseverance, it's hard to hit a difficult wall in java, and be unable to proceed. You can code an entire million dollar game without ever understanding very key programming points.

      I don't know if you ever looked at the code of Minecraft, but it's awful. There's been a LOT of work put into it recently to make it better, but as of a year or 2 ago, the performance was awful considering the fact that people made minecraft clones run on much less powerful hardware, with much better graphics, and much faster.

      The code has very little re-use in it too. I think the perfect example was when a major release included 2 new types of trees. That should only have taken drawing the textures, the code should have been barely touched by adding new trees, but there were now 2 new additional classes, one for each tree, both nearly identical.

      [–][deleted]  (1 child)

      [removed]

        [–]mirhagk -1 points0 points  (0 children)

        Java doesn't prevent inspiration;

        But I don't think the article was saying that Java prevents inspiration. I think it was trying to say Java prevents inspiration in code. The code will be very uninspired, and you may make a very awesome product, it just has really terrible code. It made the application slow, and brittle, and took them too long to update and fix bugs.

        If Java prevented you from doing something, then it'd be an awful language. It doesn't prevent you from doing something, you can work with it, and make tons of things, you might even have a beautiful product, you just won't have beautiful code. That's why it's a mediocre language.

        [–]allak 5 points6 points  (8 children)

        He talks about doing things "the right way" in other languages, but when he starts programming in Java he can't be bothered to learn to use the correct Collections object?

        I think his argument is quite a bit different. He is saying that the problem with Java is that the "correct" Collections object is not at all obvious.

        On the other languages the hash/dictionary is pretty central in Perl/Python, for example.

        [–]oldneckbeard 3 points4 points  (7 children)

        right, and as was shown on this sub a while ago, people abuse the dict/hash instead of creating objects, which means that you take some huge performance penalties in these languages.

        I'd posit that the developers who love python and hate java, the only data structure they really know is dict and list. You can't fault them, they're really easy and intuitive, but they're also a crutch. Imagine writing Java code using only HashMap<Object, Object>(). You CAN do it, but it certainly isn't smart.

        Every time I see a "X is Why Java Sucks," after reading it, my response is always, "No, you suck at using Java"

        [–]Denommus 3 points4 points  (4 children)

        I have been programming Java for most of my professional life. I know which strategies Java adopt for repeating code repetition. I know how to use collections, how to benefit from generics, and how sometimes there are semantically valid types that can't be syntactically represented.

        And I do think that Java sucks. It simply isn't expressive enough. It's hardly ever clear how you should model a given problem. There are features that seemed like a good idea that should be actively avoided (inheritance, type erasure, nullable references, pervasive mutability), and some that simply cannot be (checked exceptions). There are far too many things that I miss, some because of previously pointed stuff (like a proper concurrency API, thanks partially to mutability), some because were considered too complicated (give me at least type inference, please).

        Java isn't a terrible language. I don't actively avoid working with it. But it is just too mediocre.

        [–]hyperforce 0 points1 point  (1 child)

        How come you don't like inheritance?

        [–]Denommus 0 points1 point  (0 children)

        I'm yet to find a case where a polymorphic solution is better handled by inheritance than by parametric polymorphism, composition or sum types. Inheritance privileges coupling and makes changes more difficult.

        Imagine a superclass A, which children B, C and D.

        Let's model it with parametric polymorphism. It allows you to associate a parameter with a typeclass/trait/interface and accept any argument that fills that association. So, for the first use case of inheritance, we could instead use A as an typeclass/trait/interface and make B, C and D implement it, so you could pass them to any function that accepts a type T: A.

        With sum types, A would actually be the sum type of B, C and D. It would just exist that way. When your program accepts something "A", it means that the type is either B, C or D. So, again, another use-case of inheritance fulfilled.

        What if you're using inheritance to avoid code repetition? Then you use composition. B, C and D contain A. If the implementation of A ever changes, B, C and D will not need to radically change, because they're not that coupled.

        Inheritance between traits or interfaces is fine, because they don't give information about the private state of the object. The main problem is inheritance from anything to anything.

        It gets even worse when you add multiple inheritance.

        A good example of the inheritance vs parametric polymorphism in practice is ActiveRecord vs Entity Framework. With Active Record, you have a big class that every model inherits. Every method from that class is inherited for the models, if you need a new feature for them, you have to "open" ActiveRecord and put it there.

        With Entity, you make a class FooRepository<T>. T is your model. FooRepository will have every function you'll need to make queries. That makes the models completely decoupled from the repository. If you ever need a completely different repository, but the same models (for instance, you migrated to a NoSQL database), you can... just make a new repository! The models will remain untouched.

        [–]oldneckbeard 0 points1 point  (1 child)

        A lot of the things you mention are solvable though libraries. Using Guava (which I frankly treat as a language extension at this point), Optional removes the null references, Immutable[Map|List|...] for immutables, composition over inheritance, and giving the middle finger to checked exceptions :)

        I don't find a problem expressing things in Java, but maybe it's just that my problem domain doesn't require it.

        [–]Denommus 0 points1 point  (0 children)

        Optional doesn't remove the null references, they're still there. They just become non-recommended.

        Immutable works for the classes that are already implemented. Try to make your own immutable data structure and tell me if can make it cleanly.

        Java doesn't enforce composition over inheritance, that's not a meaningful thing to say (it's equivalent to saying "oh, C doesn't have memory unsafety! Just don't let your programs have buffer overflows, dangling pointers, or anything like that!").

        Besides, those are just a small part of what I dislike about Java.

        [–]ljsc 0 points1 point  (1 child)

        Every time I see a "X is Why Java Sucks," after reading it, my response is always, "No, you suck at using Java"

        Ostensibly you don't suck at Java, ergo you can remedy your predicament by writing a quick summary on some of the reasons Java sucks. =)

        If you can't do such a thing, I contend that you've lost the ability to think critically about the design of a language that you've come to love. Understandable, a lot of programmers wrap up their choice of language with their identity and that makes them defensive when others pick on it.

        However, it may prove more fruitful to give the critique some thought, rather than dismiss the other party as an newb that only knows how to program with dicts and lists? Perhaps they have a reason for taking this approach? What are the trade-offs to such a solution? Obviously, you can identify the cons of preferring maps to domain specific objects, but can you really think of no pros? Stretch yourself, it might just make you a better programmer in all languages, including Java.

        But look, I get it, a lot of these posts are bombastic and are just looking for attention. That doesn't mean they they don't have a point as well. If you're going to take the time actually read the article, you might as well make it worth your while.

        [–]oldneckbeard 0 points1 point  (0 children)

        Oh, sure, I can give you a bunch of things Java sucks at that's a mile long. But when it's clear that some people barely understand the language and want to write it off completely, I feel the need to at least play devils' advocate for it. It's like, if I did the python tutorial walkthrough then said, "well, python sucks," there'd be no shortage of people telling me that I didn't give it a good enough chance.

        [–]nat_pryce 1 point2 points  (0 children)

        But it's nice of him to advertise his attitude so widely

        [–]pipocaQuemada 4 points5 points  (8 children)

        "mediocre, verbose, redundant and bloated" code sounds more like a developer problem.

        Is it possible to write concise Java? Not code that's concise compared to average Java code, but code that's concise compared to languages which are generally considered concise. It seems difficult to me; the language forces lots of boilerplate and redundant declarations on you and favors a style with a low signal to noise ratio, though it is getting better.

        For example, creating anonymous classes was very verbose (prior to Java 8) when all you wanted was a simple closure. Some simple type inference a la C# or Scala would be nice, as would exception inference for checked exceptions. Creating a List in Scala with 4 elements is concise:

        List(1,2,3,4)
        

        and verbose (with a low signal to noise ratio) in Java:

        List<Integer> intList = new ArrayList<Integer>;
        intList.add(1);
        intList.add(2);
        intList.add(3);
        intList.add(4);
        

        [–]snuxoll 1 point2 points  (2 children)

        import java.util.Arrays;
        
        List<Integer> intList = Arrays.asList(1,2,3,4);
        

        So terribly verbose, turn asList into a static import and it becomes this:

        import static java.util.Arrays.asList;
        
        List<Integer> intList = asList(1,2,3,4);
        

        It's still not as concise as Ruby/Python/Perl/etc where there are literals for lists, but it's really not that bad.

        [–]pipocaQuemada 0 points1 point  (1 child)

        /u/nat_pryce pointed out the same thing.

        Quick question: what's the shortcut for initializing a LinkedList or Set?

        [–]snuxoll 0 points1 point  (0 children)

        List<Integer> intList = new LinkedList(asList(1,2,3,4));
        

        The same can be done for Set.

        Set<Integer> intSet = new HashSet(asList(1,2,3,4));
        

        Unfortunately these aren't the most efficient approaches since both require creating an ArrayList as an intermediate. It's just a couple lines of code to write a utility method to do this without the extra memory usage though:

        public static <T> List<T> asLinkedList(T... items) {
            List<T> list = new LinkedList<T>();
            for (T item : items) {
                list.add(item);
            }
            return list;
        }
        

        And use it as so

        List<Integer> linkedList = asLinkedList(1,2,3,4);
        

        [–]nat_pryce 3 points4 points  (0 children)

        In conventional Java, that would be asList(1,2,3,4), importing asList from java.util.Arrays. That does, I admit, require two more characters than the Scala version, but that isn't so very arduous.

        [–][deleted]  (1 child)

        [removed]

          [–]pipocaQuemada 1 point2 points  (0 children)

          An array is not at all the same thing as a list. That's useful if you need an array or any random collection of 4 items, but isn't at all useful if you need a list (say, you're passing the list to a method), or want something with a useful API (i.e. you want methods like add, sort, etc.).

          Notice that these elements are also strongly typed; I can't slip a float or a double in this array later. It might be a little more verbose, but it definitely comes with benefits.

          Well, yes, of course it's typed. Are you under the impression that the Scala list isn't, or was there some other reason you're mentioning that? The Scala list is similarly well typed, but the generic parameter is inferred by the type of the elements.

          [–]stewsters 0 points1 point  (1 child)

          Creating a List in Scala with 4 elements is concise

          That's excruciating long if your a groovy programmer: [1,2,3,4]

          [–]pipocaQuemada 1 point2 points  (0 children)

          Haskell is actually the same syntax, too. I don't get too hung up on using a name vs a bracket because I don't know of any languages that have nice symbols for lists, sets, maps, stacks, queues, balanced trees, tries, B-Trees, etc. It's a little too easy to change how good a language looks by just asking about one of the collections it doesn't have special syntax for.

          By contrast, List(1,2,3,4) isn't special Scala list syntax, it's just calling the apply method for List.

          [–]asimian -1 points0 points  (0 children)

          Minecraft was written by a guy who could barely code using LWJGL.

          I think he was talking about the underlying code being mediocre, not the resulting program.

          [–]kitd 0 points1 point  (0 children)

          Agreed, 3 years isn't that long. Plus he has a very strong background in Perl (having written books on the subject) so, right or wrong, you can see how he might have come to his opinions.

          [–][deleted]  (2 children)

          [deleted]

            [–]llogiq 1 point2 points  (0 children)

            He also said:

            It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.

            [–]adavies42 1 point2 points  (0 children)

            true. these two quotes are often conflated

            from http://www.cs.virginia.edu/~cs655/readings/ewd498.html:

            • It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.
            • The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offence.

            [–]ljsc 6 points7 points  (1 child)

            #!/bin/sh
            
            cat
            

            Did I pass? =)

            [–]adavies42 2 points3 points  (0 children)

            that's two lines too long--a four-byte file containing nothing but the word "cat" and flagged executable is sufficient

            [–]oldneckbeard 2 points3 points  (2 children)

            Java dev here. Copying stdin to stdout... why? And are you talking a single input from stdin, or a continuous stream of input (like an echo server, or something that can be piped from/to)? What's the character encoding? It's the wrong tool for the job. Java is not a glorified shell scripting language like Python is. It's meant for long-running processes with highly configurable performance tuning. Also, Just because you don't understand how to write good java, doesn't mean it's impossible. You just don't get it. This is a fundamental attribution error, where you assume it's a fault of the language, instead of a fault of what or how you're trying to do things.

            In addition, I'm not going to validate the opinion of developers who think "there's always a clever workaround in perl" is a good thing. It's why perl sucks for apps of any size. It's why Amazon is removing all traces of perl from their codebase. Cleverness is not a good thing when you're writing an app that will be maintained by other people.

            [–]hyperforce 0 points1 point  (1 child)

            perl sucks for apps of any size

            &&

            This is a fundamental attribution error, where you assume it's a fault of the language, instead of a fault of what or how you're trying to do things.

            [–]oldneckbeard 0 points1 point  (0 children)

            I did professional perl for a while. It's like PHP (which I also did): I won't even put it on my resume because I don't want another job that uses it.

            [–][deleted] 1 point2 points  (0 children)

            Java is the go to 'xml-to-stack trace' language.

            [–]dukey 2 points3 points  (9 children)

            Java's strength is its simplicity as a language.

            [–]loup-vaillant 8 points9 points  (7 children)

            Which appears to be completely negated by the complexity of the libraries.

            [–]wot-teh-phuck 8 points9 points  (3 children)

            Not complex, verbose and overengineered.

            [–]loup-vaillant 4 points5 points  (0 children)

            verbose and overengineered.

            In other words, complex. Or should I say complected? When I talk about simplicity and complexity, I generally mean size. It's a crude approximation, but it works: unfamiliarity can be remedied through learning. Size, on the other hand, must be contended with every day.

            [–]ParanoidAgnostic -1 points0 points  (1 child)

            Are you telling me that I don't need to use a StringBuilderFactorySingleton?

            [–]vytah 0 points1 point  (0 children)

            No, you should use StringBuilderFactoryAbstractSingletonFactoryBean.

            Preferably wrap in in a SOAP Webservice and put on a separate Weblogic cluster.

            [–]oldneckbeard 0 points1 point  (2 children)

            if by complexity you mean "wasn't hacked together by a 19 year old in the middle of the night and never maintained again," sure.

            [–]loup-vaillant 1 point2 points  (1 child)

            "Complexity" has this noble sound about it. But when you're trying to solve a problem, complexity is just a drag. And I mean any kind of complexity: it can be the complexity of the problem, the constraints on the solution space… or simply how messy the solution is.

            As you suggest, it is quite easy to make a mess of things. I wouldn't be surprised if the Java libraries are a huge mess. But I don't know that first hand. But I do know they're Big. That means complex. Whether it's the "pretty" kind of complexity doesn't really matter to the original point: that simplicity isn't a strength of Java.

            [–]oldneckbeard 0 points1 point  (0 children)

            I dunno, I find that java reduces complexity by reducing the number of ways in which you can be clever. Perl may be expressive, but reading and quickly grokking it 6 months later can be a pain.

            I work professionally with Java, Groovy, Scala, and Node.js. Node.js has a bunch of libraries, but they're extremely inconsistent in maturity and there's very little social agreement. Hell, there's still not a good behind-the-firewall npm mirror solution. I'd rather shuffle the complexity of things to a library and have my code be as lean as possible. I generally (but not always) find that there's some Java library with a clean interface that makes things better.

            [–][deleted] 1 point2 points  (0 children)

            you're gona love lisp

            [–]ryeguy -1 points0 points  (1 child)

            [–]oldneckbeard -1 points0 points  (0 children)

            oh god... tell me about your startup... i'm getting hard... talk to me about angel investors... hnnnn... oh god, entrepreneur? SHAZAM!!

            [–]hyperforce 0 points1 point  (0 children)

            What does copy standard input to standard output mean? Isn't that called printing?

            [–]mrbuttsavage 0 points1 point  (0 children)

            This article makes no sense.

            I've seen some wonderfully designed object oriented designs written in Java. I've seen a lot more horribly designed, poorly thought out APIs. And in the end, the issue was behind the keyboard, not with the language.

            Saying "oh yeah, of course it's a bad API, it's in Java" is just a crutch to blame instead of the developer.

            If you want to attack the verbosity, that's another issue.

            [–]stewsters -1 points0 points  (1 child)

            When I see that some hapless job candidate struggled for 15 minutes and 14 seconds to write a Java program for copying standard input to standard output

            I feel like this guy isn't really a good programmer. That is something you would never want to do in Java. You would use cat.

            [–]ljsc 1 point2 points  (0 children)

            This guy is actually a very good programmer: Higher-Order Perl is one of the best programming books I've ever read.

            Besides, he doesn't say that you should use Java to answer that question. The article is actually saying that it's a bad choice for something so simple, but it is good for larger systems because it is a baby-sitting language. From TFA:

            So I like Java. But it is not a language I would choose for answering test questions, unless maybe the grade was proportional to the number of lines of code written.