All streams
Search
Write a publication
Pull to refresh
95
0
Андрей Нестер @andrewnester

Software Engineer @ Amazon Web Services, AWSCloud9

Send message
да, Вы абсолютно правы — абсолютной расширяемости невозможно достичь, всё рассматривается в рамках определённой задачи и определённых требований.

По поводу второго пункта с Вами не согласен. Цитата из статьи Мартина «The Open-Closed Principle»:
1. They are “Open For Extension”.
This means that the behavior of the module can be extended. That we can make
the module behave in new and different ways as the requirements of the application
change, or to meet the needs of new applications.

2. They are “Closed for Modification”.
The source code of such a module is inviolate. No one is allowed to make source
code changes
to it.


Так что, как раз тут то, о чём я говорю — мы должны проектировать классы так, чтобы могли изменить их поведение, без изменения его исходного кода.
Использование же адаптера — это просто изменение интерфейса на более удобный, поведение в целом остаётся таким же.
функции вне класса использую довольно редко, в примере она использована просто для того, чтобы показать использование классов Square и Rectangle.

обычно использую просто функции в случаях
1) код написан с использованием парадигмы функционального программирования и не очень хорошо, мешать ООП с ФП. часто это задачи связаны с реализацией какого-нибудь алгоритма.
2) при написании относительных небольших скриптов для командной строки, где разного рода абстрагирования и иерархии — лишнее
3) когда-то при написании плагинов для Wordpress (при написании более-менее больших плагинов всё-таки переходил к ООП)
4) часто использую анонимные функции в качестве callback-функций

по поводу поля config.
если продолжать в рамках исходного примера, я бы сделал что-нибудь такое
// точка входа - index.php

//...


$config = new Config('path/to/conf');

$app = new Application($config);
$app->run();


// example controller

class ExampleController extends BaseController
{
	//...

	public function saveAction()
	{
		$config = $this->getApplication()->getConfig();
		$respository = $config->getServices()->getRepositoryManager()->getRepository('Order');
			
		//...
	}
}

// если хотим изменить источник, можно написать что-нибудь такое

public function saveAction()
{
	$config = $this->getApplication()->getConfig();
	$respository = $config->getServices()->getRepositoryManager()->getRepository('Order');
	$repository->setSource(new ApiOrderSource($config->getSources()->getApi()));

	//...
}


// сам файл конфигурации может выглядеть как-нибудь так

//...
{
	'services' : {
		'RepositoryManager' : {
			'class' => 'RepositoryManager',
			'options' => {
				//...
			}
		},
		//...
	},
	'sources' : {
		'MySQL' : {
			'host' => 'host'
			'username' => 'name',
			'password' => 'password',
			'dbname' => 'dbname'
		},
		'API' : {
			'getaway' => 'http://apipath.com/api',
			'oauth_key' => '',
		}
	}  
}
//...
в рамках примера — наследования и полиморфизма не осталось, потому что с точки зрения поведения Square не является Rectangle, а связь IS-A как раз имеет прямое отношение к поведению объектов — поэтому в данном конкретном случае решение — избавление от наследования и связи двух этих классов.
На мой взгляд, в принципах SOLID нет каких-то лишних и не нужных абстракций (если я где-то привёл в примерах что-то лишнее, что можно было бы сделать проще, то пишите, мне на самом деле всегда интересно знать другие решения)

Я же как разработчик прекрасно понимаю, что лишняя абстракция — это лишний шаг другого разработчика, который читает мой код, на пути понимания то, что я написал. И именно поэтому я немного скептически отношусь к паттернам проектирования и совсем скептически к использованию паттернов ради паттернов.
я конечно извиняюсь, но — каким образом Ваш пример отражает принцип Лисков? Возможно, Вы не привели его до конца или что-то не досказали?
возможно, моя сумбурность в объяснении связана с тем, что у меня более математический склад ума, а сам по себе принцип Лисков более математичен, поэтому приведу его математическое описание из статьи Лисков:
Пусть q(x) является свойством, верным относительно объектов x некоторого типа T. Тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом типа T


Так вот, где в Вашем пример подтип для processOpeartion? В контексте одного класса нельзя говорить о принципе Лисков.

Возвращаясь к приведённому мною в статье примеру (к слову, в приведённой Вами книги как раз описан такой же пример с квадратом и прямоугольником)

Предположим, разработчик знает о наличии классов Square и Rectangle, что они связаны в иерархию и меют методы для получения/установки высоты/ширины.

И наш программист создаёт следующий метод, который вполне логичен:

function myRectangle(Rectangle $rectangle)
{
    $rectangle->setWidth(4);
    $rectangle->setHeight(5);
    return $rectangle->getHeight * $rectangle->getWidth == 20;
}


И выполняет этот метод дважды следующим образом
myRectangle(new Rectangle()) // true;
myRectangle(new Square()) // false;


И теперь возвращаемся к принципу Лисков:
тип Т — класс Rectangle
подтип S — класс Square
свойство q — произведение width и height равно 20

но мы получаем, что для подтипа S (класса Square) свойство q не верно.
цитирую, что написано в Вашей книге
Пример с функцией показывает, что могут существовать функции, которые работают с указателями или ссылками на объекты Rectangle, но не могут оперировать с объектами Square. Таким образом, при использовании таких функций объект Square не является заменяемым для Rectangle, взаимосвязь между такими объектами нарушает принцип подстановки Лискоу


Надеюсь, сейчас пояснил чуть яснее.

Кроме того, это всё можно выразить в терминах контрактного программирования — пост и предусловия, инварианты.

И кроме того, чуть дальше в Вашей книге в этом разделе есть подтема «Неправильное поведение объекта», это как раз то, о чём я сумбурно рассказал, приводить данный раздел целиком не буду (страница 193 — «Неправильное поведение объекта»)
c LSP, на мой взгляд, ситуация следующая (хотя и со всеми принципами так, да и не только в программировании) — мы не столько что-то получаем, соблюдая принцип, а что-то теряем и получаем негативный эффект, когда не соблюли его. В случае с несоблюдением LSP мы получаем изменчивость в поведении там, где мы её не ждали.

Если можно, бытовой пример — к примеру, Вы чистите зубы по утрам каждый день и Ваши зубы здоровы. Но если бы Вы не чистили зубы, у Вас мог образоваться кариес, т.е. не соблюдение какого-то принципа приводит к негативному эффекту. Хотя можно на это посмотреть и с другой стороны, что соблюдение принципа поддерживает Ваши зубы в здоровом состоянии. Но тогда можно сказать, что профит от LSP — поддержание кода в «здоровом» состоянии :)
а изображение-то совсем не плоское)
(если что я о «филейной части Дженифер»)
извиняюсь, это всё опечатки, как мог вычитывал, но глаза замылились совсем, спасибо, что замечаете их.
… создать интерфейc IOrderSource, который будет реализовывать соответствующими класса MySQLOrderSource, ApiOrderSource и так далее...

должно быть
… создать интерфейc IOrderSource, который будет реализовываться соответствующими классами MySQLOrderSource, ApiOrderSource и так далее...
действительно интересный способ)
спасибо, что заметили, уже исправляю
спасибо, поправлю.
первый вариант предпочтительнее, я думаю, поскольку лаконичнее и тем не менее понятнее. да и вроде как Мартин Фаулер в «Чистый код» советовал писать как в первом вариант
а как насчет такого варианта — вместо работы по совместительству заняться реализацией своих идей? например, ведение своего блога или создание мобильного приложения. все плюсы работы по совместительству в виде отвлечения от постоянных задач, изучения новых технологий и тд сохраняется, но и кроме того Вы создаете что-то свое, что само по себе приятно.
а монетезировать я думаю можно любую идею, если уделять ей внимание и силы
по правде говоря на этот вопрос однозначно может ответить только сам автор, но от себя предположу следующее:
1) автор решил не запутывать пользователей, только знакомящихся с Silex и решил использовать всем привычный json_encode (хотя конечно лучше бы было приучивать сразу к написанию в едином стиле)
2) автор по-просту в спешке забыл о существовании $app->json

я же как переводчик решил оставить код как есть, но спасибо за замечание
спасибо за замечание
подправил и добавил ссылку на хабропост о Silex
как же Вы исходники тогда читаете?
а чем именно Вас не устраивает Doctrine 2?

и как я писал в заключении
Был бы очень признателен, если бы в комментариях Вы поделились своими вариантами решения по внедрению паттерна DataMapper, каких-то других ORM в Yii, о своих способах решения разрастания бизнес логики в моделях ActiveRecord в Yii, о предметно-ориентированном программировании с использовании Yii


как бы Вы решили такую проблему?
спасибо за мнение
за отсебятину извиняюсь, буду исправляться

вообще оригинальный пост был взят из последнего дайджеста по PHP и переведен для того, чтобы человек, ищущий информацию по запросу «REST PHP» и не знающий какой фреймворк ему лучше использовать, увидел статью, увидел кратенький пример как работать с HTTP маршрутами

а много дополнительной полезной информации как часто это бывает, он бы уже узнал из комментариев к посту :)
вот как раз в случаях большого роста сложности REST-приложения со временем, как мне кажется, Silex себя показывает с хорошей стороны, поскольку он построен на базе Symfony и может легко использовать все компоненты Symfony, ту же доктрину и тд. И в итоге можно из него будет собрать мощный фреймворк
гляди, так скоро дойдет и до того, что такие штрафы будут давать за упоминание названий сайтов, на которых показывают фильмы, размещенные на сторонних серверах
12 ...
12

Information

Rating
Does not participate
Location
Amsterdam, Noord-Holland, Нидерланды
Date of birth
Registered
Activity