Thursday, March 21, 2013

a good track for learning javascript

As i had mentioned earlier in my previous post, javascript is quite important and as a web developer you should know javascript well.The problem however is with the appropriate technique to learn it.I found a technique which claims to be good.
how-to-learn-javascript-properly

I have started this course and i can say i'm seeing some progress, i'm through with the first two weeks.About the resources, i would recommend professional Js for web developers.

I've not finished the week 3 and 4 sections but i really look forward to evaluating whether my skills have increased.

The codeacademy course can be very boring especially if you've chosen to start with the web fundamentals.I chose to skip some sections, but took others which looked like good refreshers.Don't skip this track entirely, you can be surprised to learn things you didn't know.



Tuesday, October 2, 2012

tinkering around but never mastering javascript

I normally hack javascript when i need to, but i have noticed that many people also do this.The reason for this i attribute to the internet and especially google.

There are plenty of resources on the internet offering solutions on how to deal with a specific problem, so one ends up googling how to do something in javascript without going through the basics of the language.

What we end up with is skills at googling and fixing problems but no mastership of the language.This can be said to be the double edge of having plenty of resources available at your finger tips.

For instance, stack overflow is an excellent resource.But i think one should turn to stack as the last resort.The habit of rushing to stack overflow and copying code does not offer any self improvement.A better alternative would be to hit the docs and read a good portion.Still this should come after attempting to solve the problem.

Nevertheless programming is a craft thats all about experience, if you continue hacking at javascript each day for 10 years, you'll eventually master it, but the point is it would be easier if you took time to go through the docs and learn the basics of a language.

This goes for jquery too, its possible to use jquery without knowing a good portion of javascript.This is a bad idea and sooner or later, if you're writing serious code, problems are going to arise that need more than just the basic knowledge of jquery.

So what will be the right time to master javascript?
Why not try a daily schedule.Taking on a chapter a day, there are plenty of good books on javascript out there.

Mac as a development environment

Apple pcs and notebooks are very elegant and offer a high level of aesthetics compared to standard hardware, but what about using a mac for development.

Experience with a macbook pro has proved that mac's are excellent for development.Want a vague proof of this, just take a look at conference videos, most serious developers use macs.And its just not for the aesthetics but there are heavier reasons for this.

Historically linux was the choice environment for many.The popularity of linux is waning due to recurrent issues involving GUI systems and the classic old drivers problem.Its just a pain that should be abstracted, and this is what mac osx does best.The UI is clean and elegant and you still get the power of the unix shell.

The write once run everywhere nature of web apps has also promoted the use of osx.Due to the fact that you can create a web app from any on any operating system that will be available to any system with a browser, this has removed the constraint of having to develop on a particular environment.Thus developers are free to choose which system provides the best user experience, and apple is well known for this.

A general trend I have noted is that most development software and library creators tend to cater for mac users since its a fact that many debs are on that platform.



Wednesday, August 22, 2012

pep 8 on pycharm

Pep 8 standard is a good convention to use when coding especially when working as a team.Standards and conventions make reading other peoples code easier.Getting yourself to start adhere to these  standards takes some time and effort, but by using the right tools it can take a shorter time.By the way, taking your time to learn these standards is quite worth the effort.

Pycharm is a wonderful python IDE which i would recommend to anybody doing development in python.Using pycharm you can set pep8 as an external tool, which you can invoke on any file you are currently working on to  check whether it violates any standards.This can be done this way.

Install pep8 package from the python package index

pip install pep8

go to: File > Settings > External Tools > Add new


if your using virtual env, use the path to pep8 installed in the virtualenv's bin directory.Otherwise point it to the location where pep8 is installed, use the whereis command to find it.
Now add an output filter as follows.

You can now access the command from the tools menu or conveniently right click anywhere within the file currently being edited and select the command.
The output should be quite helpful in identifying changes which need to be made.


Monday, August 6, 2012

django factory boy - better test management

Django factory boy is an excellent replacement for fixtures, most of the time you will encounter problems with maintenance of fixtures.For instance if you do migrations often, the set of fixtures will become invalid and has to be edited to fit the new schema, this can be extremely painful if you have a complex schema and lots of data.
Factory boy makes it easy to create objects when you need them for tests.For example..

lets say you have this set of models,
from django.db import models

class Owner(models.Model):
    name = models.CharField(max_length=200)
    phone = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

class Car(models.Model):
    name = models.CharField(max_length=200)
    owner = models.ForeignKey(Owner)

    def __unicode__(self):
        return self.name

Then your factories.py for these two will correspond to something like this
import factory
from models import Owner, Car

class OwnerFactory(factory.Factory):
    FACTORY_FOR = Owner
    name = 'bruce'
    phone = '+254728037573'

class CarFactory(factory.Factory):
    FACTORY_FOR = Car
    name = 'jeep'
    owner = factory.lazy_attribute(lambda a: OwnerFactory())

The tests for the factories themselves go something like this
from models import Car,Owner
from django.test.testcases import TestCase

class FactoryTestCase(TestCase):

    def test_car_factory(self):
        car = CarFactory()
        self.assertTrue(isinstance(car, Car))

    def test_owner_factory(self):
        owner = OwnerFactory()
        self.assertTrue(isinstance(owner, Owner))
Many to many fields are a bit tricky to emulate but this does the trick. For instance lets say you have this set of models.
from django.db import models

class Pizza(models.Model):
    name = models.CharField(max_length=120)
    toppings = models.ManyToManyField(Topping)

    def __unicode__(self):
        return self.name

class Topping(models.Model):
    name = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

Then your factories will go something like this.
from models import Pizza, Topping
import factory

class ToppingFactory(factory.Factory):
    FACTORY_FOR = Topping

    name = 'mushrooms'

class PizzaFactory(factory.Factory):
    FACTORY_FOR = Pizza

    name = 'mushroom delight'

    @classmethod
    def _prepare(cls, create, **kwargs):
        topping = ToppingFactory()
        pizza = super(PizzaFactory, cls)._prepare(create, **kwargs)
        pizza.toppings.add(topping)
        return pizza

So the key here is to override the _prepare method and assign the manytomanyfield objects here, since you have and instance of the object. In conclusion factories are a good alternative to fixtures when used in the right way.

Thursday, April 12, 2012

building web applications

The best method to use when building web applications is to use frameworks. Frameworks save on time and adhere to the principle of not repeating code all the time (DRY). So if you decide to use a framework, what should your choice be.There are many frameworks out there and therefore it would not be okay just to point you to one.To gain a deeper understanding of building web applications using frameworks it is advisable to go down the path of discovery.

  1. Pick a framework based on any language you know of and learn it, this should be the beginning.
  2. After taking a week or two to learn the new framework, do a side project with it, not a serious one but something far from the basics.Try to implement some idea you've always had.
  3. Add the side project to your portfolio and start over again from step 1 this time with another framework which is related.
After going through the first iteration, try implement the idea you had done using the new framework you have just learned.This aids you in discovering weaknesses and strengths in a framework.

Be patient
Nothing comes easy, everything requires time and effort, so don't expect to excel at it immediately.With continuous practice and diligent effort you will notice your skills and knowledge increasing.
I wish to stress the importance of persistence here.It's what will bear the results.

Monday, April 9, 2012

Django Tastypie with android client part 2

This post picks up from part 1 where we had defined the api using tastypie.The purpose of this second part is to create an android client to consume the api. here are the files that make up the android application. RecipesActivity.java
package com.thecodachi.recipe;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.dao.Dao;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class RecipesActivity extends Activity {
 
 public static String api_url = "http://10.0.2.2:8000/api/";
 
 private List recipesList = null;
 private ProgressDialog progDialog;
 private ProgressThread progThread;
 private ListView recipes;

 private DatabaseHelper databaseHelper = null;

 private ArrayAdapter adapter;
 
 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        recipes = (ListView)findViewById(R.id.lvRecipes);
        
        showDialog(0);
  
        try{
   //get our Dao and query for all customers in db
   Dao recipes = getHelper().getRecipeDataDao();
   recipesList = recipes.queryForAll();
  
  }catch(SQLException e){
   Log.e("LOG", "error getting products");
  }
  
  
        adapter = new ArrayAdapter(this,
                      R.layout.recipe_row,
                      R.id.recipeLabel,
                      recipesList);
        recipes.setAdapter(adapter);
    }

 @Override
 protected Dialog onCreateDialog(int id) {
  switch(id){
  case 0:
   progDialog = new ProgressDialog(this);
   progDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
   progDialog.setMessage("Loading data...");
   progThread = new ProgressThread();
            progThread.start();
   return progDialog;
  default:
   return null;
  }
 }
 
 private class ProgressThread extends Thread{
  
  private static final String LOG_TAG = "PROGRESS_THREAD";

  @Override
  public void run() {
   HttpClient httpClient = new DefaultHttpClient();
   HttpGet httpGet = new HttpGet(api_url+"recipes/?format=json&limit=0");
   HttpResponse response = null;
   try{
    
    response = httpClient.execute(httpGet);
    
   }catch(Exception e){
    System.out.println(e.toString());
   }
   if(response!=null){
    HttpEntity entity = response.getEntity();
    String apiResponse = null;
    try {
     apiResponse = _getResponseBody(entity);
    } catch (ParseException e) {
     e.printStackTrace();
    } catch (IOException e) {
     e.printStackTrace();
    }
    if(apiResponse!=null){
     try{
      Dao recipesDao = getHelper().getRecipeDataDao();
      
      JsonElement json = new JsonParser().parse(apiResponse);
      JsonObject rootObject = json.getAsJsonObject();
      JsonArray array= rootObject.getAsJsonArray("objects");
      Iterator iterator = array.iterator();
      
      while(iterator.hasNext()){
       JsonElement json2 = (JsonElement)iterator.next();
       Gson gson = new Gson();
       Recipe recipe = gson.fromJson(json2, Recipe.class);
       recipesDao.createIfNotExists(recipe);
       Log.d(LOG_TAG, "--------------------------------created recipe");
      }
      
     }catch(Exception e){
      Log.e(LOG_TAG, "error creating recipe from json");
     }


    }
    
   }  
   dismissDialog(0);
   adapter.notifyDataSetChanged();
  }
 }
 public static String _getResponseBody(final HttpEntity entity) throws IOException, ParseException {

  if (entity == null) { throw new IllegalArgumentException("HTTP entity may not be null"); }

  InputStream instream = entity.getContent();

  if (instream == null) { return ""; }

  if (entity.getContentLength() > Integer.MAX_VALUE) { throw new IllegalArgumentException(

  "HTTP entity too large to be buffered in memory"); }

  String charset = getContentCharSet(entity);

  if (charset == null) {

  charset = HTTP.DEFAULT_CONTENT_CHARSET;

  }

  Reader reader = new InputStreamReader(instream, charset);

  StringBuilder buffer = new StringBuilder();

  try {

  char[] tmp = new char[1024];

  int l;

  while ((l = reader.read(tmp)) != -1) {

  buffer.append(tmp, 0, l);

  }

  } finally {

  reader.close();

  }

  return buffer.toString();

  }
 public static String getContentCharSet(final HttpEntity entity) throws ParseException {

  if (entity == null) { throw new IllegalArgumentException("HTTP entity may not be null"); }

  String charset = null;

  if (entity.getContentType() != null) {

  HeaderElement values[] = entity.getContentType().getElements();

  if (values.length > 0) {

  NameValuePair param = values[0].getParameterByName("charset");

  if (param != null) {

  charset = param.getValue();

  }

  }

  }

  return charset;

  }
 private DatabaseHelper getHelper(){
  if(databaseHelper  == null){
   databaseHelper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
  }
  return databaseHelper;
 }
}
Recipe.java class which defines a recipe object which can be persisted in the sqlite database using ormlite.
package com.thecodachi.recipe;

import com.j256.ormlite.field.DatabaseField;

public class Recipe {
 
 @DatabaseField(id=true)
 private int id;
 
 @DatabaseField
 private String name;
 
 @DatabaseField
 private String content;
 
 Recipe(){
  //used by ormlite
 }
 
 
 public int getId() {
  return id;
 }


 public void setId(int id) {
  this.id = id;
 }


 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getContent() {
  return content;
 }

 public void setContent(String content) {
  this.content = content;
 }


 @Override
 public String toString() {
  // TODO Auto-generated method stub
  return name;
 }
 
}
DatabaseHelper.java responsible for persisting and retreiving objects from sqlite database using ormlite.
package com.thecodachi.recipe;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;

public class DatabaseHelper extends OrmLiteSqliteOpenHelper {

 //name of the database file for the application
 private static final String DATABASE_NAME = "Recipe.db";
 private static final int DATABASE_VERSION = 1;
 /*
  * the DAO objects we use to access the recipes* 
  */
 
 private Dao recipesDao = null;
 
 public DatabaseHelper(Context context){
  super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }
 
 @Override
 public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
  try{
   Log.i(DatabaseHelper.class.getName(), "onCreate");
   
   TableUtils.createTable(connectionSource, Recipe.class);
 
   
  }catch(java.sql.SQLException e){
   Log.e(DatabaseHelper.class.getName(),"can't create db");
   throw new RuntimeException();
  }
 }

 //called when your application is upgraded
 
 @Override
 public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion,
   int newVersion) {
  try{
   Log.i(DatabaseHelper.class.getName(), "onUpgrade");
   TableUtils.dropTable(connectionSource, Recipe.class, true);
   
   //after dropping old databases, we create the new ones
   onCreate(db, connectionSource);
   
  }catch(java.sql.SQLException e){
   Log.e(DatabaseHelper.class.getName(), "can't drop databases");
   throw new RuntimeException(e);
  }
 }
 

 /* methods that returns the Database access object(Dao) for our product class
  * will create it or just give the cached value
  */
 
 public Dao getRecipeDataDao() throws java.sql.SQLException{
  if(recipesDao == null){
   recipesDao = getDao(Recipe.class);
  }
  return recipesDao;
 }


 /*
  * close all database connections and clear any cached DAOs
  */
 @Override
 public void close(){
  super.close();
  recipesDao = null;
 }
}
You can take a look at the rest of the resources belonging to this app from the repo which i will share. The implementation of the REST architecture i took in this example is not the best and it is highly recommended not to use this approach when building an android application.The reason for this is that the app does network requests within an activity.This should be done within a service For a more detailed and recommended architecture for creating RESTful android application look here. Otherwise this is just a demo.