Chapter 20. Performing I/O to Passing Data
Input and output are problematic in code. Our program is subject to errors talking to the outside world when files disappear or network sockets fail. I/O is also an action and so limits our ability to reason with and refactor our code. How can we limit the scope of the problems that I/O causes?
Now that earlier chapters have built some foundations, we’re going to up the pace here, going straight into refactoring and learning lessons as we go.
Listening to Tests
In Chapter 10, we looked at some Java code that produced a report for marketing.
When we left the code, we had introduced extension functions to the HighValueCustomersReport
, giving us:
@Throws
(
IOException
::
class
)
fun
generate
(
reader
:
Reader
,
writer
:
Writer
)
{
val
valuableCustomers
=
reader
.
readLines
()
.
toValuableCustomers
()
.
sortedBy
(
CustomerData
::
score
)
writer
.
appendLine
(
"ID\tName\tSpend"
)
for
(
customerData
in
valuableCustomers
)
{
writer
.
appendLine
(
customerData
.
outputLine
)
}
writer
.
append
(
valuableCustomers
.
summarised
())
}
private
fun
List
<
String
>.
toValuableCustomers
()
=
withoutHeader
()
.
map
(
String
::
toCustomerData
)
.
filter
{
it
.
score
>=
10
}
private
fun
List
<
String
>.
withoutHeader
()
=
drop
(
1
)
private
fun
List
<
CustomerData
>.
summarised
():
String
=
sumByDouble
{
it
.
spend
}.
let
{
total
->
"\tTOTAL\t${total.toMoneyString()}"
}
Here are the tests after conversion to Kotlin:
class ...
Get Java to Kotlin now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.