in Back to PHP

My Way to PHP: Day 10 of 75

The tenth day. I’m still reading through PHP Internals Book and I’m at the start of the last chapter which is about the OOP system. I want to finish that today. And afterwards I’m going to start reading a book about Unit testing. My goal is  to get to page 25. I think that’s about right.


Great, let’s get back to the book. Objects are saved in the zend_object_value:

typedef struct _zend_object_value {
    zend_object_handle handle;
    const zend_object_handlers *handlers;
} zend_object_value;

This consists of a handle which is an individual ID and a list of handlers which define the actual behavior of the object.

Here’s the “standard” object structure zend_object:

typedef struct _zend_object {
    zend_class_entry *ce;
    HashTable *properties;
    zval **properties_table;
    HashTable *guards; /* protects from __get/__set ... recursion */
} zend_object;

You can see that there are two tables: properties and properties_table. The latter is for dynamic objects whereas the former is for declared ones.

This is so because using a hash table has a big overhead around 100 bytes per entry!

Then there’s guards. These are for magic calls and guard them against recursing.


Next book: PHPUnit Essentials.

The more complex the code, the bigger the chance it will break (CRAP = Change Risk Analysis and Predictions).

Great name!

The first chapter was just about installing PHPUnit and Xdebug. The following chapter is about PHPUnit and IDE integration.

Most used assertions:

  • assertTrue() and assertFalse()
  • assertEquals() and assertSame()
  • assertNull() and assertEmpty()

  • Try to test all branches!

  • Test only public methods – everything else can change but the public output shouldn’t change

This talk is called Building Testable PHP Applications:

Principles:

  • Single purpose
  • Decoupled
  • Consistent architecture

One note was especially interesting:

The more complex your objects, the way more test you have to write.

He said that related to NPath complexity. And it’s interesting. Take for example polymorphism. You could write that with a trigger in each method you want to call.

However, suddenly each function would be twice as complex (you have to test each trigger).

When using polymorphism your code suddenly gets half as complex because you enclosed that complexity and gave it to the language. So it’s no longer your problem.

At run-time however, it basically has the same complexity but the code is reduce.


He talked about onion architecture

Here’s a quote from the article:

organize the layers of your application code like the layers of an onion. Every layer of the onion is only coupled (or dependent upon) any layer deeper in the onion than itself.

I wonder if it’s just the Interface segregation principle applied.


Hoare’s Law of Large Programs:

Inside every large program is a small program struggling to get out.


Your framework should be an implementation detail, not a giant killer squid, sucking the life out your application.

UNIX philosophy again. Keep as much stuff away as you can from the framework.


Your app shouldn’t care where it runs

No flags in code between production and developing. Rather .ini or similar files.


Drupal has come back to the fold, time to pay attention aka Tech is not a zero-sum game

  • There’s a lot of popular low art
  • Same in tech

It’s funny how all the successful things seems to be the things to be critiqued

but

Familiarity dispels fears

Interesting. A lot of people said that Drupal has a bad architecture but in 2000 – when it started (around PHP 4.0) it was pretty good.

It’s interesting how isolated the Drupal community was in the past. While the PHP moved forward they seem to have developed their own stuff – just like a tribe without contact to the rest of the civilization.


Back to the book! PHPUnit annotations to test exceptions:

/**
  * @expectedException FooException
  */

Test fixtures / test context: set ups and tear downs. There is also setUpBeforeClass() which persists over individual tests.

Globals backup You can use @backupGlobals disabled when working with legacy code to enable mutable globals in your tests.

Data providers You can write a function providerFOO() which returns an iterator of arrays which are then used as input to a method annotating @dataProvider providerFOO. PHPUnit then tests with all the data provided by the data provider!

phpunit.xml You can configure your runs, create suites and groups. E.g. you can only run your unit tests and only run unit tests in the staging area.


Test doubles

  • Dummy: empty shell and not used
  • Fake: imitates real object but only for tests
  • Stub: predefined values for a method call
  • Spy: Remembers returned values which can be verified later
  • Mock: Stub with expectations (when and how will it be called)

The main functions in PHPUnit are getMock() which takes parameters and getMockBuilder() which can be chained.

Here’s an example of a mock:

$mockCalculator = $this->getMock('MyCalculator');

$mockCalculator->expects($this->any())
    ->method('getZero')
    ->will($this->returnValue(0));

$this->assertEquals(0, $mockCalculator->getZero());

Building Better Developers

Cool talk that points together a lot of ideas. I heard most of them before but nonetheless a good refresher.

After my experience in the last year or so I think that the psyche of the person is a lot more important than the industry wants to believe.


Back to the book. Chapter 9: Database Testing.

The conclusion is that when you write tests, try to make your development environment as close as possible to the production system.

And also in my opinion apply the Dependency inversion principle as much as possible. It makes testing so much easier. Abstract every IO and you’re a lot better of.


Good to know: You can directly mock PDO but you can if you inherit from it and replace the constructor with an empty one.

Then, there’s also DBUnit which is specialized for testing the connection to the DB.

Also a clever idea. If you use a ORM like Doctrine you could use SQLite as your testing tool quite easily.


Testing legacy code You can start off with black-box testing!

There are several examples using the Reflection API, Patchwork, vfsStream and runkit. However, I’m going to read an other book which is more specialized on handling legacy code. So I rather let me influence more by that.

There’s also a chapter about: Selenium, CI and Behat. I skimmed those.

All in all a pretty good book. I’m surprised that there isn’t that much more to the basics of writing tests than I thought. That makes me feel pretty good.


The Power of Abstraction by Barbara Liskov

Highly interesting talk. It’s a small part of history about data abstraction in CS. Really insightful!

I remember that time. It had never rained.

Surprising, this is the first person I’ve heard that also described memories in a sense of weather. I do the same. There are times which I remember as bright or dark and I mean literally bright. No clouds, no rain, no storms.


Ok, enough for today! I spent the last hour refactoring my soundboard. The code is now a lot cleaner. I like it!


Updates Goals:

  • Learn the intricacies: how does the interpreter work, the OOP system, etc.
  • Learn about PHPUnit
  • Learn a bit more about MySQL
  • Learn a bit more about legacy systems and how to handle them
  • Learn Symfony2
  • Write at least one web app using Symfony2 and its core components (templating, testing, forms, validation, security, caching, i18n)
  • Get a bit more exposure to OOP and OOD
  • Watch one video per day on average

Progress status

Done

  • Learn the intricacies: how does the interpreter work, the OOP system, etc.
  • Learn about PHPUnit
  • Reading PHP Internals Book [done]
  • Reading PHPUnit Essentials [done]

In Progress

  • Watch one video per day on average [25 of 75]

Write a Comment

Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.