编程与软件工程teamten.com
用 Java 做一切
Java for Everything
2014 — 2021,它一次次回到首页
黑点是上首页(≥ 50 分)的那次投稿,空心点是没冲上去的投稿,点越大分数越高。
导读
Lawrence Kesteloot 在这篇经典文章中主张:与其为不同任务挑选不同语言,不如把 Java 用于一切——从后端、脚本到 Android 应用。理由是团队已有 Java 专长、静态类型带来的编译期保障,以及全栈统一语言降低的维护成本。文章多年来多次登上 HN 首页,每次都引发关于语言选择与类型系统的激烈争论。
为什么经久不衰:“一种语言打天下”是每个开发者都会面对的永恒问题,文章观点鲜明且历经多年讨论仍能引发共鸣,是理解语言选型权衡的经典切入点。
HN 评论精选
Java 的坏名声多来自历史生态包袱,而生态和语言都在持续改善
语言和生态是两回事。很多对 Java 的负面情绪其实指向生态的历史包袱:J2EE XML 配置地狱、EJB、臃肿的应用服务器、SOAP、Maven 依赖地狱、十种日志库等等,这些东西确实很糟。但情况在改善——Dropwizard、Gradle、Spring Boot 等趋势是减少配置,生态变得更可控了。语言本身,Java 8 的 lambda 和流也带来了显著改进。
msluyter查看英文原文
There's the language and there's the ecosystem. A lot of negative feelings that still linger are, IMHO, directed more at some of the painful historical aspects of the ecosystem: J2EE XML configuration hell, EJBs, bloated application servers, XML for everything, JAX-WS, SOAP, ant, classloader problems, maven dependency hell, 10 different logging libraries, etc... A lot of this stuff truly sucked. But I feel things have improved over time. Dropwizard, gradle, embedded jetty, jersey, guava, Spring boot, etc... The trend is towards minimizing configuration and overall, the ecosystem has become somewhat more manageable. I wouldn't necessarily call it pleasant, but it's better. An as for the language itself, Java8's lambdas + streams provide significant improvements. Compare this (Java 7): public static List<Integer> sortDescending(List<Integer> ints) { ints.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1.equals(o2) ? 0 : o1 < o2 ? 1 : -1; } }); return ints; } to this (Java 8): public static List<Integer> sortDescending2(List<Integer> ints) { ints.sort((o1, o2) -> o1.equals(o2) ? 0 : o1 < o2 ? 1 : -1); return ints; } (Example is contrived, since you could use the built in Collections.reverse() to achieve the same result. My main point is that we have eliminated ~4 lines (counting braces) of ceremony.) All that said, I'd rather be using Clojure.
冗长损害可读性,且大多数项目根本用不到 Java 的性能优势,先用简单语言更划算
冗长对阅读和维护的影响远大于对编写的影响。IDE 能加快编写,却无法让代码像更有表达力的语言那样易于理解。而且代码行数是唯一被证实的 bug 风险因素。大多数网站不是 Twitter——我曾见过一家公司花两年、几十个开发者和上百万美元的 ESB 许可费,没能写出一个峰值每天 100 用户的小站;竞争对手四个人用 Ruby,第一个月就盈利了。性能优势也不是永久的,真到 Twitter 规模你反正要重写。不如像 Twitter 那样先用 Ruby 写第一版,需要时再优化。
lmm查看英文原文
Verbosity matters for reading and maintenance far more than it does for writing. IDEs can make the writing faster, but they can't make the code as easy to comprehend as it would be in a more expressive language. And remember that lines of code is the only proven risk factor for bugs. Most sites are not Twitter. They're not Stack Overflow. They're not even Nanowrimo. I've watched a company spend two years, dozens of developers, and over a million in ESB license fees failing to write a site that was expected to have, at peak, 100 users/day. Their competitor had four guys writing Ruby, and was profitable after the first month. Nor are the performance advantages "permanent"; even if you use Java, you will probably have to rewrite if you reach Twitter scale, because your initial app won't be clusterable (or if it is, it's massively overengineered and your business will fail). So do it the way twitter succeeded - write the first version in Ruby, and then worry about performance when you need to. The advantage of using the same language on both sides of a boundary are real but overstated. If you have a system with multiple components, you probably need to evolve the interfaces between them, and you need to be able to upgrade without downtime. Which means you need well-defined interfaces for which you understand the compatibility implications - in other words, you need something like Thrift. I've used Thrift even for Java-Java interfaces, but once you're using something like that it doesn't matter which language is on the other side. Still, the library point is valid, as is the point about spending time with a language. Better to have one language that you know very well than ten in which you dabble. But by the same token it's worth taking the time to make sure that language is the very best available. I use Scala for everything, and there's plenty to learn - maybe even twice as much as a "normal" language. But if I'm focusing on that one language, I can afford to take the time to learn it really well. And Scala combines the expressiveness, clarity and scripting-suitability of Python (yes, it can be unclear if you use silly method names or libraries that use silly method names - don't do that then) with the strong type-safety and performance of Java. It's a great language in any case, but especially if you want a single language for everything, I don't think anything else comes close.
文章的核心论据是“熟悉即合理”,但冗长确实妨碍理解,“为工作选对工具”仍是好建议
文章很大一部分论据其实是“作者和同事已经会 Java”。同样的论证也适用于我选 Python。作者说 Java 的冗长无关紧要,但问题不在于多打几个字,而在于类型声明和泛型的过多记号是视觉噪音,妨碍理解代码在做什么。文中关于 Python 扩展性的担忧是有效的,但那恰恰说明应该“为工作选对工具”——对很多项目 Python 足够快、生态够全、可移植性够好;对另一些项目则不然,换别的语言也没问题。
Osmose查看英文原文
A significant amount of the article is arguing that Java for everything is better because the author and his coworkers already knows it. I can make the same argument for Python _for me_. And for my company too; we have a ton of Python developers already, so it makes sense to write things in Python if possible in case someone needs to change or improve anything. The author also talks about how Java's verbosity is a trivial issue, and in terms of "stuff you have to type", I agree. The point isn't to save a few characters to type. To me, the problem with Java's verbosity is that it _impedes understanding_. The excessive notation required by type declarations and generics and so on are visual noise that distract from what the code is doing. There are some valid points raised too, such as concerns about Python's scalability, but that's an argument for _choosing the right tool for the right job_, which, while mocked at the beginning of the post as a way to avoid an interview question, is still good advice. For a lot of projects, Python is fast enough to handle the expected processing, has an ecosystem with libraries that handle all of the things the project might need to do, and is portable enough to run on the platforms necessary. For some projects, it fails one of these, and another language may be a better choice. That's okay! I think the best takeaway here is that it is sometimes useful to see if you can leverage your existing knowledge in one programming language by applying it to a task you don't normally use it for. By all means, write shell scripts in Java, maybe that's really useful! Or maybe write a GUI in Haskell! Transpile BASIC to frontend code! (For context, I use Python for web development (both small and large sites), scripting, and a few personal projects like a music player or emulator. I did a bunch of Java in college and some internships.)
冗长的真正代价是手工维护重复代码的负担,以及表达力不足的信号
冗长和重复的问题根本不在于打字更慢,而在于它制造了需要手工管理的依赖。把 Foo a = new Foo() 改成 Bar a = new Bar() 看似不难,除非你得把改动传播到整个代码库。Java 一半的工具都在解决一个在好的鸭子类型语言或有类型推断的语言里不存在的问题。冗长也是表达力不足的警示信号。注意这与静态/动态类型之争无关——冗长是个可以用多种方式解决的问题,但它确实是个问题。
one-more-minute查看英文原文
The problem with verbosity and repetition is not that it takes longer to type the code, at all. The problem is that it creates dependencies which you have to manage by hand. Changing `Foo a = new Foo()` to `Bar a = new Bar()` doesn't seem that bad... except when you have to propagate that change through the code base. Half of Java's tooling is dedicated to solving a problem that doesn't exist in good duck-typed languages or those with type inference. Verbosity is also a warning sign for lack of expressive power. If you have a pattern like `if (cmd == "run") run();` in multiple places in your codebase, you want to make it so that changing one changes them all. Java won't let you factor this out easily, but worse, it won't catch you when you make a mistake (better languages will either do first-class functions or pattern matching and exhaustiveness checks). Note that this has nothing to do with static vs. dynamic; verbosity is a problem that can be solved in many ways, but it is a problem. The author also spends a lot of time equating statically typed with fast; well, there are plenty of very fast dynamic languages. There certainly are reasons to like Java, but these aren't them.
Java 类型系统太弱,编译通过并不等于正确,ML 风格语言体验更好
“Java 代码编译通过通常就能正确运行”——我的体验恰恰相反。Java 的类型系统极其欠缺(如可空性、没有可辨识联合),我写了大量应用代码去模拟一个健壮类型系统本该强制的东西。可惜这些不是编译期检查,写错了就在生产环境报错。用过 ML 风格语言(Haskell、OCaml 等)之后,再回到这种基于类名的类型系统会很痛苦。
zumu查看英文原文
> Java’s a pretty nice language, and when my code compiles, which is often the first time, it’ll usually also run correctly. This is the exact opposite experience for me. I find Java's type system to be extremely lacking (e.g. nullability, no discriminated unions, etc.), such that I write plenty of application code to mimic what a robust type system would enforce. Unfortunately, since it's not a compile time check, if you do it wrong, you get errors in production. In this way, it is the same as a fully dynamic language—what compiles has loose guarantees about correctness. Excuse me for a moment, but I'm going to be that annoying guy—but once you get some experience with an ML style language (e.g. Haskell, OCaml, SML, etc.) it's painful to go back to these class name based type systems.
2021 年再看,“一语言打天下”的最佳答案已是 TypeScript 而非 Java
我喜欢 Java,但如果要选一种语言做所有工作,如今应该是 TypeScript:它已经主流,有众多公司在生产环境使用,工具链支持广泛;全栈不仅能共享代码还能共享类型,这对我帮助巨大;它的类型系统非常灵活,可以为任何场景指定想要的安全程度,从不觉得受限;编译成 JavaScript 后到处可运行。
dmitryminkovsky查看英文原文
I like Java but I think the right job for all jobs, if you're going to pick one, is TypeScript: - At this point you can say TypeScript is mainstream. It's not Java, but it's definitely not a niche toy. - Many companies stand behind it and use it in production. - It is widely supported by tooling. - With TypeScript, every element of your stack can not only share code, but can share types, too. This has been a huge boon for me. - The type system is really, really flexible. It seems possible to specify the exact degree of safety that you want for any given situation. I never feel bound by the type system. It's very liberating. Not so with Java or C#. - It compiles to JavaScript, so it can run anywhere. On the backend you can run it natively with Deno. I haven't tried this yet, but am looking forward.
历次讨论
同类还值得读
开源应用架构
The Architecture of Open Source Applications
《开源软件架构》(AOSA)是一本在线免费书,邀请知名开源项目的作者亲自剖析其内部设计,涵盖 SQLAlchemy、LLVM、Audacity、Apache、Bash 等系统。
编程与软件工程上首页 9 次 · 2011–2024aosabook.org编辑精选编程语言简史:简短、不完整且多半错误
A Brief, Incomplete, and Mostly Wrong History of Programming Languages
一篇以戏谑、故意不准确的方式回顾编程语言史的博客文章,用夸张轶事和讽刺定义串起 Lisp、C、C++、Java、JavaScript、PHP 等语言。
编程与软件工程上首页 8 次 · 2009–2021james-iry.blogspot.comSQLite 是如何测试的
How SQLite is tested
SQLite 官方文档页,系统介绍 SQLite 的测试体系:多种测试方法(TCL 测试、模糊测试、回归测试、静态分析等)和海量测试用例,展示了这个小型开源项目如何靠极致测试获得…
编程与软件工程上首页 8 次 · 2009–2025sqlite.org编辑精选高级编程语言(2009)
Advanced programming languages (2009)
Matt Might 的经典文章,按用途推荐“高级编程语言”:如果追求就业就选主流语言,如果追求表达力、学术研究或创业,则推荐 Haskell、OCaml、Scala 等函数式语…
编程与软件工程上首页 8 次 · 2009–2022matt.might.net我的 Forth 与栈机器经历
Yosefk - My history with Forth & stack machines
作者以亲身经历回顾了使用 Forth 语言和栈式机器的历程:既赞叹其简洁优雅、代码量小、可自举的优点,也坦率指出栈操作在实际编程中的痛苦,以及 Forth 社区文化中的问题。
编程与软件工程上首页 8 次 · 2010–2024yosefk.com编辑精选