The Roman numerals kata: TDD with and without analysis
Katas are small exercises that are repeatedly executed to improve one aspect of our programming capabilities - being design, automation, or a practice like Test-Driven Development. The Roman numerals kata attempts to create a conversion mechanism from integers to a Roman representation (a string): 1, 2 and 3 become I, II and III respectively. 5 and 10 become V and X respectively. 6 become VI, as symbols are additive. 4 becomes IV, as symbols are used subtractively (in this case subtracting 1 from 5) to avoid repeating a symbol more than three times in a row. If you have never tried the kata and want to do so in the future, I urge you to pick it up before reading further as I would spoil some of the experience for you. I recently executed the kata as a TDD exercise by myself and in a workshop in the local PHP user group in Milan. We reached two different solutions, and I want to analyze here why, and which is preferrable with regards to certain concerns. The solution is not the point of a kata: the experience (and what it teaches you) is; however, the roads you can take are part of the experience. The hardcore TDD solution When "pure" TDD is teached with this kata, one test is added at the time and production code is modified to make this test pass along with all the previously introduced ones. Then, a arbitrary long refactoring phase is performed to improve the code and prepare it to evolve further. Most of the solutions I found on the web (also in the form of videos) to compare them with mine went like this : private static final int[] VALUES = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; private static final String[] SYMBOLS = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }; public static String arabicToRoman(int arabic) { StringBuilder result = new StringBuilder(); int remaining = arabic; for (int i = 0; i < VALUES.length; i++) { remaining = appendRomanNumerals(remaining, VALUES[i], SYMBOLS[i], result); } return result.toString(); } I was not really satisfied with these kind of solutions as they are essentially an optimized lookup table more than a conversion algorithm. There is lots of duplication in this code: symbols like I and X are repeated in more than one subtractive form (IV and IX), and the subtractive rule itself is scattered among the values of the SYMBOLS array. If rules were to change (which does not happen in a kata but does in the real world), it would be difficult to adapt this code to cover Etruscan or Greek numerals, that have different models of subtractivity and symbol reuse. Again and again, TDD proved not sufficient (but facilitating) for algorithm generation; at least, for generating an algorithm well-factored enough to present changeable parts instead of a single procedure or a lookup table. How the domain comes into play If applying a pure red-green-refactor cycle cannot help us, what should we do? I took a look at Wikipedia, which is a good source to get acquainted with the domain of numerical systems (I stick to the Roman one however). Thus I discovered some interesting facts: the United States National Institute of Standards and Technology could find no authority that could describe if the year 1999 should be written as MDCCCCLXXXXVIIII, MCMXCIX, or MIM.[2] Despite the lack of standardization, an additional set of rules has been frequently applied for the last few hundred years Only one small-value symbol may be subtracted from any large-value symbol. The symbols "I", "X", "C", and "M" can be repeated three times in succession, but no more. (They may appear more than three times if they appear non-sequentially, such as XXXIX.) "D", "L", and "V" can never be repeated. "I" can be subtracted from "V" and "X" only. "X" can be subtracted from "L" and "C" only. "C" can be subtracted from "D" and "M" only. "V", "L", and "D" can never be subtracted. A number written in Arabic numerals can be broken into digits. For example, 1903 is composed of 1, 9, 0, and 3. To write the Roman numeral, each of the non-zero digits should be treated separately. In the above example, 1,000 = M, 900 = CM, and 3 = III. Therefore, 1903 = MCMIII. (All quotes are from http://en.wikipedia.org/wiki/Roman_numerals,) This knowledge is represented as a set of requirements, or can be seen as domain rules. By taking the time to find a source of knowledge about the domain of my application, I have extracted some relevant bits that can greatly simplify my model of the problem: We have clear requirements! Acceptance criteria are clearly defined as there are multiple possibilities for the numerical conversion. (1) There is a mechanism that is repeated across orders of magnitude: I is subtracted from 5 and 10, but X is subtracted from 50 and 100, and so on (2, 3, 4). We can divide the Arabic number into different ciphers and convert them separately, keeping in mind their position. Converting 42 becomes converting 40 and 2 plus a concatenation: 'XL' plus 'II'. Yet I couldn't find a single solution published online that leverages this important property to improve the code. Analysis-based solution Thus I set out to create a more flexible solution to the Roman numerals conversion problem. In this case I used only functions instead of objects to keep the solution clear for our user group audience, but I suspect that by introducing one or more classes such as OrderOfMagnitude and RomanCipher the code could speak for itself more clearly. I published on Github both this solution of mine and the classical one that we reached at the user group. function romanCipher($firstSymbol, $middleSymbol, $lastSymbol) { return function($number) use ($firstSymbol, $middleSymbol, $lastSymbol) { if ($number == 0) { return ''; } $symbols = array(1 => $firstSymbol, 5 => $middleSymbol, 10 => $lastSymbol); $roman = ''; foreach ($symbols as $denomination => $symbol) { if ($number == $denomination - 1) { return $firstSymbol . $symbol; } } foreach (array_reverse($symbols, true) as $denomination => $symbol) { while ($number >= $denomination) { $roman .= $symbol; $number -= $denomination; } } return $roman; }; } class RomanNumeralsTest extends PHPUnit_Framework_TestCase { public function setUp() { $this->toRoman = function($number) { $ciphers = array( '1' => romanCipher('I', 'V', 'X'), '2' => romanCipher('X', 'L', 'C'), '3' => romanCipher('C', 'D', 'M'), '4' => romanCipher('M', '?', '?'), ); $arabic = (string) $number; $fullRoman = ''; for ($i = 0; $i < strlen($arabic); $i++) { $position = strlen($arabic) - $i; $cipher = $ciphers[$position]; $fullRoman .= $cipher($arabic{$i}); } return $fullRoman; }; } ... The code is longer than the classic solution; but isn't well-factored code always a bit longer than a brute force version? I also found out that I could write more focused tests that collected domain properties; while refactoring I renamed tests from: public function test4IsConvertedToIV() ... public function test124ISConvertedToCXXIV() to: public function testSmallerSymbolsOnTheLeftAreSubtractive() ... public function testEvenNumbersGreaterThan100CanBeDividedIntoCiphers() { $this->assertEquals('C' . 'XX' . 'IV', $this->toRoman(124)); $this->assertEquals('CM' . 'XC' . 'IX', $this->toRoman(999)); } Conclusions I presented TDD at our workshop as a facilitating condition for writing clean code, but not as a sufficient one. Analysis is not dead and writing tests or jumping into coding some spike is not the only way you have to approach a problem. To be fair, the pure TDD approach let everyone reach a working solution, covered by automated tests; in many utility components of your application, such a result proves useful as you can write code that works and clean it up as much as you need (and no further). If numerical conversions aren't your core domain, you can just go for the brute force code where its complexity is manageable; just like you could go for bubble sort in case you needed to sort only a dozen of elements.
July 16, 2012
·
27,559 Views
·
0 Likes
Comments
Feb 20, 2018 · Giorgio Sironi
Hi John,
consider this article is from 2011, so web standards have progressed. For an up-to-date guide, look at MDN: https://developer.mozilla.org/en-US/Apps/Fundamentals/Offline
Sep 24, 2014 · Alvin Ashcraft
Hi Fabien,
you're not obliged to write different services in different languages, but only have the option to do so. Actually if I had to choose different languages I would not pick three languages so similar in approach: for example R for a project that does data mining and Java for the web applications.
Also, you should consider not only the number of interfaces but their size too. You have N interfaces instead of a big one, but each of them is easier to reason about as it exposed 1/Nth of the APIs.
Apr 07, 2014 · Mr B Loid
I tend to say you can't test your way to thread safety, it's not an efficient mean to discover design problem unless it's your application primary focus (you develop a database).
I give different resources to processes to avoid these concurrency issues (database 1..N to each PHPUnit process simultaneously run) or exercise different aggregates (a new customer for each test) to avoid interactions. Tests must be independent to be reliable.
Apr 07, 2014 · Mr B Loid
I tend to say you can't test your way to thread safety, it's not an efficient mean to discover design problem unless it's your application primary focus (you develop a database).
I give different resources to processes to avoid these concurrency issues (database 1..N to each PHPUnit process simultaneously run) or exercise different aggregates (a new customer for each test) to avoid interactions. Tests must be independent to be reliable.
Apr 07, 2014 · Mr B Loid
I tend to say you can't test your way to thread safety, it's not an efficient mean to discover design problem unless it's your application primary focus (you develop a database).
I give different resources to processes to avoid these concurrency issues (database 1..N to each PHPUnit process simultaneously run) or exercise different aggregates (a new customer for each test) to avoid interactions. Tests must be independent to be reliable.
Apr 07, 2014 · Giorgio Sironi
I tend to say you can't test your way to thread safety, it's not an efficient mean to discover design problem unless it's your application primary focus (you develop a database).
I give different resources to processes to avoid these concurrency issues (database 1..N to each PHPUnit process simultaneously run) or exercise different aggregates (a new customer for each test) to avoid interactions. Tests must be independent to be reliable.
Apr 07, 2014 · Giorgio Sironi
I tend to say you can't test your way to thread safety, it's not an efficient mean to discover design problem unless it's your application primary focus (you develop a database).
I give different resources to processes to avoid these concurrency issues (database 1..N to each PHPUnit process simultaneously run) or exercise different aggregates (a new customer for each test) to avoid interactions. Tests must be independent to be reliable.
Apr 07, 2014 · Giorgio Sironi
I tend to say you can't test your way to thread safety, it's not an efficient mean to discover design problem unless it's your application primary focus (you develop a database).
I give different resources to processes to avoid these concurrency issues (database 1..N to each PHPUnit process simultaneously run) or exercise different aggregates (a new customer for each test) to avoid interactions. Tests must be independent to be reliable.
Sep 18, 2013 · Christophe Coenraets
Believe me, I trust test suites and I currently work on projects with several thousands of unit and end2end tests running in CI. It's just that when you become very good at removing functional defects, the only kind you see is related to the categories list above. A list that is by no means exhaustive, let's just think about usability...
What I meant in the passage was automated testing is possible for some non-functional requirements (performance, via stress test) but not possible or very difficult other non-functional requirements (security). It's a spectrum.
Sep 18, 2013 · Christophe Coenraets
Believe me, I trust test suites and I currently work on projects with several thousands of unit and end2end tests running in CI. It's just that when you become very good at removing functional defects, the only kind you see is related to the categories list above. A list that is by no means exhaustive, let's just think about usability...
What I meant in the passage was automated testing is possible for some non-functional requirements (performance, via stress test) but not possible or very difficult other non-functional requirements (security). It's a spectrum.
Sep 18, 2013 · Christophe Coenraets
Believe me, I trust test suites and I currently work on projects with several thousands of unit and end2end tests running in CI. It's just that when you become very good at removing functional defects, the only kind you see is related to the categories list above. A list that is by no means exhaustive, let's just think about usability...
What I meant in the passage was automated testing is possible for some non-functional requirements (performance, via stress test) but not possible or very difficult other non-functional requirements (security). It's a spectrum.
Sep 15, 2013 · Nancy Bhullar
Aug 03, 2013 · Mike Gong
Apr 06, 2013 · topnotch
Originally written on April 1st. :) You're right on the path, delivering 3 features that work correctly is always better than 6 features that don't.
Apr 03, 2013 · topnotch
> In any case it was a temporary solution until a more definitive and imminent (!) solution should have been deployed. Right ?
I've seen even genre-savy people falling victim of this. Any new code that goes into production has to be tested somewhat, and the cost of unit-level tests is not higher than manual testing if you are good at writing tests. What is not comparable is the cost a procedural programmer bears in writing a test with respect to the cost an experienced TDDer does.
Apr 03, 2013 · topnotch
> In any case it was a temporary solution until a more definitive and imminent (!) solution should have been deployed. Right ?
I've seen even genre-savy people falling victim of this. Any new code that goes into production has to be tested somewhat, and the cost of unit-level tests is not higher than manual testing if you are good at writing tests. What is not comparable is the cost a procedural programmer bears in writing a test with respect to the cost an experienced TDDer does.
Apr 01, 2013 · topnotch
I agree that red tests without production code do not produce value. However when following TDD is usually impossible to get in this situation because the cycle of test code/production code is only some minutes long: you can't have more than 1 or 2 tests written on missing code at the same time.
Apr 01, 2013 · topnotch
I agree that red tests without production code do not produce value. However when following TDD is usually impossible to get in this situation because the cycle of test code/production code is only some minutes long: you can't have more than 1 or 2 tests written on missing code at the same time.
Apr 01, 2013 · topnotch
Nicolas,
humor articles are common, but this is part of the rules for April Fools' Day :)
Apr 01, 2013 · topnotch
Nicolas,
humor articles are common, but this is part of the rules for April Fools' Day :)
Apr 01, 2013 · topnotch
Nicolas,
humor articles are common, but this is part of the rules for April Fools' Day :)
Dec 13, 2012 · Mr B Loid
Yes, thank you for ponting it out (#goos is the hashtag used to talk about this book). I've inserted the links to the relevant books in the article.
Dec 13, 2012 · Mr B Loid
Yes, thank you for ponting it out (#goos is the hashtag used to talk about this book). I've inserted the links to the relevant books in the article.
Oct 01, 2012 · Mr B Loid
I have addressed this question multiple times; the problem is that the person experiencing flow by definition loses track of time while being neck-deep into the task. So it's easy to feel very productive, but spending 3 hours in refactoring endlessly or covering very rare error cases. The timer ringing helps me in at least two ways:
Oct 01, 2012 · Mr B Loid
I have addressed this question multiple times; the problem is that the person experiencing flow by definition loses track of time while being neck-deep into the task. So it's easy to feel very productive, but spending 3 hours in refactoring endlessly or covering very rare error cases. The timer ringing helps me in at least two ways:
Oct 01, 2012 · Mr B Loid
I have addressed this question multiple times; the problem is that the person experiencing flow by definition loses track of time while being neck-deep into the task. So it's easy to feel very productive, but spending 3 hours in refactoring endlessly or covering very rare error cases. The timer ringing helps me in at least two ways:
Jun 12, 2012 · Lincoln Baxter
Apr 10, 2012 · Amilia Crux
Mar 30, 2012 · Southern Crossian
Mar 27, 2012 · Southern Crossian
Mar 27, 2012 · Vincent Rabah
Mar 23, 2012 · Kristen Nicole
Mar 15, 2012 · Prasant Lokinendi
Mar 14, 2012 · Mr B Loid
Mar 14, 2012 · Mr B Loid
Mar 14, 2012 · Mr B Loid
Mar 13, 2012 · Southern Crossian
Mar 09, 2012 · Tim Buschtöns
Mar 09, 2012 · Southern Crossian
Mar 09, 2012 · Djaka Pribadi Maulana
Mar 02, 2012 · Rob Gordon
Feb 26, 2012 · Gökhan Kaya
Feb 23, 2012 · Giorgio Sironi
Feb 22, 2012 · Giorgio Sironi
Jan 29, 2012 · Wallace Yeung
Jan 29, 2012 · Wallace Yeung
Jan 23, 2012 · Aman Jha
Jan 23, 2012 · Prasant Lokinendi
Jan 21, 2012 · Wallace Yeung
Jan 21, 2012 · Wallace Yeung
Jan 21, 2012 · Wallace Yeung
Jan 21, 2012 · Wallace Yeung
Jan 19, 2012 · Aman Jha
Jan 17, 2012 · Aman Jha
Jan 03, 2012 · jon harrop
Jan 03, 2012 · jon harrop
Jan 03, 2012 · jon harrop
Jan 03, 2012 · jon harrop
Jan 03, 2012 · Giorgio Sironi
Jan 03, 2012 · Giorgio Sironi
Jan 03, 2012 · Giorgio Sironi
Jan 03, 2012 · Giorgio Sironi
Jan 01, 2012 · Travis Tilley
Jan 01, 2012 · Travis Tilley
Jan 01, 2012 · Travis Tilley
Jan 01, 2012 · Travis Tilley
Dec 07, 2011 · Gerd Storm
Dec 07, 2011 · Gerd Storm
Dec 07, 2011 · Gerd Storm
Dec 07, 2011 · Gerd Storm
Nov 20, 2011 · Gerd Storm
It was meant as two separate snippets, thanks.
Next week I will explore Puppet and will for sure learn how to make it behave correctly in this situations. :)
Nov 20, 2011 · Gerd Storm
Nov 20, 2011 · Gerd Storm
Nov 20, 2011 · Gerd Storm
Nov 16, 2011 · Mr B Loid
Nov 16, 2011 · Mr B Loid
Nov 16, 2011 · Mr B Loid
Nov 16, 2011 · Mr B Loid
Nov 13, 2011 · Gerd Storm
Nov 13, 2011 · Gerd Storm
Nov 13, 2011 · Gerd Storm
Nov 13, 2011 · Gerd Storm
Nov 09, 2011 · Gerd Storm
Nov 09, 2011 · Gerd Storm
Nov 09, 2011 · Gerd Storm
Nov 06, 2011 · Patrick Wolf
Nov 04, 2011 · Mr B Loid
Oct 23, 2011 · Mohammad Nour
Oct 23, 2011 · Mohammad Nour
Oct 23, 2011 · Mohammad Nour
Oct 21, 2011 · Mohammad Nour
Oct 21, 2011 · Mohammad Nour
Oct 21, 2011 · Mohammad Nour
Oct 21, 2011 · Mohammad Nour
Oct 21, 2011 · Mohammad Nour
Oct 21, 2011 · Mohammad Nour
Oct 21, 2011 · Mohammad Nour
Oct 20, 2011 · Mohammad Nour
Oct 20, 2011 · Mohammad Nour
Oct 20, 2011 · Mohammad Nour
Oct 18, 2011 · Giorgio Sironi
Oct 09, 2011 · Giorgio Sironi
Oct 09, 2011 · Giorgio Sironi
Oct 09, 2011 · Giorgio Sironi
Oct 05, 2011 · Giorgio Sironi
Oct 02, 2011 · Gerd Storm
Sep 26, 2011 · Mr B Loid
Sep 26, 2011 · Mr B Loid
Sep 26, 2011 · Mr B Loid
Sep 06, 2011 · Giorgio Sironi
Aug 05, 2011 · Mr B Loid
Aug 03, 2011 · Gerd Storm
Jul 20, 2011 · prashant.jalasutram
Jul 20, 2011 · prashant.jalasutram
Jul 20, 2011 · prashant.jalasutram
Jul 20, 2011 · prashant.jalasutram
Jul 19, 2011 · prashant.jalasutram
Jul 08, 2011 · Giorgio Sironi
Jul 08, 2011 · Giorgio Sironi
Jul 05, 2011 · Tony Thomas
Jul 05, 2011 · Tony Thomas
Jul 05, 2011 · Tony Thomas
Jul 05, 2011 · Tony Thomas
Jun 29, 2011 · Giorgio Sironi
May 29, 2011 · Mr B Loid
@Caner, take a look here:
https://github.com/giorgiosironi/Chansonnier/tree/master/chansonnier/it.polimi.chansonnier.driver.lyricwiki/code/src/it/polimi/chansonnier/driver/lyricwiki
May 29, 2011 · Mr B Loid
@Caner, take a look here:
https://github.com/giorgiosironi/Chansonnier/tree/master/chansonnier/it.polimi.chansonnier.driver.lyricwiki/code/src/it/polimi/chansonnier/driver/lyricwiki
May 29, 2011 · Mr B Loid
@Caner, take a look here:
https://github.com/giorgiosironi/Chansonnier/tree/master/chansonnier/it.polimi.chansonnier.driver.lyricwiki/code/src/it/polimi/chansonnier/driver/lyricwiki
Apr 28, 2011 · Nick Landry
Apr 28, 2011 · Nick Landry
Apr 28, 2011 · Nick Landry
Apr 28, 2011 · Nick Landry
Apr 28, 2011 · Nick Landry
Apr 28, 2011 · Nick Landry
Apr 28, 2011 · Nick Landry
Apr 28, 2011 · Nick Landry
Apr 28, 2011 · Nick Landry
Apr 16, 2011 · Giorgio Sironi
Apr 08, 2011 · Giorgio Sironi
Feb 27, 2011 · Giorgio Sironi
Feb 27, 2011 · Giorgio Sironi
Feb 27, 2011 · Giorgio Sironi
Feb 25, 2011 · Gerd Storm
Feb 25, 2011 · Gerd Storm
Feb 25, 2011 · Gerd Storm
Feb 22, 2011 · Giorgio Sironi
Feb 22, 2011 · Giorgio Sironi
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 10, 2011 · Gerard Laflaque
Feb 02, 2011 · Alex Miller
Feb 02, 2011 · Alex Miller
Feb 02, 2011 · Alex Miller
Feb 02, 2011 · Alex Miller
Jan 26, 2011 · Lebon Bon Lebon
Jan 26, 2011 · Lebon Bon Lebon
Jan 26, 2011 · Lebon Bon Lebon
Jan 26, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 25, 2011 · Lebon Bon Lebon
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 23, 2011 · Michael Meehan
Jan 16, 2011 · Gerd Storm
Jan 14, 2011 · Gerd Storm
Jan 14, 2011 · Gerd Storm
Jan 14, 2011 · Gerd Storm
Jan 14, 2011 · Gerd Storm
Jan 10, 2011 · Kaveh Shahbazian
Jan 10, 2011 · Kaveh Shahbazian
Jan 10, 2011 · Kaveh Shahbazian
Jan 10, 2011 · Kaveh Shahbazian
Jan 10, 2011 · mitchp
Jan 10, 2011 · mitchp
Jan 10, 2011 · mitchp
Jan 10, 2011 · mitchp
Jan 04, 2011 · Jon Davis
Jan 04, 2011 · Jon Davis
Jan 04, 2011 · Jon Davis
Dec 14, 2010 · Daniel Murley
Dec 14, 2010 · Daniel Murley
Dec 14, 2010 · Daniel Murley
Dec 14, 2010 · Daniel Murley
Nov 30, 2010 · Giorgio Sironi
Nov 30, 2010 · Cesar Rodas
Nov 30, 2010 · Cesar Rodas
Nov 26, 2010 · Mr B Loid
Nov 26, 2010 · Mr B Loid
Nov 26, 2010 · Mr B Loid
Nov 09, 2010 · Mr B Loid
Nov 01, 2010 · Stefan Koopmanschap
Nov 01, 2010 · Stefan Koopmanschap
Nov 01, 2010 · Stefan Koopmanschap
Nov 01, 2010 · Stefan Koopmanschap
Oct 27, 2010 · Mr B Loid
Oct 27, 2010 · Mr B Loid
Oct 27, 2010 · Mr B Loid
Oct 27, 2010 · Mr B Loid
Oct 21, 2010 · Manuel Jordan
Oct 21, 2010 · Giorgio Sironi
Oct 19, 2010 · Gerd Storm
Oct 19, 2010 · Gerd Storm
Oct 19, 2010 · Gerd Storm
Oct 19, 2010 · Gerd Storm
Oct 12, 2010 · Emanuele Bonanni
Oct 12, 2010 · Emanuele Bonanni
Oct 04, 2010 · Mr B Loid
Oct 04, 2010 · Mr B Loid
Oct 04, 2010 · Mr B Loid
Oct 04, 2010 · Mr B Loid
Sep 30, 2010 · Mr B Loid
Sep 30, 2010 · Mr B Loid
Sep 30, 2010 · Mr B Loid
Sep 30, 2010 · Mr B Loid
The tools available in a language effectively shape the solutions developed with it, to the point that for example the Python motto is the exact contrary of Perl's one, privileging consistency and simplicity over adding a bunch of features to a language like PHP and Perl do:
Sep 30, 2010 · Mr B Loid
The tools available in a language effectively shape the solutions developed with it, to the point that for example the Python motto is the exact contrary of Perl's one, privileging consistency and simplicity over adding a bunch of features to a language like PHP and Perl do:
Sep 30, 2010 · Mr B Loid
The tools available in a language effectively shape the solutions developed with it, to the point that for example the Python motto is the exact contrary of Perl's one, privileging consistency and simplicity over adding a bunch of features to a language like PHP and Perl do:
Sep 30, 2010 · Mr B Loid
It's not an all or nothing proposition, every idea is independent from the others. :)
As other commenters pointed out, public fields shouldn't be the default (but private ones should). About the static methods, keeping them on an instance is useful also for providing a seam other than to ensure no global state is maintained.
For LSP, many outiright violations come fromlarge class hierarchies. Eliminating subclassing of concrete classes would be a step in the simplifying direction.
Sep 30, 2010 · Mr B Loid
It's not an all or nothing proposition, every idea is independent from the others. :)
As other commenters pointed out, public fields shouldn't be the default (but private ones should). About the static methods, keeping them on an instance is useful also for providing a seam other than to ensure no global state is maintained.
For LSP, many outiright violations come fromlarge class hierarchies. Eliminating subclassing of concrete classes would be a step in the simplifying direction.
Sep 30, 2010 · Mr B Loid
Removing it is probably too much, but "coding without ifs" is a diffused exercise in object-oriented and functional programming circles:
http://www.google.com/search?q=coding+without+ifs
Sep 30, 2010 · Mr B Loid
Removing it is probably too much, but "coding without ifs" is a diffused exercise in object-oriented and functional programming circles:
http://www.google.com/search?q=coding+without+ifs
Sep 30, 2010 · Mr B Loid
Removing it is probably too much, but "coding without ifs" is a diffused exercise in object-oriented and functional programming circles:
http://www.google.com/search?q=coding+without+ifs
Sep 30, 2010 · Mr B Loid
Removing it is probably too much, but "coding without ifs" is a diffused exercise in object-oriented and functional programming circles:
http://www.google.com/search?q=coding+without+ifs
Sep 30, 2010 · Mr B Loid
Sep 30, 2010 · Mr B Loid
Sep 30, 2010 · Mr B Loid
Sep 30, 2010 · Mr B Loid
Sep 18, 2010 · Vladimir Carrer
Sep 18, 2010 · Vladimir Carrer
Sep 18, 2010 · Vladimir Carrer
Sep 18, 2010 · Vladimir Carrer
Sep 14, 2010 · Vladimir Carrer
Sep 14, 2010 · Vladimir Carrer
Sep 14, 2010 · Vladimir Carrer
Sep 12, 2010 · nick halstead
Why do you feel that private and protected scopes do not have a place in interpreted languages? They are really about encapsulation, and I daily thank everyone who has kept a methods with an as strict as possible visibility: for example I can easily refactor a private method by looking only at the source code of its own class, being sure of not breaking any other client code. In fact, Python is interpreted and has private methods.
Besides that, the OO paradigm of PHP 5 borrows heavily from Java, and with its object handlers system gives the possibility of building large object graphs like the ones of frameworks such as Zend or symfony. There is still much work to be done however - SPL really sucks from a design point of view (its component are used for performance), and things like collections or lists still have to be created in userland code.
Sep 12, 2010 · nick halstead
Why do you feel that private and protected scopes do not have a place in interpreted languages? They are really about encapsulation, and I daily thank everyone who has kept a methods with an as strict as possible visibility: for example I can easily refactor a private method by looking only at the source code of its own class, being sure of not breaking any other client code. In fact, Python is interpreted and has private methods.
Besides that, the OO paradigm of PHP 5 borrows heavily from Java, and with its object handlers system gives the possibility of building large object graphs like the ones of frameworks such as Zend or symfony. There is still much work to be done however - SPL really sucks from a design point of view (its component are used for performance), and things like collections or lists still have to be created in userland code.
Sep 12, 2010 · nick halstead
Why do you feel that private and protected scopes do not have a place in interpreted languages? They are really about encapsulation, and I daily thank everyone who has kept a methods with an as strict as possible visibility: for example I can easily refactor a private method by looking only at the source code of its own class, being sure of not breaking any other client code. In fact, Python is interpreted and has private methods.
Besides that, the OO paradigm of PHP 5 borrows heavily from Java, and with its object handlers system gives the possibility of building large object graphs like the ones of frameworks such as Zend or symfony. There is still much work to be done however - SPL really sucks from a design point of view (its component are used for performance), and things like collections or lists still have to be created in userland code.
Aug 22, 2010 · Mr B Loid
Aug 22, 2010 · Mr B Loid
Aug 20, 2010 · Stephen Gallo
Aug 20, 2010 · Stephen Gallo
Aug 20, 2010 · Stephen Gallo
Aug 20, 2010 · Stephen Gallo
Aug 18, 2010 · Stephen Gallo
Baudot code and telegraphs? However ASCII is the eldest character set still relevant today, since UTF-8 uses the same mapping (on 8-bit) for Latin English characters. Everything else is out of the scope of this article which was by intention and title as shortest as possible. :)
Aug 18, 2010 · Stephen Gallo
Baudot code and telegraphs? However ASCII is the eldest character set still relevant today, since UTF-8 uses the same mapping (on 8-bit) for Latin English characters. Everything else is out of the scope of this article which was by intention and title as shortest as possible. :)
Aug 18, 2010 · Stephen Gallo
Baudot code and telegraphs? However ASCII is the eldest character set still relevant today, since UTF-8 uses the same mapping (on 8-bit) for Latin English characters. Everything else is out of the scope of this article which was by intention and title as shortest as possible. :)
Jul 26, 2010 · Mr B Loid
Jul 26, 2010 · Mr B Loid
Jul 26, 2010 · Mr B Loid
Jul 16, 2010 · Mr B Loid
Your suggestions are welcome, although url rewriting is already cited in the article (not as my favorite).
Articles on DZone are published on multiple zones - this one wa not only targeted to the Java one.
Jul 16, 2010 · Mr B Loid
Your suggestions are welcome, although url rewriting is already cited in the article (not as my favorite).
Articles on DZone are published on multiple zones - this one wa not only targeted to the Java one.
Jul 16, 2010 · Mr B Loid
Your suggestions are welcome, although url rewriting is already cited in the article (not as my favorite).
Articles on DZone are published on multiple zones - this one wa not only targeted to the Java one.
Jul 15, 2010 · Mr B Loid
Jul 15, 2010 · Mr B Loid
Jul 15, 2010 · Mr B Loid
Jul 15, 2010 · Mr B Loid
Jul 09, 2010 · Schalk Neethling
Jul 09, 2010 · Schalk Neethling
Jul 09, 2010 · Schalk Neethling
Jul 09, 2010 · Schalk Neethling
Jul 09, 2010 · Schalk Neethling
Jul 09, 2010 · Schalk Neethling
Jul 08, 2010 · Schalk Neethling
Jul 08, 2010 · Schalk Neethling
Jul 08, 2010 · Schalk Neethling
Jun 30, 2010 · Mr B Loid
Jun 30, 2010 · Mr B Loid
Jun 30, 2010 · Mr B Loid
Jun 30, 2010 · Mr B Loid
Jun 30, 2010 · Mr B Loid
Jun 29, 2010 · Mr B Loid
Jun 29, 2010 · Mr B Loid
Jun 29, 2010 · Mr B Loid
Jun 29, 2010 · Mr B Loid
Jun 24, 2010 · Tony Thomas
I know the motif of the movement, the opening was more a pun on the motto than a critic. I "ordered" yesterday a Green Wrist Band from Object Mentor. :) Moreover it's also a pun on the expression red bar / green bar.
I fel that "lowering the bar" was an appropriate title because it's exactly the situation of having written a test which is too difficult to satisfy, like a bar too difficult to pass in high jump, in the athletics metaphor. Athletes never lower the bar, but we can. So its only a title, I didn't mean to offend the Software Craftsmanship movement, which I really admire.
Jun 24, 2010 · Tony Thomas
I know the motif of the movement, the opening was more a pun on the motto than a critic. I "ordered" yesterday a Green Wrist Band from Object Mentor. :) Moreover it's also a pun on the expression red bar / green bar.
I fel that "lowering the bar" was an appropriate title because it's exactly the situation of having written a test which is too difficult to satisfy, like a bar too difficult to pass in high jump, in the athletics metaphor. Athletes never lower the bar, but we can. So its only a title, I didn't mean to offend the Software Craftsmanship movement, which I really admire.
Jun 24, 2010 · Tony Thomas
I know the motif of the movement, the opening was more a pun on the motto than a critic. I "ordered" yesterday a Green Wrist Band from Object Mentor. :) Moreover it's also a pun on the expression red bar / green bar.
I fel that "lowering the bar" was an appropriate title because it's exactly the situation of having written a test which is too difficult to satisfy, like a bar too difficult to pass in high jump, in the athletics metaphor. Athletes never lower the bar, but we can. So its only a title, I didn't mean to offend the Software Craftsmanship movement, which I really admire.
Jun 17, 2010 · Mr B Loid
Jun 17, 2010 · Mr B Loid
Jun 17, 2010 · Mr B Loid
Jun 15, 2010 · Mr B Loid
Jun 15, 2010 · Mr B Loid
Jun 15, 2010 · Mr B Loid
Jun 11, 2010 · Tony Thomas
Jun 11, 2010 · Tony Thomas
Jun 11, 2010 · Tony Thomas
Jun 10, 2010 · Tony Thomas
I'm not sure this would work in my case for a few reasons:
- I am in an OSGi environment, and I kept Solr as an external app for now.
- I need already to extend other TestCase
- I need a real SolrServer since I'm testing that an HTML page makes HTTP requests to it via JavaScript.
I transitioned to keeping Solr running all the time and resetting it in every acceptance test setUp() now.
Jun 10, 2010 · Tony Thomas
I'm not sure this would work in my case for a few reasons:
- I am in an OSGi environment, and I kept Solr as an external app for now.
- I need already to extend other TestCase
- I need a real SolrServer since I'm testing that an HTML page makes HTTP requests to it via JavaScript.
I transitioned to keeping Solr running all the time and resetting it in every acceptance test setUp() now.
Jun 10, 2010 · Tony Thomas
I'm not sure this would work in my case for a few reasons:
- I am in an OSGi environment, and I kept Solr as an external app for now.
- I need already to extend other TestCase
- I need a real SolrServer since I'm testing that an HTML page makes HTTP requests to it via JavaScript.
I transitioned to keeping Solr running all the time and resetting it in every acceptance test setUp() now.
Jun 10, 2010 · Tony Thomas
Jun 10, 2010 · Tony Thomas
Jun 10, 2010 · Tony Thomas
Jun 10, 2010 · Tony Thomas
May 06, 2010 · Mr B Loid
May 06, 2010 · Mr B Loid
May 06, 2010 · Mr B Loid
May 06, 2010 · Mr B Loid
May 05, 2010 · Mr B Loid
May 05, 2010 · Mr B Loid
May 05, 2010 · Mr B Loid
May 05, 2010 · Mr B Loid
Apr 29, 2010 · Mr B Loid
In my opinion the scheme is simple.
Jobs: No proprietary layer on top of iPhone OS! Otherwise me and you would be at the mercy of Adobe! We are for open standards!
Developer: So I must develop applications that run only on the proprietary iPhone OS?
Jobs: Exactly.
Compare that with Android, an open platform for real...
Apr 27, 2010 · Giorgio Sironi
Apr 19, 2010 · mitchp
Apr 18, 2010 · Abhishek Rakshit
Apr 18, 2010 · mitchp
Apr 16, 2010 · Giorgio Sironi
Apr 07, 2010 · Phillip Howard
Apr 07, 2010 · Phillip Howard
Apr 07, 2010 · Phillip Howard
Apr 07, 2010 · James Sugrue
Apr 07, 2010 · James Sugrue
Apr 07, 2010 · James Sugrue
Apr 01, 2010 · Tony Thomas
Mar 27, 2010 · Giorgio Sironi
Mar 23, 2010 · Peter Thomas
Mar 05, 2010 · Giorgio Sironi
Feb 24, 2010 · Giorgio Sironi
Feb 23, 2010 · Justin Sargent
Feb 22, 2010 · Justin Sargent
Feb 16, 2010 · Justin Sargent
Feb 06, 2010 · Giorgio Sironi
Jan 15, 2010 · Giorgio Sironi
Dec 08, 2009 · German Escobar
Oct 14, 2009 · Giorgio Sironi
Oct 12, 2009 · Tony Thomas
Sep 23, 2009 · Ken Hess
Sep 23, 2009 · dhaval shah
Sep 14, 2009 · Shekhar Gulati
Sep 14, 2009 · Giorgio Sironi
Aug 21, 2009 · Giorgio Sironi
Aug 03, 2009 · Giorgio Sironi
Jul 19, 2009 · Peter Horner
Jul 10, 2009 · Ken Hess
Jul 06, 2009 · Donny Donny
Jul 06, 2009 · Donny Donny
Jul 02, 2009 · Mr B Loid
May 29, 2009 · Giorgio Sironi
Apr 23, 2009 · Giorgio Sironi
Apr 02, 2009 · Ann Oreshnikova
Mar 18, 2009 · Giorgio Sironi