Sunday, September 14, 2014

Modifying the DigitalOcean django one-click project to use a custom directory

Hi all,

I recently gave DigitalOcean a shot on the recommendation of someone at HackerNews. DigitalOcean has a lot of custom droplets, which are basically Virtual Machines, that you can use to set up a cloud server on which to host your website.

I had been building a Django website that I wanted to put up, and while setting it up on DigitalOcean, I ran into the following problem: The default Django droplet uses a base Django project located in the 'home' directory of the UNIX installation DigitalOcean sets up for you. I wanted it to point to a custom directory in the /opt folder that I had set up.

In order to do this, remote into the DigitalOcean droplet. Once there, run the following command:

    sudo nano /etc/init/gunicorn.conf

In this file, change 'chdir /home/django' to point to the directory that contains your django project. In my case, I changed it to '/opt/venv'.

Change the 'name' field to refer to the folder that contains your 'wsgi' file. In my case, I changed it to 'name=jobs'.

Change the 'pythonpath' field to refer to folder that contains your 'manage.py' file. In my case, I changed it to 'pythonpath=search-jobs'.

In 'django_project.wsgi:application' change 'django_project' to the name of your Django app (ie. what you changed your 'name' field to).

Now run the following command:

    sudo nano /etc/nginx/sites-enabled/django

In this file, change the media and static locations to point to where you need them to point to. In my case I changed:

    alias /home/django/django_project/django_project/media;

to:

    alias /opt/venv/search-jobs/media;

and:

    alias /home/django/django_project/django_project/static;

to:

    alias /opt/venv/search-federal-jobs/staticfiles;


That should set up the default nginx and gunicorn to serve your django project located in your custom path properly!

If you have any feedback on this post, or if it helped, drop me a comment and let me know.

Tuesday, March 11, 2014

Lessons from a salesperson

Today, I reached out to my buddy Mike at work, asking him if he had could give me his perspective on what it means to be a salesperson. He readily agreed, and I jotted down some notes from my conversation with him which I am compiling here -

Know who you're talking to

Different people in an organization have different concerns and different pain points. What's important is that you contextualize your product/service in terms of the person or people you are talking to. 

For example - let's say you have developed a fancy new CMS that is a dozen times better than Company X's old Wordpress site. However, you can't walk into a presentation to the Marketing department of Company X and excitedly tell them how scalable and maintainable it is - they won't care. You need to tell the Marketing people how easy it is to update content and apply branding, just as you need to show off scalability and maintainability to the IT people.

For the various people working different roles, you're going to want to know beforehand what their pain points are with the status quo. And then, you must get them to admit to having these pain points. This helps you build trust, and trust is vital - people like to buy from those whom they trust.

Sell by telling stories

Ask your audience a question - get them to tell you their pain points. This is especially a good way to go about the first meeting with a potential client. Once they start talking, now you have to coddle them a little bit. Tell them how you've had other clients with similar problems. Don't say, "I can help you, and here's how -" instead, tell them a story. Say something like, "You know, we had another client who was facing the [...] problem, and we built them a [...] solution that helped them save [...]."

By citing other clients, you're helping the potential client feel better - they're not the only ones with problem X - you're making yourself more relatable to them, and you're still showing off your product/service.

After that, you can follow up with more specific questions.

Keep things open

At least at first. If you have a booth set up in a conference somewhere, or are engaging in that first, initial meeting, don't tell them the nitty-gritty details about your fantastic custom e-commerce solution. At best, they'll talk enthusiastically for a few minutes, and then regretfully tell you that the problem you're solving isn't high-priority for them at the moment.

You must keep things high-level. The problem with getting too far into the details is that the moment the potential client starts focusing on details, the pain points that you had worked so hard to bring up start slipping from their memory. You need to focus on those high-level pains, and present high-level solutions. 

Ask 'how/why' questions, not 'what' questions

This ties in with phrasing - how you say things. Don't ask them what CMS they use, ask they how their experience is with their current CMS. After you've discussed it a little bit, then you can ask lead them to tell you what CMS they are using. The reason for this is that How/Why questions are open-ended;  what questions are close-ended. Especially in the early stages, you always want to keep things open-ended.

WIIFM - What's In It For Me

In the end, it comes down to adding value to the client. There are two means of adding value - time and money. Everything else - no matter what the client sites - can be boiled down to one or both of these two. It helps if you have concrete figures that you can show the client, on what their return on investment would be if they invested in you.

Secondly, it is better to lead the client to the realization that you have the means of saving them time/money. This is a better approach then telling them outright - they will trust their own conclusions better than the conclusions you present.

People buy your passion

Get them excited about you. Share your vision, and how that can help them shape their vision. You want them to buy into your vision.

Silence isn't a bad thing

This is something I have a lot of trouble with - when a potential client is silent, they are thinking. Let the wheels turn - don't feel the need to fill in the seemingly awkward silence. When they feel the need to talk to you, they will.

Ask the right questions

You must lead and direct the discussion, but be careful to do so without appearing to dominate the potential client. You must be in control, and they must feel like they are in control.




Monday, February 10, 2014

Thoughts on the Single Responsibility Principle



Today, while reading 97 things every programmer should know (disclaimer: affiliate link), I came across an explanation of the Single Responsibility Principle that finally clicked for me. I've read a fair amount of literature on Best Practices for programming, but I've often faced trouble in applying these best practices in real life projects. Here was an explanation that finally made sense.


The Single Responsibility Principle says that each class should have only one reason to change. This makes perfect sense in theory, but somehow I just couldn't find a way to implement it in practical code. However, after reading this chapter in the above book, I realized that I was getting the semantics wrong - objects in OOP don't have to correspond to objects in the real world. You don't need to have a single (possibly quite large) class for an Employee that handles the business logic related to Employees (eg. calculating wages, sick days, etc), as well as the database logic (inserting into and retrieving from a database), as well as any report generation logic - classes should be more flexible and correspond to what makes them easier to maintain. 

The chapter linked above, for example, says that instead of having an Employee class with functions that handle business/database/reporting logic, it makes more sense to have an Employee class that handles the business logic, then an EmployeeRepository class for the database logic and an EmployeeReporting class for the reporting logic. This means that if the database logic ever needs to change, I will only be touching the EmployeeRepository class that handles only the database logic. The business and reporting logic will remain untouched in their respective classes. Now, each class truly has only one reason to change.

Conclusion: don't be rigid in insisting on having classes map to real-world entities. Code your classes based on what makes them easiest to read and maintain.

Tuesday, January 28, 2014

Book Review: Apprenticeship Patterns

Apprenticeship Patterns (Disclaimer: That's an affiliate link; here's the non-affiliate one) is a book I found on linked on HackerNews. I read it over the course of this past week during my commute, and I wanted to share my thoughts on it.

Description

First of all, Apprenticeship Patterns is a very general book. There's little to no code, and it talks mostly about high-level best practices. The authors describe a set of "patterns", similar to the kind you may find in a software design patterns book. These patterns are intended to be adapted and applied to the lives of aspiring software craftsmen as they come across typical situations in their careers. The hope is that even as the pattern language led to great strides in code quality by codifying certain programming concepts, the same can be done for developers' careers using these Apprenticeship Patterns.
 

The authors structured the book in a very interesting way. It's organized it in a very hyperlink-heavy format. There are constant, hyperlinked references to other patterns in the descriptions for each pattern. Sometimes the hyperlinked reference to a pattern exists even before that pattern has been covered in the book. The authors say they did this to encourage the user to meander rather than read linearly and hence discover the relationships between families of patterns.

Each pattern in the book has a context, a problem, a solution, and an action:

  • The context is the point in life where the aspiring software craftsman may find himself. 
  • The problem describes an artifact of that situation that may be stunting his growth as a craftsman.  
  • The solution describes a general plan the developer can undertake to resolve the problem and move on to the next stage of his career. 
  • The action describes a concrete first step the developer can take towards implementing this solution.
For example - Apprenticeship Patterns contains a pattern called "Breakable Toys." Roughly paraphrased:
  • The context: As a developer, you know that you learn as much (if not more) from failure, as opposed to success.
  • The problem: You're in a high-stakes environment where success is critical and there isn't much room for failure. 
  • The solution: Design and build toy systems outside of the context of what you do for work. Do something like, build a wiki, or a calendar, or a to-do notes system. Or build a game. This will allow you to fail without suffering severe consequences. 
  • The action: Build the world's simplest wiki.
Of course, there's a lot more detail in the actual book, but that's a general idea of what these patterns look like. 

Criticisms

Apprenticeship Patterns describes the mindset you need to have in order to become a truly great developer. For me, it was a good reminder of what my motivations should be as an aspiring craftsman, and which aspects of my career I should be focusing on more. However, it's a very high-level reminder. Maybe it's the stage in my career, but I think I would have preferred something a little more gritty.

The whole hyperlinked thing definitely did not work for me. I'm the sort of person who read those old choose your own adventure series by bookmarking every choice and then once I had reached an ending, I went back to the last choice I made, and made a different decision until I had recursively "read" the entire book. If I were looking up articles online, I wouldn't mind working with the hyperlinked approach. When I'm reading a book, please let it be linear. 


Finally, a design patterns book is usually something you consider as a reference. Human lives and careers are infinitely more complex than code. I don't really see myself using this as a reference book for various stages of my career. 

Take-aways

Like I said earlier, Apprenticeship Patterns is a good reminder of what one needs to do to be a world-class developer. Here are some solid take-away points that stood out to me:
  • Surround yourself by people who know more than you
This is kind of a given. It's well known that you are the average of the five people you spend the most amount of time with. If you want to be more like someone, go spend time with them. Apprenticeship Patterns places a lot of value in social learning - learning with and from people. Social learning is much much much better than learning from a book or a video and is, I think, one of the prime benefits why going to an institution of higher education beats out MOOCs. 
  • Don't be ashamed of being dumb. Everyone was dumb once.
Ask questions. Don't worry whether someone might think you stupid. It's far more likely that they'll appreciate sharing their knowledge with you. If not, then they're not the sort of people you want to be asking questions anyway. This is something that has been driven into me at my job and something I've really come to embrace.
  • It might be a good idea to reinvent the wheel if you're doing it as an exercise.
This is something I got from the Breakable Toys pattern I mentioned above. For a while now, I've wanted to build an app that I can publish to Google Play, but every time I got an idea, I checked Google Play and someone else had already done it. I realized that "don't reinvent the wheel" is so deeply ingrained in me that I was hesitant to do something that had already been done, even if its only purpose in doing it was to hone my coding skills.
  • Don't be afraid of taking on something difficult
Sometimes, throwing yourself into The Deep End (that's a pattern) is the best way to learn. I'm a fairly conservative person myself, and I've found that every time I've pushed myself into taking ownership of a difficult task, regardless off whether I consider myself "ready", I've grown tremendously - both as a software craftsman and as a person. Yes, there's a chance that you'll drown, but as my boss at work reminds me, what's the worst that could happen? No one's going to die if I fail (my fiancée who's doing medicine can't say the same about herself).

Summary

In summary: Apprenticeship Patterns (non-affiliate link) is a very general book. It's a good reminder about the values of a software craftsman, but it's also very high-level and not as concrete as I would like. It's a short read, so if you have the time to spare and you haven't read a similar "inspirational" book recently, definitely do read it. We can all use reminders about what it means to be a software craftsman, and this book is definitely a good reminder. 

Thursday, November 21, 2013

Adding models to backbone collection without sorting

We've been using backbone.js at work a lot lately and I'm loving it so far. I wanted to share one thing I ran across recently where the solution to my problem was non-obvious.

Problem: I needed to sort a backbone collection using a natural sort algorithm. In order to sort the collection, you need to set a comparator - as in:

Collection = Backbone.Collection.extend({
    comparator : function () { // ... comparator logic }
});

However, the problem with this is that every time you do an insert, the collection resorts itself - which sucks when you're trying to add 4000 items to the list from the server like I was! In order to get around this, when you're adding something to the collection, you need to pass in the parameter sort = false, like so:

var collection = new Collection;
collection.add([model1, model2 ... modelN], { sort : false });
collection.sort()

Ta da! Now your backbone collection won't be sorted when you're adding those items to it.

I hope that helps people!

Wednesday, September 25, 2013

Facebook Post vs Status objects

I spent several hours wrestling with this, so hopefully this will help someone else:

Facebook posts and statuses are remarkably similar. The differences are as follows:
  • Facebook posts are any posts a user makes anywhere
  • Facebook statuses are posts a user makes on his or her own wall/stream
As you may notice, all statuses are also posts. However, the Facebook Graph API treats these objects differently. For one, statuses have far fewer fields. They don't even have a field for something as simple as the privacy_level. Posts are far more interesting/descriptive.

In order to request a post object instead of a status object for a "status" (since all statuses are posts) prepend the user_id of the person who made the status to the id of the post.

So for example querying the Graph API for the object with id "100006765630328_1380118238890351" will return a POST object, whereas "1380118238890351"will return a STATUS object.


Sunday, December 23, 2012

Django and sqlite3

This is a minor issue that bothered me for a while that I don't think the documentation makes clear.

When I was trying to set up an sqlite3 database with my django install, I was very confused because the tutorial I followed told me to enter in my settings.py file the location of the database. But I didn't have any database installed! Searching the internet returned several allusions to the fact that python2.5+ came with sqlite3 so I didn't have to install or download anything ... but if I didn't, how was I going to find where this elusive sqlite3 db was so that I could link django to it?

It turns out that django creates the database for you! So what you want to enter in the settings.py file is the link to the db file as you want it to be; for example: '/home/khalid/myproj/proj.db'

ProTip:

Consider defining the db url like so:

'NAME': os.path.join(os.path.dirname(__file__), '../proj.db').replace('\\','/')

This will make it so that the new db file is one directory above your settings.py file. If you want to do this, make sure you import settings.path at the top of your file.

Final Code:

import settings.path

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': os.path.join(os.path.dirname(__file__), '../proj.db').replace('\\','/'),  # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}


Cheerio.