user2066049
user2066049

Reputation: 1371

Convert legacy Java code into Scala functional idioms

I am looking at some legacy Java code which now will have to be converted to new Scala system. Legacy code looks as below. In new Scala project I have all Java value objects as case classes What's the best way you recommend to bring this Java (OO styled and side effecting) over to Scala (without side effects, mutation etc)?

EDIT Does collectFirst look appropriate for Java break equivalent ?

ln.collectFirst{case l if(availableSlot(allowedSection,vehicle,l)) >1 => vehicle.copy(allocatedSlot = Some(5), allocatedLane = Some(l))}

Upvotes: 0

Views: 134

Answers (2)

Erik Kaplun
Erik Kaplun

Reputation: 38247

In my experience, when porting imperative code to functional, it's best to first do a general clean up and only then proceed to making changes that are not obviously safe and correct.

  • vars to vals
  • Option[T] everywhere nulls can occur
  • monadic map/foreach instead of if's
  • for loops to map/filter
  • ArrayLists and Hashtables etc to immutable collections
  • general renames and refactorings
  • marking types sealed/final with the goal of migrating to ADTs
  • extract common patterns into Scala idioms such as infix operations using implicit classes

then the code will be more obvious and functional patterns will emerge and be easy to materialize, such as mutable classes to immutable ones. Also, rewriting of stateful loops to map/filter/fold is non-trivial and must be approached with attention to detail all of which necessitates a readable code base to begin with.

For example to avoid 'breakable', you must firmly understand the semantics of the iteration before you move to filter/fold.

Also, always remember to use refactoring tools and try to stay away from "manual" changes, where possible.

Upvotes: 1

wingedsubmariner
wingedsubmariner

Reputation: 13667

All case classes come with a copy method that returns a new copy of the case class with select fields updated:

vehicle.copy(allocation = 5, name = "new name")

For converting code that uses null use Option instead. Ideally you should rewrite everything to use Option, but as an interim measure you can wrap calls to methods that return null in Option:

val allowedSection: Section = Option(
  new Tools().getRequest(serviceEndpoint, vehicle.getStep(), serviceUser, servicePassword)
).getOrElse(Section(name = vehicle.step))

Upvotes: 1

Related Questions