I've just watched this interesting talk by Robert C. Martin:
It's very interesting to me the idea that the same features that make Ruby great to write might be also bad,
because you can live with bad design for too long so you can make the mess bigger and bigger until you can't go on anymore.
He argues that in other less expressive languages, you'd feel the pain of bad design much sooner which will force you to adopt good practices earlier.
Record of experiments, readings, links, videos and other things that I find on the long road.
Registro de experimentos, lecturas, links, vídeos y otras cosas que voy encontrando en el largo camino.
Friday, February 28, 2014
Thursday, February 27, 2014
Interesting Talk: "Defining Object-Oriented Design"
I've just watched this interesting talk by Sandi Metz:
I'm also enjoying a lot her book Practical Object-Oriented Design in Ruby: An Agile Primer
It's a great book!
I'm also enjoying a lot her book Practical Object-Oriented Design in Ruby: An Agile Primer
It's a great book!
Video: Required settings to use googlemock in a Visual Studio 2013 Ultimate project
I've recorded a video to show how to configure Visual Studio 2013 Ultimate project to work with googlemock:
Sunday, February 23, 2014
Interesting Podcast: "Value Objects, The Heart and Soul of OOP"
I've just listened to this interesting episode of Elephant in the Room a podcast on PHP, Software Design, and Testing:
Interesting Talk: "Domain-Driven Design"
I've just watched this interesting introductory talk by Bradley Holt with examples in PHP:
Saturday, February 22, 2014
Birthday greetings refactoring kata at Barcelona Software Craftsmanship: step by step commits and screencasts
Last Monday I hosted an event for Barcelona Software Craftsmanship community.
We practiced refactoring and learned about ports and adapters using Matteo Vaccari's Birthday Greetings kata in refactoring mode. This is the initial code in Java that we tried to refactor.
I prepared several slides to introduce what we were going to do. I thought that we could just start refactoring for two hours right after this explanation, but, thanks to the suggestions of some attendees, we changed the plan and did two iterations (extracting the employees repository in the first one and extracting the greetings sender in the second one) with a retrospective in the middle.
This was a really good idea because it gave us the opportunity to debate about different approaches to this refactoring and about ports and adapters. Some very interesting points were raised during those conversations and we could exchange personal experiences and views about this architecture and refactoring. This kind of conversations are a very important part of practicing together and they enrich the kata experience.
I think I have a lot to improve as an event host. Next time I'll make explicit that attendees need to bring their laptop and I'll try to help more the beginners.
I had published a possible solution to the kata, but it was just the final solution not the intermediate steps. Some attendees said that they would like to see how this refactoring could be done in small steps. For that reason, I redid the kata again at home committing after every refactoring step and recording the process:
- Step by step kata commits
- Screencasts of most of the process: Extracting the employees repository and Extracting the greetings sender
Take this recordings with a grain of salt because I'm still working hard to improve my refactoring skills.
Well I hope this might be useful to someone.
Just to finish, I'd like to thank all the attendees for coming, I had a great time. I'll try to do it better the next time.
I'd also like to thank netmind for their support to our community giving us a place and the means to hold Barcelona Software Craftsmanship events. Having a regular place for our events makes everything much easier.
So far the events have had much more attendees than we had expected. In fact, this last Monday we nearly run out of space. If this trend continues, we'll probably need to ask for a bigger room to hold future events.
-----------------------------------------------------------------------------
PS: Christian Soronellas shared a version of the initial code in PHP.
Thank you very much Christian!
Friday, February 21, 2014
Building GoogleMock to use it with Visual Studio 2013 Ultimate
This post explains how to build GoogleMock to use it with Visual Studio 2013 Ultimate.
First download the last version (1.7.0 when I wrote this) of GoogleMock from the GoogleMock download list.
Then extract the content of the downloaded zip on a folder of your choice. I did it inside c:\src\
Now use Windows Explorer to enter into the msvc\2010\ folder under the gmock-1.7.0 folder. There you'll find a solution file called gmock.sln, open it with Visual Studio 2013 Ultimate.
Since this solution was created with Visual Studio 10, Visual Studio 2013 will ask you to upgrade all the project files within the solution. Click Ok.
Then you'll probably see this message:
This happens because the project files have read-only permissions.
Select the Make Writable option for each of the three project files.
Once the solution is open, you'l see three projects inside the solution:
Build the solution in Debug Version pressing F7 and ignore all the warnings.
Once built, to check that everything is ok, go to the Debug folder under msvc\2010\ the you'l find an executable file called gmock_test.exe which runs the tests for the googlemock code.
Open a command line prompt, go to the Debug folder and run the tests.
You should see that all of them pass.
First download the last version (1.7.0 when I wrote this) of GoogleMock from the GoogleMock download list.
Then extract the content of the downloaded zip on a folder of your choice. I did it inside c:\src\
Now use Windows Explorer to enter into the msvc\2010\ folder under the gmock-1.7.0 folder. There you'll find a solution file called gmock.sln, open it with Visual Studio 2013 Ultimate.
Since this solution was created with Visual Studio 10, Visual Studio 2013 will ask you to upgrade all the project files within the solution. Click Ok.
Then you'll probably see this message:
This happens because the project files have read-only permissions.
Select the Make Writable option for each of the three project files.
Once the solution is open, you'l see three projects inside the solution:
- gmock
- gmock_main
- gmock_test
Build the solution in Debug Version pressing F7 and ignore all the warnings.
Once built, to check that everything is ok, go to the Debug folder under msvc\2010\ the you'l find an executable file called gmock_test.exe which runs the tests for the googlemock code.
Open a command line prompt, go to the Debug folder and run the tests.
You should see that all of them pass.
Thursday, February 20, 2014
Interesting Talk: "The Framework as an implementation detail"
I've just watched this interesting talk by Konstantin Kudryashov and Marcello Duarte:
They show how the framework (in this case Symfony) can become an implementation detail by using the hexagonal architecture.
Check also the example code they show at the end of the talk.
They show how the framework (in this case Symfony) can become an implementation detail by using the hexagonal architecture.
Check also the example code they show at the end of the talk.
Wednesday, February 19, 2014
My path to JavaScript: Refactoring fizzbuzz to accept any kind of predicates on numbers for substitutions
I've been playing a bit more with scopes to make the generalized version of FizzBuzz using Array.map and Array.join I posted about recently accept substitution rules with any predicate on a number. I also coded a factory function that creates the substitute function.
This is the factory that creates a substitute function given a list of substitution descriptions objects which are composed of a predicate on the number and a replacement for the number:
Next you can see how this factory is used in the tests to create each substitute function:
This has been a nice practice with higher order functions, closures and free variables.
Next time, I'll move on to a new kata to practice with JavaScript objects.
This is the factory that creates a substitute function given a list of substitution descriptions objects which are composed of a predicate on the number and a replacement for the number:
Next you can see how this factory is used in the tests to create each substitute function:
This has been a nice practice with higher order functions, closures and free variables.
Next time, I'll move on to a new kata to practice with JavaScript objects.
Wednesday, February 12, 2014
Different approaches to binary methods: double-dispatch, pattern matching and multimethods
I've chosen a simple problem that can be solved using binary operations to show some different approaches to them: the Rock, Paper and Scissors game
Binary methods in OOP.
This is a Ruby code that is using the double-dispatch pattern to solve this problem following a "full" OOP approach (not using any conditionals on types):
When you call hand with two variants of Gesture (Rock, Paper and Scissors are all variants/types of Gesture but since Ruby has duck typing we don't need to have this superclass), it sends the message play_against to the first variant. That's the first dispatch.
Rock, Paper and Scissors have its own version of play_against and the first dispatch sends, according to the type of the message receiver, the execution to one of them. It uses polymorphism on the receiver to get to the right method.
Once in there, instead of falling in the temptation of using a conditional depending on types, we use polymorphism again but this time on the object passed as a parameter.
For instance, if we call hand(Rock.new, Paper.new) the first dispatch will send us to the play_against method of Rock. If you've got there, you know that the first player's gesture is a Rock, so we keep that information in the name of a new method, play_against_rock and use polymorphism again sending that message to the second object. This is the second dispatch that, in this case, will send us to the play_against_rock method of Paper where we can return that a Rock is beaten by a Paper: Lose.new(aRock, self).
For three variants there are nine possible combinations (3 x 3), which originates 9 functions: a version of play_against_rock, play_against_paper and play_against_scissors for each variant.
You might imagine how complicated would be implementing n-ary methods.
You can check the whole example with its tests in Rock, Paper, Scissors game using double dispatch in Ruby.
Binary methods with functional decomposition
In functional decomposition all the cases are considered in the same function: hand.
In hand we first use pattern matching on the first variant and then pattern matching again on the second. In this code, I nested the second pattern matching but I could have used helper functions called play_against_rock, play_against_paper and play_against_scissors to make it more similar to the OOP version.
As you see there are again 9 cases, but this code is less "spread out" than the OOP one.
However it seems that implementing n-ary methods would also be very complicated using this approach.
You can check the whole example with its tests in Rock, Paper, Scissors game using pattern matching in OCaml.
Multimethods
Quoting Dan Grossman:
Clojure has multimethods:
The treatment of the binary method is much simpler in this example than in the other two. Moreover, you can use the multimethods for n-ary methods too.
You can check the whole example with its tests in Rock, Paper, Scissors using Clojure multimethods
I had been thinking about doing this posts since I finished the great Programming Language course in Coursera.
Well, better late than never.
-----------------------------------------------
PS: According to Dan, it seems that in C# one can achieve the effect of multimethods by using the type "dynamic" in the right places.
Binary methods in OOP.
This is a Ruby code that is using the double-dispatch pattern to solve this problem following a "full" OOP approach (not using any conditionals on types):
When you call hand with two variants of Gesture (Rock, Paper and Scissors are all variants/types of Gesture but since Ruby has duck typing we don't need to have this superclass), it sends the message play_against to the first variant. That's the first dispatch.
Rock, Paper and Scissors have its own version of play_against and the first dispatch sends, according to the type of the message receiver, the execution to one of them. It uses polymorphism on the receiver to get to the right method.
Once in there, instead of falling in the temptation of using a conditional depending on types, we use polymorphism again but this time on the object passed as a parameter.
For instance, if we call hand(Rock.new, Paper.new) the first dispatch will send us to the play_against method of Rock. If you've got there, you know that the first player's gesture is a Rock, so we keep that information in the name of a new method, play_against_rock and use polymorphism again sending that message to the second object. This is the second dispatch that, in this case, will send us to the play_against_rock method of Paper where we can return that a Rock is beaten by a Paper: Lose.new(aRock, self).
For three variants there are nine possible combinations (3 x 3), which originates 9 functions: a version of play_against_rock, play_against_paper and play_against_scissors for each variant.
You might imagine how complicated would be implementing n-ary methods.
You can check the whole example with its tests in Rock, Paper, Scissors game using double dispatch in Ruby.
Binary methods with functional decomposition
In functional decomposition all the cases are considered in the same function: hand.
In hand we first use pattern matching on the first variant and then pattern matching again on the second. In this code, I nested the second pattern matching but I could have used helper functions called play_against_rock, play_against_paper and play_against_scissors to make it more similar to the OOP version.
As you see there are again 9 cases, but this code is less "spread out" than the OOP one.
However it seems that implementing n-ary methods would also be very complicated using this approach.
You can check the whole example with its tests in Rock, Paper, Scissors game using pattern matching in OCaml.
Multimethods
Quoting Dan Grossman:
"Not all OOP languages require the cumbersome double-dispatch pattern to implement binary operations in a full OOP style. There are languages that support multimethods, also known as multiple dispatch that provide more intuitive solutions. Multiple dispatch is "even more dynamic dispatch" by considering the class of multiple objects and using all that information to choose what method to call."Ruby, Java and C++ don't support multimethods. Java and C++ have static overloading by which you can have multiple methods with the same name but different types for the arguments. The difference is that the method to call is determined in this case at compilation time and not in run time. This can be convenient but does not avoid having to use double-dispatch in this example.
Clojure has multimethods:
The treatment of the binary method is much simpler in this example than in the other two. Moreover, you can use the multimethods for n-ary methods too.
You can check the whole example with its tests in Rock, Paper, Scissors using Clojure multimethods
I had been thinking about doing this posts since I finished the great Programming Language course in Coursera.
Well, better late than never.
-----------------------------------------------
PS: According to Dan, it seems that in C# one can achieve the effect of multimethods by using the type "dynamic" in the right places.
Monday, February 10, 2014
My path to Clojure: Clojure Developers Barcelona meetup
Last week I attended the first Clojure Developers Barcelona meetup.
There we could listen a very interesting talk by Jiří Knesl: It was a very interesting talk full of common sense.
I think we all were a bit surprised because none of us expected there were going to be so many people interested in or already working with Clojure
There were also many ideas about new activities.
I think this has just been the beginning of a very interesting community which will produce many interesting activities.
Thanks to Jiří Knesl for his great talk and to José Raya and Jordi Pradel for organizing the meetup.
There we could listen a very interesting talk by Jiří Knesl: It was a very interesting talk full of common sense.
I think we all were a bit surprised because none of us expected there were going to be so many people interested in or already working with Clojure
There were also many ideas about new activities.
I think this has just been the beginning of a very interesting community which will produce many interesting activities.
Thanks to Jiří Knesl for his great talk and to José Raya and Jordi Pradel for organizing the meetup.
Sunday, February 9, 2014
My path to Clojure: Intro
As I'm doing with JavaScript, I'm going to start recording my Clojure learning path.
Where am I?
I'm a complete beginner in Clojure but I've been playing for a while with Racket (another Lispy language) in these two Coursera courses: So let's say that the parentheses don't make me fell dizzy anymore :)
I really enjoyed working with Racket in these two courses. I wanted to learn more Racket but I had also been hearing a lot of good things about Clojure, so I didn't know which one to choose. Then I watched this great conversation between Rich Hickey and Brian Beckman: Inside Clojure and I made my mind to start learning Clojure.
At the moment I'm reading this book by Stuart Halloway and Aaron Bedra: I'm also attending the Clojure Developers Barcelona meetup.
So let's the Lisp cycles continue forever, I'll keep you posted on any news.
Where am I?
I'm a complete beginner in Clojure but I've been playing for a while with Racket (another Lispy language) in these two Coursera courses: So let's say that the parentheses don't make me fell dizzy anymore :)
I really enjoyed working with Racket in these two courses. I wanted to learn more Racket but I had also been hearing a lot of good things about Clojure, so I didn't know which one to choose. Then I watched this great conversation between Rich Hickey and Brian Beckman: Inside Clojure and I made my mind to start learning Clojure.
At the moment I'm reading this book by Stuart Halloway and Aaron Bedra: I'm also attending the Clojure Developers Barcelona meetup.
So let's the Lisp cycles continue forever, I'll keep you posted on any news.
Articles and Posts read
I'm going to stop posting here the articles and blog posts that I read because I'm already sharing them in my Google+ account.
You can still check them there if you like.
You can still check them there if you like.
Saturday, February 8, 2014
Avoid coupling test names to implementation
In our first iteration in the JavaScript Code Retreat, we worked on the rules to tell
if a cell goes on living or if a new cell is created having the restriction of not using conditionals.
So we used two very small functions: goesOnLivingWith and isCreatedWith that accepted the number of neighbors as a parameter.
We implemented them using TDD and end up with the following tests:
The main problem with the names of these tests was that they were tightly coupled to the conditions in the rules we had coded:
So we refactored the tests names to improve that:
These new names are much better because they describe the rules focusing in their behavior without getting into details about their implementation.
Avoiding coupling test names with implementation by expressing just behavior will make test names more durable since they won't have to be changed if the implementations undergo any changes.
So we used two very small functions: goesOnLivingWith and isCreatedWith that accepted the number of neighbors as a parameter.
We implemented them using TDD and end up with the following tests:
The main problem with the names of these tests was that they were tightly coupled to the conditions in the rules we had coded:
So we refactored the tests names to improve that:
These new names are much better because they describe the rules focusing in their behavior without getting into details about their implementation.
Avoiding coupling test names with implementation by expressing just behavior will make test names more durable since they won't have to be changed if the implementations undergo any changes.
My path to JavaScript: JavaScript Code Retreat Valencia
Today I participated in the JavaScript Code Retreat in Valencia.
It was a great experience because limiting the possible languages to just one, JavaScript, (that we all knew at least enough to work on the kata) made our practice even more focused.
By not having to switch between languages and test frameworks (we all used Jasmine), we could just concentrate in doing our best to craft good code under the constraints of each iteration.
It's been fun and I learned a lot again revisiting Conway's Game of Life. I recently coded a complete solution of this game in Java, but today I tried different approaches with my partners and also focused even more in naming.
I'd like to thank Ricardo Borillo, Wolfram Kriesing and peerTransfer for making it possible.
It was a great experience because limiting the possible languages to just one, JavaScript, (that we all knew at least enough to work on the kata) made our practice even more focused.
By not having to switch between languages and test frameworks (we all used Jasmine), we could just concentrate in doing our best to craft good code under the constraints of each iteration.
It's been fun and I learned a lot again revisiting Conway's Game of Life. I recently coded a complete solution of this game in Java, but today I tried different approaches with my partners and also focused even more in naming.
I'd like to thank Ricardo Borillo, Wolfram Kriesing and peerTransfer for making it possible.
Thursday, February 6, 2014
My path to JavaScript: Refactoring fizzbuzz with Array.map and Array.join
I've just refactored the generalized version of FizzBuzz I posted about recently using Array.map and Array.join functions.
This is the version that I had before:
and this is the new version using Array.map and Array.join:
Even though it was fun coding that "map+join" recursive function of the first version, the second version is much simpler and more efficient (I used jsPerf to compare the two versions, check out the comparison).
Had I known Array.map and Array.join before, I could have saved a lot of typing and thinking to "reinvent the whell" :)
This is the version that I had before:
and this is the new version using Array.map and Array.join:
Even though it was fun coding that "map+join" recursive function of the first version, the second version is much simpler and more efficient (I used jsPerf to compare the two versions, check out the comparison).
Had I known Array.map and Array.join before, I could have saved a lot of typing and thinking to "reinvent the whell" :)
Wednesday, February 5, 2014
Some resources for Specification By Example and Behavior-Driven Development
Last Monday I attended the second event of Barcelona Software Craftsmanship.
Viktor Farcic and Jordi Falguera gave a talk about Specification By Example (SBE) and Behavior-Driven Development (BDD).
I really did like the talk, especially because it was enriched with their own experiences applying SBE in different projects.
For some people in the audience SBE was not a completely new concept, for some others it was. In either case, the topic generated a lot of interest and many questions.
Those who were already using it wanted to hear about a different approach to it (there are probably as many approaches as teams and projects).
Those who were just starting or planning to use it in their projects, were more interested in practical how-tos, ways to overcome possible obstacles and other stories from the trenches. The same goes for the people (like me) that knew about SBE through Godjko Adzic's great book or have heard or read about it in talks or posts.
Finally, I could imagine the brains of the people hearing about it for the first time, churning wildly, like mine was when I started to read Godjko Adzic's book, imagining how SBE could impact their projects, thinking in all the possibilities opening before them and in how they could get there.
To sum up when the talk ended, we were left wanting for more.
For that reason I'd like to share in this post several interesting links that I have come across while learning about SBE, so that, they can help other people interested in it to learn more and to compare some of the different approaches and tools that exist for SBE.
Dan North's original BDD post: Introducing BDD
and its great What’s in a Story? post.
Books:
PS: The great thing it's that Viktor and Jordi have proposed a BDD Workshop on March 3, 2014, so that we can practice how to write specifications.
Viktor Farcic and Jordi Falguera gave a talk about Specification By Example (SBE) and Behavior-Driven Development (BDD).
I really did like the talk, especially because it was enriched with their own experiences applying SBE in different projects.
For some people in the audience SBE was not a completely new concept, for some others it was. In either case, the topic generated a lot of interest and many questions.
Those who were already using it wanted to hear about a different approach to it (there are probably as many approaches as teams and projects).
Those who were just starting or planning to use it in their projects, were more interested in practical how-tos, ways to overcome possible obstacles and other stories from the trenches. The same goes for the people (like me) that knew about SBE through Godjko Adzic's great book or have heard or read about it in talks or posts.
Finally, I could imagine the brains of the people hearing about it for the first time, churning wildly, like mine was when I started to read Godjko Adzic's book, imagining how SBE could impact their projects, thinking in all the possibilities opening before them and in how they could get there.
To sum up when the talk ended, we were left wanting for more.
For that reason I'd like to share in this post several interesting links that I have come across while learning about SBE, so that, they can help other people interested in it to learn more and to compare some of the different approaches and tools that exist for SBE.
Dan North's original BDD post: Introducing BDD
and its great What’s in a Story? post.
Books:
- Bridging the Communication Gap: Specification by Example and Agile Acceptance Testing by Gojko Adzic.
- Specification by Example by Godko Adzic.
- The Cucumber Book: Behaviour-Driven Development for Testers and Developers by Matt Wynne.
- On Behavior-Driven Development Dan North and Liz Keogh.
- Behavior-driven Development by Liz Keogh.
- BDD: Step Away from the Tools by Liz Keogh.
- BDD: Busting the myths by Gojko Adzic.
- Growing software from examples by Seb Rose.
- Especificaciones ejecutables, acercando negocio y desarrollo Vicenç García Altés.
- Behaviour Driven Development and Cynefin by Liz Keogh.
- On BDD, Cucumber, Hexagonal Architecture by Matt Wynne.
- Reinventing software quality by Gojko Adzic.
- Using Cucumber for BDD and Agile Acceptance Testing by Gojko Adzic.
PS: The great thing it's that Viktor and Jordi have proposed a BDD Workshop on March 3, 2014, so that we can practice how to write specifications.
Tuesday, February 4, 2014
My path to JavaScript: Functions, closures and recursion
Today I read chapters 5 (Functions) and 6 (Applied Functions and Closures) of Test Driven JavaScript development. In them, Christian Johansen goes deep into JavaScript powerful functions talking about functions as first class objects, closures, free variables, recursion, binding, namespaces, etc. I'm enjoying a lot his book.
To practice a bit with recursion and closures and also get more acquainted with Jasmine, I decided to do the FizzBuzz kata again but applying some of these concepts. I did TDD to get to a result which was very similar to the solution of FizzBuzz that I produced yesterday to try Karma and Jasmine.
This is the version from yesterday:
After the new version of FizzBuzz was working, I started to refactor its code focusing on removing as much duplication as possible and trying to make the code more general, so that, it could accept different sets of substitution functions each of them still based on "multiple of" predicates. I also tried to play with the scope rules to make private helper functions and use free variables to reduce the necessary number of parameters.
This is the new version of the code:
It has two public functions: makeSubstitution that is factory of substitution functions and substitute that is the generalization of the original fizzbuzz function. Like fizzbuzz did, substitute also receives a list of numbers that will be substituted only if they fulfill certain condition (being a multiple of 3, being a multiple of 5, etc). The difference is that substitute also receives a list of substitution functions.
Taking this into account, you can see that fizzbuzz(numbers) is equivalent to substitute(numbers, [makeSubstitution(3, "Fizz"), makeSubstitution(5, "Buzz")]).
This way we can create new games using different lists of substitution functions (that use "multiple of" predicates) without having to change substitute's code.
Have a look at "FizzKozz" at the end of the tests:
If you like, you can get the code of this a bit more generalized FizzBuzz version here.
JavaScript is a lot of fun!
Monday, February 3, 2014
My path to JavaScript: Karma and Test Driven JavaScript Development book
I've started to read the book Test-Driven JavaScript Development written by Christian Johansen that both Carlos Blé and Tomás Corral recommed.
The book is great so far (after reading part one).
I wanted to follow the examples in the book so I installed JsTestDriver which is the test runner used in the book. Since the book is from 2010, I wasn't sure that JsTestDriver still were the best test runner possible, so I asked Tomás Corral.
He kindly answered me that he was now using Karma instead, because it was much faster and more effective. He also told me that he was combining it with SinonJS and Jasmine (which comes with Karma by default) and using Grunt as build tool.
Following his advice I installed and configured Karma today.
I also coded the FizzBuzz kata in JavaScript to see how it feels to work with Karma and Jasmine.
Now that everything is working (I'm using just Karma and Jasmine, not Grunt yet) I plan to use them to work through the examples in the book.
-----
PS: Thanks a million Tomás for your advice.
The book is great so far (after reading part one).
I wanted to follow the examples in the book so I installed JsTestDriver which is the test runner used in the book. Since the book is from 2010, I wasn't sure that JsTestDriver still were the best test runner possible, so I asked Tomás Corral.
He kindly answered me that he was now using Karma instead, because it was much faster and more effective. He also told me that he was combining it with SinonJS and Jasmine (which comes with Karma by default) and using Grunt as build tool.
Following his advice I installed and configured Karma today.
I also coded the FizzBuzz kata in JavaScript to see how it feels to work with Karma and Jasmine.
Now that everything is working (I'm using just Karma and Jasmine, not Grunt yet) I plan to use them to work through the examples in the book.
-----
PS: Thanks a million Tomás for your advice.
Sunday, February 2, 2014
Conway's Game of Life in Java
Last December I attended the Global Day of Code Retreat in Valencia.
It was a lot of fun and we thought and discussed a lot about the problem. Thanks to all the participants and the organizers for the great time.
When I came back to Barcelona I decided to go on practicing by developing a full solution to Conway's Game of Life on my own.
I wanted the solution to include several of the ideas that we had been discussing during the code retreat:
It took me several rewrites but finally I came up with this solution that respects all the previous ideas.
- Tracking only living cells
A Generation has a collection of cells that are alive, LivingCells, and a set of Rules.
This way the "state of the cell" concept we tried in some iterations of the code retreat becomes pointless and it requires less space to store the current generation.
I also made Generation immutable.
To generate the next Generation of LivingCells (produceNextGeneration method), it first adds the surviving cells (addSurvivors method) and then the newly born cells (addNewCells method).
- Open/Closed with regard to the rules based on the number of neighbors.
Rules is an interface with two methods, shouldStayAlive and shouldBeBorn, that you can implement the way you wish.
The rules are still based on the number of neighbors which is the parameter passed to both methods.
In this case, I only implemented the rules of the Conway's Game of Life: ConwaysRules class, but more rules based on the number of neighbors might be added.
- Open/Closed with regard to the number and location of a cell's neighbors and Open/Closed with regard to the dimensions of the grid (2D, 3D, 4D, etc).
This two are possible thanks to the Cell interface. It has only a method, getNeighbors, which returns the neighbors of a cell. It's up to the cell to know which are its neighbors.
In this way each implementation of Cell can have a different dimension and a different number of neighbors which can be located following different stencils.
In this case, I implemented several types of cells: ConwaysCell, CellX2D, CellCross3D and CellCross2D. The code that is common to all 2D cells is in the Cell2D abstract class, whereas the one that is common to all 3D cells is in the Cell3D abstract class.
You can have a look at the code on GitHub.
Update: I refactored this code making it much simpler. Take a look at the new version.
It was a lot of fun and we thought and discussed a lot about the problem. Thanks to all the participants and the organizers for the great time.
When I came back to Barcelona I decided to go on practicing by developing a full solution to Conway's Game of Life on my own.
I wanted the solution to include several of the ideas that we had been discussing during the code retreat:
- Tracking only living cells.
- Open/Closed with regard to the rules based on the number of neighbors.
- Open/Closed with regard to the number and location of a cell's neighbors.
- Open/Closed with regard to the dimensions of the grid (2D, 3D, 4D, etc).
It took me several rewrites but finally I came up with this solution that respects all the previous ideas.
- Tracking only living cells
A Generation has a collection of cells that are alive, LivingCells, and a set of Rules.
This way the "state of the cell" concept we tried in some iterations of the code retreat becomes pointless and it requires less space to store the current generation.
I also made Generation immutable.
To generate the next Generation of LivingCells (produceNextGeneration method), it first adds the surviving cells (addSurvivors method) and then the newly born cells (addNewCells method).
- Open/Closed with regard to the rules based on the number of neighbors.
Rules is an interface with two methods, shouldStayAlive and shouldBeBorn, that you can implement the way you wish.
The rules are still based on the number of neighbors which is the parameter passed to both methods.
In this case, I only implemented the rules of the Conway's Game of Life: ConwaysRules class, but more rules based on the number of neighbors might be added.
- Open/Closed with regard to the number and location of a cell's neighbors and Open/Closed with regard to the dimensions of the grid (2D, 3D, 4D, etc).
This two are possible thanks to the Cell interface. It has only a method, getNeighbors, which returns the neighbors of a cell. It's up to the cell to know which are its neighbors.
In this way each implementation of Cell can have a different dimension and a different number of neighbors which can be located following different stencils.
In this case, I implemented several types of cells: ConwaysCell, CellX2D, CellCross3D and CellCross2D. The code that is common to all 2D cells is in the Cell2D abstract class, whereas the one that is common to all 3D cells is in the Cell3D abstract class.
You can have a look at the code on GitHub.
Update: I refactored this code making it much simpler. Take a look at the new version.
Saturday, February 1, 2014
Interesting Talk: "Thinking in Patterns"
I've just watched this interesting talk by Cory Foy:
He talks about thinking in the forces and the context of a given problem before deciding if any pattern is suitable. Once you decide that a pattern is suitable, instead of using the pattern implementation by the book, he advises to go on using design principles (SOLID, DRY, etc) to guide the development. This way the pattern would just be used as a reference of how the design might end being.
He talks about thinking in the forces and the context of a given problem before deciding if any pattern is suitable. Once you decide that a pattern is suitable, instead of using the pattern implementation by the book, he advises to go on using design principles (SOLID, DRY, etc) to guide the development. This way the pattern would just be used as a reference of how the design might end being.
Subscribe to:
Posts (Atom)