I spent most of this week, and especially the weekend debugging the Project 6 - Matrix. An apparent simple project, turned out to be only hypothetically simple until I hadn't written the test cases. And as I took a step further to write my first test case to test the constructor, the program failed terribly. Lesson: write test cases as you code the program. The project Matrix is all about using Array class that was been created in the last project, though with a twist; this time Array had to be modified to use allocator's construct/destroy method to create a stack allocated array object. The Matrix, would then be implemented as an Array of Arrays.
The lectures this week, were mostly about containers, and iterators, and how the STL are implemented. The subtleties of C++ during compile time related to various constructors, and assignments didn't make much sense until I ran into the problem of having my Matrix class to work correctly. As it was discussed in the class, the compiler chooses to use a default copy constructor/assignment operation which fails to perform a deep copy for user defined classes. In order to have a deep copy, the programmer is required to explicitly define his/her copy constructor, etc. In context to project Matrix, before I created a copy constructor for the Array, I realized that doing operation such as m[2][3] = y would make m[i][3] = y for all 0 < i < R, where m is the matrix, and R is number of rows. Having developed the copy constructor for the Array overcame the problem.
Besides completing the project, I prepared for the Test #2 for which I read a paper on Unified Modeling Language (UML). It's quite interesting to see how a variety of tools/concepts help people collaborate on a project and successfully execute it.
Sunday, July 26, 2009
Sunday, July 19, 2009
Week 6
This week we studied a number of STL algorithms, and through them enforced the better understanding of different types of iterators: Input Iterator (II), Output Iterator (OI), Forward Iterator (FI), Bidirectional Iterator (BI), and Random access Iterator (RI). Having studied different algorithms such as: Find, MinElement, Transform, Remove, Reverse, Equal, and Accumulate helped in understanding the conventional concept behind different categories of iterators.
We studied the Vector class, which efficiently develops a heap allocated array of objects. The way Vector accomplishes this is by calling the copy constructor of the underlying object class, in contrast to calling the default constructor and the assignment operator as done by stack allocated array. vector uses allocator (memory) to first allocate memory space for the array to be constructed. The allocated memory space is in raw form. Thereafter, it calls the uninitialized_copy/uninitialized_fill which then calls the construct() method; consequently the copy constructor of the underlying value_type. The construct() method calls the placement version of new:
new (p) value_type(v);
A reverse process is pursued while destructing the vector object. It calls, the destory() which calls the destructor for the underlying datatype. It finally deallocates the memory that it assigned for the vector object.
In the last class we studied about iterator_traits, and how meta information inside the Iterator class can be used to infer the return datatype, which in general is not passed as a function template argument.
As for the project, we have been developing an Array class that would implement stack allocated array object and related operations, and methods. Initially we have been getting segfault when trying to call the non-const version of a method from the const method. We overcome the problem by using const_cast casting.
We studied the Vector class, which efficiently develops a heap allocated array of objects. The way Vector accomplishes this is by calling the copy constructor of the underlying object class, in contrast to calling the default constructor and the assignment operator as done by stack allocated array. vector uses allocator (memory) to first allocate memory space for the array to be constructed. The allocated memory space is in raw form. Thereafter, it calls the uninitialized_copy/uninitialized_fill which then calls the construct() method; consequently the copy constructor of the underlying value_type. The construct() method calls the placement version of new:
new (p) value_type(v);
A reverse process is pursued while destructing the vector object. It calls, the destory() which calls the destructor for the underlying datatype. It finally deallocates the memory that it assigned for the vector object.
In the last class we studied about iterator_traits, and how meta information inside the Iterator class can be used to infer the return datatype, which in general is not passed as a function template argument.
As for the project, we have been developing an Array class that would implement stack allocated array object and related operations, and methods. Initially we have been getting segfault when trying to call the non-const version of a method from the const method. We overcome the problem by using const_cast casting.
Saturday, July 11, 2009
Week 5
What an eventful week! Week contained within "containers," and week's tasks iterated over debugging "iterators" :) I spent most of this week working on the project 4 - Integer. And wow, I must say, I learned a lot. The pair programming paid off again. Having worked with the partner simultaneously on the project, allowed me to learn a lot many new concepts of C++; and most importantly their applications and usage.
The project 4 served as a good recall of elementary arithmetic operations: addition, subtraction, multiplication, and division. The project revolves around arbitrary precision integer operations; and the fun part was to calculate the 30th Mersenne prime number (2^132049 - 1) which is around 40000 digits long. And we had it calculated in less than 20 seconds on a Intel Core 2 Duo 2.2 GHz Processor. The optimization technique was to divide the exponent into some power of 2, and multiply them together to find the original power.
There was a doubt though running through me: what's the modulus x % y, when x is a negative number. For instance, -3 % 5 = ? Should it be 2, or -3. While C++ itself calculates it to be -3, while my understanding (as well as Google's) is it should be a positive number. Oh well, we went with the C++ understanding :)
The project 4 served as a good recall of elementary arithmetic operations: addition, subtraction, multiplication, and division. The project revolves around arbitrary precision integer operations; and the fun part was to calculate the 30th Mersenne prime number (2^132049 - 1) which is around 40000 digits long. And we had it calculated in less than 20 seconds on a Intel Core 2 Duo 2.2 GHz Processor. The optimization technique was to divide the exponent into some power of 2, and multiply them together to find the original power.
There was a doubt though running through me: what's the modulus x % y, when x is a negative number. For instance, -3 % 5 = ? Should it be 2, or -3. While C++ itself calculates it to be -3, while my understanding (as well as Google's) is it should be a positive number. Oh well, we went with the C++ understanding :)
Sunday, July 5, 2009
Week 4
This week we went over important concepts such as specialized templates, stacks vs heap allocations, and function pointers.
Specialized templates provide a way of defining secondary templates that can be useful where a known different (and may more efficient) algorithm is to be used to perform a particular task with a particular data type(s). From compiler's perspective, the way function calls are determined is by following order:
(i) Check if there is a non-template version available for the function call. If one does exist call that.
(ii) If the function call is a templatized version, determine the primary template structure.
(iii) Once the primary template structure is determined, check if there is a secondary template version (a specialized function with the matching signature) is available. If a secondary template is available, call that function, else call the primary templatized function.
During the week, we studied how stack allocated arrays differ from heap allocated ones, and in what ways they are similar. Heap allocation offers the flexibility of allocating memory spaces as per the need, but at the same time the programmer is responsible for tracking the allocated memory, and freeing them appropriately when need be so. A rule of thumb is to have as many delete's as there are new's (with appropriate placements). This ensures that there are no memory leakage. A few conceivable problems with heap allocated arrays can be: not freeing memory after use, deleting the wrong memory address, deleting more than needed.
Next, we started on function pointers which in a sense provides a way of customized function calls. The function pointers, allows function calls via pointers that like any other pointer can be changed to call other function.
This week, and the following week I along with my partner will be working on the Project 4 - Integer. The project involves creating a class that implements Big Integer/Arbitrary Precision operations. The idea is to represent numbers with vector/deque where each element is an individual digit, and perform operations on these digits.
Specialized templates provide a way of defining secondary templates that can be useful where a known different (and may more efficient) algorithm is to be used to perform a particular task with a particular data type(s). From compiler's perspective, the way function calls are determined is by following order:
(i) Check if there is a non-template version available for the function call. If one does exist call that.
(ii) If the function call is a templatized version, determine the primary template structure.
(iii) Once the primary template structure is determined, check if there is a secondary template version (a specialized function with the matching signature) is available. If a secondary template is available, call that function, else call the primary templatized function.
During the week, we studied how stack allocated arrays differ from heap allocated ones, and in what ways they are similar. Heap allocation offers the flexibility of allocating memory spaces as per the need, but at the same time the programmer is responsible for tracking the allocated memory, and freeing them appropriately when need be so. A rule of thumb is to have as many delete's as there are new's (with appropriate placements). This ensures that there are no memory leakage. A few conceivable problems with heap allocated arrays can be: not freeing memory after use, deleting the wrong memory address, deleting more than needed.
Next, we started on function pointers which in a sense provides a way of customized function calls. The function pointers, allows function calls via pointers that like any other pointer can be changed to call other function.
This week, and the following week I along with my partner will be working on the Project 4 - Integer. The project involves creating a class that implements Big Integer/Arbitrary Precision operations. The idea is to represent numbers with vector/deque where each element is an individual digit, and perform operations on these digits.
Sunday, June 28, 2009
Week 3
This week, more than anything else, I realized that never procrastinate. Though, once in a while, every week I do take this resolution of finishing my things (assignments, and projects, etc.) before time, but then... :(
This week most of my focus, outside the class, was on the project 3. The project was about implementing the Gregorian Calendar, and developing a class that supports Date operations such as finding the date after a given number of days, or number of days between two given dates, and similarly related operations. As Professor Downing advised, the initial plan was to just develop a modest code that would pass the basic test cases. But, even the algorithm for converting the date to number of days would fail. Oh, and on Friday was the first exam.
Nevertheless, I would say, the best part of the project was the algorithm and the mathematics behind it to convert days to date and vice-versa, so as to suffice the condition of O(1) time and space requirements. Having figured out the mathematics, we now were facing the not-so-understandable concepts of templates, and references to carry out the operations. While compiling, I came across an error like "no matching function to the call..." and it was quite interesting that the keyword "const" fixed it all. Consequently, the result of all the procrastination + the subtleties of C++ was the extra hours that we had to put to have the code working.
In essence, however, the project was interesting and I learned a lot.
This week most of my focus, outside the class, was on the project 3. The project was about implementing the Gregorian Calendar, and developing a class that supports Date operations such as finding the date after a given number of days, or number of days between two given dates, and similarly related operations. As Professor Downing advised, the initial plan was to just develop a modest code that would pass the basic test cases. But, even the algorithm for converting the date to number of days would fail. Oh, and on Friday was the first exam.
Nevertheless, I would say, the best part of the project was the algorithm and the mathematics behind it to convert days to date and vice-versa, so as to suffice the condition of O(1) time and space requirements. Having figured out the mathematics, we now were facing the not-so-understandable concepts of templates, and references to carry out the operations. While compiling, I came across an error like "no matching function to the call..." and it was quite interesting that the keyword "const" fixed it all. Consequently, the result of all the procrastination + the subtleties of C++ was the extra hours that we had to put to have the code working.
In essence, however, the project was interesting and I learned a lot.
Thursday, June 25, 2009
Pair Programming
This blog entry summarizes the key points of the paper by Laurie A. Williams and Robert R. Kessler which is about Pair Programming. "Pair programming is a style of programming in which two programmers work side-by-side at one computer, continuously collaborating on the same design, algorithm, code or test." It is one of the core practices of eXtreme Progamming (XP).
We as programmers are conditioned to work alone, as we are too much under the impression that thinking independently will allow us to formulate our deeply-concentrated thoughts better. Studies, however, show that pair programming allows us to become more efficient programmers.
The key importance lies in the below mentioned attributes:
1) Continuous code review by person watching over the shoulders
2) Exchange of ideas which could disclose possible flaws, and bring about improvements
3) Efficient, and a greater confidence in the solution
4) High level of code quality which is nearly bug free
5) Enjoyable experience
The paper then talks about the important principles of pair programming. Here are some of those:
SHARE EVERYTHING and PLAY FAIR
Two programmers are assigned to produce one artifact - design, algorithm, or program, etc. Both partners are working actively, even though one is putting the ideas together whether in a code, or in a design on the paper; the other partner on the other hand is continuously reviewing the work. Both are equally creditable or liable.
BEING LESS OF A SLACKER
I realized that I check my Facebook account, and dozens of email accounts quite frequently even though I know I am expecting nothing but tonnes of spams. And when I am saying frequently, I mean it... I mean at least once in every 15-20 minutes. While, working over the past two projects, I realized that I barely check my accounts while I am working with my partner, unless we are taking a break. In essence, I am much more focused and dedicated, and being less of a slacker :).
EXCHANGE OF IDEAS
Honestly, I have learned a lot over the past 3 weeks. The way my partner thinks, motivates me to think differently, allows me to think out of my own little box of ideology. Continuous discussion, and constructive arguments are the best training, I believe.
DON'T TAKE THINGS TOO SERIOUSLY
"Ego-less programming" as the mentioned in the paper, is the key to fully take the advantage of the pair programming. The arguments should be taken as a resource to further hone an individual's programming skills.
WASH YOUR HANDS OFF SKEPTICISM BEFORE YOU START
There should be no scope of skepticism with pair programming; if something looks confusing or non-understandable clarify the doubts. But, trust your partner. Engage in constructive arguments if need be so. One idea is that the outcome of a union of team members is more than the disjoint sets of members, contrary to traditional set theory. As experiences have shown, a pair produces more than twice as many solutions than the two working independently.
FLUSH/REVIEW WORK DONE INDEPENDENTLY
We have other commitments of time and we need to be working on some tasks independently, or just for some deep-concentration thinking. However, it is the best practice to review the work done independently together with your partner; it could possibly disclose a plethora of subtleties.
And finally,
ALL WORK and NO PLAY MAKES everyone dull... so take breaks occasionally.
For cost/benefit analysis of the Pair Programming methodology, I came across a paper by Alistair Cockburn, and Laurie Williams.
We as programmers are conditioned to work alone, as we are too much under the impression that thinking independently will allow us to formulate our deeply-concentrated thoughts better. Studies, however, show that pair programming allows us to become more efficient programmers.
The key importance lies in the below mentioned attributes:
1) Continuous code review by person watching over the shoulders
2) Exchange of ideas which could disclose possible flaws, and bring about improvements
3) Efficient, and a greater confidence in the solution
4) High level of code quality which is nearly bug free
5) Enjoyable experience
The paper then talks about the important principles of pair programming. Here are some of those:
SHARE EVERYTHING and PLAY FAIR
Two programmers are assigned to produce one artifact - design, algorithm, or program, etc. Both partners are working actively, even though one is putting the ideas together whether in a code, or in a design on the paper; the other partner on the other hand is continuously reviewing the work. Both are equally creditable or liable.
BEING LESS OF A SLACKER
I realized that I check my Facebook account, and dozens of email accounts quite frequently even though I know I am expecting nothing but tonnes of spams. And when I am saying frequently, I mean it... I mean at least once in every 15-20 minutes. While, working over the past two projects, I realized that I barely check my accounts while I am working with my partner, unless we are taking a break. In essence, I am much more focused and dedicated, and being less of a slacker :).
EXCHANGE OF IDEAS
Honestly, I have learned a lot over the past 3 weeks. The way my partner thinks, motivates me to think differently, allows me to think out of my own little box of ideology. Continuous discussion, and constructive arguments are the best training, I believe.
DON'T TAKE THINGS TOO SERIOUSLY
"Ego-less programming" as the mentioned in the paper, is the key to fully take the advantage of the pair programming. The arguments should be taken as a resource to further hone an individual's programming skills.
WASH YOUR HANDS OFF SKEPTICISM BEFORE YOU START
There should be no scope of skepticism with pair programming; if something looks confusing or non-understandable clarify the doubts. But, trust your partner. Engage in constructive arguments if need be so. One idea is that the outcome of a union of team members is more than the disjoint sets of members, contrary to traditional set theory. As experiences have shown, a pair produces more than twice as many solutions than the two working independently.
FLUSH/REVIEW WORK DONE INDEPENDENTLY
We have other commitments of time and we need to be working on some tasks independently, or just for some deep-concentration thinking. However, it is the best practice to review the work done independently together with your partner; it could possibly disclose a plethora of subtleties.
And finally,
ALL WORK and NO PLAY MAKES everyone dull... so take breaks occasionally.
For cost/benefit analysis of the Pair Programming methodology, I came across a paper by Alistair Cockburn, and Laurie Williams.
Sunday, June 21, 2009
Week 2
This week, I witnessed a plethora of interesting subtleties of C++:
i) the pointers, and the references;
ii) types of variables
iii) templates
It's interesting how placement of '&' and '*' can give a whole different meaning to variables. For example,
int i = 2;
int* p = j; // does not compile
int* p = &j; /* initializes a pointer 'p' pointing to integer 'j' */
/*increments the memory address which could lead to illegal memory access */
++p;
//increments j
++*p;
Now consider,
int k = 4;
int& r = k; /* r serves as an alias of k */
//same as ++k
++r;
Using '&' for references frees the programmer from de-referencing the variable like in pointers. However, once the reference is defined, it is glued to the variable it references; while the pointer can be changed to point to other variable (if not declared as constant).
Things become interesting when using '&' and '*' together. While, int&* x isn't valid, but
int i = 2;
int* p = i;
int*& r = p; //alias for pointer 'p'
Next, we studied about different types of variables, and compared their scopes, lifetimes, and time-line when they are allocated, and initialized. "non-static local variable" and "static local variable" both differ except in terms of their scope. Contrarily, "non-static global variable" and "static global variable" differ only in their scopes. "Non-static global variable" has the scope of whole program, while "static global variable" has the file scope. The program will compile even if a static variable is used in other file using extern, but will fail during the linkage.
C++ has a powerful feature of creating templates. But with power, comes the responsibility; and here the responsibility is of the programmer to fully understand how to create classes considering the types of variables and their instances to be created. For example,
template <typename T>
struct A {
static T sv0; // creates one sv0 per T
static int sv1; // still creates one sv1 per T
T v0; // create 1 v0 per instance of A
}
Finally, we studied how different function declaration give or don't give access to the original data.
For example,
void f(int v) {++v;} // creates a local copy of the argument
void g(int* p) {++*p;} // changes the original data
void h(int& r) {++r;} // changes the original data
i) the pointers, and the references;
ii) types of variables
iii) templates
It's interesting how placement of '&' and '*' can give a whole different meaning to variables. For example,
int i = 2;
int* p = j; // does not compile
int* p = &j; /* initializes a pointer 'p' pointing to integer 'j' */
/*increments the memory address which could lead to illegal memory access */
++p;
//increments j
++*p;
Now consider,
int k = 4;
int& r = k; /* r serves as an alias of k */
//same as ++k
++r;
Using '&' for references frees the programmer from de-referencing the variable like in pointers. However, once the reference is defined, it is glued to the variable it references; while the pointer can be changed to point to other variable (if not declared as constant).
Things become interesting when using '&' and '*' together. While, int&* x isn't valid, but
int i = 2;
int* p = i;
int*& r = p; //alias for pointer 'p'
Next, we studied about different types of variables, and compared their scopes, lifetimes, and time-line when they are allocated, and initialized. "non-static local variable" and "static local variable" both differ except in terms of their scope. Contrarily, "non-static global variable" and "static global variable" differ only in their scopes. "Non-static global variable" has the scope of whole program, while "static global variable" has the file scope. The program will compile even if a static variable is used in other file using extern, but will fail during the linkage.
C++ has a powerful feature of creating templates. But with power, comes the responsibility; and here the responsibility is of the programmer to fully understand how to create classes considering the types of variables and their instances to be created. For example,
template <
struct A {
static T sv0; // creates one sv0 per T
static int sv1; // still creates one sv1 per T
T v0; // create 1 v0 per instance of A
}
Finally, we studied how different function declaration give or don't give access to the original data.
For example,
void f(int v) {++v;} // creates a local copy of the argument
void g(int* p) {++*p;} // changes the original data
void h(int& r) {++r;} // changes the original data
Subscribe to:
Posts (Atom)