现代Java开发速度很快

Øriginally posted on return.co.de

Java开发快速而有趣。 信不信由你。

我在播客中听到了很多有关Java的抨击,大多数是从未进行过专业Java开发的开发人员,他们将Java视为笨拙的Java浏览器插件或丑陋的跨平台桌面应用程序。

但这不是我要说的。 我的意思是,如今您可以在很短的时间内用Java编写高质量的生产就绪代码。 因此,这里是我每天使用的工具和框架的概述。

下一部分将介绍我的背景以及过去与Java有关的问题。 但是请随时跳过它,并跳转到“新希望”。

The XML Hell

几年前,我几乎已经用完Java。 我使用Java ME进行了多年的开发(使用一点也不有趣的Java 1.3)以及使用Spring 2进行Java SE的后端开发。此外,我还必须维护一些遗留系统来运行前端的Struts。

<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id = "helloWorld" class = "de.co.return.HelloWorld">
      <property name = "message" value = "Hello World!"/>
   </bean>
</beans>

真正的美丽,不是吗?

基本上,我对Spring 2和Struts感到厌倦,因为它拥有大量的XML,使得重构变得很困难,而且很难阅读。

因此,我使用纯Java SE开始了下一个后端项目。 我做到了完全由测试驱动。 我使用IntelliJ生成所有样板代码非常快。 我真的很认真地考虑了DI的“过度设计”。 即使只有一个实现,我几乎每个类都有一个接口。 我没有使用任何模拟框架,因为我也有一些不好的经验-使用EasyMock甚至PowerMock(不要使用它!),并在需要时通过在测试中实现接口来编写所有模拟。 我还有一个巨大的主引导程序类,它实际上创建了生产实例并进行了实际的注入。 那是一个500loc的怪物。

MyConfiguration config = loadConfiguration();
FirstClass firstClass = new FirstClass(config);
SecondClass secondClass = new SecondClass(config, "someParam");
ThirdClass thirdClass = new ThirdClass(firstClass, secondClass);

(...)

OneHundredTwelfthClass oneHundredTwelfthClass = (...)

由于具有很好的测试覆盖范围,因此该应用程序从投入生产后的第一刻就开始工作。 我唯一没有提到并因此存在错误的地方是SQL查询,您猜对了,我使用纯JDBC编写。

全部手动。 都是因为过去我使用任何一种框架都经历过如此糟糕的经历。

我学到了很多东西,但我一生都不想这样做。 所以我一直在寻找一些小众的工作,例如Erlang Backend Developer(我仍然喜欢那种语言)。 实际上,我拒绝了Java Dev职位的很好提议,因为他们在采访中告诉我他们正在做Spring。 最终,我被一家基于Java的大公司聘用。

A New Hope

我是一个新团队的成员,该团队可以选择我们要使用的技术。 我们尝试了简单的Java,Camel,Java EE,vert.x,然后有了Spring 4和Spring Boot以及其他一些便利设施,这些使我大开眼界。

Spring - The Magic is Happening

Spring Core

With Spring core, I was obviously able to replace such an ugly bootstrap class with its @Autowire magic and, most importantly, without any XML necessary:

@Service
public class FooService {

    private final FooRepository repository;

    @Autowired
    public FooService(FooRepository repository) {
        this.repository = repository
    }
}

这是Spring的核心:依赖注入。 实际上是管家,可以为您提供所有需要的东西。 您只需要打电话。 剧透:Lombok变得更好,请参见下文。

实际上,除了需要多个实现的地方以外,我完全放弃了“每个类的接口”模式。

Spring Web MVC - Gimme Some REST

我不需要任何Web服务器设置或配置,我可以轻松编写一个@Controller返回一个Java类实例,该实例被序列化为JSON,无需任何代码。

@Controller
@RequestMapping("/appointments")
public class AppointmentsController {

    private final AppointmentBook appointmentBook;

    @Autowired
    public AppointmentsController(AppointmentBook appointmentBook) {
        this.appointmentBook = appointmentBook;
    }

    @GetMapping
    public Map<String, Appointment> get() {
        return appointmentBook.getAppointmentsForToday();
    }

    @GetMapping("/{day}")
    public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) {
        return appointmentBook.getAppointmentsForDay(day);
    }

    @PostMapping
    public String add(@Valid Appointment appointment) {
        appointmentBook.addAppointment(appointment);
        return "redirect:/appointments";
    }
}

上面的代码发布了一个新的rest终结点/约会以及两个得到端点检索一天中的所有约会和所有约会以及开机自检端点以创建新约会。 班级约定实际上可能是一个持久化的实体,该实体会自动序列化为JSON。 您将获得正确解码的路径变量,并将其输入到类型方法参数中。 无需其他代码。

See here for reference.

Spring Data

For very simple CRUD interfaces, I could use Spring Data repositories and even Spring Data REST to directly create a REST interface for my entities.

public interface OrderRepository extends CrudRepository<Order, Long> { }
对于此存储库,Spring Data REST在以下位置公开集合资源:/订单。 该路径从要管理的域类的无大写,复数,简单类名派生。 它还在URI模板下公开了资源库管理的每个项目的项目资源。/订单/{id}。 *

*See here for reference.

再说一次,虽然有很多魔术,但是却很酷。 在扫描类路径以查找Spring托管类时,它会动态找到该接口并为该存储库创建一个实现,您实际上可以使用该存储库从数据库(以及所有CRUD操作)中获取实体,此外还将创建一个REST 控制器,将请求发送到该存储库。

Spring Integration Tests

Using Mockito to mock objects in tests works like a a charm, AssertJ for test assertions and even all-set-up integration tests using @SpringBootTest with Real HTTP mock servers and in memory data bases running a complete application test without any external resources.

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {

    @MockBean
    private RemoteService remoteService;

    @Autowired
    private MyService service;

    @Autowired
    private MockRestServiceServer remoteServer;

    @Test
    public void exampleTest() {
        this.remoteServer.expect(requestTo("/greet/details"))
                .andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
        given(this.remoteService.someCall()).willReturn("world");

        String greeting = this.service.callRestService();

        assertThat(greeting).isEqualTo("hello world");
    }
}

As you see, there is a lot happing in this code. First, an actual Web Server called is started MockRestServiceServerthat will respond once /greet/details is requested. Then the service RemoteService of you application is mocked which is assumed to be called by the class under test MyService. When the method someCallis called, it will return "world". At the end, a verification using 一种ssertJ is done.

Spring Security

The only downside was using Spring Security which does authentication and autorization. It comes with a variety of ready to use implementations as well as the option to write your own AuthenticationProvider. Unfortunately, IMHO it is designed badly (from the usability perspective) and even worse documented. Once you're starting to customize it the slightest bit, It never works as you would expect and you'll end up spending hours and days fixing it by trial and error. Simply put, Spring security sucks most of the time. I hope there is some overhaul done soon.

Spring Boot

通过Spring Boot,可以轻松地创建独立的,基于生产级别的基于Spring的应用程序,您可以“运行”它们。 我们对Spring平台和第三方库持固执己见的观点,因此您可以以最小的麻烦开始使用。 大多数Spring Boot应用程序只需要很少的Spring配置。
  • See here for reference.

Spring Boot将所有内容拼凑起来,应用合理的默认配置,您的选择便大有裨益。

If you want a very funny and very good live coding example, I highly recommend Josh Long's video "Bootiful" Applications with Spring Boot - Wow, such great!

JPA / Hibernate

几年前,当我曾经使用过Hibernate时,也有我早先描述过的XML配置地狱。 但是通过最近的JPA,您只需

@Entity
public class Customer {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private String firstname;
  private String lastname;

  // … methods omitted or replaced by Lombok
} 

See here for reference.

以及与Spring Data Repository一起,您可以轻松访问实体。 这意味着,您只是在描述正在使用的数据,而不必处理如何获取它们。

最好的事情是,您不需要编写任何SQL。 Hibernate非常擅长创建优化的查询。 它将从数据库中提取数据并将其映射到@实体类。 如果您对表或列有一些难看的名称,则只需注释字段即可。 上课期待一张桌子顾客带有列columnsD,名字和LASTNAME`. You can customize everything you want if you need to access a legacy DB, e.g..

Lombok - No More Getters

Java 8发行时,我对这种旧语言的发展方式印象深刻。 但是,从我的角度来看,缺少了两件事:模式匹配以及摆脱吸气剂和吸脂剂的方法。

我们仍然没有模式匹配(例如在Erlang中),但是-确实很棒-我们可以使用库来摆脱getter和setter方法。 很多框架都依赖于getter和setter,Hibernate,Jackson和Spring本身的存在。

When I first saw Lombok I thought this must be some code generation magic or - even worse - some runtime reflection trick. Plus, the website looked like it was from the 90ies. But when I checked it out, it turned out I was completely wrong. They are using a javac feature, compile-time annotations. So during compilation, Lombok's code is executed and generates additional byte code which generates no additional runtime overhead (compared to writing getters and setters manually) and no intermediate Java code.

记住FooService从上面。 使用@AllArgsContructor,龙目岛为所有成员生成一个构造函数。

`java @服务 @AllArgsConstructor @ sl4j 公共类FooService {

private final FooRepository repository;
private final MyProperties properties;

public getUri(String path) {
    log.debug("Building uri from base Url {} and path {}", properties.getSomeUrl(), path)
    return properties.getSomeUrl() + path;
}

} `

使用@ sl4j,我们获得了一个免费的记录器(而不是Logger。getLogger(。。。)),还有更多类似生成的好东西@ToString和@EqualsAndHashcode。

With Spring 4.3, you can even drop @Autowire completely.

`java @组态 @组态Properties(prefix = "my.app") @盖特 @Setter 公共类MyProperties {

private String someUrl;
private Integer someTimeout;

} `

上面的代码可用作配置应用程序的spring属性。 您可能会争辩说,此片段包含的注释比代码更多,这是事实。 但是我还是比自己编写所有样板代码更喜欢它。

它允许您编写一个YAML文件,如下所示,将其拖放到jar旁边以更改配置:

yaml my.app: 某些网址:http://foo.bar 超时:5000

是的,它将自动允许您使用适当的命名,例如超时仍然知道如何将其映射到someTimeout。 您将免费获得应用程序的类型安全配置。 您甚至可以添加@已验证与例如@Max(1000)。

Maven

Maven是的 library management tool. Ok, Maven是a lot of XML, ok but it just works like a charm. I've worked with Ant and it was so painful to get 的 same result.

我期待在Android项目中使用Gradle,哦,天哪,这真的很糟糕。 您将需要编写可执行任何功能的可执行脚本(并且可以执行任何操作,尤其是在您不想要的情况下)。 您永远不会知道它是您要调用的方法还是其配置。 我最终花费了数小时和数天的时间来对我的构建脚本进行printf调试,直到它完成了我想要的工作为止。

仅仅因为XML,Maven的定义就很好了,而且您几乎无法以意想不到的方式破坏东西。 Maven对库的依赖关系是正确的,特别是当您将其与正在加载代码,构建它(XCode,Erlang)或诸如NPM和Bower的废话的其他“包管理器”进行比较时。 Maven只是构建过程中不可或缺的一部分,无需像下面这样预先下载库点子(Python),您将始终获得要构建的那个项目的确切版本的lib。

Java

如上所述,Java 8具有一些功能特性,虽然Lambda不一定具有功能性,但它们非常方便。 乍一看,流看起来很棒,但大多数情况下,您将得到没有人(一个星期后甚至没有人)都无法阅读的意大利面条代码。 大多数情况下,最好使用旧的for循环。

但是通常,它会尝试尽可能多地编写功能代码(自Java的第一个版本以来就可以实现)。 这意味着,方法应始终返回一个值(不为void),并且对于相同的参数应始终返回相同的值。 这需要

  • 不使用系统调用(例如currentTimeMillis())不能与文件,数据库等交互使用类变量

显然,如果您100%做到这一点,那么您的应用程序将一文不值,因为您既无法控制它,也无法获得任何输出。 因此,我想做的是保持我的核心业务逻辑尽可能整洁,并将副作用尽可能远地转移到外部。 这有益于测试。

IDE

I actually transistioned through a lot of IDE in the past, starting from QBasic, Turbo Pascal, Visual Studio, Eclipse, NetBeans, XCode and even vim. But I lost my heart to 一世ntelliJ IDEA which is just the single best IDE I've ever used. It starts with beeing beatiful and fast, supporting very good and intuitive keyboard short cuts, you can auto-type and auto-filter all menus, even context menus. It allows to use powerful refactorings and generating code for you. I supports very good debugging as well as showing code coverage in line.

您可能现在对您的IDE感到满意,但是您至少应该尝试过一次IDEA,并观看有关这些功能的视频。

尤其是当我使用XCode进行应用程序项目时,与IntelliJ相比,我感觉就像在石器时代。 不幸的是,即使JetBrains AppCode在某些方面仍然需要XCode。

It's the Eco System

因此,这与语言无关。 它与IDE或构建工具无关。 一切都使Java开发变得快速而有趣。

from: https://dev.to//stealthmusic/modern-java-development-is-fast

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值