一旦您开始使用多种语言,您可能会开始质疑现状。您可能会以不同的方式看待事物,并为您钟爱的编程语言带回一些良好的习惯。我认为“代码简单”是软件开发的一个被低估的特性,我们需要更加关注代码的可读性和简单性。
Java 是并且一直是我在整个职业生涯中使用的主要编程语言。如果我想为原型快速构建一些东西,或者如果我需要在紧迫的期限内选择技术堆栈,那么 Java 是我的第一选择。特别是在 Java 8 之后,它的功能变得越来越丰富和强大。
当来自非 Java 社区的人抱怨 Java 冗长而复杂时,我实际上不明白这是什么意思?
近年来,我有机会在我的官方项目中使用 Go 和 DotNet Core 。除此之外,我还使用了NodeJS和Python,供我个人使用。
我理解为什么很多人喜欢NodeJS和Python,因为它们是一种包含电池的东西。对于 Java 中的相同任务,您可能需要包含外部库,而在 Python/NodeJS 中,标准库本身以非详细的方式提供大多数常用功能。如果您熟悉Kotlin,那么在使用C 时您会感到宾至如归 。
我对 Go 有过这样的经历。我第一次使用它时不太喜欢它,但关于 Go 的简单让我印象深刻!
我们来看下面的Java/SpringBoot代码。
@Service @Transactional @RequiredArgsConstructor public class CustomerService { private final CustomerRepository customerRepository; private final AddressRepository addressRepository; public void createCustomer(Customer customer) { customerRepository.save(customer); addressRepository.saveCustomerAddress(customer.getAddress()); } }
对于至少使用过一次 SpringBoot 的任何 Java 开发人员,这段代码应该不需要任何解释。但是这里发生了很多事情。
在为CustomerService被标记为一个Spring bean可以注入到其它Spring Bean由于 Spring 4.x 不需要在构造函数上添加@Autowired注释。如果只有一个构造函数,它将自动用于创建 bean。该类使用@Transactional进行注释,这意味着当有人调用createCustomer()方法时,将启动并在成功完成后提交数据库事务。如果customerRepository.save()或addressRepository.saveCustomerAddress()方法抛出任何RuntimeException,则事务将自动回滚。如果CustomerService.createCustomer()是从不同类的另一个事务方法调用的,那么它将在父事务中运行而不是启动新事务。虽然这看起来很熟悉且易于阅读,但在幕后发生了很多事情。
让我们看看下面的 Go 代码,它的作用与上面相同:
type CustomerService struct { customerRepository CustomerRepository addressRepository AddressRepository } func (c CustomerService) createCustomer(customer Customer) error { // Get a Tx for making transaction requests. tx, err := db.BeginTx(ctx, nil) if err != nil { return err } // Defer a rollback in case anything fails. defer tx.Rollback() err := customerRepository.save(tx, customer) if err != nil { return err } err = addressRepository.saveCustomerAddress(tx, customer.Address) if err != nil { return err } // Commit the transaction. if err = tx.Commit(); err != nil { return err } return nil }
嗯,这是我们上面实现的相同功能的典型 Go 实现。假设它做了它打算做的事情,乍一看,这就是我的感觉:
每次第三条语句的错误检查都非常冗长DB 事务处理无处不在,我们可能需要对所有 DB 交互方法重复相同的 *** 作。业务逻辑和底层技术细节(错误/事务处理)纠缠不清这里没有魔法:没有隐藏的魔法。一个有 20 多年经验的开发人员可以阅读和理解这段代码,就像一个有 6 个月经验的毕业生可以阅读和理解它一样。
但是,没有魔法意味着:……只有当你不明白它是如何运作的时候,它才是魔法。
这一点将我引向我想讨论的下一点。但首先让我们不要急于得出哪种语言更好的结论,因为这不是本文的意图。
开发人员在软件开发过程中面临的最大挑战是什么?
我们都知道,与编写新代码相比,我们花在阅读现有代码上的时间更多。在典型的长期企业应用程序开发中,现有开发人员离开,新开发人员加入项目,最大的挑战是理解现有代码。如果代码很简单,那么它很容易理解。
但是量化“代码简单性”并不容易。对你来说看起来更简单的东西,对我来说可能看起来很复杂,反之亦然。所以我们(开发人员和社区)尽最大努力寻找尽可能简单地编写代码的方法。不同的社区根据上下文、时间、需求等采取不同的方法。
下面是我对 Java 和 Go 如何采用不同方法来实现代码简单性的看法。
Java实现简单代码的方式:抽象
我觉得 Java 的标准库太低级和冗长,无法执行许多常见任务,例如读取文件、进行 HTTP 调用等。为了避免样板和冗长,创建了commons-lang、Guava等库,提供更高级别的抽象屏蔽开发人员的所有低级细节。
最重要的是,许多企业应用程序需要一组通用的功能,如日志记录、配置、监控等。因此创建框架来解决这些通用需求,抽象出通用应用程序级样板代码。
随着时间的推移,抽象之上有抽象之上的抽象……
但是,这些抽象通过处理应用程序级样板代码并 让您专注于业务逻辑来帮助您更快地构建业务应用 。
这样做的缺点是:程序员如果很好奇,需要“了解这些抽象在幕后如何工作,并在框架/库中发挥作用”。
在我看来,这就是事情严重出错的地方
现在,每家公司都希望全栈开发人员能够编写前端、后端和一些基础设施即代码。没有时间正确学习所有这些抽象在幕后是如何工作的。为了满足交付时间表,开发人员希望尽快完成工作。在那里添加这 2 个注释,在此处添加这 4 行配置,如果它正在工作,那么它就完成了。如果遇到任何错误,请搜索 stackoverflow 中的第一个建议,如果它有效,则完成。工作已经完成,但没有任何关于它实际工作方式的线索。
随着时间的推移,这种工作模式让人害怕说“Java 很复杂”。
Go实现简单的方式:清晰/详细胜过聪明
Go 社区更喜欢通过“no-magic”来保持代码简单,这意味着没有注释、没有反射、没有 ORM 等。有很多用于 ORM、Http 路由器等的库,但 Go 社区更喜欢“如果可能的话坚持标准库”方法。
Go 社区似乎更喜欢编写更清晰和冗长的代码,而不是创建巧妙的更高抽象。
最好的部分是使用 Go 的标准库,您可以在不需要外部依赖的情况下实现大部分应用程序需求,当然还有更多的代码行。
冗长的好处是“任何对 Go 有点熟悉的人都可以轻松阅读任何惯用的 Go 代码并理解它”!
如果你现在是 Go 的崇拜者,你可能会因为一遍又一遍地阅读“冗长”而生气,并问“冗长”是什么意思?
上面代码中几乎每三行实现一次错误检查,我们检查Map是否包含键等的方式在我看来都很冗长。
基于我对 Go 的有限经验,我非常喜欢它,因为它的“无聊”性质。为了学习 Go,我在 GitHub 上阅读了许多文章和开源代码库,没有太多新东西要学习。
在看到几个 Go 代码存储库后,认为:从企业长期应用程序开发的角度来看,这是一件了不起的事情。学习的魔力更少,新开发人员更容易入职。
我们如何让 Java 变得“更简单”?
Java 是大型企业的首选是有原因的。开发速度快,上市速度快。我可以自信地说,您可以在几个小时内使用 SpringBoot/Quarkus/Micronaut 创建生产级 Java 应用程序,而不是几周或几个月。由于这些框架已经提供了包含电池的应用程序框架,您需要做的就是编写业务逻辑。
如果我能从 Go 中汲取一些想法并将它们带到 Java,特别是 SpringBoot,那么这些将是:
除非是简单的 CRUD 应用程序,否则不要用ORM。我更愿意花费编写更多代码的一次性成本而不是重复调试成本。我更喜欢 JOOQ 而 不是JPA。我知道向后兼容性是 Java/SpringBoot 成功的关键原因之一。但我喜欢从 SpringBoot 中剥离一些东西 支持 XML 配置,我没有看到任何使用 XML 配置的绿地项目。XML 支持可以作为单独的模块提取。无需 从 14 个不同来源加载配置属性使用和调试 AOP 的一些更简单的方法(如果您曾经尝试过调试 AOP 代码,那么您就知道我在说什么)Quarkus喜欢实时重新加载和连续测试我们真的需要“com.mycompany.myproject.mymodule”的私有业务应用程序封装结构吗?对于开源库是的,但是对于商业应用程序??总结
如果您是从未尝试过 Go 的 Java 开发人员,我强烈建议您看看 Go。你可能完全喜欢也可能不喜欢 Go,但你会爱上的东西却很少。
说了这么多,“Java 是并将永远是我最喜欢的语言”,从其他语言中学习东西的感觉很好。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)