Example of SetEnvironmentVariable and GetEnvironmentVariable

Sometimes you may want to communicate between different DLL's using some sort of flags. The simplest way to do it probably is using environment variable. Here is a simple example but can be modified to suit multiple DLL's.





//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>
#include<atlstr.h>

using namespace
std;

int
main()
{

//Suppose we want to have a temporary environment variable called "ZahidVar" whose value could be "120" or "140"
string varName("ZahidVar");
CString value;
DWORD len = GetEnvironmentVariable(varName.c_str(), value.GetBuffer(100), 100);
value.ReleaseBuffer();

if
(len)
cout<<"Value of environment variable = "<<value<<endl;
else

cout<<"environment variable was empty"<<endl;

//Set the environment variable now
SetEnvironmentVariable("ZahidVar", "120");

len = GetEnvironmentVariable(varName.c_str(), value.GetBuffer(100), 100);
value.ReleaseBuffer();

if
(len)
cout<<"Value of environment variable = "<<value<<endl;
else

cout<<"environment variable was empty"<<endl;

return
0;
}







The output is as follows:


It should be noted that the scope of this environment variable is temporary and will cease to exist once the program exits.

You can also look at this example to show you how to print all the environment variables.

Takeaways on Responsive Design

I recently have attended a great talk from Kent Beck who is the thought leader in Extreme Programming, Test-Driven-Development and Code refactoring. This talk "Responsive Design" outline a set of key principles of how to create a design that is "malleable" so it can respond quickly to future changes.

Anticipating Changes
I don't think one can design a system without knowing the context of the problem. You have to know what problem your solution is trying to solve. Of course, you may not know the detail of every aspects, or you may know that certain parts of the requirements may undergoing some drastic changes. In these areas where changes are anticipated, you need to build in more flexibilities into your design.

In my opinion, knowing what you know well and what you don't know is important. Good designers usually have good instinct in sensing between the "known" and "unknown" and adjust the flexibility of his design along the way as more information is gathered.

As more information is gathered, the dynamics of "change anticipation" also evolves. Certain parts of your system has reduced its anticipated changes due to less unknowns so now you can trade off some flexibility for efficiency or simplicity. On the other hand, you may discover that certain parts of the system has increased its anticipated changes and so even more flexibility is needed.

Safe Steps
If the system is already in production, making changes in the architecture is harder because there are other systems that may already depend on it. And any changes on it may break those other systems. "Safe Steps" is about how we can design the changes to existing system with minimal impact to those other systems that depends on it.

Design for Evolution
One important aspect when design a system is not just by looking at what the end result should be, but also look at what the evolution path of the system should look like. The key idea is that a time dimension is introduced here and the overall cost and risk should be summed along the time dimension.

In other words, it is not about whether you have designed a solution that finally meet the business requirement. What is important is how your solution bring value to the business as it evolves over time. A good design is a live animal that can breath and evolve together with your business.

Kent also talk about 4 key design approaches under different conditions

1. Leap

"Leap" is a brave approach where you go ahead to design and implement the new system. When complete, swap out the existing components with the new one. This approach requires a very good understanding of the functionality of system you want to build, how the existing system and how other systems depends on the existing system.

"Leap" can be a very effective approach if the system is very self-contained with clearly defined responsibilities. But in general, this approach is somewhat high-risk and is an exception rather than a norm for large enterprise applications.

2. Parallel

"Parallel" takes a "wrap and replace" approach. The new system is designed to run in parallel with existing system so that migration can be conducted gradually in a risk-containing manner. If there is any problem happens during the migration, the whole system can be switched back to the original system immediately so the risk is contained.

After 100% client has been migrated to the new system for some period of time, the old system can be shutdown without even the clients notice it.

"Parallel" approach still requires you to have a clear understanding of what you want to build. But it relax you from knowing the dependencies of existing system. Of course, the design may be more complicated because it needs to run in parallel with the existing system and has to deal with things like data consistency and synchronization issues.

"Parallel" is a predominant approach that I've seen people used in reality.

3. Stepping Stone

"Stepping Stone" is very useful when you don't exactly know your destination, but you know that there are some intermediate steps that you have to do. In this approach, the designer focus in those intermediate steps that will lead to the final destination.

"Stepping Stone" requires the designer to have a "scope of variability" in mind about the final solution and then identify some common ground across the perceived variability. Knowing what you don't know is important to define the "stepping stone".

This approach is also very useful to design the evolution path of the system. Since you need to look at how the "stepping stone" will provide value to the existing systems while it evolves.

4. Simplification

"Simplification" is the about how you can simplify your intermediate design by breaking down the requirement into multiple phases. I personally don't think the designer has the flexibility to change the ultimate requirement but she definitely can break down the ultimate requirement into multiple phases so she can control the evolution path of her design. In other words, by simplifying the requirement in each phase, she can pick the challenges that she want to tackle in different phases.

"Simplification" is also an important skill for experienced designers. The only way to tackle any complex system beyond a human's brain power is to break the original complexity down into simpler systems and tackle them in incremental steps.

"Simplification" is also an important abstraction skills where experience designer can generalize a specific problem case into a generic problem pattern where a generic solution can be found (e.g. design pattern), and then customize a specific solution from the design pattern.

BOOL to bool

I faced a very simple problem the other day. The compiler started generating a warning:

warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)

The reason being that because I was including some Windows file that included windef.h. In windef.h, it says: typedef int BOOL;

What I was trying to do was to cast that BOOL to bool. Of course we can suppress the warning easily by the #pragma directives as discussed earlier but there has to be a better and a simpler way. Then it clicked, how about a simple != 0 comparison. Here is the sample code:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>
#include<windows.h>
#include<windef.h>

using namespace
std;

int
main()
{

BOOL someVal = 1;

bool
firstApproach = someVal; //Generates warning C4800
cout<<"firstApproach = "<<firstApproach<<endl;

bool
secondApproach = (someVal != 0); //No Warning
cout<<"secondApproach = "<<secondApproach<<endl;

return
0;
}

Catching the 'Divide By Zero' exceptions

I was surprised to find that C++ does not catch divide by 0 exceptions by default. The code will crash when a divide by 0 situation occurs. As a result the only option is to write our own class or method to handle divide by 0 scenario. The example below shows how to handle the Divide by zero scenario and how to construct an exception.







//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>

using namespace
std;

class
Division
{

public
:
double
quotient(int numerator, int denominator);
private
:

};


double
Division::quotient(int numerator, int denominator)
{

if
(!denominator)
{

exception e("Divide by 0 exception");
throw
(e);
}

return
(static_cast< double >( numerator ))/denominator;
}



int
main()
{

Division d;
try

{

cout<<"1. (100/10) = "<<d.quotient(100, 10)<<endl;
cout<<"2. (10/4) = "<<d.quotient(10, 4)<<endl;
cout<<"3. (10/0) = "<<d.quotient(10, 0)<<endl;
cout<<"4. (30/9) = "<<d.quotient(30, 9)<<endl;
}

catch
(exception& e)
{

cout<<"Exception caught with cause :"<<e.what()<<endl;
}

return
0;
}








The output is as follows:


You can read more on this topic here.

Using constants with functions

There always seems to be confusion in using const with functions. I am not referring to const functions that have const after the function name, that is straightforward. Also, the way functions behave when you have const before them is different than the built-in types. I have earlier provided a table for that.

Here is a simple program that shows different types of const with functions.



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>
#include<string>

using namespace
std;

class
A
{

public
:
int
x;
};


class
B
{

public
:
string y;
};


A* const createA()
{

return
(new A);
}


const
B* createB()
{

return
(new B);
}


int
main()
{

A* a = NULL;
a = createA();
a->x = 100;
cout<<"a.x = "<<a->x<<endl;
delete
a;

const
B* b = NULL;
b = createB();
//b->y = "Hello"; - Compilation error because b is constant
(const_cast<B*>(b))->y = "Hello";
cout<<"b.y = "<<b->y<<endl;
delete
b;

A* const a2 = NULL;
//a2 = createA(); - Compilation Error:
// you cannot assign to a variable that is const

A* const a3 = new A; //not possible to change what a3 points to now
a3->x = 23456;
cout<<"a3.x = "<<a3->x<<endl;
delete
a3;

return
0;
}






The output is as follows:

Words of wisdom

I've always been a big fan of the Forth programming language. It is nothing like BASIC, but here is a page from forth.com with some words of wisdom from Chuck Moore that I figure are just good food for thought no matter what language you prefer.

http://www.forth.com/resources/evolution/evolve_1.html

Check out this stream