Yehor Bondar
Yehor Bondar
Slowness of software is a complex aspect:
The important point about verbosity is not the time you spend typing: it’s about how difficult it is to read and understand the code.
VS
And verbosity makes code easier to read. You don’t have to know anything to understand the code. Everything you need to know is there in front of you.
The verbosity of Java code also encourages developers to implement more abstractions and reusable components. It’s easier to just write more code than to stop and think about reusable solutions. In Java and other verbose languages, ‘coding for the moment’ is a losing strategy.
Well known patterns:
Project Lombok
public class Person {
@Getter @Setter private int age = 10;
@Setter(AccessLevel.PROTECTED)
private String name;
@Override public String toString() {
return String.format("%s (age: %d)", name, age);
}
}
case class Person(age: Int, name: String)
class Person(var age: Int, var name: String)
val person = Person(10, "Bob")
person.age = 25
Scala
public class Test {
// No throws clause here
public static void main(String[] args) {
doThrow(new SQLException());
}
static void doThrow(Exception e) {
Test.<RuntimeException> doThrow0(e);
}
@SuppressWarnings("unchecked")
static <E extends Exception> void doThrow0(Exception e) throws E {
throw (E) e;
}
}
Scala
val result = Try {
throw new SQLException("DB is failed")
}
if(result.isSuccess) ???
else ???
result foreach { db =>
//execute only if DB is OK
}
Scala
def test(age: Int, name: String = "exampleText"): Unit = {
}
test(10)
test(10, "realName")
test(age = 10, name = "goodName")
public void test(int age) {
test(age, "exampleText");
}
public void test(int age, String name) {
}
trait Person {
def age: Int
def name: String
}
case class Employee(department: String, age: Int, name: String) extends Person
case class Student(university: String, age: Int, name : String) extends Person
val person: Person = Student("KNURE", 30, "Bob")
person match {
case Employee(_, 30, "Bob") => println("Correct man")
case Employee(_, 25, "July") => println("Correct woman")
case Student("KNURE", _, _) => println("Student from KNURE")
case _ => println("somebody else")
}
List<Student> students = persons.stream()
.filter(p -> p.getAge() > 18)
.map(Student::new)
.collect(Collectors.toList());
If you have Java 8
If not
val students = persons.collect {case p if p.age > 18 => new Student(p)}
def students = persons.findAll { person ->
person.age > 18
}.collect { person ->
new Student(person)
}
Groovy Collections API
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.12.1</version>
</dependency>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
J2EE
Play 2 Framework
EJB (ejb-jar.xml) | JAX-WS (sun-jaxws.xml) |
JPA (persistence.xml) | JAX-RS (web.xml) |
Servlet-Api/JSP (web.xml) | JMS(*-jms.xml) |
JSF (faces-config.xml) | CDI (beans.xml) |
WPPs
public abstract class BaseDao<T extends BaseEntity> {
@PersistenceContext(unitName = "enterpriseless-world")
private EntityManager em;
protected Class<T> entityClass;
public BaseDao() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
this.entityClass =
(Class) genericSuperclass.getActualTypeArguments()[0];
}
@TransactionAttribute
public Long save(T entity) {
em.persist(entity);
return entity.getId();
}
public T find(Long id) {
return em.find(entityClass, id);
}
@TransactionAttribute
public void remove(T entity) {
em.remove(entity);
}
protected EntityManager getEntityManager() {
return em;
}
}
BUT
Use Spring Boot
If you understand whole Spring Ecosystem
class ForeignExchangeController @Inject()(wsClient: WSClient,
foreignExchangeService: ForeignExchangeService) extends Controller {
def postLatestData() = Action.async {
wsClient.url("http://api.fixer.io/latest").get().map { response =>
response.status match {
case play.api.http.Status.OK =>
foreignExchangeService.batchPersist(getData(response.body))
Ok("OK")
case _ => InternalServerError
}
}
}
private def getData(content: String): Seq[(String, Double)] = {
val pattern = "\"(\\S{3}?)\":(\\d+\\.?\\d*)".r
pattern.findAllMatchIn(content).toSeq.collect {
case a if (a.groupCount == 2) => (a.group(1), a.group(2).toDouble)
}
}
}
GET /post controllers.ForeignExchangeController.postLatestData()
@Singleton
class CurrencyDao @Inject() (val config: Configuration) extends BaseDao {
def batchPersist(data: Seq[(String, Double)]): Unit = DB autoCommit { implicit session =>
val batchParams = data.map {d => Seq(d._1, d._2)}
sql"insert into currencyScala(currency, created, rate) values(?, now(), ?)"
.batch(batchParams: _*).apply()
}
}
case class Currency(id: Option[Long], created: DateTime, currency: String, rate: Double)
object DB {
val currencies = TableQuery[CurrencyTable]
}
DB.currencies.filter(_.currency === currency).sortBy(_.created.asc)
val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)
val currencies = TableQuery[CurrencyTable]
def add(currency: Currency): Future[String] = {
dbConfig.db.run(currencies += user)
}
def delete(id: Long): Future[Int] = {
dbConfig.db.run(currencies.filter(_.id === id).delete)
}
Frameworks battle