Skip to content

Better Interface Segregation (Future Version?) #198

@designermonkey

Description

@designermonkey

Hi @rtheunissen.

I use this extension every day, and in our current project, I have been creating wrappers for classes to handle concurrency with OpenSwoole. That's not the point of this, though ;)

While doing so, I've found it challenging to type hint my application classes to be able to handle the extension classes or my decorated concurrent replacements because I believe the interfaces provided aren't as good as they could be.

To try to help out, I've spent a couple of hours going through everything with a fine-toothed comb to see what would work better, as many classes share similar, if not the same, methods but with no interface backing them up.

I'm wondering if a v2 is on the horizon for this reason and also for better type hinting for PHP 8.x. What I have done I have added below for your review and criticism (everything is interfaces for ease of description).

I'm not formally qualified in computer science, so I might not fully understand the data structures. I am also not a C programmer, so I wouldn't be able to offer any coding help with a new version, though I wish I could.

Anyway, please let me know what you think and whether there will be a v2.

<?php declare(strict_types=1);

namespace Ds;

use ArrayAccess;
use Countable;
use IteratorAggregate;
use JsonSerializable;

/**
 * Original Hierarchy:
 *
 * Hashable
 * Pair
 * Collection
 *   Sequence
 *     Deque
 *     Vector
 *   Map
 *   Set
 *   Stack
 *   Queue
 *   PriorityQueue
 */


/**
 * Proposed Hierarchy:
 *
 * Equatable
 * Hashable
 * Pair
 * DataStructure
 *   Collection
 *     TransformableCollection
 *       Set
 *       Map
 *     Sequence
 *       Deque
 *       Vector
 *   LinearSequence
 *     Stack
 *     Queue
 *     PriorityQueue
 */


interface DataStructure extends Countable, IteratorAggregate, JsonSerializable
{
    public function clear(): void;
    public function copy(): DataStructure;
    public function isEmpty(): bool;
    public function toArray(): array;
    public function allocate(int $capacity): void;
    public function capacity(): int;
}

interface Pair extends JsonSerializable
{
    public function clear(): void;
    public function copy(): Pair;
    public function isEmpty(): bool;
    public function toArray(): array;
}

interface Equatable
{
    public function equals(object $obj): bool;
}

interface Hashable extends Equatable
{
    public function hash(): mixed;
}

interface Collection extends DataStructure
{
    public function filter(callable $callback = null): Collection;
    public function first(): mixed;
    public function last(): mixed;
    public function merge(mixed $values): Collection;
    public function reduce(callable $callback, mixed $initial = null): mixed;
    public function reverse(): void;
    public function reversed(): Collection;
    public function slice(int $index, int $length = null): Collection;
    public function sort(callable $comparator = null): void;
    public function sorted(callable $comparator = null): Collection;
    public function sum(): int|float;
}

interface TransformableCollection extends Collection
{
    public function diff(Collection $map): Collection;
    public function intersect(Collection $map): Collection;
    public function union(Collection $map): Collection;
    public function xor(Collection $map): Collection;
}

interface Set extends TransformableCollection, ArrayAccess
{
    public function add(mixed ...$values): void;
    public function remove(mixed ...$values): void;
    public function contains(mixed ...$values): bool;
    public function get(int $index): mixed;
    public function join(string $glue = ''): string;
}

interface Map extends TransformableCollection, ArrayAccess
{
    public function apply(callable $callback): void;
    public function get(mixed $key, mixed $default = null): mixed;
    public function hasKey(mixed $key): bool;
    public function hasValue(mixed $value): bool;
    public function keys(): Set;
    public function ksort(callable $comparator = null): void;
    public function ksorted(callable $comparator = null): Map;
    public function map(callable $callback): Map;
    public function pairs(): Set;
    public function put(mixed $key, mixed $value): void;
    public function putAll(mixed $pairs): void;
    public function remove(mixed $key, mixed $default = null): mixed;
    public function skip(int $position): Pair;
    public function values(): Sequence;
}

interface Sequence extends Collection
{
    public function apply(callable $callback): void;
    public function contains(mixed ...$values): bool;
    public function find(mixed $value): mixed;
    public function get(int $index): mixed;
    public function insert(int $index, mixed ...$values): void;
    public function join(string $glue = ''): string;
    public function map(callable $callback): Sequence;
    public function remove(int $index): mixed;
    public function rotate(int $rotations): void;
    public function set(int $index, mixed $value): void;
    public function shift(): mixed;
    public function unshift(mixed $values = null): void;
}

interface Deque extends Sequence, ArrayAccess
{
}

interface Vector extends Sequence, ArrayAccess
{
}


interface LinearSequence extends DataStructure
{
    public function peek(): mixed;
    public function pop(): mixed;
    public function push(mixed ...$values): void;
}

interface Stack extends LinearSequence, ArrayAccess
{
}

interface Queue extends LinearSequence, ArrayAccess
{
}

interface PriorityQueue extends LinearSequence
{
    /** Using push(mixed ...$values) would add items as `0` priority */
    public function pushPriority(mixed $value, int $priority): void;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions