I'm porting to scala a java application I wrote as a learning exercise. Part of it is communicating with another machine using a protocol directly over TCP. This protocol has 2 layers (Application and Transport) with corresponding headers and trailers. So a given message would end looking like
tHeader | aHeader | message | aTrailer | tTrailer
I thought of using a
trait Layer{
def write(s:String) : Unit
def read :String
}
Each layer would complete the message with its header|trailer and pass it to the next layer. I would then have a TransportLayer
and a ApplicationLayer
which I could combine in an implementation like
val layer = new TcpLayer with ApplicationLayer with TransportLayer
I was thrilled with this design, it allowed me to reuse the components at will. And then my dilemma appeared:
write
method should not return Unit
,but the modified String
, which should then be sent. This minimizes the side effects, eases testing, but the client code would need to send the completed String
over the socket itself ( which already has a side effect but no way around that one, or?). write
on a given Layer
and don't care about the modified String
( which might be gibberish to him anyway) . Therefore I think to return Unit
is the correct choice for the return value. Any thoughtful insights on which version is more functional programming - friendly?
If the only side-effect is in the socket, then how about this:
val layers = new TcpLayer with ApplicationLayer with TransportLayer
socket.write (layers.write (message))
unitTestEngine.check (layers.write (message))
Or if the client only have the layer
to work with, then:
val layers = new TcpLayer (socket) with ApplicationLayer with TransportLayer
layers.sink (layers.write (message))
unitTestEngine.check (layers.write (message))
Where sink
is a method returning the Socket instance.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.