스칼라 대 자바: 스칼라를 배워야 하는 이유

게시 됨: 2022-03-11

"Scala는 어렵다"는 말에는 어느 정도 일리가 있지만 학습 곡선은 투자할 가치가 충분히 있습니다. 언어의 좀 더 복잡한 기능(튜플, 함수, 매크로 등) 중 일부는 궁극적으로 개발자가 Scala로 프로그래밍하여 더 나은 코드를 작성하고 성능을 향상시키는 것을 더 쉽게 만듭니다. 솔직히 말해서, 우리는 프로그래머이고, 우리가 약간의 복잡성을 지닌 언어를 배울 만큼 똑똑하지 않다면 잘못된 사업을 하고 있는 것입니다.

Scala는 객체 지향 및 기능 프로그래밍을 모두 매우 간결하고 논리적이며 매우 강력한 언어로 통합하는 유형 안전 JVM 언어입니다. 어떤 사람들은 스칼라가 2003년에 처음 소개된 이래로 생각만큼 새롭지 않다는 사실을 알고 놀랄 수도 있습니다. 그러나 특히 지난 몇 년 동안 스칼라가 상당한 추종자들을 개발하기 시작했습니다. "왜 스칼라인가?"라는 질문을 던집니다.

이 기사에서는 특히 Java와 비교하여 Scala의 장점을 살펴봅니다(Scala는 JVM에서 실행되도록 작성되었기 때문에). Scala는 "더 나은 Java"를 만들기 위한 유일한 시도가 아닙니다. Kotlin 및 Ceylon과 같은 대안도 그 경로를 따라갔지만 학습 곡선을 최소화하기 위해 Java 언어 자체에 구문을 매우 가깝게 유지하기로 근본적인 결정을 내렸습니다. 이것은 훌륭한 아이디어처럼 보일 수 있지만 처음부터 "더 나은 Java"를 만들고자 하는 이유였던 바로 그 동일한 Java 패러다임의 수에 머물도록 강요한다는 점에서 궁극적으로 어느 정도 자기 패배적입니다.

대조적으로, Scala는 개발자에게 제한적이거나 지나치게 지루하거나 좌절감을 주는 Java의 측면을 없애 더 나은 언어 가 되는 것을 목표로 특별히 만들어졌습니다. 결과적으로 스칼라 프로그래밍의 조기 학습을 조금 더 어렵게 만들 수 있는 코드 구별과 패러다임 전환이 실제로 존재하지만, 그 결과 궁극적으로 사용하기 쉽고 생산성을 높이는 훨씬 깨끗하고 잘 조직된 언어가 됩니다.

Scala와 Java를 나란히 비교할 때 Scala의 효율성은 분명합니다.

Scala 대 Java: 어느 것이 실제로 더 복잡합니까?

Java 언어의 단순성은 성공의 일부였지만 아이러니하게도 복잡성에도 기여했습니다. 물론 Java로 거의 모든 것을 작성할 수 있지만 그렇게 하는 데 필요한 코드 줄은 벅찰 수 있습니다. 반면에 스칼라 프로그래밍은 약간 더 복잡한 구조를 가지고 있습니다. 그러나 20개의 "간단한" Java 행을 대체하는 약간 더 복잡한 단일 코드 행을 작성할 수 있다면 어느 것이 실제로 더 복잡할까요?

진실은 Java가 종종 너무 장황하다는 것입니다. 스칼라에서 컴파일러는 매우 똑똑하므로 개발자가 컴파일러가 유추할 수 있는 것을 명시적으로 지정할 필요가 없습니다. 예를 들어 이 간단한 "Hello World!"를 비교하십시오. 자바 대 스칼라의 프로그램:

자바의 Hello World:

 public class HelloJava { public static void main(String[] args) { System.out.println("Hello World!"); } }

스칼라의 Hello World:

 object HelloScala { def main(args: Array[String]): Unit = { println("Hello World!") } }

여기서는 두 언어 사이에 큰 차이가 없지만 Scala는 이 간단한 예제에서도 덜 장황합니다.

보다 실용적인 예를 위해 간단한 문자열 목록을 만드는 방법을 살펴보겠습니다.

자바:

 List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3");

스칼라:

 val list = List("1", "2", "3")

확실히 Java에는 코드를 약간 단축하는 몇 가지 트릭이 있지만 표준 사용에서는 그렇지 않습니다.

이제 숫자인 문자열 목록이 있지만 그 목록을 정수 목록으로 변환하려는 경우를 고려하십시오.

자바:

 List<Integer> ints = new ArrayList<Integer>(); for (String s : list) { ints.add(Integer.parseInt(s)); }

스칼라:

 val ints = list.map(s => s.toInt)

Scala의 기능적 속성 덕분에 이 변환은 매우 간단해집니다.

클래스 예제: 자바 대 스칼라

한 단계 더 나아가 자바와 스칼라에서 표준 빈/POJO(Plain Old Java Object) 생성을 비교해보자.

먼저 자바 버전:

 public class User { private String name; private List<Order> orders; public User() { orders = new ArrayList<Order>(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Order> getOrders() { return orders; } public void setOrders(List<Order> orders) { this.orders = orders; } } public class Order { private int id; private List<Product> products; public Order() { products = new ArrayList<Product>(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public List<Product> getProducts() { return products; } public void setProducts(List<Product> products) { this.products = products; } } public class Product { private int id; private String category; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } }

휴. 로타 코드.

이제 스칼라 버전:

 class User { var name: String = _ var orders: List[Order] = Nil } class Order { var id: Int = _ var products: List[Product] = Nil } class Product { var id: Int = _ var category: String = _ }

우리는 어떤 언어가 더 복잡하다고 말했습니까?!

우리는 공정하고 있습니까?

여기까지 했고 Java 프로그래머라면 이 시점에서 내가 코드를 부당하게 비교하고 있다고 생각할 수 있습니다. 결국, Java에서 공용 변수를 만든 다음 getter와 setter를 제거하는 것을 막을 수는 없습니다.

그러나 Java의 getter 및 setter 뒤에 있는 추론을 다시 생각해 보면 이는 특히 미래 보장을 위한 것입니다. 즉, 나중에 변수를 가져오거나 설정하는 데 일부 논리를 추가해야 하는 경우 대신 메서드를 사용하도록 해당 공용 변수를 다시 작성해야 합니다(이것이 Java에서 getter 및 setter를 사용하여 시작하는 것이 권장되는 이유입니다. ). 그러나 Scala 프로그래밍에서는 그렇지 않습니다. 언어 설계로 인해 추상화는 getter 및 setter 없이 그대로 유지됩니다. 예를 들어 이름을 null로 설정하려고 하면 NullPointerException 을 발생시키는 Scala의 다음과 같이 수정된 User 클래스를 고려하십시오.

 class User { private var _name: String = _ var orders: List[Order] = Nil def name = _name def name_=(name: String) = { if (name == null) { throw new NullPointerException("User.name cannot be null!") } _name = name }

그리고 여전히 다음과 같이 이름을 설정할 수 있습니다.

 user.name = "John Doe"

이렇게 하면 메서드 접근자를 미리 구성할 필요가 완전히 제거됩니다.

게다가 스칼라는 불변성을 선호하기 때문에 케이스 클래스를 사용하여 스칼라에서 이것을 훨씬 더 간결하게 작성할 수 있습니다.

 case class User(name: String, orders: List[Order]) case class Order(id: Int, products: List[Product]) case class Product(id: Int, category: String)

얼마나 적은 코드를 작성해야 하는지 정말 미쳤습니다.

예제를 조금 더 진행

이제 위의 클래스에서 User 가 주문한 모든 Products 목록을 반환하는 멋진 메서드를 User 클래스에 추가하려는 시나리오를 고려하십시오.

장황한 Java 세계에서:

 public List<Product> getProducts() { List<Product> products = new ArrayList<Product>(); for (Order order : orders) { products.addAll(order.getProducts()); } return products; }

다행히 java.util.List 에는 addAll 메소드가 있거나 Java에서는 getProducts() 가 훨씬 더 길었습니다.

반면에 Scala에서는 다음과 같은 것이 필요합니다.

 def products = orders.flatMap(o => o.products)

Scala 언어 구현이 얼마나 작은지 알 수 있습니다. 예, Scala 초보자에게는 더 복잡해 보일 수 있지만 실제로 그 이면의 개념을 완전히 이해하고 나면 Scala 코드가 Java 코드보다 훨씬 더 단순해 보일 것입니다.

여기서 좀 더 복잡해 보겠습니다. 특정 Category 내에서만 Products 을 얻으려면 어떻게 해야 합니까?

이 경우 java.util.ListaddAll 메소드를 사용할 수 없으므로 Java에서 상황이 더 나빠집니다.

 public List<Product> getProductsByCategory(String category) { List<Product> products = new ArrayList<Product>(); for (Order order : orders) { for (Product product : order.getProducts()) { if (category.equals(product.getCategory())) { products.add(product); } } } return products; }

그러나 Scala 에서 코드는 상당히 간단합니다. 우리는 단순히 flatMap 을 사용하여 단일 목록으로 병합된 각 Order 의 제품 목록을 결합한 다음 범주와 일치하는 항목만 포함하도록 필터링합니다.

 def productsByCategory(category: String) = orders.flatMap(o => o.products).filter(p => p.category == category)

동적 대 정적

확실히 지난 몇 년 동안 새로운 언어가 부족하지 않았지만 최근에 등장한 거의 모든 다른 언어가 동적인 반면 Scala는 정적으로 유형이 지정됩니다.

전문 개발자로서 많은 동적 언어를 알고 사용하지만 견고한 코드를 작성하려면 컴파일 시간 검사가 매우 중요하다고 생각합니다. 동적 언어에서는 다양한 시나리오에서 실제로 실행할 때까지 코드에 버그가 없고 강력하다고 확신할 수 없습니다. 이로 인해 코드가 생산될 때까지 실현되지 않는 잠재적으로 심각한 코드 결함이 발생할 수 있습니다.

마무리

바라건대, 이 기사는 스칼라의 힘과 능력에 대한 예비 감각을 제공하고 언어 학습에 대한 욕구를 불러일으키기에 충분할 만큼 자바와 스칼라를 비교합니다. 프로그래밍을 덜 지루하고 즐겁게 만들 수 있는 훌륭한 언어일 뿐만 아니라 세계에서 가장 큰 회사(LinkedIn, Twitter, FourSquare, Guardian 등)에서도 사용하고 있습니다.

Scala 개발자를 위한 공석이 계속해서 증가하고 있음을 알 수 있듯이 Scala의 인기와 사용은 빠르게 증가하고 있습니다. 아직 그렇게 하지 않았다면 지금이 파도 타기를 시작하고 "왜 Scala를 배우나요?"라는 질문을 중단하기에 좋은 시간이 될 것입니다.

관련 항목: Scala 매크로 및 준따옴표로 상용구 코드 줄이기