omise-php icon indicating copy to clipboard operation
omise-php copied to clipboard

Proposal for 3-0-0 design

Open iwat opened this issue 7 years ago • 2 comments

I do not see any design document yet, so I propose a new one here:

If Omise is going to create a new 3-0-0 release, if backward compatibility is not an issue, I would like to propose 2 new designs:

  1. Use static as usual, but add service locator pattern for testability. Bonus: this can be partially implemented on 2.x.
use \Http\Client\HttpClient;

use \Omise\Credential\CredentialProvider;
use \Omise\Credential\EnvarCredentialProvider;
use \Omise\OmiseClient;
use \Omise\TestSupport\FixtureHttpClient;
use \Omise\ServiceLocator;

class ChargeTest
{
    public function setUp()
    {
        $locator = ServiceLocator::getInstance();
        $locator->restoreDefault();
    }

    public function testListCharges()
    {
        $locator = ServiceLocator::getInstance();
        $locator->register(HttpClient::class, function () {
            return new FixtureHttpClient(__DIR__.'/../fixtures/'));
        });
        $locator->register(
                CredentialProvider::class,
                function () {
                    return new EnvarCredentialProvider('OMISE_PUBLIC_KEY', 'OMISE_SECRET_KEY');
                }
        );

        $charge_list = OmiseClient::listCharges();
        $this->assertInstanceOf('\Omise\Resorce\List', $charge_list);

        foreach ($charge_list->data() as $charge) {
            $this->assertInstanceOf('\Omise\Resource\Charge', $charge);
        }

        // backward compatibility is still partially supported
        $charge_list = OmiseCharge::retrieve();
        $this->assertInstanceOf('\Omise\Resorce\List', $charge_list);

        foreach ($charge_list->data() as $charge) {
            $this->assertInstanceOf('\Omise\Resource\Charge', $charge);
        }
    }
}

The idea:

  • Keep using static, for ease of use.
  • Use service locator for inversion of control.
  • No define constants, for testability. (One may use class constant, if it's really a constant.)
  • Use pluggable PSR-7 client, for testability, and extendability. (see PSR-7 and httpplug)
  • FixtureHttpClient implements \Http\Client\HttpClient is a way to handle fixture testing, it decouples fixture management from core code that usually resides in OmiseApiResource.
  • EnvarCredentialProvider implements \Omise\Credential\CredentialProvider is an example of various ways to configure pkey/skey secret, one may use static coded, Hashicorp's Vault, or even AWS's Parameter Store, Azure's KeyVault, this one reads from environment variable which works well on dev box.
  • OmiseClient is a facade to all Omise APIs and libraries.

Edit

  • Using static still have the same problem testing plugins that user wants to mock OmiseClient to test their plugin only.
  1. No static methods, no service locator, all hard wired.
use \Omise\Credential\EnvarCredentialProvider;
use \Omise\OmiseClient;
use \Omise\TestSupport\FixtureHttpClient;

class ChargeTest
{
    public function testListCharges()
    {
        $http_client = new FixtureHttpClient(__DIR__.'/../fixtures/');
        $credential_provider = new EnvarCredentialProvider('OMISE_PUBLIC_KEY', 'OMISE_SECRET_KEY');
        $omise_client = new OmiseClient($credential_provider, $http_client);

        $charge_list = $omise_client->listCharges();
        $this->assertInstanceOf('\Omise\Resorce\List', $charge_list);

        foreach ($charge_list->data() as $charge) {
            $this->assertInstanceOf('\Omise\Resource\Charge', $charge);
        }
    }
}

The idea:

  • No static methods, for testability.
  • No define constants, for testability. (One may use class constant, if it's really a constant.)
  • Use pluggable PSR-7 client, for testability, and extendability. (see PSR-7 and httpplug)
  • FixtureHttpClient implements \Http\Client\HttpClient is a way to handle fixture testing, it decouples fixture management from core code that usually resides in OmiseApiResource.
  • EnvarCredentialProvider implements \Omise\Credential\CredentialProvider is an example of various ways to configure pkey/skey secret, one may use static coded, Hashicorp's Vault, or even AWS's Parameter Store, Azure's KeyVault, this one reads from environment variable which works well on dev box.
  • OmiseClient is a facade to all Omise APIs and libraries.

One unanswered question: $charge['captured'] versus $charge->captured(), does dynamic array access still make sense?

iwat avatar Apr 03 '17 07:04 iwat

Hi, @omise-php

After trying to use 2.x branch in my personal project but have no luck (case of pure static implementation), i decided to create an alternative repo https://github.com/phpmob/omise that designed for SOLID use.

Hope to see SOLID package in 3.x branch. 👍

Feedback & PR welcome!

liverbool avatar Sep 15 '17 07:09 liverbool

@liverbool That is pretty interesting one! I'll definitely check!

guzzilar avatar Sep 15 '17 08:09 guzzilar

Since there hasn’t been any activity on this issue for a while, we’re going to close it. If you’re still experiencing this issue, please feel free to reopen it with more details and we’ll take another look.

aashishgurung avatar Mar 10 '23 08:03 aashishgurung