Is TDD Language Neutral? 119

Posted by Brett Schuchert Tue, 09 Feb 2010 15:38:00 GMT

On another blog, a commenter wrote (I’m leaving names out, though you can see the original blog if you look):
I don’t think that it makes sense to say “teach a TDD class in several languages simultaneously”. TDD is a language-independent technique.

What follows is a slightly changed version of my response. What I’m wondering is this: Do you think the practice of TDD is fundamentally impacted by your programming language?

Read on for my response. You might want to add a comment before reading my response to avoid “group think.”

Based on the original comment, I started with: It seems to me that you’ve not written professionally in many different languages. Or if you have, you’ve not effectively used those different programming languages.

Now let me be a bit more clear. Java and C++ are different languages, to be sure. However, they are both class-based, statically typed languages without lambdas (well C++ and Java will both be getting them, but they don’t have them now).

Contrast Java and C++ with Smaltalk and Self. Smalltalk is class based and supports inheritance but it is dynamically typed. Self is object-oriented, but it does not have classes. In fact, it technically does not have inheritance, but it fully supports OOP. How? Delegation. JavaScript is closer to Self than it is to Smalltalk. But JavaScript, Self and Smalltalk are all closer than C++, Java, C# and Objective-C.

How about the Open/Closed principle? How I interpret that design principle depends on the context (language) in which work. In raw Java, what I think needs to be closed is different than say raw Ruby. If I add Aspect Oriented Programming into the mix (yes, I’ve actually written and deployed systems that used Aspect J – in a limited fashion), then that opens things up a bit, but still not as much as in Ruby.

In Smalltalk, the closest analog to static methods are class methods. However, a class method in Smalltalk is actually an instance method on a class object, which is a subclass of the Class class. (Yes, that’s what I meant.)

Why is this important? When I’m working with legacy code in C++/Java/C#/VB.Net – languages where static methods are never dynamically bound, I avoid using static methods and, in fact, I redesign using what Michel Feathers calls “Introducing an Instance Delegator”.

In Smalltalk, this technique is irrelevant and unnecessary.

In languages like JavaScript, Self, Smaltalk, Ruby, etc., interfaces are not really necessary. Sure you can use them, but they are more for documentation.

Consider templates in C++ versus generics in Java. In Java, generics experience type erasure so you often need to use interfaces with generics – or at least tell the compiler a type it can assume will always be used with a generic. In C++, the most you really need to do is let the complier know that a template parameter is a typename as opposed to a primitive. When the code is compiled, any implied requirements of the type parameter will either be satisfied or not. (Woe be it to you if they are not!)

Why? In Java, generics are syntactic sugar. C++ generates a unique class for each template occurrence. C# is much closer to C++ than Java in this respect. Java got it wrong (in my opinion) – though what they did add did improve the language a bit.

How about moving away from OO languages? Scala is a mixed language, as is F#. Haskel is not. Lisp as well. How you break a problem into parts is (or at least should be) different in these languages. I don’t mean different in syntax, to be sure it will be. I mean how you break a problem into its parts is fundamentally different in pure functional languages than OO languages.

Or consider COBOL. I’ve programmed in it. I can thank COBOL for my touch-typing skills. COBOL is yet a different kind of language. Yes, syntactically, but that’s not the interesting difference. COBOL is a record-oriented processing language. It is well suited to batch processing. AWK is similar in this respect as is SNOBOL. (I’ve used AWK quite a bit, and I’ve used a variant of SNOBOL called SPITBOL as well.)

Let’s continue with a building analogy. If all I have to build is bamboo then I have available to me certain techniques for building a house. If I have steel, I have different alternatives. The design of my house will be directly impacted by the media (language) available.

Additionally, if I’m building on clay versus bedrock, I will also make fundamentally different design issues. When I lived in Texas I had a floating slab foundation, which were common for several reasons: cost, temperature zone, available building materials. Texas was the first place I lived that did not in general have basements. The other option, pier and beam, was no longer practiced in general due to cost.

I’m originally from the Mid-West (Iowa). In Iowa, buildings are built such that their foundation is below the frost line. The frost line was something like 30” (I’m remembering something from 20 – 30 years ago). So all the houses had basements. Or if not basements, half-basements.

The same kinds of things can be said about programming languages as well as their ecosystems as well as the political environment. I’ve already made the language point above. But what about the political environment?

I have worked at places where open source was forbidden. So this rules out Hibernate and Spring. Taking away these tools does not stop me from building a system, but it does have an impact on gross assignment of responsibility, which is an important component of software architecture.

Now, back down to a TDD class. When I teach TDD, I am not teaching just TDD. Furthermore, I am not just talking about TDD. I want students to apply the practice. So I start with a problem – a requirements statement. That does not initially vary with the language. In practice it eventually does for several reasons:

  • How far the class can get with the problem is impacted by by their skills as well as the programming language. C++ and vi are slower to work in that Java and Eclipse.
  • What you can reasonably do is impacted by both the language as its environment. For example, it is easy to look at a DLL and dynamically find all concrete implementations of an interface in any .Net language. It’s harder to do that in Java, though possible. In C++ it is platform specific.
  • There are more…

The students do need to learn the mechanics:

  • How to write a test using a particular unit testing framework
  • How to write production code
  • The shortcut keys of the environment
  • The refactoring support in the IDE

But what are the students testing? Units? Sure, let’s go there.

Language affects the units. You are testing units. Different kinds of units, different kinds of responsibilities. Different kinds of responsibilities to be verified, different unit tests.

Things are not so cleanly separated as you would like to imagine.

This very idea can be seen in natural languages. Different languages are better/worse at expressing things. The language you use directly affects how you interpret the world. This actually impacts the physical wiring in the brain. Really, it does.

So I do not agree.

And I challenge you to write the same problem in two fundamentally different languages (e.g. Java and Lisp) using TDD. Then have those two different solutions reviewed by experts in each of those languages.

I claim that if you’ve done an effective job of using those languages, your solutions will be different AND the unit tests you created to get to those solutions will be fundamentally different (not just mechanically different).

If, on the other hands, the unit tests are the same (other than the mechanics), then at least one group of people will say your solution is a bad use of their particular language. You’ll either be programming Java in Lisp or Lisp in Java.

Comments

Leave a response

  1. Avatar
    Matt B about 1 hour later:

    I believe the principles of TDD are language neutral (Red, Green, Refactor, keep the bar green, etc.), but the approaches for actually unit testing in a particular language will vary. If the intent of the course is not only to teach them how to effectively apply TDD, but to also teach them how to unit test in their different languages then teaching it in multiple languages is completely valid.

    I’m the process of developing a TDD class of my own that will be internal to our organization, but I will be teaching it in only one language. My reason is that I want them to learn about TDD, not just about unit testing. You can unit test without doing it test first, but TDD is a different beast. The differences are subtle but meaningful. Because our organization has clients who develop in varying languages, I want my students to leave knowing how to apply TDD but rely on them learn how to unit test their specific languages on their own. Each language (or language type as you’ve categorized above) could be its own course, especially with the nuances you’ve pointed out with different language constructs.

  2. Avatar
    Samuel A. Falvo II about 1 hour later:

    I am shocked at this blog post—it tells me you’re very ignorant of generalizations surrounding the software development practice, and concerned exclusively with the specifics. In other words, you cannot see the forest for all the trees.

    I’m writing software in FORTH right now using TDD. FORTH!! I’ve successfully applied TDD (and its more contemporary cousin, BDD) in languages as diverse as Forth, C, BASIC, Python, Lisp, and assembly language. Yes, sir, I wrote assembly language. I also wrote the C unit testing tool named CUT after having to put up with the retardations of CppUnit in a C context. Now, I prefer CUT even for C++ work, because unlike CppUnit, it doesn’t try to behave like SUnit. Instead, it exploits the natural development cycle for C/C++.

    And, there are examples of folks using TDD with Lisp. Eric Normand’s LispCast series has a few examples of this in action, IIRC. It’s been almost a year since I last watched the series, so I could be wrong on the specifics, but I distinctly remember him employing TDD in at least one episode.

    Just because TDD is language independent practice DOES NOT IMPLY that the end result will be the same for all languages you use it with. Of course they’ll be different. It’s the PRACTICE that’s the same (meaning, how you think about the development process), NOT the finished, shrink-wrapped result. This is why it’s called Test Driven DESIGN, and not Test Driven Code-Monkeying.

    That being said, I encourage the use of multiple languages to demonstrate TDD concepts, for how else are the core principles to be illustrated? You cannot generalize until you’ve practiced in more than one language. This, too, should be self-evident.

  3. Avatar
    Kevin Stevens about 1 hour later:

    Personally, I wouldn’t choose to attend a TDD class taught across multiple languages. I would prefer to have the language factored out of the core material being taught (i.e., the practice of TDD), then I feel it is up to me to learn to apply those techniques across different languages. Quite frankly, I think it would dramatically slow the class down.

  4. Avatar
    Steve Rees about 2 hours later:

    Here are my thoughts prior to reading the bulk of the post.

    There is bound to be a difference in the practice of TDD depending on whether you are using a statically (eg. C++, Java, etc.) or dynamically (Ruby, Smalltalk, Python) typed language, but probably a more important factor is the integration of the xUnit implementation into your IDE. Where xUnit is closely integrated with the IDE as it is in Eclipse, for example, it enables a more rapid iteration around the TDD edit test/make it pass/refactor loop than where the integration is looser.

    The is also true of the quick fixes available in your, though they tend to be more applicable to statically typed languages – knowledge of the messages that I can send to a given object reference can easily highlight an error and allow an automatic fix (eg. the introduction of a skeleton for a new method) while still editing the test.

    That’s less easy to do in a dynamically typed language, and arguably less necessary when proper edit-and-continue support is included in the debugger.

  5. Avatar
    GABOTO about 3 hours later:

    I think that TDD was thought for dynamic environment like smalltalk, where you can create classes and methods while you are debugging. So imagine, you create the test first, you run it, it fails (as expected), you debug it, and you program while debugging!!. Then, you can use the refactoring browser to refactor clases and methods. It is great, i couldn´t achive this in other languajes. What do you think about it?

  6. Avatar
    bish boria about 4 hours later:

    In my job I, unfortunately, have to use a grpahical based programming environment (that dips into JavaScript for the parts that can’t be done any other way). This graphical environment also requires an app server to be running.

    Because of this language environment TDD is practically impossible:

    Time to see changes is long – if app server restart is required this can take several minutes.

    The architecture of the tooling was also designed in such a way that the UI is very difficult to separate from business logic.

    The graphical nature means that refactor means re-write…

    TDD is definitely not language neutral.

  7. Avatar
    Roland about 5 hours later:

    @bish boria, yes, TDD is neutral to language. Your problem is that you either doesn’t have access to the code or the tool doesn’t allow you to change the generated code.

    TDD relies on code. If you don’t control your code, well, lets just say that your ability to good things with your code are limited.

  8. Avatar
    Anonymous Coward about 5 hours later:

    Details matter in practice. (Summarizes Brett’s post, I think)

    I don’t think the fundaments of TDD are impacted: – know what the code should do before you write it – since your a software developer, write software to prove to yourself that the code is doing what you expect it to – since your smart, write the proving code before writing the target code.

    But the actual details of how to implement Red/Green/Refactor? Those may vary (especially, I’ve seen, the cycle times).

    [Samuel, I’m pretty sure Brett is very aware of “generalizations surrounding the software development practice”. That’s quite a generalization you’ve made, which at least is nicely consistent.

    Reminds me of a quip from Michael Jackson that goes something like “Any software development process general enough for all projects will be useless on your project.”

    ]

  9. Avatar
    Brett L. Schuchert about 6 hours later:

    Samual wrote:

    I am shocked at this blog post—it tells me you’re very ignorant of generalizations surrounding the software development practice, and concerned exclusively with the specifics. In other words, you cannot see the forest for all the trees.

    Who is ignorant? Are you responding to ME or to the person to whom I was originally responding?

    Before I respond further, I need to know your target.

  10. Avatar
    Brett L. Schuchert about 6 hours later:

    Kevin wrote:

    I wouldn’t choose to attend a TDD class taught across multiple languages
    Not my idea. The customer asked for it. As a service provider, I can provide pros and cons and then let the customer make the decision rather than me.

    Having said that, I think a one language class is better than a multi language class.

    On the other hand, I have done it. It does slow things down a bit. But it can be done, just not my personal preference. However, as I am not paying for the class, it is not my decision to make!-)

    Someone could argue that the speed and quality hit are so severe that I should stand up for what I believe in. And in circumstances where I think an approach will do more harm than good, I will (and have) walked away. I don’t see this as that situation. It’s a preference.

  11. Avatar
    John Haugeland about 10 hours later:

    Testing rigs are about a dozen lines of code in most languages. Yes, some people are affected by their pre-extance, but those people aren’t practicing TDD, they’re just writing test sets and using a name they heard.

    TDD is absolutely language neutral. It’s as neutral a concept as a given datastructure, and I’ve never seen a turing complete language in which testing was even slightly difficult to set up.

    TDD is not in any way an object oriented technique; that common testing kits (particularly FooUnit) are typically class deployed is merely a design decision (and arguably not a very good one) on the part of those kits. TDD doesn’t need, or even benefit from, object orientation except in languages like Smalltalk and Java, where being OO is part and parcel to general interaction in the first place.

    Look, try writing a TDD kit in a language which is OO-hostile, like Erlang. (I continue to maintain that Erlang is in fact object oriented, but I’m in the dramatic minority by claiming such, and the language’s original author hates object orientation.)

    It’s still very easy: you just pass in lambdas and verify that their results match the argument, and where necessary return an error with the string given for what would be said in an error.

    There’s nothing at all of language orientation to test driven design. Indeed, electrical engineers were TDD in the 1950s, and building architects can be argued to have been so by building code law for more than 100 years.

    Writing work verification isn’t in any way new, and doesn’t require any kind of specific tool support. That programmers think TDD is a recent development is essentially just an exposition of the recklessness and naivete of our industry, and that we think it requires some specific language or metaphor or approach is just an exposition that most of us haven’t put much effort into thinking about how else it could be done.

    Are there testing things that do need language support? Sure. Mutative testing (like the Ruby library “heckle”) needs a language that gives you software access to the parse tree and also that allows you to compile a parse tree directly. Languages that are lisps (or at least lisp-influenced, like erlang, ruby and arguably haskell) generally afford such tools; languages like C# generally do not, and languages like C++ fundamentally cannot.

    But unit testing?

    C’mon, that’s one of the very easiest simple tools to roll.

    I see you telling a long story. The story ends without you addressing the question directly at any apparent point. You tell stories about COBOL (by the way, the vast bulk of COBOL code is fully unit tested, as it’s typically run by banks, and banks know that testing is cheaper than paying for mistakes).

    But I’ve got to be clear: the guy you’re responding to is Doing It Right™ (r). The reason it’s best to teach TDD in several languages at once is that the way one goes about it in Language 1 isn’t always available in Language 2, and so students need to see it set up different ways in different systems, so that they don’t get trapped asking themselves whether because the single way they’ve ever seen it done means it’s somehow not language neutral.

    Do you have any turing complete language in mind which you believe is impractically difficult to unit test? Please skip references to toy and joke languages such as befunge, brainfuck or intercal; I mean languages intended for real world use.

    Indeed, can you think of any compelling pretext of any form to suggest that TDD isn’t neutral?

    I see you making a snarky comment about how because things you imagine must be different, that if someone suggests they aren’t different, then something about writing Lisp in Java, as if Java (not the JVM, the language) could ever handle Lisp-style code.

    But dude, I hate to break it to you: you’re already deeply undermined by things like Test Anywhere Protocol.

    In one of my projects which I have not yet released to the public, I have a full unit, regression and stochastic test system with partial model checking that simultaneously checks C++, Erlang, OCaml, PHP, SQL in four different database backends, JavaScript and ActionScript code (and depending on how you look at it, there’s a good argument that I’m also testing the XML engines in use.)

    Those are some pretty fantastically different languages, yet they’re all covered by the same test set. And what you imagine about code you’ve never seen aside, I assure you I am not writing code in Language 1 as idiomatic code from Language 2 (though that isn’t actually a problem when it’s done so much as it is a warning sign; sometimes, when you’re writing in limited languages, imitating more powerful languages is your only option to get a job done.)

    And they’re all running at a single time, with client/server matching, from the same test set, from the same rig.

    So, help me understand why you believe that TDD is anything other than language neutral. You asked the question, but proceeded never to address it directly, and indeed I’m not even certain from this article what your position on the matter specifically is.

  12. Avatar
    Mike Long about 15 hours later:

    I think TDD as a practice is language neutral, but I also think that is missing the point. The real challenge in starting with unit testing is in writing testable code, not learning how to assert expectations. In my experience good TDD training focuses on techniques for writing testable code and that is a language specific problem. My 2 cents..

  13. Avatar
    Joshua Lewis about 17 hours later:

    For me, TDD is not about testing. Its how you approach building your system – design. In TDD, testing is the mechanism of feedback, hence the test drives the design.

    ‘Pure’ TDD practice does rely on having certain tools available to you, but it also relies on certain facets of a language, such as indirection/delegation. For example, if you have two stored procedures in MSSQL with a dependency, there’s no way to test the calling SP without the dependency SP.

    Howevery the point of TDD is to tell you where to go, how to get there, and to tell you when you are there, as well as defining the boundaries of a unit so it can be isolated, and setting pre- and post-conditions. Therefore, you can practice TDD to some extent without having the required tools.

    Have a look at my blog post Applying TDD in Principle if not in Practice: http://joshilewis.wordpress.com/2009/11/16/applying-tdd-in-principle-if-not-in-practice/

    Yes, in different languages your actual test may look different, but since TDD is not about testing, I would say TDD is language neutral.

  14. Avatar
    Martin Vilcans about 17 hours later:

    My thoughts before reading the post: Of course the language affects how you work with TDD. For once, the speed of the build/run cycle makes all the difference. You wouldn’t use TDD with punched cards. You could, but I guess you shouldn’t. (Unit tests, sure, but not TDD.)

    My thoughts after reading the post: When I wrote the above, I didn’t think you’d be arguing that the results of TDD will differ depending on the language. Of course a Java solution implemented with TDD will be different to a test driven Lisp solution of the same problem. That is so obvious that it goes without saying.

    I’d suggest that teaching TDD should be done with one language. TDD is so close to programming that it would be impossible to do a course on it without showing code. But showing code in more than one language and framework is probably not a good use of the time (unless you’re speaking to a highly experienced audience).

  15. Avatar
    Chris Salter about 23 hours later:

    Someone who’s taught TDD in, say, C# should understand the details well enough to adapt the whole business to Java, to Lisp, to Assembly, to whatever the hell they want. If you’re teaching a TDD course, then it’s a measure of your success as a teacher that they understand TDD well enough to do that adaptation on their own. I think the “TDD is language independent!” folks are arguing this point.

    You, on the other hand, are pointing out that there is still that adaptation—sure, the concepts are the same, but TDD in C# is still a little different from TDD in Java, and both are going to involve different techniques and skills than TDD in Lisp or Assembly or JavaScript or… whatever else you feel like naming. Sure you can take all the tricks and techniques you used in C# and hack them into your Ruby TDD, but then you’re no longer working in Ruby.

    At least, this is my interpretation of the discussion.

  16. Avatar
    David Workman about 24 hours later:

    My initial thoughts to the question were ‘The high level details of TDD are language-agnostic, but the actual process and tests being driven and highly language, and even framework, dependent’.

    I think that matches what most others are saying though. A purely theoretical look at TDD can be language neutral, but once you actually start putting it into practice, the choice of language, tools, frameworks, libraries, experience and personal preference will start to affect how you test and what you test in a project specific fashion.

    Kind of like building a house. You can easily say that a house is building material neutral (make it out of wood, concrete, brick, glass, general principles are kind of the same) but the type of house and the methods used will vary greatly depending on your actual choice.

  17. Avatar
    David Fauber 1 day later:

    Your point that different languages would have different approaches and different tests for the same problem doesn’t invalidate his contention that TDD is language-independent. I won’t get into the tone of the reply…

  18. Avatar
    Nick 3 days later:

    There’s a major issue with TDD.

    If you do TDD, go and have a look at your code. Look through each test and I guarantee that almost all of them involve setting up data with certain conditions, making a call, and then testing the condition of the results.

    ie. Tests just exercises the contracts for particular functions.

    So why not go the whole hog? Why not implemented design by contract. http://en.wikipedia.org/wiki/Design_by_contract in the language?

    Then in effect all the things that you test will be tested by the contracts when you run your code. With TDD its just the test that you think are needed, and that’s going to be a small subset.

    Now if you then factor in something like Pex. http://research.microsoft.com/en-us/projects/pex/ and you can start automating much of the code you would otherwise have to write.

    ie. Language and runtime make a huge difference to what tests you need to write, and what testing ‘the system’ can do for you

  19. Avatar
    Brett L. Schuchert 3 days later:

    I think there is quite a bit of agreement and the big issue is that of “system boundary.” I’m using the term as it was defined by Derrick Coleman in Object Oriented Development: The Fusion Method.

    The system boundary affects what events go into and out of the system. Consider, for example, if I ask you to describe taking a shower but from the following different system perspectives:
    • The door to the bathroom
    • The shower curtain
    • The wall of the shower itself

    You’ll describe different steps and different levels of granularity.

    If we discuss TDD as: red, green, blue (original scheme) or red, green, refactor, that is a high-level black-box description.

    If we go a little deeper and use the three laws:
    • Write no code without a failing test
    • Write only enough of a test sufficient to make it fail (and not compiling is failing)
    • Write only enough production code to make a test pass

    Then we’re getting a bit more detailed, but even so, this is language neutral.

    However, as soon as we start applying (practicing) it, we have to pick a language. When we do that, things happen. For example, what is “not compiling” to a scripting language? What about the pragmatics of stopping and starting when working in C++?

    And, while I was a bit all over the place in the original post, different kinds of languages produce different kinds of units. OO versus functional versus… Statically typed versus dynamically typed. Class based versus object-based. These kinds of things determine the kinds of “chunks” into which we break our solutions.

    So if we use the “words” of TDD, Test Driven Development, then the process includes everything form test to production code. Since production code and tests affect each other (tests express desire, code implements intent, chunks affected by structure of language), then the language affects the work you do.

    So does TDD include actually programming? Conceptually you can talk about it independent of language. In fact, you can apply the principles to things other than development (think of test-driven-meetings, what outcomes do you want, how will you know you’ve got them – the tests, have the meeting, was it a success?). Personally I do not think there’s much value in talking about the high-level concepts until someone has had the experience of practicing it. In my experience teaching it, people think they get it until they realize that they didn’t get it. That happens several times until they actually get it. I generally think bottom up, application of a principle, to understanding a principle, to generalizing it, to expanding to find where it breaks. That’s how I build up models.

    Once I have that model, I generally think top-down.

    In any case, I stand by my belief that TDD is not language neutral. In the end, it doesn’t matter if anybody agrees or not (some do, some don’t). I strongly defect weakly held beliefs. When someone convinces me of a better model, I’ll defend it.

  20. Avatar
    Esko Luontola 3 days later:

    When I teach TDD, I am not teaching just TDD.

    Exactly. There are many separate things which must be learned to use TDD effectively.

    I consider the following to be language-independent skills:

    - how to program (decomposing problems and describing them to a computer)

    - how to program in programming paradigm X (learning a new paradigm requires a new way of thinking and expands your mind, but learning a new language with the same paradigm is easy)

    - how to program using TDD (red-green-refactor cycle; thinking about what the program should do, before thinking about how to implement it; using tests to drive the design)

    - how to write tests (arrange-act-assert, expected-actual, choosing good test names)

    - how to write modular code (low coupling, high cohesion, choosing good names, things which make code testable or untestable)

    And the following I consider to be language-dependent skills:

    - what is the syntax, semantics and API of language X

    - what are the idioms of language X

    - how to express your thoughs in language X

    - how to use language X’s testing framework Y

    - how to use language X’s features to write modular code

    The thing with TDD and the above things is that they are independent. It’s possible to write modular code without knowing TDD, and it’s possible to use TDD without knowing how to write modular code. Just about only prerequisite for them is knowing how to program. And if you know how to use TDD and write modular code in one language, then transferring that knowledge to another language is easy, the same as learning a new programming language is easy once you know how to program (and of course really learning how to program will take 10 years, as said by Peter Norvig ;).

    Language affects the units.

    Not to me – or at least I try to avoid it as much as I can, so that the tests would be decoupled from implementation details. I try to keep my “units” at a higher level of abstraction, at the problem domain’s level of abstraction. For me “a unit” is “a behaviour”. I just finished writing an article explaining it in more detail: http://blog.orfjackal.net/2010/02/three-styles-of-naming-tests.html

    The real challenge in starting with unit testing is in writing testable code, not learning how to assert expectations.

    Exactly. Last autumn I lectured a TDD course (“TDD programming technique and designing code” at the University of Helsinki) and I structured the course so that out of the 12 lectures only 1 was about TDD, 2½ were about how to write tests, 4½ were about writing clean code, 2 were coding dojos, 1 about agile, and 1 about craftsmanship and personal practice. The exercises (6 weeks) on the other hand were all about using TDD and refactoring, because TDD requires lots of hands-on practice.

  21. Avatar
    Brett L. Schuchert 4 days later:

    Esko wrote:

    I consider the following to be language-independent skills: - how to program (decomposing problems and describing them to a computer)

    Well you and I are going to have to agree to disagree.

    Decomposition is about breaking things into parts. What parts you have available to you is directly affected by what forms of expression that are available to you.

    Sure, I can say “break things into parts.” But that’s so simplistic as to have no practical application whatsoever.

    As for writing behavior-oriented units, fine. I’d call those acceptance tests, not unit tests. You can start there, and I think I already said (and if not, I’ll say it now), I think acceptance tests might be language neutral. I think to be consistent with previous arguments, I might actually have to disagree with that, but let’s say I concede that.

    For anything other than trivial behavior, there will be a difference between a unit at the behavioral level and a unit all the way into final implementation level.

    Different levels of abstraction will be better suited to different kinds of testing techniques. In a sense, many of the things we do are the same. For example, inversion of control works for both low-level dependences as well as service-level or layer-level dependencies. (More generally, coupling and cohesion are fractal in nature.) I want to be able to write acceptance tests for my front-end that do not have a real body (body-less testing complimenting headless testing). I also want to write fully-integrated front-end based tests (both are a good idea, many fewer of the fully-integrated, of course). So I would want to design for DI of layers or services as well as objects.

    However, the window through which a test executes is related to how far away the test is from the ultimate code. It is generally quite difficult for acceptance-level tests to get very good coverage across a system simply because the cost of setting everything to do so is too expensive both in creation and maintenance.

    So we write acceptance level tests for gross correctness of behavior. We write unit level tests for detailed, path-based (cyclomatic complexity based) correctness. (There are more than two layers, these might be the ends of a spectrum.) To get to all the paths you’re going to have to consider the actual units.

    This is where you and I break down, I suppose. The units and the very way in which a problem is decomposed is heavily influenced by the model offered by the language.

    In my original rant, that’s why I spent so much (too much probably) time listing differences in languages.

    You can also take this to the level of natural language. Different languages are better at different forms of expression. English is an OK general purpose language, but other languages are better at expressing some ideas than English.

    And it’s bi-directional. The language one uses affects how their brain is wired. So in fact language affects expression, expression is limited by language. Learning different languages potentially gives you different forms of expression.

    This starts with the Sapir-Whorf hypothesis and continues into modern cognitive theory. It’s a pretty well-established model. (I know: all models are wrong, some are useful.)

    If units were truly language neutral, then there really would not be a need for different languages. Maybe the whole DSL movement is crazy (they are not, mostly).

    In fact, you even concede this:
    Not to me – or at least I try to avoid it as much as I can,

    That inability to not always close the gap is probably more related to your choice of problems than an inability to not always manage to go language neutral.

    If you are teaching a class, then you are using small problems. Small? Less than 100,000 lines of code – I don’t know, but the kinds of problems one finds in a CS curriculum. I have a CS degree, and I worked in both the CS and EE departments so I’ve seen the kinds of problems used in classes. I also have taught on and off since 1985, so I do have some context.

    Is it possible that your perspective comes from a lack of context? Do you primarily teach? Or have you only though about these issues since you have been teaching? Or have you only worked on relatively small problems?

    I can see how for small problems there may not appear to be much difference between behavior and units. As problems grow, however, so does this gap. The largest system I’ve worked on any extent was roughly 2.5 million lines of code (medium sized) with up to 60 developers at its peek (I’ve also worked on a project where I was cog # 344, but that was a whole different experience).

    So far I have not been convinced by any arguments I’ve read in this thread.

    Luckily, unlike TDD, there is no red, green, refactor. Part of the power of natural language is its ambiguity. So we can disagree, both be right or wrong (whatever that actually means) and still work effectively.

    We can all practice TDD, however we define it.

    I think we generally agree that TDD is an effective practice. I suspect if we were to work together, after some getting used to each other, we could write good tests and decent production code. And even though we were working together, what each of us would say about what we are doing would be different.

    That neither of us has convinced the other really in the end does not change a thing. Though, as often happens when arguing, I’ve become more convinced of my position. Have you as well?

  22. Avatar
    Esko Luontola 4 days later:

    As for writing behavior-oriented units, fine. I’d call those acceptance tests, not unit tests. You can start there, and I think I already said (and if not, I’ll say it now), I think acceptance tests might be language neutral. I think to be consistent with previous arguments, I might actually have to disagree with that, but let’s say I concede that.

    The term “unit test” brings so many misleading ideas, that I prefer to avoid using the term. Just as J.B. Rainsberger said in http://www.infoq.com/presentations/integration-tests-scam – “This week I’m calling them isolated object tests, but I have been known to also call them focused tests. My good friends at Industrial Logic like to use the term micro test, although that’s not quite what I mean it’s pretty close.”

    You can call them “acceptance tests” if you like, but then they are acceptance tests at all levels of abstraction. I prefer using the term “specification”.

    Here is a specification of a stack, from the article linked in my previous post (this blog had problems in formatting it with empty lines, so ignore the dots which I added).

    func StackSpec(c gospec.Context) {
      stack := NewStack()
    .
      c.Specify("An empty stack", func() {
    .
        c.Specify("is empty", func() {
          c.Then(stack).Should.Be(stack.Empty())
        })
        c.Specify("After a push, the stack is no longer empty", func() {
          stack.Push("foo")
          c.Then(stack).ShouldNot.Be(stack.Empty())
        })
      })
    .
      c.Specify("When objects have been pushed onto a stack", func() {
        stack.Push("one")
        stack.Push("two")
    .
        c.Specify("the object pushed last is popped first", func() {
          x := stack.Pop()
          c.Then(x).Should.Equal("two")
        })
        c.Specify("the object pushed first is popped last", func() {
          stack.Pop()
          x := stack.Pop()
          c.Then(x).Should.Equal("one")
        })
        c.Specify("After popping all objects, the stack is empty", func() {
          stack.Pop()
          stack.Pop()
          c.Then(stack).Should.Be(stack.Empty())
        })
      })
    }

    Even though it specifies a very low-level programming element – a data structure – it is very much language-independent. No matter in what language you create a stack, the names of the tests (the specification) will be the same (well, if the language does not have objects, then replace “object” with “element” or something similar).

    The same way of writing specifications works at all levels of abstraction; from individual assembly language instructions, up to the level of buttons and text fields which are visible to the end-user (which some people call “acceptance tests”).

  23. Avatar
    Brett L. Schuchert 4 days later:

    Esko,

    1. A stack is a trivial, well-understood data structure. 2. That a solution may or may not use a stack is already pre-supposing a particular kind of solution solution approach. 3. In a functional language with tail-end recursion optimization, for many places where a traditional algorithm would use a stack, the functional language would more strongly suggest a recursive algorithm.

    Specific examples include traveling salesmen, in-fix to post-fix conversion, pretty much any graph traversal algorithm, etc.

    So again, your context is too small and trivial. You’ve done nothing to reinforce your argument with this example. If anything, you’ve proven my point even more.

    Your specification assumes the need for a stack, which is a design you came to based on the language your are using.

    While your decision is somewhat general for any OO language or even languages like Pascal and C, given the same problem and set of requirements, someone working in a different kind of language (e.g. List, Haskel) would not use a stack at all.

    So what you are saying is that for a given set of design-oriented constraints imposed upon you by your language of choice, TDD is neutral. Fine, I can agree to that. But your example is not a good example of language neutral TDD. It simply reinforces what I have been saying the entire time.

    I’m really surprised you don’t see that at this point.

  24. Avatar
    Esko Luontola 4 days later:

    Do you primarily teach? Or have you only though about these issues since you have been teaching?

    No. For me teaching is a hobby – something to get new experiences – the same way as some people learn a new programming language each year as a hobby. I’ve done it part-time during the last 3 years (User Interface Design/Interaction Design 3 times and TDD 1 times, each course 6 weeks long), but I can’t see myself doing teaching for a long time, at least not lecturing, because I don’t have talents for lecturing. I also find teaching is boring, because there you are all the time talking about things which you already know – it’s much more fun to always do and learn new things.

    Or have you only worked on relatively small problems?

    The most complex problem that I have worked on is a distributed, transactional, scalable, high-availability, low-latency application server/object database which provides to the application programmer the illusion of a simple single-threaded programming model.

    The largest system I’ve worked on any extent was roughly 2.5 million lines of code (medium sized) with up to 60 developers at its peek

    That reminds me about a couple of quotes:

    “Measuring programming progress by lines of code is like measuring aircraft building progress by weight.” —Bill Gates

    “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” —Antoine de Saint-Exupéry

  25. Avatar
    Esko Luontola 4 days later:

    Specific examples include traveling salesmen, in-fix to post-fix conversion, pretty much any graph traversal algorithm, etc.

    Are you sure, that if I write a language-independent specification of a in-fix to post-fix conversion, then you will accept my point of view? I wouldn’t like to waste my time on it, if you anyways will eat your words and say “that special case proves nothing”. This reminds me about last year on this blog, when somebody was claiming in the comments that TDD is not a design method…

    Your specification assumes the need for a stack, which is a design you came to based on the language your are using.

    No. You are thinking at the wrong level of abstraction (this time a too high level). In the context of that example, the problem domain is the stack. So the stack is not an implementation or some design which was needed to solve a higher level problem, but the stack itself is the problem that is to be solved.

    The point of the example was to show that this kind of specification-style tests can be written even at the lowest levels of abstraction. It was aimed at your claim that “For anything other than trivial behavior, there will be a difference between a unit at the behavioral level and a unit all the way into final implementation level.”

    For each problem domain of some level of abstraction, the structure of specification-style tests is language-independent. But of course each problem domain itself is not language-independent. An example:

    Let’s say you need to build a system for a technical support call center, to keep track of the service request. Now the problem domain is “a call center”. The specification for solving that problem domain consists of how the UI components of the system will behave when it is used. The UI specification is obviously language-independent – you can implement a UI with the same behaviour in just about any language.

    Now to implement the UI, we need to make many design decisions about how to implement the UI. Let’s say that we make the design decision, that the system will maintain a queue for processing incoming phone calls. Maybe this design decision was somehow affected by the programming language and frameworks which we use – in some other language we might not have needed a queue, but we would have launched a lightweight process for each phone call (for example in Erlang). So the need for a queue depends on the language.

    Then we go one abstraction level down. Now the problem domain is “a queue of incoming phone calls”. The specification for that problem domain consists of getting information about phone calls, putting them into a queue, taking them from the queue and forwarding them for processing. This specification is again language-independent – you can implement a queue with the same behaviour in just about any language.

    And again, to implement the phone call queue, we will need to make many design decisions. If the complexity of the queue’s implementation is big enough, we might need to again go down one level of abstraction. But once we go down to that level of abstraction (for example to persist the queue into a database), it will become our current problem domain, and the specs that we write will be language-independent within the context of that problem domain.

    It’s just as Kent Beck says in http://www.infoq.com/presentations/responsive-design @ 46 min – “One thing about my thinking about design is it’s scale-free.”

  26. Avatar
    Esko Luontola 4 days later:

    So we can disagree, both be right or wrong (whatever that actually means) and still work effectively.

    We can all practice TDD, however we define it.

    I think we generally agree that TDD is an effective practice. I suspect if we were to work together, after some getting used to each other, we could write good tests and decent production code. And even though we were working together, what each of us would say about what we are doing would be different.

    I agree. :)

    Who knows, maybe some day we will have the opportunity to meet (in a conference or somewhere) and do some pair programming.

  27. Avatar
    Brett L. Schuchert 5 days later:

    Esko,

    So let’s have a look at your examples (the term JB would recommend if it were RSpec):
    func StackSpec(c gospec.Context) {
      stack := NewStack()
    .
      c.Specify("An empty stack", func() {
    .
        c.Specify("is empty", func() {
          c.Then(stack).Should.Be(stack.Empty())
        })
        c.Specify("After a push, the stack is no longer empty", func() {
          stack.Push("foo")
          c.Then(stack).ShouldNot.Be(stack.Empty())
        })
      })
    .
      c.Specify("When objects have been pushed onto a stack", func() {
        stack.Push("one")
        stack.Push("two")
    .
        c.Specify("the object pushed last is popped first", func() {
          x := stack.Pop()
          c.Then(x).Should.Equal("two")
        })
        c.Specify("the object pushed first is popped last", func() {
          stack.Pop()
          x := stack.Pop()
          c.Then(x).Should.Equal("one")
        })
        c.Specify("After popping all objects, the stack is empty", func() {
          stack.Pop()
          stack.Pop()
          c.Then(stack).Should.Be(stack.Empty())
        })
      })
    }

    Most of your examples mutate the stack, correct? So in the design of your tests you’ve made a huge assumption about the language and how it operates. Objects (data) are mutable.

    This same spec will not work in any number of languages where objects are immutable. A stack in a functional language would be a data structure with functions that returned new instances of a immutable object. It would change your test.

    So even in your very simple example, which I said was trivial and a well-understood data structure, you demonstrate my point yet again.

    Your specification is simply not language independent.

    Furthermore, if I am working in a highly concurrent application, one design approach I might take is to use immutable objects where the language does not enforce such things. If I were to do so (and I have done so in deployed applications), then your tests would not work as written. So your design also presumes that the underlying system design does not take an immutable object approach.

    Your example fails both as a demonstration of language-neutral specification and context-neutral specification.

    I will read the rest of your posts and reply as well. I need to see if you’ve yet managed to provide a counter example to my point. Notice, I did not change the size of the problem to ignore what you are saying. I took your actual “domain” of a stack as the system and demonstrated that its internal design makes strong design assumptions about the system under test.

    This reminds me of Goedel’s Incompleteness Theorem in that it almost seems to have truly language neutral tests, you will have to write them in a “higher-level” language. In that respect, the specification of the validation can be language neutral. However, there’s still the need for translation to make the tests execute. If TDD does not include that translation, then sure tests can be language neutral at the expense of not being executable – which violations a strong assumption about the use of TDD. On the other hand, if the specification requires translation, and that translation is considered part of the system, which I think it should be, then once again the “system boundary of TDD” is large enough to make it language/environment/context dependent.

  28. Avatar
    Brett L. Schuchert 5 days later:
    Esko wrote:
    This reminds me about last year on this blog, when somebody was claiming in the comments that TDD is not a design method…

    Please find that quote and post it. Until then, I’ll reject that as hearsay.

    Are you sure, that if I write a language-independent specification of a in-fix to post-fix conversion, then you will accept my point of view? I wouldn’t like to waste my time on it, if you anyways will eat your words and say “that special case proves nothing”.
    If fact yes I am sure. Don’t waste your time. It won’t be because I’m going to “eat my words” it is because I’ve have already shot holes in your so-called language neutral demonstration. So far you have provided no examples nor evidence of this so-called TDD language neutrality. Once you do, then we can talk.

    As for you whole “going down one level thing” I reject that premis. I use TDD to develop a system. At each level of abstraction I happen to work, I can create logical specifications. However, those logical specifications are in fact directly impacted by the level of abstraction directly above them. So by their very nature, they are affected by higher-level design decisions.

    Those design decisions are impacted by the language, the architecture, the context, etc. So that I am to any particular logical point in your hierarchy presumes decisions that have been informed by the language of choice.

    This, by definition, is not language neutral. It’s quite the opposite.

  29. Avatar
    Esko Luontola 5 days later:

    Please find that quote and post it. Until then, I’ll reject that as hearsay.

    At http://blog.objectmentor.com/articles/2009/10/08/tdd-triage it was said by that “Jeffries’s Sudoku Solver is an example of what happens when “design” is done with TDD. [...] Utterly unconvincing. In the end, if you claim TDD is a design method, you must provide examples of codebases evolved with TDD which show superior design (as compared to non TDD’d code bases).” and also Cedric had like-minded comments, mostly about TDD causing code churn.

    This reminds me of Goedel’s Incompleteness Theorem in that it almost seems to have truly language neutral tests, you will have to write them in a “higher-level” language.

    I use English.

    A stack in a functional language would be a data structure with functions that returned new instances of a immutable object. It would change your test. [...] Your specification is simply not language independent.

    Your and my mental models about what constitutes the specification appear to differ. You are focusing mostly on the code in the body of the test, which is typical for example-style tests, but in the specification-style tests that I write the focus is on the name of the test.

    Let me remove all the distracting noise from the previous code sample:

    An empty stack
      - is empty
      - After a push, the stack is no longer empty
    .
    When objects have been pushed onto a stack
      - the object pushed last is popped first
      - the object pushed first is popped last
      - After popping all objects, the stack is empty

    That is the specification.

    When I’m writing tests in TDD, most of my time goes into thinking about the name of the test, because that is when I’m thinking about these things:

    1. What is the next important behaviour that the system should do, but which is not yet implemented?

    2. What would be a suitably small piece of that behaviour to be specified first, so that I can do TDD with small enough steps?

    3. How should I describe that piece of behaviour to the programmer who will read the code in the future, so that my intent will be conveyed correctly to the next programmer who will read the code?

    When I have collected the idea in my mind, I write down the name of the test. Then I re-read the name that I wrote and do some adjustments to its wording, until it communicates my intent well enough.

    After I have the name of the test written down, then I write into the body of the test some code which does what the test’s name – the specification – says. Writing the test code is very straightforward and requires very little thinking (more thinking will be done later, when refactoring the test code for readability), at least when writing tests for clean and testable code (complex test code is a smell that the system being tested is too complex).

    This translation from the specification to the test code is the language-dependent part of writing tests in TDD. And that translation is very simple to someone who has written hundreds and thousands of tests. I consider the gist of TDD to be elsewhere.

    As it is said in https://objectmentor.com/resources/articles/craftsman4.pdf

    “Do you think the value of a program is in the code?” he asked. “It’s not. The value of a program is in your head.”

  30. Avatar
    Brett L. Schuchert 5 days later:

    We are clearly getting nowhere. Just to be clear, this continues to be an interesting discussion to me because it is helping me to refine my story on my assertion that TDD is language dependent. You might be getting the same thing (opposite interpretation) out of this discussion (I sort of hope you are).

    In any case, a few more counter points:

    At http://blog.objectmentor.com/articles/2009/10/08/tdd-triage it was said by that …

    So let it be shown that this is now part of the public record.

    OK, so what? I did not write that. If you’ll notice, there are several blog categories. That blog was written by Uncle Bob. So what did you have in mind when making that reference?

    I use English.

    Clearly not, your original specifications were not English. Even your refined “English” specifications are in fact not full English. You are not executing them with a natural language translator. In fact, you are using a DSL to some extent. This is practiced both in TDD and to a greater extend in BDD. You are attempting to use an inherently ambiguous language, English, in a constrained manner to create a formal specification. Doing so requires either the use of a natural language translator, which makes your specifications ambiguous, or a DSL, which makes them not really English. In fact, you are technically using a sub-set of English.

    There is an obvious 3rd interpretation. Your tests are not executable, but then you’d not be practicing TDD. Since this is what we are discussing, I’ll rule out this possibility.

    What objects have been pushed onto a stack
     - the object pushed last is poped first
     - ...
     - After popping all objects, the stack is empty

    You’ve gone to a higher-level representation. Thus my comment about Goedel’s Incompleteness Theorem.

    Second comment, your specification contains two mentions of a stack: “a stack”, “the stack”. So you are still assuming a single stack OR there is some implied tacit knowledge in the translation. Now to be fair, not all of your statements make that assumption. In fact I believe you’ve successfully created a language-neutral way of saying something about ordering. Or have you? From where? If I have immutable objects, the act of pushing creates a new stack. The act of popping creates yet a third stack. So there’s the need for some mapping from your specification to the underlying language.

    Let’s assume that this truly is language neutral (again, I don’t agree that it is, but that won’t matter).

    You go on to write:
    ...test code is the language-dependent part of writing tests in TDD.
    Language dependent and absolutely necessary. If you are not writing executable tests, then you are not practicing TDD, NOR BDD for that matter. The mapping will vary greatly depending on the language of choice. So this is not trivial, it is necessary and it is language dependent.

    So a fundamental part of the act of practicing TDD requires a language-dependent translation at some point in its practice.

    You just wrote that yourself.

    You do go on to say:
    And that translation is very simple to someone who has written…”

    I’ll remind you of your Bill Gates quote, just change lines of code to numbers of tests.

    But since I originally used the numbers game, I’ll mention this. As someone who has written thousands of tests, in different languages, using different tools and different representations. And as someone who as also taught that, I reject the trivial nature of this work.

    As for your reference to Bob’s Craftsman article, again so what?

    I’m not Bob, I’m Brett. Different people.

    FWIW, I am quite aware of mental models, example style tests, specification style test, etc.

    I also believe the following:
    • Everything is a model
    • All models are wrong, some are useful

    I’m also aware that the first bulled is self-contradicting, which brings us back to Goedel’s Incompleteness Theorem.

    This began as a question, is TDD language neutral?

    At some point in the middle I mentioned the idea of “system boundary”.

    I believe in your mental model, TDD stops for you after you’ve written a supposedly language neutral specification. I wholeheartedly disagree. Since you are so apt to quote people, let me reference the three laws of TDD: From Uncle Bob (paraphrased)
    • Write no production code without a failing test
    • Write just enough code for the test to fail
    • Write just enough production code for the test to pass.

    This is also the definition from which I work. Notice that this involves writing executable tests and production code?

    Since we are writing executable tests and production code, that trivial translation you mention is absolutely part of the process of TDD. So there is, by your own admission, a language specific part of the overall TDD process. As to whether this is trivial or not, that is a matter of opinion. I don’t believe it is, I think you do.

    Furthermore, using standard English interpretation of your specification, I get that you are still thinking of a mutable data structure in your specification. So, as before, your so-called language neutrality is not in fact language neutral. If that is implied, then your specification has multiple, ambiguous interpretations.

    Now you can disagree with this last statement. In fact, I expect you will. But then we get into two issues:
    • Ambiguity of English
    • Tacit knowledge

    The first I already mentioned above.

    The second is at the heart of TDD. The three laws of TDD are not enough to write code. Not even close.

    Notice, the three laws do not mention refactoring. Someone might say, sure but that was “blue” from Smalltalk days.

    Also, testability requires isolation. Isolation requires the application of design techniques. Design techniques are both contextual and language driven.

    TDD is a constrained way to write working software. The three laws require an ability to design. That tacit knowledge is fundamental to a successful application of TDD.

    Problem with tacit knowledge is we typically use it without being aware of it. Just because we are not aware of it, does not mean it is not there, or that it is not strongly directing us in a particular way.

    That tacit knowledge is heavily language (both natural and programming) driven.

    Back to you.

  31. Avatar
    Esko Luontola 6 days later:

    OK, so what? I did not write that. If you’ll notice, there are several blog categories. That blog was written by Uncle Bob. So what did you have in mind when making that reference?

    You won’t change your mind, regardless of what examples others show you, the same as did not change his mind.

    “Write no production code without a failing test Write just enough code for the test to fail Write just enough production code for the test to pass.” This is also the definition from which I work. Notice that this involves writing executable tests and production code?

    Notice that it does not say anything about which language is used? The three rules are the same, regardless of the language. The important things about TDD, which make TDD what TDD is, are not tied to any language.

    If I have immutable objects, the act of pushing creates a new stack. The act of popping creates yet a third stack.

    Then replace “stack.Push(x)” with “stack = stack.Push(x)” and replace “x := stack.Pop()” with “x, stack := stack.Pop()”. The names of the tests do not need to change. The implementation details (mutable/immutable) are in the body of the test – the high-level concept of a stack is in the test names.

    TDD is a constrained way to write working software. The three laws require an ability to design. That tacit knowledge is fundamental to a successful application of TDD.

    And the ability to design is still yet another skill. Good design can be done without using TDD (although TDD surely helps in getting feedback about the design and in evolving the design), so although the skill of designing is a prerequisite of using TDD, it is not part of TDD.

    When decomposing the skill of TDD, there are lots of things which TDD requires, but which themselves do not depend on TDD: http://groups.google.com/group/agile-developer-skills/browse_thread/thread/613e32cea74f2bd5

    Like I said in my original comment, which you did not even quote fully in your article:

    I don’t think that it makes sense to say “teach a TDD class in several languages simultaneously”. TDD is a language-independent technique. It would be better to say the things separately: “learn how to program using TDD” and “learn how to write tests in language/framework X”. The former requires learning a way of thinking. The latter requires just memorizing the API, syntax and idioms.

    Notice that your concept of TDD was decomposed to two parts? “Learn how to program using TDD” and “learn how to write tests in language/framework X” and I even explained that which things I included in those parts. There are also many more things which are needed for using TDD – some of them language-dependent, others language-independent – and the ability to design is at the forefront of them. See the thread at agile-developer-skills for more.

    -

    You did not even agree to the more fundamental idea, that knowing how to program is a language-independent skill. Until you can see software development from that point of view, it’s pointless for me to continue this discussion.

    To illustrate how I think about the skill of programming: Many times in casual discussions, when I tell people that I’m a programmer, a typical reply is “In what language?” or “What kind of programs can you make?” I find those questions absurd. My usual reply to both questions is “Whatever is needed.”

    Of course I know that there are some areas where I have no experience, for example I haven’t worked on 3D games, so I don’t know the math for describing things in 3D space (I do know linear algebra, though haven’t used it much), and neither would I know how to create a new encryption algorithm, because of not knowing any of the cryptography theory. Neither have I worked in every language that there is.

    But the majority of software development is the same, regardless of the problem being solved or the programming language being used. That’s why I find it degrading to call somebody “a Java programmer”, “a C# programmer”, “a mobile phone programmer” or similar – implying that they would not be able to work in a different environment, after a couple of weeks of training, and not be able to take advantage of their years of programming experience. (Probably there are some who think like that about themselves, but I take that it means they just recently learned programming, or have not actively pushed themselves to try new things, which is sometimes called “1 year’s experience repeated 20 times.”)

  32. Avatar
    Brett L. Schuchert 6 days later:
    You won’t change your mind, regardless of what examples others show you, the same as did not change his mind.
    First rule of feedback: feedback is more about the giver than the receiver. Gauss and Weinberg. So this statement is more about you than me. I don’t know you but the same can be said about you, clearly, from what you’ve written on this blog. Regarding myself:
    • I can remember a time before which I did not think unit testing was important. It was how I was taught.
    • I can remember a time after which I was test-infected
    • I can remember a time before which I did not think that TDD was useful for legacy development
    • I now believe that to be the case
    • I can remember a time before which I actually though TDD was about testing – it’s not. (I’ve blogged about that as well.)

    Can you deal with the fact that so far you have not provided any good examples (yours other others) to convince me? Your inability to be convincing is not a reflection on my ability to change my mind.

    What you basically did with that particular quote was grab something from the internet and use it as evidence. The person did not leave contact information. I’m not saying that anonymous speech has no value but I am saying that it certainly is not open to scrutiny. Just because someone wrote an opinion does not mean I have to agree (or disagree with it).

    But to not just deflect it, let me point out an assertion you quoted:
    if you claim TDD is a design method, you must provide examples of codebases evolved with TDD …
    OK, WHY? What evidence has this anonymous writer given to back up this claim?

    Do I think you’ll have better design because of the use of TDD. I think you probably will, but that’s not the goal in my opinion.

    I think a loftier goal is to determine whether or not you will have more maintainable code. Why? Look up the numbers. Between 1980 and now, the distribution of the cost across the live of a software development project is heavily weighted towards maintenance; from around 75% – 80% in the 80’s to 90% – 95% now.

    So anything we can do to help software maintenance is going to help the vast majority of software development.

    So I reject the anonymous author’s opinion. It bears no evidence or backing material to support it. Did you just blindly accept what that person said? If so, why? Where’s the critical through?

    So I did reject the quote. I did not (until now) give you all the reason to. But you’ve given an example of why I am unable to change my mind, and I’ve just given you the background on why I reject that quote.

    I’m not just disagreeing to disagree.

    Notice that it does not say anything about which language is used? The three rules are the same
    Yes, I did notice that. So what? Did you notice the use of the word “write”? Did you? Apparently not. (See how useless of an arguing technique you’ve used, doesn’t work very well.)

    You have to write tests, and they need to execute. Do you see anything in the mention of the three laws about test automation? Nope, so I guess that is not part of TDD? Right? Wrong. In fact, go back to XP’s definition. TDD is part of a whole system of supporting practices.

    TDD without continuous integration leads to failing tests in practice.

    There’s more than just the words. Words have meaning. A surface-level interpretation of the three laws gets you little.

    The important things about TDD, which make TDD what TDD is, are not tied to any language.
    Hogwash. Again, in those rules is the word “write”. The act of TDD involves writing code, both tests and production code. If you are not doing that, you are not practicing TDD. Since you prefer the opinion of other people, ask Kent, Ward, Uncle Bob, JB, ... Go ahead, go ask them – they are all approachable people.
    Then replace “stack.Push(x)” with “stack = stack.Push(x)” and replace “x := stack.Pop()” with “x, stack := stack.Pop()”.
    You are changing the test to accommodate a change to a class based on a language decision. Time and time again, you prove my point over and over. You are clearly as blind to my logic as I am to yours. Really, at this point I’m amazed. I’m wondering if this is about the exchange of ides or an underlying need to be right (this applies to both of us, by the way).

    I’m wrong often, I’m corrected and I change my ideas all the time.

    You seem to be obsessed with names:
    the high-level concept of a stack is in the test names.
    You keep coming back to this idea. You are wrong about this. Wait, let me say that a different way. You are focusing on one thing at the expense of other things. Either the names are clear and do not need steps for explanation or they do need steps for explanation. If they do not need steps to make them clear, then the name is the test. But you have not shown any examples of names that are inherently clear. They always need:
    • A sequence of detailed steps
    • A translation (in some cases) to an underlying language

    Thees are part of the TDD process. Go back to the three laws and read the word “write” over an over until you understand that, because apparently you do not.

    Apparently in your world, pop has some intrinsic meaning to you. However, it does not have any meaning not already given to it by work done in previous years. That meaning is encoded within a world of tacit knowledge.

    But more fundamentally, when developing a system, TDD comes from requirements. Requirements are written in a natural language (and if you want to get into an argument about using formal languages and program correctness proofs, I’m all for that – but that’s a side point right now). Those requirements are refined through a series of interpretations. That meaning eventually gets coded into various forms of tests (I hope), whose names are not nearly as clear as pop. Yes, I know, you mentioned the whole layering thing.

    But the layering thing is a form of decomposition. The type of decomposition you do depends on the language. (Please say that it doesn’t, I’ll get a great laugh out of that.)
    Good design can be done without using TDD (although TDD surely helps in getting feedback about the design and in evolving the design), so although the skill of designing is a prerequisite of using TDD, it is not part of TDD.
    I agree that good design can be done without TDD. But it does not follow that TDD is independent of design. I don’t think in this conversation thread I’ve made that point.

    I don’t agree that good design is language neutral, at all. I also reject the idea the good programming skills are language neutral. That’s demonstrably false. And if you’d like I can bring in other, much older experts to back me up. But I don’t think there’s much of a point because like me, you won’t change your mind.

    So good design requires good language skills. Good TDD requires good design skills. They are coupled. They are not nearly as orthogonal as you’d like to believe they are.

    ...I’m a programmer, a typical reply is “In what language?” or “What kind of programs can you make?” I find those questions absurd. My usual reply to both questions is “Whatever is needed.”
    In a sense I both agree and disagree with this. I prefer working with people who are good thinkers, who can pick up new ideas and who can change how they approach problems based on context.

    However, I have personally transitioned, and both watched and helped other people transition from one programming model to another. People who have programmed in languages like C, FORTRAN and COBOL generally have a very hard time making the transition to using OO languages. There is a steep learning curve (6 – 12 months generally for a successful transition) to learn how to think in the new ways that OO languages allow you to express yourself. The same can be said of learning how to programming using functional programming languages.

    I’ve worked with people who downplay the importance of learning the implied model of programing offered by a particular language. Sure, you can write C code in C+, but it is flawed on many levels. I have seen people write COBOL in C+ and the code was buggy, hard to maintain and hard to even read.

    Often, switching languages is no big deal. For example, C# and Java are pretty much the same language (up to C# 2.0). As soon as you add in LINQ and Lambdas, C# allows for more expression. Someone writing Java code in C# will do something similar to someone writing COBOL code in C++. To a lesser extent, to be sure.

    Neither have I worked in every language that there is.
    Neither have I. And yet, that’s NOT my point. There are categories of languages. I’ve already mentioned some dimensions of those categories in previous posts on this thread. So in many respects, Java, C#, C++, Objective-C are the same language. However, there are some fundamental differences in those languages (available of a meta-model, lack of a VM, type system, support for generics) that lead to very different solutions when using the language effectively.

    There is an alternative, program in one language and multiple syntaxes. That’s taking the lowest common denominator approach. It can work quite well for much of software development. I don’t prefer to practice that myself.

    Until you can see software development from that point of view, it’s pointless for me to continue this discussion.
    Wow, really? So because I do not share your world view, this is a waste of your time? If that’s the case, then why did you been in this conversation in the first place? Clearly, I have not at any point shared your world view.

    Why give up now?

    And a related question, why am I still involved? (I’ve though about that a bit.)

    I originally started this based on a strongly-worded response to someone about whether or not TDD was language neutral. My original response expresses my surprise that someone could think that about TDD.

    Obviously many people share that opinion. I still do not.

    So I am getting insight into how one person thinks about TDD. This is valuable to me because when I teach, there will be more people that have your world view. To actually converse with someone I need to have insight into their perspective. This conversation is helping with that. But make no mistake, understanding someone’s perspective is not the same as accepting it.

    That someone holds a different perspective on TDD does not them write or wrong, nor does it make me right or wrong. This is not an issue of right or wrong, it is a matter of perspective.

    Can we discuss TDD without ever brining up language issues? Yes, at least superficially.

    However, TDD is a practice. It manifested itself most recently in XP as an extreme form of testing. That is, there’s a bug, make it repeatable, fix it. Now replace bug with missing feature and you have TDD. Oh, and the X in XP, do it all the time.

    So in a nutshell: express an intent, manifest it. That’s the essence of TDD conceptually. So we can talk about TDD in a language neutral manner. In fact, at this level it applies to more than just programming.

    But as a practice, TDD requires making informed decisions at every step of the journey. Those decisions are informed both by the language as well as the requirements, context, political environment, skill level of the team, time frame, etc.

    So can we talk about TDD in a language neutral manner? Sure. Can we practice it? I don’t believe we can.

  33. Avatar
    Esko Luontola 6 days later:

    The other commenters appear to already have been smart enough to stop posting here. I’m doing that also.

  34. Avatar
    Blu-ray ripper mac 2 months later:

    Best Blu-ray to iPad- easily convert Blu ray(.m2ts) and DVD (.vob) to iPad

  35. Avatar
    Ashley 3 months later:

    My tdd training course was taught with only one language, not multiple, and I thought it was very successful.

  36. Avatar
    DVD to HTC 3 months later:

    dsgs thanks,the post is really good PDF to BMP Converter will give you the satisfied

    output quality and conversion speed. Whether you are professional or novice, you can apply it without any errors. You can even set

    the personalized output effect

  37. Avatar
    five finger shoes 3 months later:

    i believe you are good at writing. a good writter need many good topics

  38. Avatar
    m2ts to mkv converter 4 months later:

    M2TS to MKV Converter is the best software for user to convert M2TS to MKV file, With the powerful M2TS to MKV converter,you can convert M2TS to MKV with best quality and convert M2TS to all the video formats.m2ts to mkv converter

  39. Avatar
    karfau 5 months later:

    In the end, I really loved to read this.

    Two people that obviously are experienced with TDD in practice, discussing an interesting topic. Both with repeatedly very good arguments.

    Sadly, from my point of view, there was a drift of locking the own opinion, literally saying “You are wrong”, and not reading the whole sentence before “striking back” (which I assume when seeing quotes that are cut in a way that changes there expression), and by acting this way giving the discussion a slight taste of a “flame war” about the original questions.

    Attacking the other person seldom helps the discussion.

    That being said, thanks for the “talk” and many great resources that are collected here.

    karfau

  40. Avatar
    Mario oyunlar? 5 months later:

    i believe you are good at writing. a good writter need many good topics

  41. Avatar
    türkçe porno 6 months later:

    hakketten saoL isime yaradi burasi

  42. Avatar
    Mosquito repellent plants 6 months later:

    So this rules out Hibernate and Spring. Taking away these tools does not stop me from building a system, but it does have an impact on gross assignment of responsibility, which is an important component of software architecture.

  43. Avatar
    cheap vps 6 months later:

    What follows is a slightly changed version of my response. What I’m wondering is this: Do you think the practice of TDD is fundamentally impacted by your programming language?

    Read on for my response. You might want to add a comment before reading my response to avoid “group think.”

    Based on the original comment, I started with: It seems to me that you’ve not written professionally in many different languages. Or if you have, you’ve not effectively used those different programming languages.cheap VPS

  44. Avatar
    supplynflshop 7 months later:

    thanks for sharing

  45. Avatar
    Low Glycemic Foods 8 months later:

    Amazing post Maki. Like reading copywriting book from Joe Sugarman or Dan Kennedy. Now I just have to apply the information to my business ;-) Please keep it up. I look for your posts on my iphone rss feed every day.

  46. Avatar
    Corum Replica Watches 8 months later:

    Corum Replica Watches was also during this period that Corum Replica Watches began adding reference numbers to the watches it sold, usually by stamping a four-digit code on the underside of a lug. In fact, many collectors refuse to accept a as an original unless these numbers are present.

  47. Avatar
    Peter 9 months later:

    Any example to show how mainframe CICS COBOL can be developed using TDD?

  48. Avatar
    Cheap golf Gloves 9 months later:

    The post and comments are very useful with me. Thanks.

  49. Avatar
    Payday loans with bad credit online 10 months later:

    Thanks for sharing these comments. I found some new things about TDD language. Really, The post is quite informative and useful too.

  50. Avatar
    Pandora 10 months later:

    If you go for cheap, you’re going to pay double; and maybe even triple.

  51. Avatar
    http://www.blacktowhiteiphone4.com 11 months later:

    If you want to follow the fashion trend, you can never miss the hottest White iphone 4 Conversion Kit. With smooth and liquidity design, we sure White iphone 4 Conversion Kit is what you want.

  52. Avatar
    rolex oyster perpetual datejust ladies watch 11 months later:

    With smooth and liquidity design, we sure White iphone 4 Conversion Kit is what you want.

  53. Avatar
    IC componenets 12 months later:

    good sharing and post

  54. Avatar
    iPhone SMS to Mac Backup about 1 year later:

    I really like this essay. Thank you for writing it so seriously. Would you like to banckup iphone SMS to mac, macBook, macbookPro as .txt files? Now a software iphone SMS to Mac Backup can help you to realize it.

  55. Avatar
    http://www.instantloansneed.co.uk/ about 1 year later:

    Interesting. I agree with the fact that TDD is language neutral. Nice post.

  56. Avatar
    nimol about 1 year later:

    I admire the value of information you offer in the blog and the presentation style is really impressive which having some good example of Java and C++ I know only that TDD stands for test driven development but here I found something new about TDD. Xtreme Fat Loss Diet Review

  57. Avatar
    dory about 1 year later:

    This is a good post. Thank you so much. Keep up the good works. Social Network

  58. Avatar
    Seobaglyak about 1 year later:

    a Seobaglyak igazán éjszaka érzik elemükben magukat. Szinte ”kétlaki” életet élnek. A Seobaglyak éjszaka sokkal éberebbek, és agresszívabbak, olyannyira, hogy olyankor saját fajtársaikat tartják a legnagyobb ellenségeiknek.

  59. Avatar
    Golf Simulators about 1 year later:

    This technology is no longer useful.

  60. Avatar
    designerbagssale about 1 year later:

    Wholesale recruits create a large amount of wholesale designer bags sale to clients. One of several forms of below wholesale equipment that will general providers make available so that you can company is purses and Prada Leather Handbag – Black.

  61. Avatar
    How to have a boy about 1 year later:

    I think the practice of TDD is fundamentally impacted by my programming language

  62. Avatar
    okey oyunu oyna about 1 year later:

    Thanks a lot.

    internette görüntülü olarak okey oyunu oyna, gerçek kisilerle tanis, turnuva heyecanini yasa.

  63. Avatar
    sonyyx about 1 year later:

    Adoption of Test driven development technique is an important requirement for new developer. I have really excited to get more knowledge about TDD.In my point of view,TDD is a testing language.so valuable stuffs.Credit Card Collections

  64. Avatar
    cheap brand watches about 1 year later:

    It is really a nice post, it is always great reading such posts, this post is good in regards of both knowledge as well as information. Very fascinating read, thanks for sharing this post here.

  65. Avatar
    Ramzes1 about 1 year later:

    T mobile internet

  66. Avatar
    Beats By Dre UK about 1 year later:

    Do things you like to do, not loved constraint

  67. Avatar
    mbt shoes sales about 1 year later:

    THANKS A LOT!!! SAGA IS HOOOOT

  68. Avatar
    Nike Max Sale about 1 year later:

    Adoption of Test driven development technique is an important requirement for new developer.

  69. Avatar
    Nike Max Sale about 1 year later:

    THANKS A LOT!!! SAGA IS HOOOOT

  70. Avatar
    bodybuilding about 1 year later:

    I did a search on the topic and found most people will agree with your post.

  71. Avatar
    jewellery store about 1 year later:

    I think TDD language is neutral, I was discussing with my friends yesterday, they also have the same opinion !! So TDD is definitely neutral !!

  72. Avatar
    deadbeat millionaire review about 1 year later:

    Would you like to banckup iphone SMS to mac, macBook, macbookPro as .txt files? Now a software iphone SMS to Mac Backup can help you to realize it.

  73. Avatar
    Flat Roofing about 1 year later:

    I found some new things about TDD language. Really, The post is quite informative and useful too.

  74. Avatar
    design and print about 1 year later:

    Taking away these tools does not stop me from building a system, but it does have an impact on gross assignment of responsibility, which is an important component of software architecture.

  75. Avatar
    car colour about 1 year later:

    For anything other than trivial behavior, there will be a difference between a unit at the behavioral level and a unit all the way into final implementation level.

  76. Avatar
    cookies gift baskets about 1 year later:

    it needs a bokmark so i can come back to it later ,nice stuff

  77. Avatar
    custom logo about 1 year later:

    I don’t think that it makes sense to say “teach a TDD class in several languages simultaneously”. TDD is a language-independent technique. custom logo

  78. Avatar
    hiv cure about 1 year later:

    I agreed I don’t think that it makes sense to say “teach a TDD class in several languages simultaneously”. TDD is a language-independent technique hiv cure

  79. Avatar
    nlp about 1 year later:

    I see that any efforts and work that give any kind of help and useful informations to people anywhere must be thanked and respected efforts , if it is small or big , from one person or group , your informations also must be thanked

  80. Avatar
    analysis essay about 1 year later:

    I AGREED On another blog, a commenter wrote (I’m leaving names out, though you can see the original blog if you look): analysis essay

  81. Avatar
    reviews of provillus about 1 year later:

    it needs a bokmark so i can come back to it later ,nice stuff

  82. Avatar
    dallas zip codes about 1 year later:

    I think that TDD was thought for dynamic environment like smalltalk, where you can create classes and methods while you are debugging. So imagine, you create the test first, you run it, it fails (as expected), you debug it, and you program while debugging!!. Then, you can use the refactoring browser to refactor clases and methods. It is great, i couldn´t achive this in other languajes. What do you think about it?

  83. Avatar
    beats by dre store about 1 year later:

    Are there testing things that do need language support? Sure. Mutative testing (like the Ruby library “heckle”) needs a language that gives you software access to the parse tree and also that allows you to compile a parse tree directly. Languages that are lisps (or at least lisp-influencebeats by dre sale cheap beats by dre

  84. Avatar
    Headset about 1 year later:

    Better than rice porridge pumpkinAfter a summer of sunshine and growth, cheap beats by dr dre Dre Studio and now the pumpkin is the best time to nutrition, pumpkin porridge now is the season most suitable for people currently make up the porridge autumn. cheap beats by dr dre Dre Pro Pumpkin porridge is warm porridge, cheap beats by dr dre Solo HD and other cool of porridge than a mild autumn pumpkin porridge is easier to fit the needs of the human gastrointestinal warming.

  85. Avatar
    bagsupplyer about 1 year later:

    It is nice of you to post this.Thank you very much.I will pay more attention on it.Waiting for update. Discount designer men Evisu long sleeve t shirt from China at on line store

  86. Avatar
    Michael Vick Jersey about 1 year later:

    Philadelphia eagles WR the star’s Vick Jersey took over twice all-star,another one is Brent Celek who like wear Asomugha Jersey, Jackson hope to get a new contract last season, Jackson has 47 times catch 1056 yards and six touchdown, his every catch 22.5 yards top ranking NFL

  87. Avatar
    hf g about 1 year later:

    mn ‘gl ’;n

  88. Avatar
    Kantamal about 1 year later:

    Hearing you all taking about TDD is really refreshing although you have different points of view. I personnally fight against (or may I say ‘among’) a group of developpers that still don’t work in Agile way beyong the fact that we “officially” say we do XP.. What I think about the question ‘is TDD neutral to language’, the answer can only be yes if one consider, more like Samuel say it, that TDD is a “principle of developping (or of development)”... I usually extend, or try to extend, that TDD idea in every aspect of my work not only pur development : Write a test for what you want (to obtain, or sometimes do), then make a pace in developping the part that will do the work, refactor or not and continue again, micro step by micro step.

    I think that it is the essence of XP itself : having the best possible feedback which can be always considered as “the fastest feedback possible” doesn’t it ?

    I have a question that may not be correct to post here but I face a problem with the “framework” itself but not the language : it happens too often to me that the language itself is not a problem for TDD but I’m still stuck in doing ‘integration tests’ against ‘unit tests’ because the framework itself prevent me from isolating my function. What can one do in that case ?

    To be clear, if I am to test my function, I have to include almost all the framework and then I’m stuck to the way the framework works… or stuck to reproduce so much functionality (for example in mock functions…), I can really see what I can do in that case because my ‘micro step’ become so long, the TDD losts its advantage (but still I have the guiding failing test yes). Not to say that, that framework itself is almost anti-TDD because of the ‘heaviness’ is represents and because of the “indirect feedback” it gives me about my function.

  89. Avatar
    best sleep aid about 1 year later:

    Blog posts about wedding and bridal are always rare to find , at least with great quality,you qualify for a great blog post writer title,kep the great job happening

  90. Avatar
    Tran Dang Khoa about 1 year later:

    Thanks !

  91. Avatar
    Christian about 1 year later:

    ass fg+0s0dgd9f8g5sd

  92. Avatar
    moncler about 1 year later:

    asdf sdfg7dfh7f98fdf

  93. Avatar
    Louboutins about 1 year later:

    asds dfg+sd80f+0gd666f

  94. Avatar
    sex about 1 year later:

    very useful!I’m still waiting for some interesting thoughts from your side in your next post

  95. Avatar
    bakiretr about 1 year later:

    I think TDD language is neutral, I was discussing with my friends yesterday

  96. Avatar
    Fake Oakley Radar about 1 year later:

    It really a good article.replica Oakley Enduring Pace Sunglassescheap oakley five squared sunglassesoakley five squared sunglasses wholesalereplica oakley five squared sunglassescheap Oakley Fives SunglassesOakley Fives Sunglasses wholesalereplica Oakley Fives Sunglassesoakley flak jacket sunglasses wholesaleReplica Oakley Juliet SunglassesReplica Oakley Fuel Cell SunglassesReplica Oakley Half Jacket SunglassesReplica Oakley Holbrook SunglassesFake Oakley Radar sunglassesFake Oakley Oil Rig sunglassesFake Oakley Polarized sunglassesFake Oakley Antix sunglassesOakley Enduring Pace SunglassesOakley Zero SunglassesOakley Active SunglassesOakley Juliet Sunglasses

  97. Avatar
    Sunglasseshut discount online shop about 1 year later:

    I like the style of this article, is very good.oakley mens flak jacket sunglassesoakley half jacket sunglassesdiscount oakley half jacket sunglassesoakley half jacket sunglasses saleoakley mens half jacket sunglassesoakley jawbone sunglassesdiscount oakley jawbone sunglassesoakley jawbone sunglasses saleoakley mens jawbone sunglassesoakley m frame sunglassesdiscount oakley m frame sunglassesoakley m frame sunglasses saleoakley mens m frame sunglasses

  98. Avatar
    discount oakley fives sunglasses about 1 year later:

    I like it. come on oakley mens antix sunglassesoakley batwolf sunglassesdiscount oakley batwolf sunglassesoakley batwolf sunglasses saleoakley mens batwolf sunglassesoakley dispatch sunglassesdiscount oakley dispatch sunglassesoakley dispatch sunglasses saleoakley mens dispatch sunglassesoakley fives squared sunglassesdiscount oakley fives squared sunglassesoakley fives squared sunglasses saleoakley mens fives squared sunglasses

  99. Avatar
    Fake Oakley Gascan sunglasses about 1 year later:

    I love this article, it’s very well.Fake Oakley Batwolf SunglassesFake Oakley BottlecapFake Oakley CrosshairFake Oakley Flak Jacket

  100. Avatar
    oakley radar sunglasses wholesale about 1 year later:

    It’s wonderful, thank you. Oakley Antix SunglassesOakley Batwolf SunglassesOakley Dispatch SunglassesOakley Fives Squared SunglassesFake Oakley Half X sunglassesFake Oakley Hijinx sunglassesFake Oakley M Frame sunglassesFake Oakley Minute sunglassesReplica Oakley Minute SunglassesReplica Oakley Monster Dog SunglassesReplica Oakley Pit Boss SunglassesReplica Oakley Restless SunglassesReplica Oakley Half WireReplica Oakley Half XReplica Oakley Hijinxoakley m frame sunglasses wholesalereplica oakley m frame sunglassescheap oakley minute sunglassesoakley minute sunglasses wholesalereplica oakley minute sunglassescheap oakley monster dog sunglassesoakley monster dog sunglasses wholesale

  101. Avatar
    Ashley Bowling about 1 year later:

    Q: How many QA testers does it take to change a lightbulb? A: QA testers don’t change anything. They just report that it’s dark.

  102. Avatar
    moncler piumini about 1 year later:

    great post,thank you very much

  103. Avatar
    luxe boots about 1 year later:

    buy australia luxe boots on sale

  104. Avatar
    canada goose jakke about 1 year later:

    Om canada goose jakke spørgsmål vedrørende fødevaresikkerhed, canada goose Gruppen af otte forventes canada goose outlet at lancere “Aquila fødevarer belstaff outlet security initiative”, vil være os $ 10-15 milliarderi belstaff støtte begået for landbrugs udvikling i fattigere Canada Goose Ungdom Freestyle lande.Med hensyn til finansforordningen forventes gruppen af otte ledere at være “Lecce rammen” Hot Salg på grundlag af vedtagelsen canada goose jakke af en politikfil, cross-domæne Canada Goose Banff Parka for at styrke tilsynet med banker, institutioner og virksomhedsledelse, og I am legend og har Hot Salg for nylig udgivet selvmord.I dag, efteråret Canada Goose Handsker på ny hylden, ikke kun mode, men vil holde dig tilsluttet på legender af læder.

  105. Avatar
    BRAM about 1 year later:

    Noumerous contrast between Java and C++....

  106. Avatar
    UGG Broome about 1 year later:

    in an exclusive variety of styles, colors Uggs Soldes and sizes to keep the little feet just as happy

  107. Avatar
    Headset about 1 year later:

    Myth: nutrition is not better.”Nutrition” can not lack, cheap beats by dr dre Solo HD but not better.Also to the protein, for example to illustrate the “nutritional” amount of importance. cheap beats by dr dre Dr. Dre Tour Growth and development of children is not enough if the intake of protein, it will affect height, weight, and intelligence and other aspects of normal development.So many people in addition to food intake of protein, cheap beats by dr dre it also eat a little protein powder.

  108. Avatar
    personal statement about 1 year later:

    Nice Post. Please visit our website for college consulting and essay editing

  109. Avatar
    nikewomenheels about 1 year later:

    One of the most famous and widely-practiced dance women jordan heels form is ballet. Almost everyone around the globe knows what ballet is, regardless of whether you are into the art, know someone women jordan heels practicing ballet, have seen it on television or movies, in musical plays or stage presentations. Ballet is the predominant dance art that has enjoyed global appeal.Of all the dance arts Jordan Heels For Women or forms that are being practiced, aside from the territorial or regional ethnic dance forms- ballet enjoys a reputation a notch above the rest since it is associated with prestige and sophistication.

  110. Avatar
    iPhone to Mac Transfer about 1 year later:

    it is possible for most of us to use this well? if so, I think most of the programmer would like to use it.

  111. Avatar
    TS Konverter over 2 years later:

    TS Konverter can easily convert ts to avi, mpeg, wmv, divx, xvid, flv, etc, free download supported. TS Konverter Mac is a powerful and faultless TS Converting Tool for Mac combining video and audio editting functions.

  112. Avatar
    Windows 7 Support over 2 years later:

    TDD is faster in the long-run, not the short-run. There’s no way around the fact that writing tests requires an upfront time commitment. But oftentimes the cost is worth it… Windows 7 Support

  113. Avatar
    video games over 2 years later:

    Thanks for the information, I’ll visit the site again to get update information video games

  114. Avatar
    language lab over 2 years later:

    Really wonderful! I read various articles from this site. I like your articles and will continue follow you site!!

  115. Avatar
    eworking over 2 years later:

    Unique concept with comprehension details have that much ability to take attention of readers to get knowledge on this concept.Fabulous addition.eworking

  116. Avatar
    CPAD over 2 years later:

    For better acknowledgment with this briefly represented but fabulous contents supports to acquire huge ideas on tdd language.Above blogs allows readers to know its different principles and approaches.CPAD

  117. Avatar
    Silicone Molding over 2 years later:

    With more than 20 years of experience, Intertech provides an extensive integrated operational ability from design to production of molds 100% made in Taiwan. Additional to our own mold making factory, we also cooperate with our team vendors to form a very strong working force in Taiwan.

    For the overseas market, we work very closely with local representatives in order to take care of the technical communication and after-sales service to our customers. We also participate in the EUROMOLD & FAKUMA exhibitions and meet our customers every year in Europe. By concentrating on mold “niche markets”, we play a very useful mold maker role from the Far East whenever customers want to develop their new projects. We provide services from A to Z to our customers on a very economic cost and effect basis.

  118. Avatar
    fitflop over 2 years later:

    Because of give us the information. If only an individual best of luck!

  119. Avatar
    plastic injection mold over 2 years later:

    Intertech Machinery Inc.

    With more than 25 years of experience, Intertech provides an extensive integrated operational ability from design to production of molds 100% made in Taiwan. Additional to our own mold making factory, we also cooperate with our team vendors to form a very strong working force in Taiwan.

    Main Products:

    Injection Mold, Silicone Molding, Rubber Mold, Silicone molding, PC High-Gloss Plastic Mold, Die Casting Mold, Silicone Mold, Silicone Rubber Mold, Liquid Silicone Rubber , Cosmetic Packaging Mold, Medical Products Mold, Engineering Plastic Molds, Home Appliances Mold, etc…

Comments