Sunday, October 04, 2009

Some thoughts on redesigning education

Some time back I read a blog post on redesigning education. It asked some very good questions. Stuff which I had been thinking of myself. I left my thoughts on the blog, but I would also like to start a conversation around these ideas with those who read this blog as well.

I would like to know what other people think of the issue of redesigning (college) education.

I have often thought about how college education can be improved. To answer this question, we first have to ask a very basic question. What is the purpose of education?

To me, we need education for 3 things:

  1. To learn more about the world around us
  2. To lead positive constructive lives
  3. To earn a good living / fulfill our ambitions

I think education has to a large extent evolved to fulfill #3 (with a bias towards earning a comfortable living). The semester system, along with multiple choice tests, and grading, has made our education system into an assembly line. Students are pushed into the assembly line, given classes, administered tests, branded with a grade and pushed out of the assembly line, into the workforce.

Even though this is not the best way to teach, this system has for the most part worked till now. I think there are several reasons.

1. For many of students, getting an education is simply a means to gain employable skills (I do not say this in a negative way).
2. A university has to provide these skills in a time and cost efficient way to the students. It has to provide some branding which will be valuable to students, and make it easy for employers to spot the talent they want to recruit.

In the last few years I have taught programming classes at a local college. In one semester, I tried to move away from the regular grading mechanism. I wanted to focus on deep learning of programming skills, sharing and brainstorming ideas, code reviews, collaborating with the community of practice, etc. However, students still needed to be graded, so I had to come up with a way to fulfill that requirement also. Without going into details I will simply say, in that semester, I put in an effort which was orders of magnitude greater than the regular effort (because I had to fulfill the grading requirement). Students learned a lot in that semester, and I too enjoyed running that course, but towards the end of the semester, I was tremendously stressed out managing the course, and my regular programming work.

So even though the current education system is sub-optimal, I do not think it is because of evil intentions. It is possibly the most practical mechanism that has emerged over time.

However, many things have changed in the past few decades. The shelf life of knowledge has greatly reduced. The Internet has made it possible to share information, and collaborate with people at a distance. Many businesses have started valuing knowledge over degrees (this is at least true in software, and probably in media, advertising, etc as well). The read-write web has made it possible for students to easily create a digital portfolio, and to establish alternate credentials. So all the things a student needs for learning (information, interactions, guidance, review and feedback, and credentials) can be put together in a non traditional way. I stress so much on non traditional because the traditional education system excludes many learners, and this I feel can be changed.

So here is the ideal education system according to me:

A student enters the education system with some goals, and connects with mentors who will help her in fulfilling those goals. These mentors may be traditional teachers who work for a university, or may be employees of an organization, senior practitioners who choose to help on the Internet, friends, family, or people who have retired from the workforce, but would like to share their wisdom and help others.

With the help of mentors, the student defines learning goals, and identifies resources. These resources could be traditional classes, books, or digital material (videos, text, audio...).

With these materials and a micro mentor network, the student begins her learning process. When they have questions, there are a several resources from their mentor network they can turn to. These students may be part of a traditional classroom in some cases, whereas in other cases they may be part of a local or virtual study group. Think of it as being part of an appropriate group for every course they want to take. There are several tools, both real world as well as digital to enable this.

As the student learns, they leave a digital learning trail. One possible way is using blogs, audio recordings, wikis, contributions on forums, and other digital artifacts. So students blog their assignments and problem sets. They participate on Internet forums asking and answering questions. They may create a podcast (or screencasts) of their assignments and presentations. Maybe some students will be able to do practical work which is similar in nature to the assignments and problem sets.

Senior practitioners, traditional teachers, mentors from the community, help the student understand the strengths and weaknesses in their knowledge. The student subsequently fills in the holes by seeking help from their mentor network, and by revisiting those concepts. Community members endorse a students' understanding of their topic of study. Maybe tests still have a place... I don't know...

When a student knows enough, they can enter the workforce. Proof of their knowledge already exists on the Internet. Some organizations may accept them purely based on their digital portfolio and an interview, while others may expect them to take some tests. Students can prepare for these tests, if they wish to work for that organization.

Students however, do not stop their education after getting employed. The process outlined above continues, but perhaps at a slower pace. Thus even after starting work a person continues to accumulate (non credit) credentials. These credentials may either be continuing education certificates from a university or Internet endorsements from the community of practice.

This to me is the ideal educational scenario. But it will not be without problems.

There will always be the issue of credibility of an online portfolio, and endorsements from random mentors. Is there a process using which we can streamline online credentials and validate the credibility???

There will be issues with self-discipline. College gives a certain structure. Doing it by oneself needs a lot of will-power and discipline. One can easily while away time, thinking they are learning something. Maybe the Pomodoro technique can help here.

But I think this scenario is workable. I like it because it allows students to learn at their own pace (without excluding students who do not have resources to attend traditional colleges), from many mentors, thus gaining knowledge and wisdom from many sources. But most importantly, it allows students to take control of their education, and seek out the best, albeit disparate sources for knowledge.

Here's my own humble effort towards contributing towards this goal - http://www.adaptivelearningonline.net

Monday, August 24, 2009

Fixing a mistake after commiting in Git

So, I ran into an interesting issue while coding today. I made a lot of changes and committed code to my Git repository. Just after committing, I realized that I still had to make some changes to a file and those changes should also have gone in with the previous commit.

Fixing a commit mistake can be done in two ways. Revert the commit, make the changes and then recommit them. This is the preferred way if we have already made the changes public (and thus someone may already have pulled them). However, in my case I am the only one working on this project right now and I had not pushed the changes to GitHub, so I could try the other method.

So here's what I did. I made changes to the file, added it to the index, and committed it thus:

$git commit --amend


Committing code with the --amend switch will cause the index to be committed as part of the previous commit. Git also brings up the editor window, in case we want to change the commit message. This method can also be used to change the commit message without adding any files to the commit.

Reference:

Sunday, August 23, 2009

Lack of design patterns in Python

While searching for PyCon videos, I came across Joe Gregorio's very good video on (lack of) design patterns in Python. I have also added the video timeline along with some notes I made for myself and my takeaway. Enjoy the video.




Timeline:
[00:00] - Start
[00:15] - People pick tools based on a mythology and not necessarily facts
[02:35] - Python isn't just Java without the compiler
[03:34] - Design patterns are also a sign of weakness in a language
[04:06] - Lack of design patterns in Python (proof of lack)
[06:10] - Patterns are built into Python
[07:00] - Strategy pattern in Python the wrong and right way
[07:36] - The strategy pattern is invisible in languages with first-class functions
[08:07] - Some other language features in Python (first class functions, metaprogramming, iterators, closures)
[09:17] - The iterator pattern (iterators) is also built into Python
[09:36] - The observer pattern is also built into Python
[10:17] - Factory method pattern in Python (
[10:34] - Abstract Factory Pattern
[10:40] - Strategy pattern goes away becaise of first class functions
[11:08] - Drawing some useful conslusions
[12:20] - Drawing light on Python from the perspective of patterns
[12:31] - Thread Pool and Concurrency patterns (should we be talking about language features in Python for concurrency patterns???)
[13:49] - Channels (a model for concurrent processes)
[15:12] - PyCSP (implmentation of csp on top of Python)
[18:42] - Conclusions, summary, and questions
[19:17] - end (video goes on for a few more seconds waiting for questions)



Notes:
There are very few references to design patterns in Python mailing lists and discussions around Python... design patterns could be a sign of weakness in a language... patterns are built into Python (hence very little discussion)...strategy pattern is invisible in languages with first class functions...



Takeaway:
If you have to implement a design pattern, first look at language features and try to determine if any can be used instead of the pattern or at least assist in the implementation of the pattern while programming in that language.

Ask yourself if a language feature would make that pattern part of the language itself.

Concurrency patterns are a rich area to look at.



References:


Monday, August 17, 2009

iAccelerator

iAccelerator

I took a sabbatical from my consulting work this summer to participate in the iAccelerator program. This is a program for early stage software startups, similar to YCombinator, but the first of it's kind (I believe) in India.

I enjoy teaching programming, I have taught programming classes at a college, done corporate workshops, and more recently have been working on a website for participatory learning. This time I was looking for a different kind of mentoring experience, something which would be free form and fun. After a discussion with Freeman, I decided to go spend the summer at iAccelerator.

In the first few days of the program we had introductions by all the teams where they spoke about their product and vision. This was followed by a session on team building and thinking out of the box, a few legal sessions, sessions on accounting and company law, and several other mentoring sessions. All this is very useful for early stage software stratups, especially when they are founded by techies who are excelent hackers but need some help with legal and business stuff.

iAccelerator had ten very motivated and talented teams. I split my time helping them with technical stuff and working on my participatory learning project.

We worked out of a large hall, converted very tastefully into a working area. Each team had their own space towards the walls, and the centre was furnished with couches, projector, a large whiteboard (where we had presentations and brainstorming sessions) and a wii for fun and entertainment.

Even though everyone had their own work areas, many people chose to work on the couches. Working from the couches was a lot more fun and it gave opportunities for discussions, knowledge exchange, and friendly bantering. The couch culture (as I call this) in retrospect has been a very important part of the cameredierie and the excellent environment we had among us.

A good, positive, and helpful environment is one of the best things in such a program. Whenever anyone was stuck with a problem, or needed help with something new, they would always find someone who had that knowledge and was willing to share it. Everyone had their unique strengths, and collectively we all had a lot of talent which flowed freely. Entrepreneurship is also often a journey of highs and lows. There are times when you feel like your product will take over the world, and then there are times which can be described as not so pleasant. Being in a good environment with friends, means that you are not in this alone. If someone is down he can be sure that his buddies will pull him up.

One team found their first few customers within the group itself, and another team made a kick-ass software for internal communication which had passionate users from day one.

Ever so often we would have mentors, and successful entrepreneurs come talk to us about various things related to business and startups. Many guests spoke about their journey as entrepreneurs, their successes, failures, and lessons learned. Besides these sessions, we were also invited for many talks given by various mentors to the IIM students. This was a benefit of being on the IIM-A campus. Several mentors also worked one on one with the teams to help them with their vision and business plans.

Since we all had technical skills, internally we did several TechTalks on topics such as security, Amazon EC2 & cloud computing, designing with GIMP, JQuery, version control with SVN and Git, and many more. Sometimes we played tech videos from the Internet and had discussions around them. These sessions were a lot of fun and we all learned from them.

Since Freeman has successfully created and exited a startup in the past, he had many insights about how to run a startup. He shared his knowledge and insights with everyone, helping with business plans, vision, fund raising pitches, and many other nitty gritties of creating startups.

However, it was not just work all the time. We had a great time watching MTV while eating breakfast in the college mess. I can now tell you that watching MTV is far better than reading the morning newspaper. We played ping pong (Freeman and me had some really fun and intense ping pong sessions) ... we played cricket... on weekends we watched movies on the office projector. We also had a lot of diverse talent in the group. Jeevan Ram rocked everyone with his dancing and Ghazal made us laugh with his mimicry.

It's amazing how well we all got to know each other in just a few months. Thinking back, this was the best time I have had after graduating. Most importantly, I cannot stress enough the fact that I made really good friends, and I am very grateful for the wonderful time we all spent together.

This year's iA program will end in a few weeks. I wish all the teams lot of success and good luck.

Friday, August 07, 2009

Custom JSON Encoder in Django

I have been messing around with how to display date formats (in questions and answers) for my web based learning site from the past couple days. After trying various things, I settled for what seems to be a web 2.0 standard for displaying dates - displaying dates as '2 days 4 hours ago' instead of the actual date and time '4th August, 2009 5:50 PM'. I like this because I do not have to deal with any browser localization issues. Everything is a delta between the UTC time a question was asked and the current UTC time (btw if you are working with datetime in Python, do read this blog post).

In my Django based application, I use JQuery to get questions and answers for forums on every topic page. The application sends back JSON to the Javascript functions which display the questions and answers from the JSON objects.

The DjangoJSONEncoder (scroll to the end of this module) provided by Django serializes dates in a specific format. I wanted to change this so that a date would be serialized as '2 days ago'.

A bit of Googling bought me to Jessy's very nice blog post, which explained very nicely how to create a custom Encoder to be used for serializing objects in Python. This seemed like a good idea, so I wrote my custom encoder to change the way dates are displayed;


class Web20DatesEncoder(DjangoJSONEncoder):
SECONDS_IN_HR = 60 * 60
SECONDS_IN_MIN = 60
def default(self, object):
if isinstance(object, datetime.datetime):
delta = datetime.datetime.now() - object
return self.get_delta_as_string(delta)
else:
return super(Web20DatesEncoder, self).default(object)

def get_delta_as_string(self, delta):
days = delta.days
seconds = delta.seconds
hours = 0
minutes = 0
hours = seconds / self.SECONDS_IN_HR
seconds = seconds % self.SECONDS_IN_HR
minutes = seconds / self.SECONDS_IN_MIN
seconds = seconds % self.SECONDS_IN_MIN
delta_str = ''
if days > 0:
delta_str += str(days) + ' days, '
if hours > 0:
delta_str += str(hours) + ' hours, '
if days <= 0 and seconds > 0:
delta_str += str(seconds) + ' secs, '
return delta_str


However, I could not figure out how to hook this class into the call chain so that it is used when my QuerySet is serialized as such;


res = serializers.serialize(”json”, questions)


One solution which came up was to use the 'cls' parameter in the call to serialize.


res = serializers.serialize(”json”, questions, cls=Web20DatesEncoder)


However, when I ran my code, there was an error:

dump() got multiple values for keyword argument ‘cls’

Why do we get this error? Maybe (I still do understand Python well enough to be sure) because, the end_serialization method in django.core.Serializers.json.Serializer has the following line:

simplejson.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options)

As you can see it specifically passes cls=DjangoJSONEncoder to simplejson.dump(...), and this is the reason why we get the above error message.

Now I do not know what is the right way to resolve this issue, but here's how I did it. I created a subclass of JSONSerializer, such that my subclass used my custom encoder.


from django.core.serializers.json import Serializer as JSONSerializer

class DateModifyingJSONSerializer(JSONSerializer):
def end_serialization(self):
self.options.pop('stream', None)
self.options.pop('fields', None)
simplejson.dump(self.objects, self.stream, cls=Web20DatesEncoder, **self.options)

and the client code which earlier instantiated JSONSerializer now uses DateModifyingJSONSerializer.


#Here is the code snippet which uses the above class
json_serializer = DateModifyingJSONSerializer()
res = json_serializer.serialize(query_set)

#instead of old code shown below
#serializers.get_serializer("json")()
#res = json_serializer.serialize(query_set)


I hope you find this solution useful. Please leave a comment if it helped you, or if you know a better way to perform this task.

Thursday, July 23, 2009

Git supports commiting specific parts of a file

While working on my web based learning project, I made a lot of changes to a Django view file without committing them. When I actually decided to commit, I realized that the changes in my view file should go into separate commits. I knew it was possible to commit parts of a file in Git, but I was not sure exactly how it could be done.

I asked the question on StackOverflow and got an answer within minutes :-)

Anyways here's how I did it. I had 3 files in my index:


urls.py
app/courses/templates/course/show.html
app/courses/view.py


The first 2 files were fine, but I did not want to commit the entire view file with the first two, I wanted only one change in that file to go in this commit.

Since I had already added the view file to the index, I first had to unstage it with:


git reset app/courses/view.py


Then I did an interactive add to add only one hunk from the view file:


git add --patch apps/courses/view.py


Running this command showed me the first hunk from the file and an option asking me if I wanted ti stage that hunk. I decided I did not want the first hunk, then it showed me the second hunk. This was the change I wanted, so I entered 'y' at the option and proceeded to enter 'n' for all the remaining hunks.

After this I wanted to ensure that the right hunk from the file was staged to be committed, so I typed:


git diff --color --cached apps/courses/view.py


This showed me all the changed that were staged. After ensuring that the changes I wanted were the ones staged, I commited them with:


git commit

Saturday, July 11, 2009

JQuery selectors and future elements

I am using JQuery for the AJAX and dynamic aspects of my web based learning platform.

I like the fact that JQuery allows us to use CSS type selectors to select elements on the page to either manipulate them, add event handlers, or a host of other things.

So, the code below intercepts clicks on all links and dynamically adds a new link when a link is clicked.


<html>
<head>
<link rel="stylesheet" type="text/css" href="/site-media/al/style.css" />
<script type="text/javascript" src="./jquery-1.3.2.min.js"></script>
</head>

<body>
<script type="text/javascript">
$(document).ready(function() {
$("a").click(function() {
$("ul#questions").append("<li><a href='#'>click me</a></li>");
});
});
</script>
<div>
<ul id="questions">
<li><a href="#">Click Me: 0</a></li>
</ul>
</div>
<textarea style="Width: 400px; Height: 200px" name="textarea" cols=20>
<head>


There is a problem with this code. Everytime you click on the link called "Click Me: 0" a new link is added, but if you click on the new link, then nothing happens. So, why does JQuery not work with dynamically added elements?

The reason is because the following call


$("a").click(function() {
//...
});


only binds to the anchor elements present on the webpage when the $(document).ready() function is called. It will not bind to future elements. To bind to future elements as well, we have to use the live() function.

Try using this code to bind to the "a" elements and it will work.

$("a").live("click", function() {
$("div#questions").append("click me");
});

Thursday, July 02, 2009

Refreshing iptables

The last time I played around with IPTables was about 6 - 7 years back. I have been working with a Linux box again from the last few months and I am absolutely thrilled about it. Nevertheless, I have also been meaning to set up a simple IPTables firewall on my machine.

Since I had forgotten all my IPTables concepts, I decided to hunt the Internet for some good articles. I found some really nice resources to refresh my memory as well as learn new things.

Here is a nice 3 part video series from Linux Journal.
  1. iptables part 1
  2. iptables part 2
  3. iptables part 3
The entire series takes less than a half hour and is a good refresher or introduction to IPTables.

Here is a nice picture which explains how a packet is routed through various chains in the ip tables. If you are looking for a quick refresher, this might help you out.

If you want more details, here is a tutorial, and yet another tutorial, and Netfilter's excellent documentation on IPTables.

So now there is no excuse for not setting up a little firewall on your Linux box.

Monday, June 22, 2009

Inheritance vs. composition depending on how much is same and how much differs

I am reading the excellent Django book right now. In the 4th chapter on Django templates, there is an example of includes and inheritance in Django templates.

Without going into details about Django templates, the include is very similar to composition where we can include the text of another template for evaluation. Inheritance in Django templates works in a way similar to object inheritance. Django templates can specify certain blocks which can be redefined in subtemplates. The subtemplates use the rest of the parent template as is.

Now we have all learned that inheritance is used when we have a is-a relationship between classes, and composition is used when we have a contains-a relationship. This is absolutely right, but while reading about Django templates, I just realized another pattern in these relationships. This is really simple and perhaps many of you may have already have had this insight...

We use inheritance when we want to allow reuse of the bulk of one object in other objects such that it can change a few things as per it's requirements. So in a way we have a template which we want to allow reuse of in the greater part and modification of in the smaller part. On the other hand we use composition when we want to reuse another object in this object. So we have a template in which we want to plug some holes in functionality.

Does this make sense?

Monday, June 15, 2009

Slashy strings in Groovy

Groovy has done a great job of enhancing Java Strings. It offers a lot of features like String interpolation with GStrings, triple quoted Strings, multi-line Strings, and slashy Strings.

In this post I will talk about slashy Strings in Groovy. But before doing that let us see how we represent a regular expression in Java. Let's say I have a list of fully qualified file names and I want to match all files in my 'c:\tmp' directory.

I would create a String to represent my regex in Java like this:
String exp = "C:\\\\tmp\\\\.*"

The four '\' are needed because '\' is a meta character in regular expressions, so we need to represent a '\' as a '\\'. Because a '\' is used for escaping special characters in Java, we need to represent '\\' as '\\\\'. Wow doesn't this look cumbersome. Well, this is not just one case. Regular expressions make use of the '\' character for special classes. Everytime we want to use a '\w' or a '\d' or something like that we will have to use '\\w' and '\\d' instead.

Slashy Strings in Groovy give us a way around this by allowing us to represent regular expressions just like they would be represented without having to escape the '\' in Java.

Using them we can write

def file = /C:\\tmp\\.*/

Notice that slashy Strings have to be surrounded by forward slashes, and are mostly used when Strings need to represent regular expressions.