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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions