HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

OOP Decision Maker Class - ServerArbiter

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
oopserverarbiterdecisionclassmaker

Problem

I am writing a ServerArbiter, the job of which is to make a decision about which server to "choose" given a set of rules. The aim is to be able to add / remove rules at will - for ease of future maintenance. My language of choice is php, so please bear this in mind when answering.

Basically, a server will be chosen depending on various factors. One may be 'server load'. Imagine this arbiter is used to decide which server to add a torrent to - it will choose the server with the least number of torrents in the download queue.

Architecture

My current architecture for this solution consists of a ServerArbiter object:

public function __construct(RuleSet $ruleSet, array $servers);


The RuleSet is effectively just a list of Rule objects that implements \Iterator so it can be foreach()d around.

public function addRule(Rule $rule);


And the actual Rule objects implement the Rule interface:

public function resolve(Server $server);


A Server is just a (doctrine) Entity - that is, it contains class members, setters and getters, and some validation. These properties are populated with data from the servers database table. One of the properties is ipAddress.

Rules

I currently have rules such as the ServerActiveRule, which is just a property that is returned.

class ServerActiveRule implements Rule
{
    /**
     * {@inheritdoc}
     */
    public function resolve(Server $server)
    {
        return $server->isActive();
    }
}


For torrents example described above, I was going to have a ServerDownloadsComparisonRule:

```
class ServerDownloadsComparisonRule
{
/**
* @var Server[]
*/
private $servers;

public function __construct(array $servers)
{
// -- SNIP --
// Make sure each $server is instance of Server entity
// -- SNIP --
}

public function resolve(Server $server)
{
// I'm guessing this is where I will compare the downloads to get the one

Solution


  • Why does the decide() method do more work? It's the problem of the object constructing your Rules, which is not necessarily the ServerArbiter.



  • Isn't that already a part of the Server entity? Why do you need to inject yet another dependency. If the server's address isn't in the Server entity, why the hell the server's address isn't in the Server entity?!



  • Your architecture is fine. Easily separated, Servers don't know about the Rules.



-
Yes. Since querying all the servers to get their downloads count, it makes sense to remember the best server in the ServerDownloadsComparisonRule the first time resolve is called, and then just reference it from the cache.

if ($bestServer == null) {
    $bestServer = $this->findServerWithLeastDownloads();
}
return $server === $bestServer;

Code Snippets

if ($bestServer == null) {
    $bestServer = $this->findServerWithLeastDownloads();
}
return $server === $bestServer;

Context

StackExchange Code Review Q#52515, answer score: 2

Revisions (0)

No revisions yet.