CSC/ECE 517 Fall 2011/ch6 6c p: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
(Created page with "<p style="font-size: 24px">'''Generics'''</p> =='''Introduction'''== In a broad definition, generic programming is a style of computer programming in which algorithms are writ...")
 
No edit summary
 
(10 intermediate revisions by the same user not shown)
Line 1: Line 1:
<p style="font-size: 24px">'''Generics'''</p>
<p style="font-size: 24px">'''Generics'''</p>


=='''Introduction'''==
=='''Introduction'''==
Line 6: Line 5:
In a broad definition, generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters.  
In a broad definition, generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters.  


=====Why Generics?=====
====Why Generics?====
 
This approach involves writing common functions or types that differ only in the set of types on which they operate when used, thus reducing duplication.
This approach involves writing common functions or types that differ only in the set of types on which they operate when used, thus reducing duplication.


Duplicate code is a computer programming term for a sequence of source code that occurs more than once, either within a program or across different programs owned or maintained by the same entity. Duplicate code is generally considered undesirable.
Duplicate code is a computer programming term for a sequence of source code that occurs more than once, either within a program or across different programs owned or maintained by the same entity. Duplicate code is generally considered undesirable.


=====Problems with code duplication=====
====Problems with code duplication====
 
====Unit====
A unit is the building block of a code. It can be a class, typically individual methods or lines within methods, an interface etc.
 
====What does Unit Testing mean?====
[http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2010/ch1_1f_vn Unit testing] is the process of testing a code by focusing on a small chunk (unit) of code at a time, checking whether it functions properly, to give the desired results.


====Why Unit Testing?====
=====Avoiding bulk code=====
Code duplication frequently creates long, repeated sections of code that differ in only a few lines or characters. The length of such routines can make it difficult to quickly understand them. Hence, code duplication is discouraged.


=====Benefits of Unit Testing:=====
=====Purpose masking=====
The repetition of largely identical code sections makes it difficult to identify how they differ from one another, and therefore, identifying the specific purpose of each code section. Often, the only difference is in a parameter value. The best practice in such cases is a reusable subroutine. If the parameter type differs then it is called a generic case.


 Fast – It gives instant feedback on the accuracy of your code.
=====Update anomalies=====
Any modification to a redundant piece of code must be made for each duplicate separately which is very tedious.  At worst, some locations may be missed, and for example bugs thought to be fixed may persist in duplicated locations for months or years. The best practice here is a code library.


 Design – For testing, the code is designed as small modules facilitating the reusability of the units.
The generics approach was popularized by Ada - programming language.
Code set written using generic programming are known as generics. They are used in programming languages like Ada, Java, C++ and Visual Basic .NET. Generics create dynamically high parameterized software which can be difficult to follow.


 Individuality – Each unit is designed independent of each other and tested individually making error identification easy.
The term generic programming was originally coined by David Musser and Alexander Stepanov.


 Efficiency - Bugs can be scanned in the probable bug prone code areas making debugging efficient.
====Popular Example of Generics====
Early examples of this programming approach were implemented in Ada, although the best example is the  [http://en.wikipedia.org/wiki/Standard_Template_Library Standard Template Library (STL)] in which iterators are used to access different values of an algorithm and provide them with varying datatype inputs.


 Understanding – Helps any reader, easily understand the methods’ functionality.
=====The Standard Template Library (STL)=====
It is the C++'s Standard software library. It provides four components such algorithms, containers, functors, and iterators. We are mainly concerned with the algorithm and iterators.  Here, as mentioned above algorithms are accessed with iterators where the values provided through iterators and make the algorithm work with different data types having same functionality.


=====Limitations of Unit Testing:=====
The STL provides a ready-made set of common classes for C++, such as containers and associative arrays, that can be used with any built-in type and with any user-defined type that supports some elementary operations (such as copying and assignment). STL algorithms are independent of containers, which significantly reduces the complexity of the library.


 Tedious Job for Complex Codes – Implementing and running test cases for complex codes is time consuming. Moreover, coding a unit test is as tedious as coding the target program itself.
=='''Understanding Generics'''==
Let us consider an example in STI.  A sequence of data structures, e.g. a vector etc., and some algorithms to operate on them, e.g. find, sort etc., a direct approach would implement each algorithm specifically for each data structure which would be highly impossible.  
In the generic programming approach, each data structure returns a model of an iterator concept (a simple value type which can be dereferenced to retrieve the current value, or changed to point to another value in the sequence) and each algorithm is instead written generically with arguments of such iterators. Thus, reducing the data structure-algorithm combinations need be implemented and extensive reusability.


 Impact of Change in the Code Requirements - In an agile project that is accompanied with periodic changes in requirements will result in constant updating of test cases to match the latest developments.
Iterators are of different types for e.g. forward iterators only provide movement to the next value in a sequence (e.g. suitable for a singly linked list), whereas a random-access iterator also provides direct constant-time access to any element of the sequence (e.g. suitable for a vector). An important point is that a data structure will return a model of the most general concept that can be implemented efficiently—computational complexity requirements are explicitly part of the concept definition.  


Here, Arrays and Structs can be viewed as predefined generic types. Every usage of an array or struct type instantiates a new concrete type, or reuses a previous instantiated type. Array element types and struct element types are parameterized types, which are used instantiate the corresponding generic type. All this is usually built-in in the compiler and the syntax differs from other generic constructs.


=='''Testing Techniques'''==  
=='''Generics in Object Oriented Programming Languages'''==
Generic programming first appeared in Ada and was subsequently adopted by many object-oriented languages. Implementation in languages such as Java and C++ are formally based on the notion of parametricity.


====Test-Driven Development(TDD)====  
====Generics====
[http://en.wikipedia.org/wiki/Test-driven_development Test Driven Development (TDD)]is an advanced technique of using automated unit tests to drive the design of software. The result of using this practice is a comprehensive suite of unit tests that can be run at any time to keep track of the code development.
Define Common Block
 
{ Code statements
Here
  }
   
 Test cases are written initially keeping in mind the final result.


 The initial test is conducted which eventually fails because of absence of a target code.  
Program
{ Call Common Block  // For different data types and values.
}


 The test suggests further steps to build/refactor an error free code and only those programs associated with the tests go into production.
====Example of generic programming[http://www.boost.org/community/generic_programming.html [1]]====
Let us consider the memcpy() function to copy a set of array values and then generalize it using generics approach.


 Tests are then re-conducted until satisfactory results are achieved.
void* memcpy(void* region1, const void* region2, size_t n)
{
  const char* first = (const char*)region2;
  const char* last = ((const char*)region2) + n;
  char* result = (char*)region1;
  while (first != last)
    *result++ = *first++;
  return result;
}


[[File:TDD development cycle.png|thumb|400px|center|Development Cycle of TDD]]
The memcpy() function is used to copy arrays of different kinds of data. Now considering the case were the data we would like to copy is not in an array? Perhaps it is in a linked list. We can generalize a copy function to any sequence of elements? Looking at the body of memcpy(), the function's minimal requirements are that it needs to traverse through a sequence using pointer to access elements, write them to the destination, and compare pointers to know when to stop. The C++ standard library groups requirements such as these into concepts, in this case the Input Iterator concept (for region2) and the Output Iterator concept (for region1).


====Behavior driven development (BDD)====
====Generic approach code====
template <typename InputIterator, typename OutputIterator>
OutputIterator
copy(InputIterator first, InputIterator last, OutputIterator result)
{
  while (first != last)
    *result++ = *first++;
  return result;
}


[http://en.wikipedia.org/wiki/Behavior_Driven_Development Behavior driven development (BDD)]is a software development technique that relies on the use of simple vocabulary. Tests are designed using natural language so that even a non-technical participant will be able to follow. BDD is an evolution in the thinking behind Test Driven Development but stresses extensively on the behavior aspect of the methods used in the code.
Using the above generic copy() function, we can now copy elements from any kind of sequence, including a linked list that exports iterators such as std::list.


#include <list>
#include <vector>
#include <iostream>


Eg: Tests result such as “the point cannot be created without code description” is more understandable than something like Test_category_ThrowsArgumentNullException .
int main()
{
  const int N = 3;
  std::vector<int> region1(N);
  std::list<int> region2;


  region2.push_back(1);
  region2.push_back(0);
  region2.push_back(3);
 
  std::copy(region2.begin(), region2.end(), region1.begin());


=='''Frameworks'''==
  for (int i = 0; i < N; ++i)
    std::cout << region1[i] << " ";
  std::cout << std::endl;
}


A framework is a tool to support writing and running of a program. A Unit Test framework is a set of reusable libraries or classes for a software system. Code is written in these frameworks, they are capable of running and checking the test code by themselves.


Here, a unit test framework will evaluate the code based on a variety of inputs provided in the test case and check for the accuracy of results.
====1) Generics in ADA====
In a generic a parameter is a value, a variable, a constant, a type, a subprogram, or even an instance of another, designated, generic unit that is used in the generic routine. For generic formal types, the syntax distinguishes between discrete, floating-point, fixed-point, access (pointer) types, etc. Some formal parameters can have default values.


====Testing Framework Parlance:====
To instantiate a generic unit, the programmer passes actual parameters for each formal. The generic instance then behaves just like any other unit. It is possible to instantiate generic units at run-time, for example inside a loop.


a. '''Test Case:'''  It is a main class where test methods are coded. All the units to be tested are inherited to this class.
One of the ways in which the Ada language supports this characteristic is by means of generic units.  


The generic here uses a package which contains a general operation to be performed.


b. [http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html '''Assertions (Test::Unit::Assertions):'''An assertion is the main condition that when held true would result in successful culmination of the test. If the assertion fails then the test would generate an error message with pertinent information so that the programmer can make necessary changes.
=====The specification of a generic package[http://en.wikibooks.org/wiki/Ada_Programming/Generics [2]]=====
  generic
  type Element_T is private;  -- Generic formal type parameter
procedure Swap (X, Y : in out Element_T);


procedure Swap (X, Y : in out Element_T) is
  Temporary : constant Element_T := X;
begin
  X := Y;
  Y := Temporary;
end Swap;


c. '''Test Fixture:'''  A test fixture is used to clean up methods for conducting more than one test, eliminating duplication of methods.  
The Swap subprogram is said to be generic. The subprogram specification is preceded by the generic formal part consisting of the reserved word generic followed by a list of generic formal parameters which may be empty. The entities declared as generic are not directly usable, it is necessary to instantiate them.


To use the generic we instantiate by
procedure Instance_Swap is new Swap (Float);
procedure Instance_Swap is new Swap (Integer);
procedure Instance_Swap is new Swap (Element_T => Stack_T);


d. '''Test Method:'''  It is a process to handle individual units referred for testing.
Here, the parameters passed have different data types making the generic widely usable.


=====A generic using a sub program=====
It is possible to pass a subprogram as a parameter to a generic. The generic specifies a generic formal subprogram, complete with parameter list and return type (if the subprogram is a function). The actual must match this parameter profile. It is not necessary that the names of parameters match, though.


e. '''Test Runners:''' Test Runners GUI’s that are used to conduct testing and provide with the results. Test runners such as Test::Unit::UI::Console::Test Runner and GTK test runners are used.
  generic
  type Element_T is private;
  with function "*" (X, Y: Element_T) return Element_T;
function Square (X : Element_T) return Element_T;




f. '''Test Suite:'''    It is a collection of tests.
Function description


function Square (X: Element_T) return Element_T is
begin
  return X * X;  -- The formal operator "*".
end Square;




We need a target code to conduct tests.
Usage of the generic
with Square;
with Matrices;
procedure Matrix_Example is
  function Square_Matrix is new Square
    (Element_T => Matrices.Matrix_T, "*" => Matrices.Product);
  A : Matrices.Matrix_T := Matrices.Identity;
begin
  A := Square_Matrix (A);
end Matrix_Example;


====Example Problem Statement for Target Code:====
To instantiate a generic unit, use the keyword new
To find whether a given point lies on the x-axis, y-axis or the origin.


Solution: We write a class to define the position (x-axis, y-axis or origin) of the point.
  function Square_Matrix is new Square
    (Element_T => Matrices.Matrix_T, "*" => Matrices.Product);


====Code : Position of a Point====  
=====Advantages=====
class Point
The language syntax allows precise specification of constraints on generic formal parameters. For example, it is possible to specify that a generic formal type will only accept a modular type as the actual. It is also possible to express constraints between generic formal parameters; for example:
attr_writer :xcoordinate
attr_writer :ycoordinate
def initialize(xcoordinate,ycoordinate)
  @xcoordinate = xcoordinate
  @ycoordinate = ycoordinate
end
#-----------Location of point on X-axis ----------------#
def isOnXaxis?
    if @ycoordinate == 0
    return true 
  end
end
#---------- Location of point on Y-axis ----------------#
  def isOnYaxis?
    if @xcoordinate == 0
      return true
  end
  end
#---------- Location of point on Origin-----------------#
  def isOnOrigin?
    if @xcoordinate == 0 && @ycoordinate == 0
    return true
  end
  end
end


=='''Testing Frameworks'''==
generic
    type Index_Type is (<>); -- must be a discrete type
    type Element_Type is private; -- can be any nonlimited type
    type Array_Type is array (Index_Type range <>) of Element_Type;


====Test::Unit====
In this example, Array_Type is constrained by both Index_Type and Element_Type. When instantiating the unit, the programmer must pass an actual array type that satisfies these constraints.


=====Overview=====
All instances of a generic being exactly the same, it is easier to review and understand programs written by others; there are no "special cases" to take into account.


a. It is based on the Test Driven Development Technique (TDD).  
=====Limitations=====
Ada does not allow specialized generic instances, unlike C++ and requires that all generics be instantiated explicitly but all instantiations being explicit, there are no hidden instantiations that might make it difficult to understand the program.


b. The Test::Unit framework integrates the following features:
Ada does not permit "template metaprogramming", because it does not allow specializations.
1. Way of expressing individual tests.


2. Provides a framework for structuring the tests.


3. Has flexible ways of invoking the tests.
====2) Generics in C++[http://en.wikipedia.org/wiki/Template_%28programming%29 [4]]====
When creating containers of objects it is possible to write specific implementations for each data type contained, even if the code is virtually identical except for different data types. In C++, this duplication of code can be circumvented by defining a template class. C++ has can support Generic Programming very well through this template system.


=====Process of Testing=====
Concepts have no direct representation in C++, so they are represented only within the documentation for a generic library. The documentation for the SGI Standard Template Library established the de facto standard for documenting concepts.


=====a. Installation=====
=====Specifications=====
  Valid Expressions are C++ expressions which must compile successfully for the objects involved in the expression to be considered models of the concept.


Test::Unit framework is pre-installed on all Ruby versions.
  Associated Types are types that are related to the modeling type in that they participate in one or more of the valid expressions. Typically associated types can be accessed either through typedefs nested within a class definition for the modeling type, or they are accessed through a traits class.


=====b. Algorithm=====
  Invariants are run-time characteristics of the objects that must always be true, that is, the functions involving the objects must preserve these characteristics. The invariants often take the form of pre-conditions and post-conditions.


We use a UI is used to run the Test code and display the gathered results. Here, we have used the web based UI.
Complexity Guarantees are maximum limits on how long the execution of one of the valid expressions will take, or how much of various resources its computation will use.


 Structuring the tests: Inherit the required classes.
Tem plate<typename T>
class swap (T x, T y)
{
  T temp;
  temp =y;
  y=x;
  x=temp;
return x
}


a. Here, “point” class is inherited to call the target units which have to be tested.
Instantiation is done by calling as an ordinary function
Swap_x << swap(5, 10);  // outputs 10


b. The “test/unit” class is inherited for methods required to conduct testing.
The compiler examines the arguments used to call swap and determines that this is a call to swap(int, int),  it then instantiates a version of the function where the parameterizing type T is int.


 Write the test methods.
This works whether the arguments x and y are integers, strings, or any other type for which the expression x interchanges y is sensible. Common inheritance is not needed for the set of types that can be used, and so it is very similar to [http://en.wikipedia.org/wiki/Duck_typing#Templates_or_generic_types duck typing]. In the context of a comprehensive library like the STL it allows the programmer to get extensive functionality for a new data type, just by defining a few operators for it. Merely defining < allows a type to be used with the standard sort(), stable_sort(), and binary_search() algorithms or to be put inside data structures such as sets, heaps, and associative arrays.
C++ templates are completely [http://en.wikipedia.org/wiki/Type_safety type safe] at compile time.


 Test methods are prefixed with test. Eg: test_examp where examp is the unit being tested.
A powerful feature of C++'s templates is template specialization. This allows alternative implementations to be provided based on certain characteristics of the parameterized type that is being instantiated. Template specialization has two purposes: to allow certain forms of optimization, and to reduce code bloat.


 In the methods write Assertions comparing them with expected results for the target units.
=====Advantages=====
Both macros and templates are expanded at compile time. Macros are always expanded inline; templates can also be expanded as inline functions when the compiler deems it appropriate. Thus both function-like macros and function templates have no run-time overhead.
#define max(a,b) ((a) < (b) ? (b) : (a))
However, templates are generally considered an improvement over macros for these purposes. Templates are type-safe.


 Text fixtures are optional; they can be used to clean the methods.
=====Limitations=====
Here are three primary drawbacks to the use of templates: compiler support, poor error messages, and code bloat. Many compilers historically have poor support for templates, thus the use of templates can make code somewhat less portable. Support may also be poor when a C++ compiler is being used with a linker which is not C++-aware, or when attempting to use templates across shared library boundaries. Most modern compilers however now have fairly robust and standard template support, and the new C++ standard, C++0x, is expected to further address these issues.


 Run the tests as Test::Unit test class name.rb
Almost all compilers produce confusing, long, or sometimes unhelpful error messages when errors are detected in code that uses templates.[10] This can make templates difficult to develop.


 To run only a particular method we can its name as classname.rb --name method
Finally, the use of templates requires the compiler to generate a separate instance of the templated class or function for every permutation of type parameters used with it. (This is necessary because types in C++ are not all the same size, and the sizes of data fields are important to how classes work.) So the indiscriminate use of templates can lead to code bloat, resulting in excessively large executables.[citation needed] However, judicious use of template specialization can dramatically reduce such code bloat in some cases. The extra instantiations generated by templates can also cause debuggers to have difficulty working gracefully with templates.


 If there are bugs, refactor the code.


 Repeat testing until all the bugs are fixed.
====3) Generics in JAVA====
Generics are a facility of generic programming that was added to the Java programming language in 2004 as part of J2SE 5.0. They allow "a type or method to operate on objects of various types while providing compile-time type safety. “A common use of this feature is when using a Java Collection that can hold objects of any type, to specify the specific type of object stored in it.


=====Flowchart=====
=====Specifications=====
[[File:Test unit flowchart.png|thumb|400px|center|Development Cycle of TDD]]
  A type variable is an unqualified identifier. Type variables are introduced by generic class declarations, generic interface declarations, generic method declarations, and by generic constructor declarations.


=====CODE Test::Unit=====
A class is generic if it declares one or more type variables. A generic class declaration defines a set of parameterized types, one for each possible invocation of the type parameter section. All of these parameterized types share the same class at runtime.
require "Point"
require "test/unit"
  class TestCase_Point < Test::Unit::TestCase
  def test_isOnXaxis
    assert(Point.new(3,0).isOnXaxis?)
    end
  def test_isOnYaxis
      assert(Point.new(0,4).isOnYaxis?)
  end
  def test_isOnOrigin
      assert(Point.new(3,4).isOnOrigin?)
  end
end


=====Result Test::Unit=====
  An interface is generic if it declares one or more type variables. A generic interface declaration defines a set of types, one for each possible invocation of the type parameter section. All parameterized types share the same interface at runtime.
Below are the test results that are obtained after running the above test cases.


=====Failed output=====
  A method is generic if it declares one or more type variables. These type variables are known as the formal type parameters of the method. The form of the formal type parameter list is identical to a type parameter list of a class or interface.
This is how the failed test cases are shown once we run the test cases,
[[File:Testunit failed.png|center|700px|center|Development Cycle of TTD]]


=====Passed output=====
  A constructor can be declared as generic, independently of whether the class of the constructor is declared in is itself generic. A constructor is generic if it declares one or more type variables.  
[[File:Testunit passed.png|center|800px|center|Development Cycle of TTD]]


=====Storing Test Files=====
=====Example of generic classes and methods in JAVA[http://en.wikipedia.org/wiki/Generics_in_Java [3]]=====
Test files can be stored in the same directory as the target file but eventually the directory gets bloated storing 2 files for the same target code. Instead we can store it in a separate test directory for better organization. Here, one must take care to clearly specify the path of the target code for inheritance purpose in the test file.
  public class Entry<K, V> {
 
    
Eg: If point.rb is stored in the directory lib and test_point.rb is stored in the test directory then to inherit point.rb we specify the path.
   private final K mKey;
require “../lib/point”
   private final V mValue;
----
 
   public Entry(K k,V v) {  
 
    mKey = k;
====Shoulda====
    mValue = v; 
 
  }
=====Overview=====
 
  public K getKey() {
a. Shoulda is a library that allows us to write better and easily understandable test cases for the ruby applications compared to Test::Unit.
    return mKey;
 
  }
b. It allows us to use the "it"-blocks from RSpec to define nice error-messages if a test fails.
 
c. In other words it is improvised form of Test::Unit and Rspec. It works inside the Test::Unit — you can even mix Shoulda tests with regular Test::Unit test methods.
 
=====Process of Testing=====
 
 
=====a. Installation=====
 
Shoulda is installed by running “gem install shoulda” in command prompt after setting the environment path as “…\Ruby\bin”
 
=====b. Algorithm=====
 
 Inherit all the classes involved in testing i.e. the target class and the shoulda library class. To achieve this add require "rubygems", require ”Point” and require "shoulda" to the test class.
 
 Then setup up a context “Point” (context is nothing but a region of code which deals with the functionality you are interested in.)
 
 Then define a method starting with should “method name” do and then describe the entire method.
 
 Make proper assertions to test the functionality in your method.
 
=====Code shoulda=====
require "rubygems"
require “Point”
require "test/unit"
require "shoulda"
  class TestCase_Point_Shoulda < Test::Unit::TestCase
   context "Point" do
   should "lie on the X-axis " do
      assert(Point.new(3,0).isOnXaxis?)
   end
  should "lie on the Y-axis " do
      assert(Point.new(0,4).isOnYaxis?)
  end
   should "lie on the Origin" do
    assert(Point.new(0,4).isOnOrigin?)
  end
  end
  end
 
=====Result=====
Below are the test results that are obtained after running the above test cases,
 
=====Failed Output=====
[[File:Shoulda failed.png|center|800px|center|Development Cycle of TTD]]
 
=====Passed output=====
[[File:Shoulda passed.png|center|600px|center|Development Cycle of TTD]]
----
 
 
====RSpec====
 
=====Overview=====
a. RSpec is Behavior Driven Development Unit test tool for ruby.
 
b. It allows us to write an initial code specifications (spec) document. The spec document talks about the program’s function.
 
c. Thereby, we can write the code based on the specifications (spec file).
 
d. The (spec) document is written in Domain Specific Language which makes it simple for the programmer to handle.
 
e. Better understanding of the test cases compared to shoulda as the cases and notifications are more descriptive.
 
f. In other words it is improvised form of Test::Unit and Rspec. It works inside the Test::Unit — you can even mix Shoulda tests with regular Test::Unit test methods.
 
=====Process of Testing=====
 
=====a. Installation=====
RSpec is installed by running “gem install rspec” in command prompt after setti ng the environment path as “…\Ruby\bin”
 
=====b. Algorithm=====
 
 We start by describing what our application behaves like. So we write down a specifications file.
 
 Using RSpec's “describe” block we describe the basic functions of the application.
 
 We then write the behaviors/expectations defining what we expect our system to behave like (expectations are similar to assertions in Test::Unit framework).
 
 There are two methods available for checking expectations: should() and should_not(). Spec::Expectations - Object#should(matcher) and Object#should_not(matcher).
 
 The code returns list of all the methods to be implemented.
 
 Main code implementing all the specified methods is written.
 
 Then, a recheck is done for fulfillment of all the expectations.
 
=====Code RSpec=====
 
======Initial Requirement(spec)======
 
In the below code describe() method returns an ExampleGroup class(similar to TestCase in Test::Unit).
The it()method returns an instance of the ExampleGroup in which that example is run.
 
require "Point"
describe "The location of a point" do
  it "should check whether point lies on X-axis correctly"                       
  it " should check whether point lies on Y-axis correctly "
  it " should check whether point lies on Origin correctly "
end
 
The are two methods available to check the expectations and they are should and should_not.
The result obtained by running the initial requirement doc by using $ spec rspec_test.rb is
   
   
****
  public V getValue() {
Pending:
    return mValue;
The location of a point should check whether point lies on X-axis correctly (Not Yet Implemented)
  }
./02file.rb:2
The location of a point should check whether point lies on Y-axis correctly (Not Yet Implemented)
./02file.rb:3
The location of a point should check whether point lies on Origin correctly (Not Yet Implemented)
./02file.rb:5
Finished in 0.021001 seconds
4 examples, 0 failures, 4 pending
   
   
Hence it clearly says that the above methods are yet to be implemented. This helps us in developing the code more efficiently such that they pass the above tests
  public String toString() {
Code block with expectations :
    return "(" + mKey + ", " + mValue + ")";  
 
   }
require “Point”
  }
require "rubygems"
describe "The location of a point" do
  before(:each) do
    @point = Point.new(0,2)
  end
  it "should check whether point lies on X-axis correctly" do
    @point.isOnXaxis?.should be_true
  end
  it "should check whether point lies on Y-axis correctly" do
    @point.isOnYaxis?.should be_true
  end
  it "should check whether point lies Origin correctly" do
    @point.isOnOrigin?.should be_true
  end
end
 
=====Failed output=====
Below are the test results that are obtained after running the above test cases,
[[File:Rspec failed.png|center|600px|center|Development Cycle of TTD]]
----
 
 
====Cucumber====
 
Cucumber is becoming highly popular because of its easy coding features.
 
=====Overview=====
 
a. Cucumber is a Behavior Driven Development Unit test tool for ruby.
 
b. It follows a similar pattern of RSPEC with some added features.
 
c. It allows the behavior of a system to be written in the native language of the programmer as either specs or functional tests.
 
d. It implements the GWT (Given, When, Then) pattern. Given is a behavior, accordingly coding is done. When all the specifications are met, then the tests are deemed successful.
 
e. Cucumber itself is written in Ruby.
 
=====Process of Testing=====
 
=====a. Installation=====
If your Environment path is set to " ...\Ruby\bin" then open command prompt and run gem install cucumber.
 
=====b. Algorithm=====
 We first create a feature file to describe about our requirements.
 
 Then we will create a ruby file to give a code to implement the function.
 
 Then, a recheck is done for fulfillment of all the expectations.
 
=====Code Cucumber=====
 
The requirement(spec) file for the cucumber is given below,
Feature: Check the point location
  In order perform check
  As a user
  I want the two coordinates of a point
  Scenario: check the location on X-axis
  Given I have entered <xcoordinate>
  And  I have entered <ycoordinate>
  When  I give check
  Then  The result should be <output>
 
The code implementation based on the above Requirement for Cucumber is as shown below,
require “Point”
require "rubygems"
Before do
@xcoordinate=3
@ycoordinate=0
  end
Given /^I have entered <input(\d+)>$/ do |arg1|
   @point = Point.new(@xcoordinate,@ycoordinate)
end
When /^I give check$/ do
  @result = @point.isOnXaxis?
end
Then /^The result should be <output>$/ do
puts @result
  end
----
 
====RIOT====
 
RIOT aids in speedy execution of test cases.
 
=====Overview=====
 
a. Riot does not run a setup and teardown functions before and after each test like in case of Test::Unit.
 
b. This is what speeds up the test execution.
 
c. Tests are written differently in RIOT. We only receive a Boolean output for our test case.
 
c. Here, assertions are done using a generalized attribute instead of specific variables.
 
=====Process of Testing=====


=====a. Installation=====
Note that the above class is for illustration of Java generics only.  


This can be installed by running “gem install riot” in command prompt after setting the environment path as “…\Ruby\bin”
This generic class can be used in the following way:
Entry<String, String> grade440 = new Entry<String, String>("mike", "A");
Entry<String, Integer> marks440 = new Entry<String, Integer>("mike", 100);
System.out.println("grade: " + grade440);
System.out.println("marks: " + marks440);


=====b. Algorithm=====


 We inherit all the classes that are required.
A generic method using the generic class above:
public static <T> Entry<T,T> twice(T value) {
    return new SimpleImmutableEntry<T,T>(value, value);
}


 A “Context” block is used to specify behavior of the class.
In many cases the user of the method need not indicate the type parameters, as they can be inferred:
Entry<String, String> pair = twice("Hello");


 Now, a setup block does not use specific variables but instead uses a generalized attribute “topic” to access objects in assertions.
The parameters can be explicitly added if needed:
Entry<String, String> pair = this.<String>twice("Hello");


 Assertions only return a boolean value. When using asserts, true indicates a pass while false indicates a fail.
Note that you cannot use native types, ex:
Entry<int, int> pair; // this fails. You have to use Integer instead.


=====Code RIOT=====
There is also the possibility to create generic methods based on given parameters.
  require “Point”
  public <T> T[] toArray(T... elements) {
require "rubygems"
    return elements;
context "The point locater" do
  }
  setup{Point.new(3,0)}
  asserts("Location on Xaxis") {topic.isOnXaxis?}.nil
  end
----


 
In such cases you can't use native types either, ex:
=='''Comparision between Frameworks'''==
Integer[] array = toArray(1,2,3,4,5);
[[File:Comparision.jpg]]
 
 
=='''Conclusion'''==
Test::unit is the traditionally used unit testing framework as it comes by default with ruby but based on the readability of the test cases Rspec is preferred by majority.
Below is the plot showing the comparison of the times taken to execute the test cases in various unit test frameworks,  
 
[[File:Conclusion.png|center|600px|center|Development Cycle of TTD]]
 
Hence we can infer from the above tabulation that riot is faster compared to majority of the unit test Frameworks
 
Each of the frameworks have their specific advantages and are used depending upon the situation.


==See also==
==See also==
*[http://www.ultrasaurus.com/sarahblog/2009/08/ruby-unit-test-frameworks/ Unit Testing Frameworks for Ruby]
* http://msdn.microsoft.com/en-us/library/512aeb7t%28VS.80%29.aspx
*[http://stackoverflow.com/questions/1479361/what-is-the-community-preferred-ruby-unit-testing-framework Community Preferred Unit Testing Framework]
* http://msdn.microsoft.com/en-US/library/0zk36dx2%28v=VS.80%29.aspx
* http://download.oracle.com/javase/1,5.0/docs/guide/language/generics.html


==External Links:==
==External Links:==
*[http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html Test::Unit]
* http://lcsd05.cs.tamu.edu/papers/dos_reis_et_al.pdf
*[http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/ Ruby-doc]
* http://en.wikibooks.org/wiki/C_Sharp_Programming/Generics
*[http://rdoc.info/github/thoughtbot/shoulda/master/file/README.rdoc Shoulda]
*[http://rspec.info/ RSpec]
*[http://rspec.info/documentation/ RSpec Documentation]
*[https://github.com/thoughtbot/shoulda Shoulda]
*[http://cukes.info/ Cucumber]
*[http://en.wikipedia.org/wiki/Unit_testing Unit testing]
*[http://en.wikipedia.org/wiki/Test-driven_development Test-driven development]
*[http://alexyoung.org/2009/10/26/riot-testing/ Riot]


==References:==
==References:==
[http://www.mobilein.com/WhitePaperonUnitTesting.pdf R.Venkat Rajendran, White Paper on Unit Testing]
* http://en.wikipedia.org/wiki/Generic_programming
 
* [1] http://www.boost.org/community/generic_programming.html
[http://ironshay.com/post/A-Mini-Review-Benchmark-of-Rubye28099s-Different-Testing-Frameworks.aspx Benchmark Conclusions]
* [2] http://en.wikibooks.org/wiki/Ada_Programming/Generics
* [3] http://en.wikipedia.org/wiki/Generics_in_Java
* [4] http://en.wikipedia.org/wiki/Template_%28programming%29

Latest revision as of 20:36, 16 November 2011

Generics

Introduction

In a broad definition, generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters.

Why Generics?

This approach involves writing common functions or types that differ only in the set of types on which they operate when used, thus reducing duplication.

Duplicate code is a computer programming term for a sequence of source code that occurs more than once, either within a program or across different programs owned or maintained by the same entity. Duplicate code is generally considered undesirable.

Problems with code duplication

Avoiding bulk code

Code duplication frequently creates long, repeated sections of code that differ in only a few lines or characters. The length of such routines can make it difficult to quickly understand them. Hence, code duplication is discouraged.

Purpose masking

The repetition of largely identical code sections makes it difficult to identify how they differ from one another, and therefore, identifying the specific purpose of each code section. Often, the only difference is in a parameter value. The best practice in such cases is a reusable subroutine. If the parameter type differs then it is called a generic case.

Update anomalies

Any modification to a redundant piece of code must be made for each duplicate separately which is very tedious. At worst, some locations may be missed, and for example bugs thought to be fixed may persist in duplicated locations for months or years. The best practice here is a code library.

The generics approach was popularized by Ada - programming language. Code set written using generic programming are known as generics. They are used in programming languages like Ada, Java, C++ and Visual Basic .NET. Generics create dynamically high parameterized software which can be difficult to follow.

The term generic programming was originally coined by David Musser and Alexander Stepanov.

Popular Example of Generics

Early examples of this programming approach were implemented in Ada, although the best example is the Standard Template Library (STL) in which iterators are used to access different values of an algorithm and provide them with varying datatype inputs.

The Standard Template Library (STL)

It is the C++'s Standard software library. It provides four components such algorithms, containers, functors, and iterators. We are mainly concerned with the algorithm and iterators. Here, as mentioned above algorithms are accessed with iterators where the values provided through iterators and make the algorithm work with different data types having same functionality.

The STL provides a ready-made set of common classes for C++, such as containers and associative arrays, that can be used with any built-in type and with any user-defined type that supports some elementary operations (such as copying and assignment). STL algorithms are independent of containers, which significantly reduces the complexity of the library.

Understanding Generics

Let us consider an example in STI. A sequence of data structures, e.g. a vector etc., and some algorithms to operate on them, e.g. find, sort etc., a direct approach would implement each algorithm specifically for each data structure which would be highly impossible. In the generic programming approach, each data structure returns a model of an iterator concept (a simple value type which can be dereferenced to retrieve the current value, or changed to point to another value in the sequence) and each algorithm is instead written generically with arguments of such iterators. Thus, reducing the data structure-algorithm combinations need be implemented and extensive reusability.

Iterators are of different types for e.g. forward iterators only provide movement to the next value in a sequence (e.g. suitable for a singly linked list), whereas a random-access iterator also provides direct constant-time access to any element of the sequence (e.g. suitable for a vector). An important point is that a data structure will return a model of the most general concept that can be implemented efficiently—computational complexity requirements are explicitly part of the concept definition.

Here, Arrays and Structs can be viewed as predefined generic types. Every usage of an array or struct type instantiates a new concrete type, or reuses a previous instantiated type. Array element types and struct element types are parameterized types, which are used instantiate the corresponding generic type. All this is usually built-in in the compiler and the syntax differs from other generic constructs.

Generics in Object Oriented Programming Languages

Generic programming first appeared in Ada and was subsequently adopted by many object-oriented languages. Implementation in languages such as Java and C++ are formally based on the notion of parametricity.

Generics

Define Common Block	
{ Code statements
}
Program
{ Call Common Block  // For different data types and values.
}

Example of generic programming[1]

Let us consider the memcpy() function to copy a set of array values and then generalize it using generics approach.

void* memcpy(void* region1, const void* region2, size_t n)
{
  const char* first = (const char*)region2;
  const char* last = ((const char*)region2) + n;
  char* result = (char*)region1;
  while (first != last)
    *result++ = *first++;
  return result;
}

The memcpy() function is used to copy arrays of different kinds of data. Now considering the case were the data we would like to copy is not in an array? Perhaps it is in a linked list. We can generalize a copy function to any sequence of elements? Looking at the body of memcpy(), the function's minimal requirements are that it needs to traverse through a sequence using pointer to access elements, write them to the destination, and compare pointers to know when to stop. The C++ standard library groups requirements such as these into concepts, in this case the Input Iterator concept (for region2) and the Output Iterator concept (for region1).

Generic approach code

template <typename InputIterator, typename OutputIterator>
OutputIterator
copy(InputIterator first, InputIterator last, OutputIterator result)
{
  while (first != last)
    *result++ = *first++;
  return result;
}

Using the above generic copy() function, we can now copy elements from any kind of sequence, including a linked list that exports iterators such as std::list.

#include <list>
#include <vector>
#include <iostream>
int main()
{
  const int N = 3;
  std::vector<int> region1(N);
  std::list<int> region2;
  region2.push_back(1);
  region2.push_back(0);
  region2.push_back(3);
 
  std::copy(region2.begin(), region2.end(), region1.begin());
  for (int i = 0; i < N; ++i)
    std::cout << region1[i] << " ";
  std::cout << std::endl;
}


1) Generics in ADA

In a generic a parameter is a value, a variable, a constant, a type, a subprogram, or even an instance of another, designated, generic unit that is used in the generic routine. For generic formal types, the syntax distinguishes between discrete, floating-point, fixed-point, access (pointer) types, etc. Some formal parameters can have default values.

To instantiate a generic unit, the programmer passes actual parameters for each formal. The generic instance then behaves just like any other unit. It is possible to instantiate generic units at run-time, for example inside a loop.

One of the ways in which the Ada language supports this characteristic is by means of generic units.

The generic here uses a package which contains a general operation to be performed.

The specification of a generic package[2]
generic
  type Element_T is private;  -- Generic formal type parameter
procedure Swap (X, Y : in out Element_T);
procedure Swap (X, Y : in out Element_T) is
  Temporary : constant Element_T := X;
begin
  X := Y;
  Y := Temporary;
end Swap;

The Swap subprogram is said to be generic. The subprogram specification is preceded by the generic formal part consisting of the reserved word generic followed by a list of generic formal parameters which may be empty. The entities declared as generic are not directly usable, it is necessary to instantiate them.

To use the generic we instantiate by

procedure Instance_Swap is new Swap (Float);
procedure Instance_Swap is new Swap (Integer);
procedure Instance_Swap is new Swap (Element_T => Stack_T);

Here, the parameters passed have different data types making the generic widely usable.

A generic using a sub program

It is possible to pass a subprogram as a parameter to a generic. The generic specifies a generic formal subprogram, complete with parameter list and return type (if the subprogram is a function). The actual must match this parameter profile. It is not necessary that the names of parameters match, though.

generic
  type Element_T is private;
  with function "*" (X, Y: Element_T) return Element_T;
function Square (X : Element_T) return Element_T;


Function description

function Square (X: Element_T) return Element_T is
begin
  return X * X;   -- The formal operator "*".
end Square;


Usage of the generic

with Square;
with Matrices;
procedure Matrix_Example is
  function Square_Matrix is new Square
    (Element_T => Matrices.Matrix_T, "*" => Matrices.Product);
  A : Matrices.Matrix_T := Matrices.Identity;
begin
  A := Square_Matrix (A);
end Matrix_Example;

To instantiate a generic unit, use the keyword new

function Square_Matrix is new Square
   (Element_T => Matrices.Matrix_T, "*" => Matrices.Product);
Advantages

The language syntax allows precise specification of constraints on generic formal parameters. For example, it is possible to specify that a generic formal type will only accept a modular type as the actual. It is also possible to express constraints between generic formal parameters; for example:

generic
   type Index_Type is (<>); -- must be a discrete type
   type Element_Type is private; -- can be any nonlimited type
   type Array_Type is array (Index_Type range <>) of Element_Type;

In this example, Array_Type is constrained by both Index_Type and Element_Type. When instantiating the unit, the programmer must pass an actual array type that satisfies these constraints.

All instances of a generic being exactly the same, it is easier to review and understand programs written by others; there are no "special cases" to take into account.

Limitations

Ada does not allow specialized generic instances, unlike C++ and requires that all generics be instantiated explicitly but all instantiations being explicit, there are no hidden instantiations that might make it difficult to understand the program.

Ada does not permit "template metaprogramming", because it does not allow specializations.


2) Generics in C++[4]

When creating containers of objects it is possible to write specific implementations for each data type contained, even if the code is virtually identical except for different data types. In C++, this duplication of code can be circumvented by defining a template class. C++ has can support Generic Programming very well through this template system.

Concepts have no direct representation in C++, so they are represented only within the documentation for a generic library. The documentation for the SGI Standard Template Library established the de facto standard for documenting concepts.

Specifications

 Valid Expressions are C++ expressions which must compile successfully for the objects involved in the expression to be considered models of the concept.

 Associated Types are types that are related to the modeling type in that they participate in one or more of the valid expressions. Typically associated types can be accessed either through typedefs nested within a class definition for the modeling type, or they are accessed through a traits class.

 Invariants are run-time characteristics of the objects that must always be true, that is, the functions involving the objects must preserve these characteristics. The invariants often take the form of pre-conditions and post-conditions.

 Complexity Guarantees are maximum limits on how long the execution of one of the valid expressions will take, or how much of various resources its computation will use.

Tem plate<typename T> 
class swap (T x, T y)
{ 
  T temp;
  temp =y;
  y=x;
  x=temp;
return x
}

Instantiation is done by calling as an ordinary function

Swap_x << swap(5, 10);   // outputs 10

The compiler examines the arguments used to call swap and determines that this is a call to swap(int, int), it then instantiates a version of the function where the parameterizing type T is int.

This works whether the arguments x and y are integers, strings, or any other type for which the expression x interchanges y is sensible. Common inheritance is not needed for the set of types that can be used, and so it is very similar to duck typing. In the context of a comprehensive library like the STL it allows the programmer to get extensive functionality for a new data type, just by defining a few operators for it. Merely defining < allows a type to be used with the standard sort(), stable_sort(), and binary_search() algorithms or to be put inside data structures such as sets, heaps, and associative arrays. C++ templates are completely type safe at compile time.

A powerful feature of C++'s templates is template specialization. This allows alternative implementations to be provided based on certain characteristics of the parameterized type that is being instantiated. Template specialization has two purposes: to allow certain forms of optimization, and to reduce code bloat.

Advantages

Both macros and templates are expanded at compile time. Macros are always expanded inline; templates can also be expanded as inline functions when the compiler deems it appropriate. Thus both function-like macros and function templates have no run-time overhead.

#define max(a,b) ((a) < (b) ? (b) : (a))

However, templates are generally considered an improvement over macros for these purposes. Templates are type-safe.

Limitations

Here are three primary drawbacks to the use of templates: compiler support, poor error messages, and code bloat. Many compilers historically have poor support for templates, thus the use of templates can make code somewhat less portable. Support may also be poor when a C++ compiler is being used with a linker which is not C++-aware, or when attempting to use templates across shared library boundaries. Most modern compilers however now have fairly robust and standard template support, and the new C++ standard, C++0x, is expected to further address these issues.

Almost all compilers produce confusing, long, or sometimes unhelpful error messages when errors are detected in code that uses templates.[10] This can make templates difficult to develop.

Finally, the use of templates requires the compiler to generate a separate instance of the templated class or function for every permutation of type parameters used with it. (This is necessary because types in C++ are not all the same size, and the sizes of data fields are important to how classes work.) So the indiscriminate use of templates can lead to code bloat, resulting in excessively large executables.[citation needed] However, judicious use of template specialization can dramatically reduce such code bloat in some cases. The extra instantiations generated by templates can also cause debuggers to have difficulty working gracefully with templates.


3) Generics in JAVA

Generics are a facility of generic programming that was added to the Java programming language in 2004 as part of J2SE 5.0. They allow "a type or method to operate on objects of various types while providing compile-time type safety. “A common use of this feature is when using a Java Collection that can hold objects of any type, to specify the specific type of object stored in it.

Specifications

 A type variable is an unqualified identifier. Type variables are introduced by generic class declarations, generic interface declarations, generic method declarations, and by generic constructor declarations.

 A class is generic if it declares one or more type variables. A generic class declaration defines a set of parameterized types, one for each possible invocation of the type parameter section. All of these parameterized types share the same class at runtime.

 An interface is generic if it declares one or more type variables. A generic interface declaration defines a set of types, one for each possible invocation of the type parameter section. All parameterized types share the same interface at runtime.

 A method is generic if it declares one or more type variables. These type variables are known as the formal type parameters of the method. The form of the formal type parameter list is identical to a type parameter list of a class or interface.

 A constructor can be declared as generic, independently of whether the class of the constructor is declared in is itself generic. A constructor is generic if it declares one or more type variables.

Example of generic classes and methods in JAVA[3]
public class Entry<K, V> {
 
  private final K mKey;
  private final V mValue;

  public Entry(K k,V v) {  
    mKey = k;
    mValue = v;   
  }

  public K getKey() {
    return mKey;
  }

  public V getValue() {
    return mValue;
  }

  public String toString() { 
    return "(" + mKey + ", " + mValue + ")";  
  }
}

Note that the above class is for illustration of Java generics only.

This generic class can be used in the following way:

Entry<String, String> grade440 = new Entry<String, String>("mike", "A");
Entry<String, Integer> marks440 = new Entry<String, Integer>("mike", 100);
System.out.println("grade: " + grade440);
System.out.println("marks: " + marks440);


A generic method using the generic class above:

public static <T> Entry<T,T> twice(T value) {
   return new SimpleImmutableEntry<T,T>(value, value);
}

In many cases the user of the method need not indicate the type parameters, as they can be inferred:

Entry<String, String> pair = twice("Hello");

The parameters can be explicitly added if needed:

Entry<String, String> pair = this.<String>twice("Hello");

Note that you cannot use native types, ex:

Entry<int, int> pair; // this fails. You have to use Integer instead.

There is also the possibility to create generic methods based on given parameters.

public <T> T[] toArray(T... elements) {
   return elements;
}

In such cases you can't use native types either, ex:

Integer[] array = toArray(1,2,3,4,5);

See also

External Links:

References: