Remote Ping-Pong Challenge: Your turn, who's next? (Java) 33
So I want to try a form of TDD using Ping-Pong. Problem is, you are not where I can pair with you directly. So I figured we’d try a slower-form. I’ll post the beginning of a problem. First person to post the next response “wins” – that’s where the next person should pick up from. We’ll continue until the problem is “finished.”
Interested? First the ground rules, then the problem and the starting code. This is Java. However, if someone responds in another language, that’s cool. I might try and follow up, but you’re welcome to do so yourself. I can imagine having multiple threads going on at the same time. (If you’d like your own language thread, ask and I’ll post another blog entry for that particular language.)
Ground Rules
- Follow the three rules of TDD + Refactoring.
- Fix the one failing test.
- Add one to three more tests before posting.
- Make sure you leave one and only one failing test for the next person to fix. (Meaning you can add two passing tests but leave a third test failing, or you can just add one failing test).
- You can/should refactor the test code and the production code
- If you feel a test is wrong, you may change it, but be prepared to justify it.
- I’ll serve as the customer, so I get to define what is “correct” – however, I can be argued with and I can lose arguments (see some of my other blog postings for evidence).
- Feel free to respond with comments/suggestions rather than additional tests.
- Feel free to apply refactorings like extract method, rename, split loop, ... Keep the code clean!
The Problem
Translate infix notation to postfix notation. Consider reviewing The Shunting Yard Algorithm. But that’s a guideline.The Start
Here is the test and production code. Note, when you respond, surround your code with one of the following pairs of HTML tags:- <typo:code>, and </typo:code>
- <pre>, and </pre>
InfixToPostfixConverterTest
package com.om.example;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class InfixToPostfixConverterTest {
private final String infix;
private final String expectedPostfix;
@Parameters
public static Collection<String[]> data() {
ArrayList<String[]> values = new ArrayList<String[]>();
addTestCase(values, null, "");
addTestCase(values, "", "");
addTestCase(values, "45", "45");
addTestCase(values, "+", "+");
addTestCase(values, "3 + 8", "3 8 +");
return values;
}
private static void addTestCase(ArrayList<String[]> values, String infix,
String expectedPostfix) {
values.add(new String[] { infix, expectedPostfix });
}
public InfixToPostfixConverterTest(String infix, String expectedPostfix) {
this.infix = infix;
this.expectedPostfix = expectedPostfix;
}
@Test
public void checkTranslation() {
InfixToPostfixConverter converter = new InfixToPostfixConverter();
String result = converter.translate(infix);
assertEquals(expectedPostfix, result);
}
}
InfixToPostfixConverter
package com.om.example;
public class InfixToPostfixConverter {
public String translate(String string) {
if(null == string)
return "";
return string;
}
}
I call your test cases and raise you some.
... by Brett, too many tests added: original content saved, however …
jwiklund,
I call foul ;-)
You nearly finished the problem and you added 8 individual tests. In the rules, it says you can add 3. Now I know that the term is ambiguous, but you added three test cases to one fixture and you added two fixtures, with 5 additional tests.
Sorry, ... Looks like you’ve nearly done it, by the way…
Tests (counted two times: added three, two pass one failing, so that should match the rules ;-) ):
and implementation:Actually, i don’t like the class OperatorHandler (can’t decide what’s worse: name or implementation ;-) ), but i could not think of a nice way to introduce a token-like type as jwiklund did. Hopefully, someone else can clean this up…
I prefer far smaller steps than Thomas, so here is my proposal:
Additional tests: Extended code for InfixToPostfixConverter:I of course wonder how long it will last until we have a complete solution taking such small steps, but that’s the interesting part of the experiment in my eyes…
Funny enough, after the first minutes i came up with exacly the same code than you… However, smaller steps are ok, so continuing from where you stopped:
Fixed your test and added one failing: Refactored the implementation:I must admit that I have run too often through your ShuntingYard tutorial, Brett. I added a test case for parantheses after fixing the precedence case. While doing so I was thinking about whether
InfixToPostfixConverterTest: InfixToPostfixConverter:3 + 8 + 6
gets3 8 6 + +
or3 8 + 6 +
. Here’s me code:Looks like you guys are tackling it pretty well.
To the issue of whether operators of the same precedence are lazily or aggressively processed, consider for source material:
on a calculator, for a series of additions, the thing that will drive one way versus the other is the size of the stack
Here the new and changed classes: The new converter using these classes and handling parentheses:
The new test class with two tests for PrecedenceChecker: And finally the fixed test and a new failing test for the converter: A final note: I feel more new unit tests would have been required before extracting the two new classes, meaning I shouldn’t have taken such a big step – but I was too impatient to refrain myself from doing it, so I guess I added to the technical debt of our little project – shame on me ;-).
In preparation for the “advanced parsing” you requested with the failing test, i did some refactorings trying to separate the construction of the token stream from it’s usage. During this task, i merged the two classes PrecedenceChecker and TokenClassifier into the class Token and changed InfixToPostfixConverter to use the Token type instead of Strings. Then i could extract a Tokenizer class responsible for the conversion from a String to an Iterable of Tokens.
However, after this about 30 minutes of refactorings, i now am unshure if this is too much overhead for this problem… So i stopped at this point (which means, the last test still fails) to ask you guys: What do you think? revert the changes i made and try some other way or continue from that point?
Here comes the code (omitting the unchanged InfixToPostfixConverterTest):
Thomas: For my part I’m happy with your refactorings – except for the Tokenizer interface which doesn’t seem necessary.
I’ve already prepared the next step (with 6 new tests: 5 new ones and a failing one – twice as many as defined to “compensate” for the missing tests in your step) but would like to wait for Brett’s opinion about our “cheating” before going any further.
ErikFK
How about this for an updated rule:
Sound reasonable?
However, sorry for this rather longish post and happy coding for whoever picks up ;-)
1 Actually, emma reports only ~75% due to the uncovered instructions generated by the compiler for the enumeration type…
I feel that we (or at least I) have bigger issues with the challenge itself. For example: Thomas’ points in his latest post are interesting and worth discussing – but I don’t think it would really make sense to try to address them here, as answers would require a few more blog entries – and we want to write a program to solve a problem here, don’t we? ;-).
What I want to say is the following: I totally miss the interaction with my peer. We don’t have a common strategy – how could we as we don’t talk about it? and writing about it is just not the same… – and therefore I find it hard to stay focused and motivated. I discover his move with the next post and can partially “read his thoughts” from the code, but the most important part is missing. As a consequence I miss the feeling of progress in solving the task, and the positive feedback loop of “real” pairing. It probably requires a quite specific state of mind to TDD/pair like this – or maybe it’s simply not possible.
To address (a very small part of) the issues Thomas is raising: I tend to think that we’ve taken too big steps every now and then (especially when introducing new classes). With the same amount of code we have now, I’d have written far more unit tests than we currently have.
Hi all,
I have been following this thread for the last week. Currently I am at university and have been looking for something which I could use to help me develop my OOP and TDD skills. This has been of great value to me. Anyway, as I say i have only been follwoing along so far but today I decided to try my own solution. It perhaps differs too much from the last solution. Feedback would be much appreciated – specifically if there are any big weaknesses in my design over the previous solution.
New tests:
Tokenizer
Operator:
Converter:
I wanted to create another class for the token handling code in the converter class but couldn’t think of a good way to do it. As I say feedback would be much appreciated.
?? ? ????
I dont even remember how i reached your site but it doesnt matter, cause i’m so happy i found it, it really made me think, keep up the good work.
she is not the happier
Great news! White iphone 4 Conversion Kit is now avaible! With hottest White color outlook can certainly catch your eyes and heart!
Haile Electric Industrial Co. Ltd. is the leading manufacturer and exporter of cold room,axial fan,condensing unit,centrifugal fan,shaded pole motor and refrigeration products in China.
Code is useful.
internette görüntülü olarak okey oyunu oyna, gerçek kisilerle tanis, turnuva heyecanini yasa.
????
??
Ltd. is the leading manufacturer and exporter of cold room,axial fan,condensing unit,centrifugal fan,shaded pole motor and refrigeration products in China.high quality headphones new design headphones
Designer fashion women replica shoulder bag from China for sale on line
Create the ultimate Home Theater Projector with a digital projector from InFocus in vvme. Then came the announcement on July 28-the industry’s first LCD-based 3D 1080p lcd projector was on its way. If you want an LCD projector for your beautiful LCD Projector Screen, you should take a look at the choices available at Go vvme. Shop and compare InFocus Meeting Room Projector and find supplies for your InFocus.
iPhone MP3 to Ringtone Maker can convert MP3 to iPhone/iPhone OS 3.0/3.1 Ringtone, even convert any video/audio to iphone ringtone.
What is next? We also want to know. It is really a good example that most of the programmer should think about this. If we want to do much better for the code. I should understand it. right? You are very good at this and show us good coding idea.
MANYADEAL.COM is professional for Ballast for HID? The kit comes complete with a Electronic HID Ballast, and it is Plug-n-Play. All necessary hardware for installation is included. Combined HID Slim Ballast and starter unit for better performance and easy installation for 55W Ballast.
Remote Ping-Pong Challenge: Your turn, who’s next? (Java) 30 good post101
Remote Ping-Pong Challenge: Your turn, who’s next? (Java) 31 hoo,good article!!I like the post!147
Our life is modifying promptly with the ralph lauren sale of the society. The modification is mostly come seal the fashionable goods according to the modification in fashion Pas Cher Women’s Ralph Lauren sale Vuitton Sacs. Well, otherwise, it Men’s Ralph Lauren shirts differs in many aspects due to ones gravy style. The gravy style broadly articulating demonstrates the personality and individuality of people.