Crazy thoughts about solving sudokus using PHP

In my previous post I explained how I implemented a sudoku solver using PHP and OOP.

More or less, this is it. You can dig the code to see the details. But in this post I would like to share with you some thoughts about the designing and implementation process.

For me, it is the more interesting part. To be able to play with designing and coding without any time pressure and limitations. So, I can give the most of myself.

Of course, they are just my own opinions. Perhaps you agree with them. Perhaps you don’t. Software building is an activity complex enough to give room for more than one opinion.

The iterative process

When I start a new application on my own, my first step is to come up with some general idea about the involved classes and use cases.

The designing stage

Even thouh I take my time planning my classes, when I start coding I find lots of hidden behaviours and I need to do a lot of redesigning. This takes time.

I wonder if I can discover these hidden behaviours at the designing stage so my coding would be more straightforward. I will try this approach my next experiment.

As soon as I get comfortable with this preliminary design, I start coding bottom up. And the iterative process starts:

  • I code a first draft of one supporting class.
  • When I finish this draft, I start coding its related phpunit to test its public behaviour.
  • It is very usual that when I start coding the phpunit, I find some missing additional behaviours of the tested class. Or I need to change its original behaviour. So I start coding both the class and its phpunit at the same time.
  • When I have finished the supporting classes, I start the upper level classes.
  • It is possible I find this upper level classes need some additional behaviour from the supporting classes. So I start refactoring them (I usually don’t add new phpunit test cases, I just refactor the phpunit just enough to make them work when needed).
  • Once I finish the coding of this upper level class, I start phpunit it.
  • And the cycle of coding of classes and phpunit repeats until I reach the use case level class.

It is important to highlight I try not to mock anything when I code my phpunits. In my phpunit I always try to use the original supporting classes. This way, when I test a class, I am testing it and all its supporting classes.

I find very enriching this approach: discovering new behaviours when I am coding both the classes and their phpunits and when I use them in the upper layers.

As you can see, I spend most of my time coding and refining Domain classes. I just deal with the entry point with the outside world in a very late stage.

Testing, testing, testing

It is clear I do a lot of testing. It means lots of time. But I think it really worths it:

  • Testing the class along with the class itself allows me to think about it and refine the desired behaviour of the tested class.
  • I do lots of refactoring. Phpunits assure me that whatever refactoring I am doing, my code is still healthy.

With so much testing and coding bottom up, when I implemented the upper level classes (in this project, the command line interface) it almost worked in my first try.

More testing, testing, testing

I am perhaps a bit obsessed about code coverage of my applications. It is very easy to check it in Phpstorm (when you have properly configured it).

Code coverage performed by PhpStorm

When I stabilize my code and my code coverage is not as good as I expect. I review which parts of my code is not covered. This inspection usually raises some use cases I have not tested. So, I complete my phpunits to cover this missed scenarios.

Sometimes, some loops are not covered by my phpunits. It is a good opportunity to refine them

Clean code?

I try to use as much tools I have available to make sure my code is good enough. Let’s not forget PHP is interpreted and there may be some bugs that will only raise when some scenarios are executed.

Which tools I am refering to?:

  • PHP 7 new features like:
    • Strict typing.
    • Typed class members.
    • Typed arguments to functions.
  • I also use PhpStorm tools as much as possible:
    • On line code checking.
    • Code inspections.

I am not happy until PhpStorm informs me that all my files are ok.

I take lots of attention to make sure PhpStorm is «happy» with my code

This strategy has one drawback: sometimes PhpStorm is a bit ‘special’ and I need to write some additional phpdocs to make it happy.

My criteria is:

  • I don’t write any phpdoc unless it is necessary.
  • I only write them to make Phpstorm happy.
PhpStorm doesn´t like polymorphic vars, so I write a phpdoc to make it happy

Inheritance, really?

Well… I agree that we should try to avoid inheritance and use some alternative design patterns instead (like composition or decoration). I also find PHP traits very useful in these situations.

But I try to be pragmatic: if I need some feature and inheritance can help me to implement it efficiently and without any further undesired side effects , I will use it.

For example: all my structural classes (Board, Cell, Row, etc) inherit from an abstract class Entity. It has allowed me all these classes share some common behavior (like event publishing). And it is just first level inheritance. So I think the trade-off is good.

Managing events

At first, I didn’t think I would need any kind of events for my application. But when I reached my Strategy classes I realized they might be very useful:

  • To debug the application (how the strategies are working in their inside).
  • To return the user a list of all performed steps.

So I decided to implement events.

To do this:

  • I implemented a new class Domain\Sudoku\Entity\EventBus (I decided the event bus is an entity of my domain).
  • I linked it to my parent class Domain\Sudoku\Entity\Entity as a static member.
  • I created a new static public method subscribe so any object can subscribe to the event bus.
  • I created a new protected method publish so any class inheriting from Entity can publish into the event bus.
  • Usually, the use case level class will be the only one to subscribe to the event bus. But I have also subscribed to the event bus in my phpunit classes to debug them.

Which events do I publish into the bus? So far, the only class publishing events is Cell. It publishes whenever its content is modified.

Logging

In my personal opinion. Logging is not the same as event publishing. I usually log any information useful to check from the outside what’s happening inside my application as easy as possible.

My first design didn’t have logging. But when I reached the console command Infrastructure\Command\SolveSudoku and I started running it from the command prompt, I realized I wanted some logs.

The only class I wanted logging is Domain\Sudoku\Application\Handler\SolveSudoku (this is the class responsible to implement the use case). So I decided to inject the logger from the calling class (Infrastructure\Command\SolveSudoku).

As this logger object is optional, I needed to check if it is a valid one before logging anything. To do so, if the logger object is not valid, I use a dummy logger.

Conclusions?

I have enjoyed a lot implementing this application. I has given me the opportunity to think about and to practice new ways of coding.

It’s possible you don’t agree with my conclusions. It’s ok, and I would love to read your feedback!!!!