简体   繁体   中英

Choosing between side effects and good API design in functional programming with scala

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:

  • In order to avoid side effects, the 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?).
  • Since the client code should 'fire and forget', it should be able to call 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM