10 Dec 2012
The process through which software is built and shipped varies widely between companies, and even teams within any one company.
As a student of software leadership and an active participant on many development teams, I’m going to share a few thoughts on how I believe we can collectively build better software.
Small Teams, Individual Ownership.
In my opinion, teams should be no bigger than 5 people and they must be capable of owning what is built from inception to production.
Scalability comes from a focus on not repeating yourself and building tools to abstract away grunt work. Want an architecture like Netflix? You must iterate relentlessly and never settle on good enough.
We must focus on getting good at going from an initial idea or concept to implementation. Speed and efficiency come from reusing common patterns and techniques (and technologies), not reinventing the wheel.
Case in point, here’s my (current) set of preferred frameworks and tools:
-
Dropwizard (for simple RESTful APIs)
-
AngularJS (for client-side JS)
-
Compass/SASS (for client-side CSS management)
-
Fabric (for programmatic deployment)
-
AWS (for relational and non-relational data stores, etc.)
Just as every carpenter carriers a hammer, every developer must aim to master a set of tools and ever-changing frameworks. What are yours?
Be Goal Oriented, not Task Focused.
Just because you broke an idea, goal or user story down into a series of tasks does not mean that you’ve captured the essence of what needs to be delivered.
All too often it’s easy to get lost in the details of crossing items off an implementation checklist and losing site of the fact that what is being built is a piece of crap. Focus on the customer and if the original breakdown is not aligned with your actual progress, adjust accordingly and talk with your team or stakeholders.
Personal rule of thumb, never go longer than a day without committing code and getting feedback from a peer, even if it’s just bouncing your progress off them for a quick sanity check. Always talk about what has already been done before discussing what will be tackled next.
A tool like JIRA, used incorrectly and without oversight, can make it easy to head off in the wrong direction. Put another way, JIRA will let you create all the sub-tasks and record as much time as you’d like against them, but it will never tell you you’re doing the right, or wrong, thing.
You don’t always get what you want.
As engineers, it can be rare to find an environment that day in and day out is going to push you to improve. I feel that we owe it to ourselves to find outlets outside of the office that offer rewarding technical challenges, be it taking Martin Odersky’s Scala course or working on a side-project.
On a personal note, I self-funded* my own 20% time last year and invested in personal experimentation. Learning to quickly take ideas from concept to implementation, and getting knee deep in Python, MongoDB, the App Store and much much more along the way.
Looking back, this was probably one of the best decisions I could have made.
* self-funded, in this case, meant taking an unpaid day off each week for a year from my regular job to focus on personal projects.
That’s it for now. Stay tuned!
09 Jul 2012
For anyone looking to have Python (CentOS 5.8) connect to an Oracle instance (RDS):
$ yum install python26 python26-devel (I was using a Rightscale instance that already had the EPEL repository loaded, otherwise see: http://fedoraproject.org/wiki/EPEL)
$ wget http://pypi.python.org/packages/2.6/s/setuptools/setuptools-0.6c11-py2.6.egg#md5=bfa92100bd772d5a213eedd356d64086
$ sh setuptools-0.6c11-py2.6.egg
$ easy_install-2.6 pip
$ pip-2.6 install virtualenvwrapper
Add to /etc/profile
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python2.6
. /usr/bin/virtualenvwrapper.sh
export ORACLE_HOME=/opt/oracle/instantclient_11_2
export ORACLE_BASE=/opt/oracle/instantclient_11_2
export TNS_ADMIN=/opt/oracle/instantclient_11_2
export ORACLE_HOME=/opt/oracle/instantclient_11_2
export LD_LIBRARY_PATH=/opt/oracle/instantclient_11_2
$ mkdir -p /opt/oracle
$ unzip instantclient-basic-linux.x64-11.2.0.3.0.zip -d /opt/oracle
$ cd /opt/oracle/instant*
$ mkvirtualenv oracle –system-site-packages
Create /opt/oracle/instantclient112/tnsnames.ora
TOYBOX =
(DESCRIPTION =
(ADDRESSLIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = X.Y.us-east-1.rds.amazonaws.com)(PORT = 1521))
)
(CONNECTDATA =
(SERVICE_NAME = ORCL)
)
)
Connect via Python
(oracle)[root@domU-12-31-39-16-36-60 python-connect]# python2.6
Python 2.6.8 (unknown, Apr 12 2012, 20:59:36)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-52)] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.
import cx_Oracle
connection = cxOracle.connect(‘USERNAME/PASSWORD@TOYBOX’)
cursor = connection.cursor()
cursor.execute(“SELECT count(*) FROM sys.dba_tab_privs WHERE grantee=’PUBLIC'”)
<__builtin__.OracleCursor on <cxOracle.Connection to ajordens@TOYBOX>>
count = cursor.fetchall()[0][0]
print count
2494
cursor.close()
connection.close()
12 Feb 2012
This past week I spent a little time working with LinkedIn’s JavaScript APIs.
The APIs themselves are quite powerful and easy to work with. Complications arose when it came time to convert the temporary JSAPI tokens to their oAuth equivalents.
https://developer.linkedin.com/documents/exchange-jsapi-tokens-rest-api-oauth-tokens
First things first, LinkedIn only passes the JS API oAuth 2.0 token over an SSL connection. Slighly annoying from a development perspective, as I wasn’t normally running SSL on my local Mac. That being said, getting nginx setup through homebrew was straight forward. It works fine with a self-signed certificate as well.
Once you have SSL setup
<script type="IN/Login" data-onAuth="onAuth" data-onLogout="onLogout"></script>
function onAuth() {
$.post("https://" + window.location.hostname + "/my-app/token-exchange");
}
After a successful LinkedIn authentication, the onAuth() function will be invoked and a POST made to your backend resource over SSL.
def token_exchange(request):
oauth_token = None
oauth_secret = None
if request.session.get('linkedin_oauth_token'):
oauth_token = request.session.get('linkedin_oauth_token')
oauth_secret = request.session.get('linkedin_oauth_secret')
else:
oauth_token = request.COOKIES.get('linkedin_oauth_%s' % settings.LINKEDIN_API_KEY)
oauth_token = urllib.unquote(oauth_token)
oauth_token = json.loads(oauth_token)
consumer_key = settings.LINKEDIN_API_KEY
consumer_secret = settings.LINKEDIN_SECRET_KEY
access_token_url = 'https://api.linkedin.com/uas/oauth/accessToken'
access_token = oauth_token.get('access_token')
consumer = oauth2.Consumer(
key=consumer_key,
secret=consumer_secret
)
client = oauth2.Client(consumer)
resp, content = client.request(access_token_url, "POST", body='xoauth_oauth2_access_token=%s' % access_token)
request_token = dict(urlparse.parse_qsl(content))
oauth_secret = request_token.get('oauth_token_secret')
oauth_token = request_token.get('oauth_token')
request.session['linkedin_oauth_token'] = oauth_token
request.session['linkedin_oauth_secret'] = oauth_secret
The code snippet above is a django view *that requires *oauth2.
And that’s it. You’ve now successfully converted JS API tokens to oAuth tokens in a Python/Django environment.