Friday, 23 May 2014

PHP TDD Shopping Cart from scratch.

So, I've finally taken the plunge again and started seriously looking into refreshing my dusty old brain cells about TDD and unit testing.

Over the past few weeks I have been re-reading various books, reading articles and watching video-casts by some of the leading names surrounding Testing, TDD, Design patterns and tackling legacy code, and the inspiration has finally got to me that I just need to tackle this head on.  Consuming a wealth of information about greenfield and brownfield systems and how to tackle them.

I have also revisited daily coding Kata's, taking 15mins in the morning or evening to tackle a simple Kata to get my brain in "test first" mode.

The array of books and information I have consumed has been immense and I'll probably re-read and watch everything again, and get a different perspective on things, although I guess the main way to learn is by doing, which is why I raked through the archives (then ended up password resetting) my github account to allow me to post updates to here with my personal coding ventures.  I have only hooked up tonight's work, but I do hope to get a few of my Kata's in there for people who haven't seen them before, as well as links to where you can find these for practicing yourself.

Tonight's project has been getting the basis of a shopping cart system up and running TDD style. So you'll see at my github account, I've literally written 3 tests and a few lines or production code.  There is quite a way to go, but I do hope to take time and regularly update and work on this as a reference for anyone who wants to follow along or help out.


Well enough typing for tonight, here are a quick list of links to some resources I've been consuming the past while.

Github - https://github.com/williamcameron/tdd-cart
Art of Unit Testing - http://artofunittesting.com/ and http://www.amazon.co.uk/Art-Unit-Testing-examples/dp/1617290890/
Various Roy Osherove talks and videos on youtube.
Working Effectively With Legacy Code - http://www.amazon.co.uk/Working-Effectively-Legacy-Robert-Martin/dp/0131177052
Refactoting Existing Code - http://www.amazon.co.uk/Refactoring-Improving-Design-Existing-Technology/dp/0201485672/

Wednesday, 7 May 2014

Why you should never extend the interface

Hello, there
What's wrong with this code sample?

<?php
    class MyClass {
        public function myFunction() {
        }
    }
    
    class myOtherClass extends MyClass {
        public function MyOtherFunction() {
        }
    }
   
    class Controller {
        public function doSomething(MyClass $object) {
            $object->MyOtherFunction();
        }
    }



On first blush, it might seem that this is ordinary inheritance, and we're doing everything we should be doing. But there's something very wrong here.

The problem here is that we're extending the interface. Extending the interface itself isn't necessarily bad, but we're making a second mistake: we're then typehinting on the wrong object type.

Let's talk about why we want to avoid this practice.

The Liskov Substitution Principle
I've discussed the Liskov Substitution Principle a few times through this newsletter. But let's go over it again.

The Liskov Substitution Principle says that one object should be replacable with another object of the same type, without breaking the program.

In other words, all objects of type A should replace one another, and the application should work just fine.

But our code sample above has a big problem: we're typehinting on one object type (MyClass) but we're relying on the interface of a different object type: myOtherClass. This means that if we actually pass in an instance of MyClass, our application will break.

Let's fix it.
So, now that we know what the problem is, how do we fix it? There are three different possible solutions.

1. Treat as abstract. First, we can treat MyClass as an abstract class, and mark it abstract. We can then include the abstract method definition, but not the code. This fixes our typehint.


<?php
    abstract class MyClass {
        public function myFunction() {
        }
    
        abstract public function MyOtherFunction();
    }



Once we've done this, our typehint is accurate and we don't have to worry about the method we want not existing, because the abstract definition guarantees it.

2. Change the typehint for the object being used. Instead of fixing the base class, we can fix the typehint and typehint on the actual object type we want. This solves the problem by ensuring that we are telling the application precisely what to expect.

<?php
    class Controller {
        public function doSomething(MyOtherClass $object) {
            $object->MyOtherFunction();
        }
    }


Of course, we are now hinting on a specific object, instead of an interface. But this is still better than relying on an interface that may or may not exist in future.

3. Define different interfaces, and hint on the one we want. It's possible in PHP to define two interfaces, and implement both of them in the same object. For example:


<?php

interface MyClass {
  public function myFunction(); }
  
  interface myOtherClass extends MyClass {
    public function MyOtherFunction();
  }


With these two interfaces, we can typehint on the interface we want, but leave the implementation details up to the future object that's going to be created. We're still guaranteed a particular interface, and this makes it easy to follow the Liskov Substitution Principle.

Objects know one another by their interface.
Regardless of the solution you might choose, there's one rule that you have to remember and understand: objects know each other by their interfaces.

The public methods form the "interface" or "API" that other objects use to communicate with a given object. Outside objects know nothing of the internal protected and private methods an object has; they can't use them. So, an object's interface is the only way to describe it to the outside world.

This interface therefore define's an objects type. In PHP, interfaces can't define anything besides public methods, and this is by design: when we typehint, we're saying "give me an object that has these methods."

Thursday, 24 April 2014

Upgrading from Sagepay protocol 2.23 to Sagepay protocol 3.00

I have recently been involved in upgrading a sagepay integration on an ecommerce site from Sagepay Protocol v2.23 to Sagepay Protocol v3.00.

Once this has been actioned, I am to update this blog as a point of reference for anyone else working on a similar update.


Saturday, 22 February 2014

LinkedIn offer ability to block 'friends'

LinkedIn on Friday announced a new feature that members have been requesting for quite some time: the ability to block other members. It’s a feature that will no doubt be incredibly useful, especially on a social network where many can be relentless in their pursuit of making a professional connection.

In a post on the matter, Paul Rockwell, LinkedIn’s head of Trust & Safety, said they built the feature not only because it was requested but simply because it’s the right thing to do. The feature is being made active as of today to all members, Rockwell noted.

To enable member blocking, simply head over to your LinkedIn profile and navigate to the profile of the person you wish to block. Select “Block or report” in the drop-down menu located next to the Connect and Send InMail buttons.

Pro tip – if you want to avoid an awkward moment, enable anonymous profile viewing before doing so. That way, you can visit and block the person’s profile without them knowing about it.

Once blocked, neither you nor the person you blocked will be able to view each other’s profile. In the event that you are already connected with said person, that connection will automatically be severed. What’s more, you will no longer be able to communication with said person (not that you’d want to anyway) and all recommendations and endorsements will be removed.

PHP refactoring in legacy code

http://www.tomslabs.com/index.php/2012/01/php-refactoring-in-legacy-code/

The story we’ll talk about is a true story. It happened to be challenging and helped the team keep testing its beliefs in XP, iterative developments and code quality.

Product elevator statement

Imagine a well legac”ied” project you don’t know.
  • Product is a web forum with millions of messages.
  • We want to rebuild the categorization mechanism (messages are “categorized” meaning they are assigned to a category that best describes their content).
  • Mission : fix all bugs
  • “Short delay” and “no regression” are the words.
  • Only few people share the knowledge of the categories system to be refactored.
  • Numerous bugs (useless to mention that several generations of developers brought contributions to the project).
  • 20 commiters.
Background
From the team’s point of view, here are the goals we anticipated we needed to achieve:
  • Understand the expected behavior of the categorization mechanism
  • Bring no regression to the actual behavior
  • Replace the old mechanism by a new one
First decision we took was to use Git to work on that project. We won’t explain in details that choice (20 commiters, we wanted to avoid working in a dedicated branch for weeks and commit in the HEAD trunk of the project…). It has already been discussed here.

Refactoring strategy

As a Team, we decided to do the refactoring as follow:
  1. With the Product Owner, write BDD scenarii describing how the categories mechanism works
  2. Switch on the “Test Harness” by automating (implementing) the BDD scenarii
  3. Encapsulate ALL calls to the old categories mechanism behind an API (adding Unit Tests to that new API aswell)
  4. Based on the API contract, build the new mechanism relying on a new categories data model

1. Write BDD scenarii to describe the categorization behavior

First two weeks were spent “extracting” all the possible knowledge from the Product Owner about the product and translate it into BDD scenarii.
Example:

Given I am a visitor
When I go to url "http://www.infos-du-net.com.sf/forum/"
Then below the meta-category "Multimédia", I have the following sub-categories with content
| cat name                 | decrypted url                                      |
| Image et son             | http://www.infos-du-net.com.sf/forum/forum-20.html |
| Appareils photo, cameras | http://www.infos-du-net.com.sf/forum/forum-47.html |
| Consoles                 | http://www.infos-du-net.com.sf/forum/forum-29.html |
At the end of this step:
  • 100 BDD scenarii written
  • Shared knowledge of the expected application behavior

2. Switch on the “Test Harness”

We used Behat (PHP based) to implement the scenarii.
Some of the scenarii written with the Product Owner describe a behavior involving integration with third-party systems. They were not implemented because such tests, seen as “integration tests”, were seen as complicated and hard to maintain. We preferred to invest on Unit Tests by Contract (as well explained byJBrains).
Some scenarii were implemented but not automated because describing a behavior that highlights a bugor describing the future behavior. They got RED at the time of the implementation and would go GREEN by the end of the project.
At the end of this step:
  • The “Test Harness” is switched on !
  • Thanks to the Continuous Integration Platform, we are able to frequently test the categories behavior and ensure we will not break anything during the refactoring.

3. Encapsulate old categorization mechanism behind an API

Example of code BEFORE encapsulation (old DAO was FrmCategoryTable)

public function executeIndex(sfWebRequest $request) {

$categoryList = FrmCategoryTable::getForumList($idSite, $culture, $user);

}
In order to better test and avoid perturbation with other commiters, we’ve encapsulated all calls to the old category mechanism behind a new API.
We keep the calls to the old category mechanism, but we isolate them into a dedicated API.
Example of code AFTER encapsulation (new API is categoryProvider)

public function executeIndex(sfWebRequest $request) {

$categoryList = $this->categoryProvider->getAllCategories($culture, $brand, $country, ICategoryProvider::SERVICE_FORUM, $user);

}
Code that implements the new API

class CategoryProvider implements ICategoryProvider {
public function getAllCategories($culture, $brand, $country, $service, $user) {
$categoryList =
CatBrandAndCountryTable::getInstance()
->getAllCategories
($culture, $brand, $country, $service, $user);
return $categoryList;
}
}
At the end of this step:
  • The old mechanism is isolated behind an API
  • The “Test Harness” is still switched on !

4. Based on the API contract, build the new mechanism relying on the new categories data model

During the encapsulation step we’ve created the API that is the CONTRACT of our categories mechanism.
At this time we made the choice to start the implementation of the new API. It was probably not the best choice because for several days the new behavior was only partly implemented. We should have worked on another implementation of the API based on the CONTRACT we had extracted from the previous step.
Only once this is done, we should have switched from one implementation of the API to the other.
Code that implements the new API

class CategoryProvider implements ICategoryProvider {
public function getAllCategories($culture, $brand, $country, $service, $user) {

$categoryList = FrmCategoryTable::getForumList(
$siteId, $culture, $user, $categoryLevel);

}
}
At the end of this step:
  • The new mechanism is plugged (new DAO CatBrandAndCountryTable)
  • The “Test Harness” is still switched on !

Conclusion

  • Quite a big system was refactored without service interruption
  • No merge conflicts because we always committed in the trunk/HEAD
  • No projects conflicts because we isolated the pieces of code that were aimed to be re-factored
  • The writing of BDD scenarii WITH THE Product Owner helped implementing the right behavior and sharing the knowledge.

Kali Linux

Kali Linux Features

Kali is a complete re-build of BackTrack Linux, adhering completely to Debian development standards. All-new infrastructure has been put in place, all tools were reviewed and packaged, and we use Git for our VCS.
  • More than 300 penetration testing tools: After reviewing every tool that was included in BackTrack, we eliminated a great number of tools that either did not work or had other tools available that provided similar functionality.
  • Free and always will be: Kali Linux, like its predecessor, is completely free and always will be. You will never, ever have to pay for Kali Linux.
  • Open source Git tree: We are huge proponents of open source software and ourdevelopment tree is available for all to see and all sources are available for those who wish to tweak and rebuild packages.
  • FHS compliant: Kali has been developed to adhere to the Filesystem Hierarchy Standard, allowing all Linux users to easily locate binaries, support files, libraries, etc.
  • Vast wireless device support: We have built Kali Linux to support as many wireless devices as we possibly can, allowing it to run properly on a wide variety of hardware and making it compatible with numerous USB and other wireless devices.
  • Custom kernel patched for injection: As penetration testers, the development team often needs to do wireless assessments so our kernel has the latest injection patches included.
  • Secure development environment: The Kali Linux team is made up of a small group of trusted individuals who can only commit packages and interact with the repositories while using multiple secure protocols.
  • GPG signed packages and repos: All Kali packages are signed by each individual developer when they are built and committed and the repositories subsequently sign the packages as well.
  • Multi-language: Although pentesting tools tend to be written in English, we have ensured that Kali has true multilingual support, allowing more users to operate in their native language and locate the tools they need for the job.
  • Completely customizable: We completely understand that not everyone will agree with our design decisions so we have made it as easy as possible for our more adventurous users to customize Kali Linux to their liking, all the way down to the kernel.
  • ARMEL and ARMHF support: Since ARM-based systems are becoming more and more prevalent and inexpensive, we knew that Kali’s ARM support would need to be as robust as we could manage, resulting in working installations for both ARMEL and ARMHFsystems. Kali Linux has ARM repositories integrated with the mainline distribution so tools for ARM will be updated in conjunction with the rest of the distribution. Kali is currently available for the following ARM devices:
Kali is specifically tailored to penetration testing and therefore, all documentation on this site assumes prior knowledge of the Linux operating system.

Friday, 21 February 2014

Help! I'm drowning in legacy code!

It can be easy to feel dejected when looking at a pile of code you inherited from four generations of programmer ago. None of the best practices or principles. No tests. Hell, you're lucky if you even have objects that don't rely on PHP 4 style constructors. You're in legacy code hell.

But there's hope.

Software as a long game

Even though it can feel hopeless when starting at such a massive pile of crap, there is in fact hope. There is a redemption waiting for you. That redemption is found in a simple revelation: software is a long game.

Consider: that steaming pile of detritus you're working on didn't get that way overnight. In fact, it took a long time to get a code base that big together in the first place. Code takes time to grow. Rome wasn't built in a day, and neither was your application.

PHP has been around for a long time, over 10 years. Much of that time, PHP didn't many of the features that now make it a world class programming language. Add to that the fact that PHP's low barrier to entry means that best practices we now take for granted weren't known let alone followed means there's lots of in production business-critical code that we're now responsible for maintaining.

What can you do, today?

But everything doesn't need to be fixed overnight. In fact, it can't be fixed overnight, so relax.

Writing software is a long process that takes time. It's okay - in fact, it's expected, that you'll take time to make incremental changes. The first step is to make something better, today, that wasn't better yesterday. Refactor something small. Create a group of objects that talk to each other a little bit more reasonably. Decouple a few small things. Make incremental improvements.

As you move through the code, you have an opportunity to improve each part of it in small ways. Combined with the fact that new additions you make will adhere to current best practices, over time the code will begin to dramatically improve. That's how you make a difference in a legacy code base - through small, incremental changes over time.

To defend everything is to defend nothing.

And even though it's easy to be a perfectionist and think "everything has to be perfect", that kind of thinking won't get you where you need to go. Frederick the Great told his men, "to defend everything is to defend nothing." You have to pick and choose your battles. Maybe you can't refactor the entire database logic section this week. But if you can refactor one model, one controller, one function or one algorithm, you can make steady, incremental progress. And that's something.

Good luck!

The road to CAIO

The Engineer Who Stops Owning Only the Code For much of a software engineer’s career, progression appears straightforward. Junior Develope...