AK

Tactical Tornadoes

Jul 09 2020
John Ousterhout, in his talk at Google on 'A Philosophy of Software Design', talks about a special kind of programmers, called tactical tornadoes. 

Person who turns out enormous amounts of pretty shoddy code that kind of 80% works, at a huge rate, and leaves a wake of destruction behind them. In many organizations, these people are considered heroes. This is who management goes to, when they need a feature tomorrow, and they will have a feature tomorrow, that works for most of the day tomorrow..Management actually rewards tactical tornadoes. 
How many tactical tornadoes do you know at your company? 

Looking for a Roommate

Jun 25 2020
I am looking for a roommate to share my one bedroom apartment on Quadra-Mckenzie. It's a semi-private room, most suitable for students who are looking for temporary stay.

About the apartment:
- Fully furnished.
- Coin operated laundry in the building.
- Thrifty Foods, Tim Hortons, Starbucks within a walking distance
- Convenient access to UVic (26, 16), Downtown (6), and Uptown (26, 16).
- Galloping Goose trail and Swan lake within a walking distance
- There is no lease.

I have a car, and can share rides to Walmart for grocery shopping etc., if needed. I don't smoke/drink, and absolutely no smoking/alcohol in the apartment.

If you are in Victoria and looking for a place, drop me an email. 



Why We Have Bugs

Jun 25 2020
Well, one obvious reason is that of programmer incompetence. I came across a more interesting theory while reading Fred Brooks' classic book, The Mythical Man Month this morning. 

Your users get sophisticated and find new bugs. 

This is how it works. As software is built and delivered to the users, new bugs are found and solved in future releases. All goes well for a few months. Then, as we keep releasing new versions of the software, old bugs found and solved in previous releases tend to reappear. 
Bugs Climbing
The common reason for this is that as the users get more familiar with the software, they try to use the new, advanced capabilities offered by the software. This in turn finds new bugs that the developers and the QA overlooked in the initial phase of the development process.

As you keep on releasing new versions of the software, the complexity increases exponentially. The bug fixes, often done by new programmers other than the programmer who wrote the original code tend to destroy the structure of the system and add disorder. As time goes on, less and less effort is spent on fixing the bugs in the original design and more on fixing bugs added by earlier bug-fixes.

Then we call it legacy software, and hope that re-writing the software with a new technology will solve all the problems. But it won't, it will just delay them until the cycle repeats.

Finally, we have bugs because of fear. Because this information can be threatening, we all develop kind of information immunity. It protects us from all the information that we don't want to hear. No matter how well testing we do, if the people who are dealing with these test reports have developed this immunity, it's all waste.

This is how fear-driven development sounds like:

Developer: "That stupid bug shows people I'm not as good a programmer as I'd hoped to be."

QA: "The developer will get angry if I report this bug, because it makes him look bad"

Project Manager: "With all these bugs, I won't make my schedule."

Sales: "This product is so full of bugs, it isn't going to sell very well, and I won't make my numbers."

User: "It can't be a bug in the software. Definitely I am doing something stupid. I must find a workaround."

Go Pointers!!

Jun 20 2020
One of big myths in software industry was perpetuated by Joel Spolsky in his 2006 classic The Guerilla Guide to Interviewing. I love and respect Joel, and fully agree with the article, except the following paragraph. 

I’ve come to realize that understanding pointers in C is not a skill, it’s an aptitude.

In first year computer science classes, there are always about 200 kids at the beginning of the semester, all of whom wrote complex adventure games in BASIC for their PCs when they were 4 years old. They are having a good ol’ time learning C or Pascal in college, until one day the professor introduces pointers, and suddenly, they don’t get it. They just don’t understand anything any more. 90% of the class goes off and becomes Political Science majors, then they tell their friends that there weren’t enough good looking members of the appropriate sex in their CompSci classes, that’s why they switched.

For some reason most people seem to be born without the part of the brain that understands pointers. Pointers require a complex form of doubly-indirected thinking that some people just can’t do, and it’s pretty crucial to good programming. A lot of the “script jocks” who started programming by copying JavaScript snippets into their web pages and went on to learn Perl never learned about pointers, and they can never quite produce code of the quality you need.
For a long time, I believed this. Whenever I tried learning pointers in C, I'd struggle for a while, remember the above words and finally give up thinking pointers are not just not my cup of tea.

Then I started learning Go

One of the things that make Go syntax beautiful is how variables are declared. In most C-based languages, you write the type of the variable first, then the name of the variable. When reading a sentence, you have to read it from right to left. For example,
int x, y;     // x and y are integers
int *p;       // p is a pointer to an integer
However, in Go, the name comes first, followed by a type. So you read it from left to right. For example,
var x, y int;    // variables x and y are integers 
var p *int;      // variable p is a pointer to an integer
That brings me back to the subject of pointers and why I don't agree with the above paragraph, especially the line understanding pointers in C is not a skill, it’s an aptitude

When you are learning a new concept, especially a hard one like pointers, it matters a lot how it's being presented to you. When the concept doesn't make sense at first, it's easy to blame yourself and give up, rather than try to find a new teacher, tackling it from another angle, or learn it using a different approach. 

That's what happened with me when learning pointers in C. Often I'd start on solid grounds, understanding what is a pointer, and how it points to another object in memory, by containing the actual memory address of the location where that object resides. The trouble came when de-referencing that pointer to get the underlying value of that object. I'd always get confused between the meaning of * of de-reference and the * of declaration. 

In C, you'd do this:
int x, y;
int *p;
p = &x        // so far so good.
y = *p        // ???
In Go, you do it as shown below. Notice the second line, where we are defining p (not *p) as a pointer to an integer. This is not confusing (for me, at least) as it looks different from the pointer declaration. There's a clear distinction between a pointer and a de-reference from a pointer. 
var x, y int
var p *int
p = &x
y = *p       // de-reference p to get the value at the memory address it's pointing to
Agreed, you can do this in C:
int* p;
But this is not the same: 
int* p, q    // p is a pointer to an int, q is an int
In Go, this is how you declare two pointer to integers:
var p, q *int 
It was not until I started learning Go, that I finally understood how pointers work. That opened new doors into how computer memory works, why strings are immutable in C#, the difference between Value Types and Reference Types in C#, and much more, which would have been next to impossible without learning pointers.

So if you are a new developer, and struggling with pointers in C, I'd recommend learn them in Go first. Once you understand the basic idea, you can go back to C and the pointers start to make sense. But don't think, for a moment, that you are born without the part of the brain that understands pointers, just because Joel said so. 

Arrays in Go

Jun 14 2020
In Go, arrays are passed by values. When a function is called, a copy of the array is made and is assigned to the corresponding parameter variable in the function. Hence the called function receives a copy, and not the original.

In this example, all the values in grades array in main() are copied by value into grades array in change(). If I change one of the grade in change(), it won't be reflected in main()
func main() {
    grades := [3]int {1, 2, 3}
    change(&grades)
}

func change(grades [3]int) {
    grades[2] = 20 // caller doesn't see this change
}
Passing large arrays in this way can be inefficient, and any changes that the function makes to array elements affect only the copy, not the original. This behavior is different from languages that implicitly pass arrays by reference, such as C#.

In C#, the reference is passed by value. As arrays in .NET are stored on the heap, we have a reference. That reference is passed by value to the function, meaning that changes to the contents of the array will be seen by the caller. However, if we reassign that reference to another array, that change won't be visible. 
void Modify(int[] data) {
    data[0] = 1; // caller sees this
}
void Assign(int[] data) {
    data = new int[20]; // but not this
}
To pass an array by reference in Go, we have to pass a pointer to that array, so that any modifications the function makes to array elements will be visible to the caller. For example, the following function changes the contents of an array of 3 integers.
func change(ptr *[3]int) {
    ptr[2] = 20
}
You can call this by passing a pointer to the original array:
change(&arr)
Here is a complete example
package main

import (
    "fmt"
)

func main() {
    grades := [3]int {1, 2, 3}

    fmt.Printf("\nOriginal array:\n")
    for i, v := range grades {
        fmt.Printf("arr[%d] = %d\n", i, v)    // prints 1 2 3
    }

    change(&grades)
    fmt.Printf("\nModified grades:\n")
    for i, v := range grades {
        fmt.Printf("arr[%d] = %d\n", i, v)    // prints 1 2 20
    }
}

func change(ptr*[3]int) {
    ptr[2] = 20
}
Although passing a pointer to an array is efficient and allows the called function to change the caller’s variable, arrays are still fixed in size. Hence, slices are recommended, which are passed by reference and are dynamic in size. For example, 
func SliceDemo() {
    grades := []int{1, 2, 3}
    fmt.Println(grades)  // prints [1 2 3]
    changeSlice(grades)
    fmt.Println(grades)  // prints [1 2 20]
}

func changeSlice(grades []int) {
    grades[2] = 20
}
Here is the StackOverflow question that inspired this post, and my answer to it.