What are Design Patterns?

In software engineering in general, and PHP web development in particular, design patterns are general repeatable solutions to commonly occurring problems. A design pattern is not a finished design that can be transformed directly into code - it is more like a description or template for how to solve a problem that can be used in many different situations.

In PHP web development not all design patterns are known play a big role. However, the once that play a role, play a major one and are often discussed on forums. The implementation of design patterns in PHP is sometimes not very easy and there has been a lot of discussion going on in the past about the differences between certain patterns and the differences of patterns in web development and application programming.

By the way, algorithms are not thought of as design patterns, since they solve computational problems rather than design problems.

The design patterns described on PHP-Design-Patterns.com share the same architecture. There are many approaches to writing articles or even book about design patterns and every author has to choose one. I have decided to follow a similar approach to the Gang of Four Book:

The name of the design pattern is important, because it creates a unique terminology for a given problem and the pattern that solves it. Via communicating a design pattern's name to fellow programmers, they all know what kind of problem you are facing and how you intent to solve it.

The kinds of problems to which the pattern should be applied is discussed in the When to apply it section. Of course, a discussion about when not to apply can be foun there too.

The Implementation section of the patterns on PHP-Design-Patterns.com discusses in detail possible pitfalls when implementing the pattern. This rather big section shows you code snippets and any further information that you need to successfully apply the patterns to problems.

In Web Development, a rather limited field for software design, certain patterns appear over and over again in special parts of web application. Those parts are named in the Known Uses section and are discussed there.

As often as in application programming, design patterns go alongside each other in PHP web development, too. Relatonships between patterns and way how patterns can be best used together are discussed in the Related Patterns section.

Now people think that by applying a design pattern they get full-fletched tried-and-true-design. That's not really true. Please read on when you want to know how design pattern solve problems.

Have a solid Testbase

Whenever you do refactoring you should always ensure you have a solid test base. Not tests written on paper, but Unit Tests. The tests are essential, because even when you follow the refactorings' structures, you are a still a human-being and therefore make mistakes. You need solid tests. Simple.

It is vital to make your tests self-checking. Meaning that you alter how they print out their results. You could either make them print "OK" or "Something was wrong". Or you could of course tell them what went wrong. If you do not make your tests self-checking you lose much time manually checking numbers against numbers, strings against strings. Consider using a testing framework like Simpletest that prints nice messages like "Test #1 failed: got 'string1' when 'string2' was expected. It helps a lot and saves plenty of time.

It's essential to lean on tests. Writing tests takes up time...of course. But they will give you that *lost* time back when you alter the program later. They give you confidence about your code and prevent you from getting hairloss.

Compare with your requirements

You have to know what the code is supposed to do and what it is doing already before you refactor. Refactoring is good for getting from an overly complex solution to a simple one. You should not break anything or even lose functionality. Tripple-check with your requirements list, your specification and - if necessary - with your client, that nothing broke.

Make sure you have your refactoring hat on

As a programmer we usually wear two hats - the feature hat and the refactoring hat. It is absolutely critical that you do not add new functionality to your system when you are doing a refactoring. The risk of breaking things is just too high. Even with good tests - good meaning that they cover many state possibilities of your system - you can end up wasting too much time getting to know what is really going on. You will find yourself changing hats quite often. You start by trying to add a new function, and you realize this would be much easier if the code was structured differently. Swap hats and refactor for a while. Once it is better structured, swap hats again and get the new function working. You realize you could use some 3rd party code and you swap hats again. This could only take a couple of minutes. Always be aware of which hat you are wearing, though.

Following up on yesterday's part 1 of this introduction we have to deal with the question why someone like you or me should use Test-driven Development. Why should someone take on very small steps in programming?

Why should we use Test-driven Development?

Test-driven Development is about managing fear in programming. We have all been in a situation where we had to tackle a complex programming problem where we couldn't see the end from the beginning. We are afraid of not getting the system to work - at least not without a long bugtrail. Fear in general, and particularly in programming, has a host of other effects, too:

Fear makes you tentative.

Fear makes you want to communicate less.

Fear makes you shy away from feedback.

Fear makes you grumpy.

Fear makes you inferior.

Fear gets you out of control.

None of these effects want to be experienced - especially not in programming. When you are tackling one of these very hard programming problems, these effects of fear can be the reason for the project to fail. They can be the reason for you to fail. Test-driven Development is about eliminating fear when programming.

How should we tackle a difficult programming situation?

Instead of being tentative, begin learning concretely as fast as possible.

Instead of hiding in your pit, get out and communicate more clearly.

Instead of avoiding feedback, go out and ask people for feedback.

Instead of getting inferior and out of control, work on being superior all the time.

Avoid getting grumpy - life's too short to waste your energy. :)

Programming is like facing all other sorts of tasks. When you break a big task up into small chunks you cannot only measure your progress, but you can also better organize yourself and get the task done. The tests in Test-driven Development are like subtasks of the one big task - the project. Once we get one test working, we got it working forever. If it fails, we can quickly fix it up. The important thing to note is that we have someone (our tests) notifying us about crashes in our application.

With another test working we are one step closer to getting the overall system to work. When one test fails, we didn't go one step back. We went forward another one, because our code taught us a lesson about itself - about its relation to other code, input, etc.

Should we always use Test-driven Development?

I am a firm believer in Test-driven Development. However, some people like Kent Beck - author of Test-driven development by Example, say that it's also good enough to revert to your ordinary programming practices as long as you reserve TDD for special occasions. However, there are occasions where TDD is still insufficient.

Think of PHP security. Of course you can test whether your security barriers work. However, you cannot test whether your security methods are efficient enough to make hacking the system impossible.

Getting setup with Test-driven Development

There are numerous frameworks for using Test-driven Development with PHP. The two most popular ones are PEAR's PHPUnit and SimpleTest. I very much prefer the latter, because it has an easy-to-use Eclipse plugin, my preffered IDE / Editor. However, SimpleTest is not limited to Eclipse. You can of course use the framework with any IDE or set up, simply by including the appropriate SimpleTest files within your code.

I would like you to download SimpleTest follow the installation instructions in the readme. Then you can play around with it already and tomorrow we will really delve into the topic of Test-Driven Development. :)

Hi folks! Since Test-Driven-Development (TDD) is probably t h e way to develop in a world of failing software, I thought I could write an introduction to it today. It will be broken up into a series of parts (planned are three parts), which I will release on a day-to-day basis.

The goal of Test-Driven-Development

Clean code that works is the goal of Test-Driven-Development. Clean code that works is a worthwhile goal for a whole bunch of reasons:

It gives you a chance to learn the lessons the code has to teach you. If you only hack together the first thing you can think of, you won't have the chance to think of a second, better thing.

It improves the lives of the users of your software. Keep in mind that if you don't test your software, your users will..

It is a predictable way to develop. You know when you are finished without worries about a long bug trail.

It lets your teammates count on you, and you on them.

It just feels good to see the green bar (i.e. all tests passing).

However, how do we get to clean code that works, with all the external factors that seem to be preventing us from doing so? We drive development with automated tests - which is ultimately called Test-Driven-Development.

What do we do in Test-Driven-Development?

We write code only if an existing automated test has failed. We eliminate duplication (check for The DRY-principle).

These two rules / behaviors introduce complex technical implications. To make them work we have to:

..design dynamically, with running and working code providing feedback between decisions.

We must write our own tests, because we cannot wait 20 times a day for a colleague to write our tests.

Our development environment must provide rapid response to small changes.

Our designs must consist of encapsulated components in order to make testing of each of those easy. This is very i mportant and very difficult to achieve in existing environments.

The TDD-mantra

Red - Green - Refactor, according to Kent Beck, author of Test-Driven-Development by Example, is the TDD-mantra. Red means a test failed, green means you make the test work by writing code that satisfies the test and refactor...you use refactoring to make the code as simple and reusable as possible.

Social benefits of Test-Driven-Development

If you can avoid long bugtrails, then quality assurance (QA) work can be proactive instead of reactive.

If you can avoid long bug trails, managers can actually manage and plan the project and are able to involve your customers in day-to-day development.

If clean code that works can be written really fast, planning of programming teams can be made in day-to-day cycles instead of week-to-week or even month-to-month. making software is going to get a lot more profitable for your company.

If there are no long bug trails, we have shippable software everyday. We can provide our customers with a fresh update everyday with new functionality, making all people involved very happy.

Conclusion

The concept is rather simple, but why would a highly-qualified systems engineer take on small steps in programming - each step so simple that it is plain crazy? What does test-driven-development look like? We will see in the second part of this introduction, which will contain a code sample, too. :)

Introduction

As php programmers, we collect, organize, maintain and use knowledge and information. We document our knowledge in specifications, use it when we test and write the source code of our application.

Alas, our knowledge changes, everyday and quite quickly, too. When a client wants us to add, change or remove a feature, when government sets out a new rule that lets our program's functionality become nonsense, our knowledge changes. When our knowledge changes, we have to reorganize. Most people think, maintaining the project starts when it is released. Actually, maintaining starts with the first word about the project written anywhere. As programmers we are in a constant state of maintaining our codebase. As project managers we are in a constant state of maintaining our documentation, plans, glossars, etc.

Avoid knowledge duplication

When the project's requirements change, we have to alter all code that is written on top of that knowledge. We will spend a lot of time finding all that code. We will have to write tests that document that everything we changed behaves in the new way we want it to.

According to the Pragmatic Programmers the principle to avoid duplication of knowledge is called the DRY-principle ("Don't repeat yourself"). What does that mean? It means you should ensure that every bit of knowledge of your system, be it in the source code, its documentation or any other documentation, should have a single representation.

The alternative is to write down the same bit of knowledge on multiple places. When something changes, you have to update all places or else your requirements list, project documentation or source code documentation becomes out of date.

Possible problems with repetitive knowledge

Most problems caused by knowledge repetition, belong to one or more of the following categories:

Enforced repetition - Programmers think they have no choice. Circumstances seem to enforce the duplication.

Undeliberate repetition

- We programmers don't recognize that we repeat information.

Repetition due to impatience

- We get lazy and put repetitions in because the situation seems to get easier with them.

Repetition due to many developers

- Different developers from the same team (or different teams) repeat information.

Repetition caused by deadlines

- This often happens in php webdevelopment. A client needs the job done today, so we hack away without thinking about repetition.

Let's look at them in more detail.

Enforced repetition

Sometimes we seem to be enforced to repeat information. Project standards might force us to develop documents about our source code, which of course will contain duplicate information. What can you do to make changes possible and avoid knowledge repetition?

Use scripts and generators that generate code and all the documents.

Write abstract explanations why you do something in the source code the way you do it. Don't repeat what the source code is already telling the reader.

Document information to use code in your phpdoc comments and document details that someone doesn't need to know to use your code in the implementation.

Undeliberate repetition

Everybody has a bad day once. We often struggle with different problems, probably from our family, friends and what not. Don't let them too close to you!

Programming is a highly sophisticated action that requires lots of concentration. Only program when you are really conscious, feel fine and are relaxed. Try to avoid repetition. When you cannot avoid it now, then document that repetition and fix it later.

Repetition due to impatience

That's what I find myself doing quite often. I want the project to be done now and don't abide by the DRY-principle. This is the wrong way to go about it. Why? Because you will end up in a repetition mess making it impossible to find all the things you need to change to fix the repetition. Often projects fail due to such repetition messes. This happens when nobody, not even the project leader, knows what's going on and what documents are the once the team should use. Fixing repetitions will make you spend precious time and very much of it! Code without repeating information in the first place and you will be fine. You may save a couple of minutes today at the potential risk to lose hours later. Code disciplined!

Repetition due to many developers

This is the most difficult form of repetition to find out and to fix. The only thing, in my opinion, which you can do about it, is to enforce communication among the team and across multiple teams. Ensure everybody is hacking away at a different piece of the system to avoid conflicts. Set up discussion forums, trac and what not to avoid the repetition. Regular meetings help, too. Fix any repetition as you find it.

Repetition caused by deadlines

This is also another very difficult one and I must admit I am not really sure yet what the best way is to handle it. On the one hand I agree that when the deadline is close you must make the code work. As long as it performs well, is secure and fulfills all requirements you are fine. If the deadline is still a week away, you should code with repetition in mind, though. Avoid it at all costs, or else it could lose you many hours, which may in turn cost you the deadline.

Conclusion

Make reusability easy. Try to build up an environment that lets you reuse and alter information easily. If something is not easy, people will not use it. Think about it.