>Virtual Functions: no need for that.     
   
 No, sorry, but once you start writing unit tests in the large scale, you 
will understand. Code needs to be written to maximize unit-testability. 
When you write code that's designed to be testable, you will do things 
that you wouldn't have done if you were just designing for performance.  
   
 When you design for performance, you are basically writing assembler code 
except it's in a high-level language.  
   
 But when you write testable code, you are writing exquisitely modular 
code that makes very few assumptions about what it's interfacing with. 
Basically you need to code to interfaces or abstract classes all over the 
place, so that you can test one unit (typically, unit=a class) at a time 
without becomingb bogged down by coping with that unit's interactions with 
other units.  
   
 So you replace the other units with mock implementations tthat do 
something artificial, for test purposes. I know a lot of people who are 
new to unit testing say "no, but that's artificial, that's not testing a 
real scenario, that's not testing your whole application from end to end." 
 
   
 This is totally missing the point of unit testing. Unit testing isn't 
SUPPOSED to test everything from end to end, it's simply supposed to be a 
step in the right direction of having a test for ANYTHING, at ALL. Also, 
unit testing gives you a way to achieve 100% test coverage without the 
extreme complexity of devising functional test cases that would achieve 
the equivalent coverage. Functional testing for the same coverage is 
always more difficult because of the number of paths through the code that 
must be traced. It's more difficult in terms of developer man-hours and 
it's also more difficult in terms of the CPU and disk resource consumption 
of the automated tests, because the entire application must be executed 
repeatedly, with many different inputs, to achieve the same coverage. For 
a reasonably complex application that accesses a database, for instance, 
this will result in many many calls to the database layer, more than is 
needed to actually test the database layer. So really, making a mock 
implementation of AT LEAST your database layer is the only sane way to 
proceed.  
   
 This naturally maps to object orientation, and you end up coding to an 
interface that you can swap out. That means virtual functions, in C++ 
parlance. Of course you can do virtual functions in C, by passing around 
pointers to jump tables. But it's really pointless to bother doing so. If 
you are already doing this design pattern, you have already lost the 
(slight) performance advantage of remaining in C-land. It's actually 
better to move to a language that can manage that for you--and in the 
right circumstances, you can regain the lost performance by using a 
compiler and runtime that are aware of object orientation and can optimize 
it for you. If you're using OO concepts, it's really better to use a 
language that can express those concepts as a first-class language 
construct and does not relegate them to the status of a second class 
citizen.  
  

Reply via email to