class Payment {
pub func charge(amount int) void {
if (this.holdAmount < amount && this.initAmount < amount) {
throw new PaymentException('Unavailable charge amount')
}
if (this.status === PaymentStatus:finish) {
throw new PaymentException('Payment already fisnished')
}
this.chargeAmount = amount
this.holdAmount -= amount
this.status = PaymentStatus:finish
}
}
<?php
class Node{
private $arr = [];
public function getChildren($node)
{
if (!empty($node->data)){
array_push($this->arr, $node->data);
}
if (!empty($node->left)){
$this->getChildren($node->left);
}
if (!empty($node->right)){
$this->getChildren($node->right);
}
return $this->arr;
}
}
$node = createNode(
6 . '_base',
createNode(7 . '_right'),
createNode(8 . '_left',
createNode(81 . '_left'),
createNode(82 . '_right',
createNode(821 . '_right',
null,
createNode(824 . '_left')
)
)
)
);
function createNode($data, $right = null, $left = null) {
$obj = new stdClass();
$obj->data = $data;
$obj->right = $right;
$obj->left = $left;
return $obj;
}
var_dump((new Node)->getChildren($node));
// [
// "6_base"
// "8_left"
// "82_right"
// "821_right"
// "824_left"
// "81_left"
// "7_right"
// ]
а? Если нет и нужно все равно писать абсолютно всю логику в обьекте модели, то тогда он станет просто god обьектом на 100500 строчек
final class HandleCheckOutShoppingCart
{
public function __construct(Carts $carts, PaymentGateway $gateway)
{
$this->carts = $carts;
$this->gateway = $gateway;
}
public function __invoke(CheckOutShoppingCart $command) : void
{
$shoppingCart = $this->carts->get($command->shoppingCart());
$payment = $this->gateway->captureCharge($command->charge());
$shoppingCart->checkOut($payment);
}
}
где фичи для приложения выносятся в отдельные модули
как разбить приложение на переиспользуемые модули-фичи
<?php
$catalog = new stdClass();
$catalog->product = new stdClass();
$catalog->product->item = 'Short';
$catalog->product->model = 'Adidas';
$catalogPaths = ['product.item', 'product.model'];
function extractValuesByPath(object $obj, array $paths) {
return array_reduce($paths, function(array $values, string $pattern) use($obj) {
$values[] = extractPathValue($obj, $pattern);
return $values;
}, []);
}
function extractPathValue($obj, $pattern) {
$paths = explode('.', $pattern);
foreach($paths as $path) {
if (!property_exists($obj, $path)) {
// Можно нулл вернуть или к пример `undefined $path`
throw new InvalidArgumentException('Нет такого свойства во входящих данных!');
}
$obj = $obj->$path;
}
return $obj;
}
$res = extractValuesByPath($catalog, $catalogPaths);
var_dump($res);
// [
// 'Short',
// 'Adidas',
// ]
создавать отдельный метод getProductList, в котором будет инициализирован класс
class Order
{
private ProductStorageInterface $products;
public function __construct(ProductStorageInterface $products)
{
$this->products = $products;
}
public function refundProduct(Product $product): void
{
// логика возврата товара
// и соответственно изменение состава $this->products
}
}
getProductList()
, это ужасно! Называйте как есть: createProductList()
или loadProductList()
, ну в зависимости от логики.class Observer(ABC):
@abstractmethod
def update(self, subject: Subject) -> None:
"""
Получить обновление от субъекта.
"""
pass
class Hello(object):
def __init__(self):
self.msg = 'Hello'
def hello(self, world):
self.msg = self.msg + ', ' + world
return self
def print(self):
return self.msg
caller = Hello()
msg = caller.hello('niriter').print()
print(msg) # Hello, niriter
class Hello(object):
def __init__(self, msg='Friend'):
self.msg = msg
def print(self):
init_msg = self.hello()
return init_msg + ', ' + self.msg
def hello(self): # этот метод вызываем изнутри другого метода
return str("Hello")
caller1 = Hello()
print(caller1.print()) # Hello, Friend
caller2 = Hello('Maks')
print(caller2.print()) # Hello, Maks
И в будущем удобно будет тестировать ?
interface SenderInterface
{
public function send(): void {};
}
class Order
{
// тут будет любой, но обязан реализовать SenderInterface
private $sender;
public function __constuctor(SenderInterface $sender) {
$this->sender = $sender;
}
public function save(): void
{
// какой в приватном поле сидит, тот и отправит,
// а кто -- текущему объекту все равно, это есть инверсия зависимости
// и принцип единственной ответственности, данный класс не отправляет, а поручает
$this->sender->send();
}
}
class MailSender implement SenderInterface
{
public function send(): void
{
// тут отправка почтой
}
}
class TelegramSender implement SenderInterface
{
public function send(): void
{
// тут отправка телегой
}
}
// Пример полиморфной работы Order
$order = new Order(new TelegramSender());
$order->save(); // тут отправка телеграмом
$order = new Order(new MailSender());
$order->save(); // тут отправка mail
$order->save()
, и вообще его код не трогатьНе складывается все пока в единую структуру
Во внешнем сервисе есть авторизация, добавление/изменение n-го количества сущностей (пользователь, заказ и т.д.). Основная задача паттерна, обойтись малой кровью при замене одного внешнего сервиса на другой, когда потребуется ее заменить. Или возможность переключаться между несколькими внешними системами.
// Принимает ваши учетные данные
DeliveryClientInterface::__construct(?string $account = null, ?string $password = null)
// Регистрируем покупателя в сервисе
DeliveryClientInterface::registerCustomer(DeliveryCustomer $customer): int
// Получаем заказы покупателя в сервисе
DeliveryClientInterface::getOrders(int $customerId): DeliveryOrder
// Добавляем заказ покупателю
DeliveryClientInterface::addOrder(int $customerId, DeliveryOrder $order): int
// Оповещение покупателя в сервисе о неком действии, связанной с ним в этом сервисе
DeliveryClientInterface::notifyCustomer(DeliveryEvent $event): bool
// что в конструктор сервиса запихнете, например PochtaClient или PickPointClient,
// с тем и будете работать
class DeliveryService
{
public function __construct(DeliveryClientInterface $deliveryClient, User $user)
}
$userOrders = $this->deliveryService->getOrders($user->getUuid());