patternphpMinor
Generic Networking Class for PHP
Viewed 0 times
genericnetworkingphpforclass
Problem
I am in the process of writing networking code for PHP that is meant to be used in long-running PHP processes. I realize that PHP is supposedly not well suited for long-running processes, however that is not my question, and I already am well aware of the implications. This is meant as an OOP learning exercise for the most part.
My idea is to write a networking class that can be dependency-injected into a protocol-handling class. In the final product, these are meant to be two separate files, that use namespaces properly! I've put them here as namespace-less files:
The entire structure ends up looking like:
and so on, and so on.
I've commented some of the code that I'm feel most unsure about. In addition - the idea was to add PSR-compatible logging, so mind the dingy echo statements. (This will actually run as-is without any additional code).
The Generic Network Class
```
class StreamClient {
private $socket;
private $status = 'disconnected';
private $recvBufferSize = 4096;
private $parent; // Is the "parent" the correct term for this?
// in reality this would be a generic interface as the type for $parent
public function __construct(TcpReverseEcho $parent = null) {
$this->parent = $parent;
}
public function setParent(TcpReverseEcho $parent) {
$this->parent = $parent;
}
public function connect($where) {
if($this->status != 'disconnected') {
echo " > c
My idea is to write a networking class that can be dependency-injected into a protocol-handling class. In the final product, these are meant to be two separate files, that use namespaces properly! I've put them here as namespace-less files:
- \MyApp\Net\Stream\Client (which implements the interface \MyApp\Net\Generic\Client)
- \MyApp\Net\SomeProtocol\Client (which implements \MyApp\GenericProtocol\Client, or something another)
The entire structure ends up looking like:
- \MyApp\Net\Generic\Client
- \MyApp\Net\Generic\Server
- \MyApp\Net\Stream\Client (uses newer style stream_* for underlying functionality)
- \MyApp\Net\Stream\Server
- \MyApp\Net\Socket\Client (uses old style socket_* for underlying functionality)
- \MyApp\Net\Socket\Server
- \MyApp\ProtocolName\Client (gets an implementation of \MyApp\Net\Generic\Client injected into it)
and so on, and so on.
I've commented some of the code that I'm feel most unsure about. In addition - the idea was to add PSR-compatible logging, so mind the dingy echo statements. (This will actually run as-is without any additional code).
The Generic Network Class
```
class StreamClient {
private $socket;
private $status = 'disconnected';
private $recvBufferSize = 4096;
private $parent; // Is the "parent" the correct term for this?
// in reality this would be a generic interface as the type for $parent
public function __construct(TcpReverseEcho $parent = null) {
$this->parent = $parent;
}
public function setParent(TcpReverseEcho $parent) {
$this->parent = $parent;
}
public function connect($where) {
if($this->status != 'disconnected') {
echo " > c
Solution
class StreamClient {I would recommend using namespaces or if you are targeting pre-namespace PHP pseudo-namespaces
private $socket;Marking your variables as private will make it difficult to extend and reuse this class.
// in reality this would be a generic interface as the type for $parent
public function __construct(TcpReverseEcho $parent = null) {
$this->parent = $parent;
}
public function setParent(TcpReverseEcho $parent) {
$this->parent = $parent;
}It looks like you are passing parent is for event notification. A better pattern is to to allow other objects to subscribe to events using the observer pattern
// oes this look too redundant? This allows us to instead of injecting
// this class/object into a protocol handler, we could actually instead
// just extend this class and override these methods below. Maybe
//even make sense to check for $this->parent being..
// Or is this "wrong?"
function on_connect() {
if($this->parent != null) {
echo " > calling parent on_connect()\n";
$this->parent->on_connect();
}
}The main thing that stands out as an issue is single repressibility principle and separation of concerns. You classes doesn't have clear repressibility and they are trying to do to much. You need to make StreamClient as dumb as possible. You then inject StreamClient into TcpReverseEcho. The communication should flow from TcpReverseEcho to StreamClient with only responses coming back from method calls and from registered callbacks (events).
You are on the correct track with trying to separate out StreamClient and inject. You need to make a cleaner break.
Code Snippets
class StreamClient {private $socket;// in reality this would be a generic interface as the type for $parent
public function __construct(TcpReverseEcho $parent = null) {
$this->parent = $parent;
}
public function setParent(TcpReverseEcho $parent) {
$this->parent = $parent;
}// oes this look too redundant? This allows us to instead of injecting
// this class/object into a protocol handler, we could actually instead
// just extend this class and override these methods below. Maybe
//even make sense to check for $this->parent being..
// Or is this "wrong?"
function on_connect() {
if($this->parent != null) {
echo " > calling parent on_connect()\n";
$this->parent->on_connect();
}
}Context
StackExchange Code Review Q#94954, answer score: 5
Revisions (0)
No revisions yet.