Лучшая книга о программировании

Не смог удержаться чтобы не завинрарить:

765abdd7b6644d3580ce032de4be4272

Увидел в качестве иллюстрации к этой статье на хабре.

Рубрика: Побочное | Метки: , , | Оставить комментарий

Спаммер 80-левела

И так, переходящий титул “лучший” сео-специалист месяца в апреле 2016 достаётся горемычным осваивателям бюджета на раскрутку магазина looks4you.

irina-looks4you-advansed-spamer

Текст для комментариев, похоже что позаимствован на хабре. Вот такой высокоинтеллектуальный спамер. Хорошая попытка, сеошнег, но нет, в этот раз только титул, никаких ссылок. Спасибо Akismet.

Рубрика: Сайт месяца | Метки: , , , | Оставить комментарий

Смена shared-хостинга на VDS

Последние пару дней samizdam.net был недоступен. Никакого оправдания кроме лени у меня нет — надо было вовремя оплатить хостинг =)

Кстати, в конце прошлого кода, timeweb стал сообщать о превышении сайтами на моём аккаунте допустимой для shared-хостинга нагрузки. Пришлось искать альтернативу. После недолгих раздумий, я воспользовался советом коллеги и промо-акцией приуроченной к т.н. «чёрной пятнице» и заказал vds на ihor.ru. Самый простой вариант с 20 GB SSD, 1 CPU и 1 GB RAM, стоимостью 250 руб. в месяц. В течении недели настроил веб-сервер под Debian, перетащил сей бложег и другие pet-проектики. Аккаунт в timeweb я оставил в качестве единого места для оплаты доменов и конфигурации их DNS и почты, переведя на почтовый тариф, так удобней.

Будучи клиентом timeweb более семи лет, я по прежнему могу его смело рекомендовать в качестве недорого, стабильного и удобного shared-хостига. Хорошая техподдержка, дешёвые домены, ssh, git и всё такое. Так что — рекомендую!.

За несколько месяцев с Айхор, я не испытывал проблем с аптаймом, нужно больше времени чтобы объективно оценивать vds. В тех. поддержку обращаться не доводилось — когда есть root доступ к собственному виртуальному серверу — какие могут быть проблемы =) В этом смысле — я доволен тем, что наконец-то решился на переезд. Вот настрою автоматические бэкапы в какое-нибудь облако — и стану доволен совсем =)

И напоследок: если вам прямо сейчас или в ближайшее время нужен недорогой VDS, то до конца апреля у Айхора действует первоапрельский промо-код 1APRIL: скидка 25% при покупке VDS на тарифах OVZ SSD.

Рубрика: Хостинг | Метки: , , , , | 2 комментария

Современные тили (от 23 марта 2013)

Этой запись сегодня исполнилось бы 3 года!


Помните у Дюма в «Двух Дианах» персонажа Мартена Герра, и его коварного двойника Арно дю Тиля? Сегодня в аналогичную ситуацию попала служба поддержки timeweb.ru. Не без участия почтового сервиса mail.ru.
Письмо с предупреждением об очередной фишинг-акции злодеев выдающих себя за саппорт крупного хостинг-провайдера упало мне сегодня в inbox. А письмо с предупреждением о массовой фейк-рассылке лежит со вчерашнего дня в папке «спам», куда его определил робот mail’а. Оба письма подписаны именем одного и того же сотрудника, письмо новоявленного «Тиля» полностью соответствует шаблону, который включен в письмо с предупреждением от поддержки.

Рубрика: Побочное | Метки: , , , , | Оставить комментарий

SeekableIterator — на примере реализации коллекции объектов

А вот ещё одна статья, написанная больше года назад, и пролежавшая всё это время в черновиках. В тот период я в качестве упражнений в TDD- и DDD- методологиях писал некий сферических фреймворк в вакууме для работы с генеалогическими деревьями, что-то в этом роде. По мере использования разных хороших ООП практик был написан ряд статей с примерами их использования в коде этого проекта. Конечно сейчас я не очень доволен тем что код не соответствует PSR, но в целом он достаточно годен для просветительских целей.


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

Немного теории. На самом деле массив — это одна из реализаций абстрактного типа данных коллекция.

Теперь к делу. Использование отдельного объекта коллекции для хранения набора объектов вместо привычного массива, даёт ряд преимуществ. Например:

  • Контроль типа хранимых объектов
  • Добавление в интерфейс коллекции методов для удобства работы с хранимыми объектами
  • Реализация своего итератора для перебора данных и доступа к данным

В phamily framework для хранения детей персоны, был спроектирован специальный интерфейс:



Исходник на bitbucket.

Данный интерфейс расширяет SeekableIterator и Countable из SPL, пока парой методов:

  1. add() — для добавления объекта ребенка к коллекции.
  2. contains() — для проверки, чтобы избежать повторного добавления ребенка

Реализация SeekableIterator позволяет производить перебор с переходом к определенному элементу. Для этого метод seek() происходит установка курсора в переданное значение. Как и все итераторы, этот наследует тип Traversable, а значит класс ChildrenCollection может быть использован внутри цикла foreach().

Вот сама реализация, class ChildrenCollection:


parent = $parent;
	}
	
	/*
	 * ChildrenCollectionInterface implemantation
	 */
	
	public function add(PersonaInterface $child){
		if($this->contains($child)){
			throw new LogicException("Persona already has this child");
		}
		if($this->parent === $child){
			throw new LogicException("Persona can't be parent for self");
		}
		$this->children[] = $child;
	}
	
	public function contains(PersonaInterface $child){
		return in_array($child, $this->children, true);
	}
	
	/*
	 * SPL Countable implementation
	 */
	
	public function count(){
		return count($this->children);
	}	
	
	/*
	 * SPL SeekableIterator implementation
	 */
	
	protected $position = 0;
	
	public function seek ($position) {
		if($position >= $this->count()){
			throw new OutOfBoundsException("Persona has only {$this->count()} children");
		}
		$this->position = $position;
	}
	
	public function current () {
		return $this->children[$this->position];
	}
	
	public function next () {
		++$this->position; 
	}
	
	public function key () {
		return $this->position;
	}
	
	public function valid () {
		return $this->position < $this->count();
	}
	
	public function rewind () {
		$this->position = 0;
	}
}

Исходник на bitbucket.

А вот пример как данный класс тестируется (coverage: 100%):


createPersonaStub();
		$collection = new ChildrenCollection($parent);
		
		$childA = $this->createPersonaStub();
		$childB = $this->createPersonaStub();
		
		$collection->add($childA);
		$collection->add($childB);
		
		$this->assertEquals(2, $collection->count());
	}
	
	public function testDoubleChildAddException(){
		$parent = $this->createPersonaStub();
		$collection = new ChildrenCollection($parent);
		
		$childA = $this->createPersonaStub();
		
		$collection->add($childA);
		$this->setExpectedException(self::EXCEPTION_BASE_NS . 'LogicException');
		$collection->add($childA);
	}
	
	public function testSeekSuccess(){
		$parent = $this->createPersonaStub();
		$collection = new ChildrenCollection($parent);
		
		$childA = $this->createPersonaStub();
		$childB = $this->createPersonaStub();
		$collection->add($childA);
		$collection->add($childB);
		
		$collection->seek(1);
		$this->assertEquals(1, $collection->key());
		$this->assertEquals($childB, $collection->current());
		
		$collection->rewind();
		$this->assertEquals(0, $collection->key());
		$this->assertEquals($childA, $collection->current());
	} 
	
	public function testSeekException(){
		$parent = $this->createPersonaStub();
		$collection = new ChildrenCollection($parent);
		
		$child = $this->createPersonaStub();
		$collection->add($child);
		
		$this->setExpectedException(self::EXCEPTION_BASE_NS . 'OutOfBoundsException');
		$collection->seek(5);
	}
	
	public function testParentSelfChildException(){
		$parent = $this->createPersonaStub();
		$collection = new ChildrenCollection($parent);
		
		$this->setExpectedException(self::EXCEPTION_BASE_NS . 'LogicException');
		$collection->add($parent);
	}
}

Исходник на bitbucket.

Дискуссионный момент. К ChildrenCollectionInterface я планирую добавить ещё несколько методов, и немного изменить реализацию.

  1. Позиция ребёнка должна устанавливаться в зависимости от его возраста: старшие будут помещаться в начало коллекции.
  2. Проверки, приводящие к исключениям, стоит перенести в классы соответствующих валидаторов.
  3. Стоит подумать над методом для удаления ребёнка из коллекции.
  4. Стоит проверять на корректность тип аргумента seek() и выбрасывать InvalidArgumentException для не числовых значений.
  5. Сейчас в конструкторе принимается родитель детей. Этот объект используется только для проверки, исключающей цикличное добавление себя в качестве собственного ребёнка, но стоит подумать, не перенести ли и некоторую другую логику связанную с детодобавлением из Persona в ChildrenCollection?
Рубрика: PHP, Статьи-заметки | Метки: , , , , | Оставить комментарий