Thursday, January 19, 2012

Learning and Software

Michael Gove's speech on the digital literacy campaign, currently underway in the UK, got me thinking about how software developers go about learning new software systems.  The digital literacy campaign aims to resolve deficiencies in the educational system.  This is a fantastic initiative and I think other nations follow suit.  Without transitioning from traditional teaching techniques we're used to, our children will be left behind.

What I'm thinking about isn't so much the education system.  I'm looking at the young working adults, many of whom don't have a formal education to speak of — friends and colleagues of mine that have gone on to lead promising careers in IT. The positions they hold require they really know their stuff.  How do they obtain this knowledge?  How do you beat the competition when it comes to know-how?

The Ecosystem
There is an important difference between learning the principles of computer science, and learning how to work with pre-built components.  If those entering the field were taught an important lesson, they'd know that re-inventing the wheel is a no-no.  It's highly probably that you can build what you need by assembling parts, possibly customizing them slightly along the way.  With computer science, everything is from the ground up.  And that's important too, to have a sound theoretical understanding of what software is made of.  Competing in the job market requires that you have at the very least a rudimentary understanding of everything that goes on between the keyboard and the screen.

The software ecosystem of today is uninterruptedly growing and evolving.  Some software components stabilize over time, attracting a wider development audience and thus making further improvements.  Some software components don't gain acceptance in any communities — they subsequently die off.  Understanding the context in which these open source software packages are used is a valuable asset.  It would be a much better learning opportunity to participate in the development of something with staying power.  Something that has proven feasibility and impacts a large group of users for a long time.  Before embarking on a new software project — an experience where you learn a new programming language or a new problem domain — do some research into why you prefer one project over another.  Is there a real future for this project?  Is there an alternative that might better suit your learning goals for the long term?

The way software systems work with one another is increasingly relevant — a lot of development work these days is integration rather than writing new code.  Reusing existing components, utilizing the best tool for the job — skills that matter.  If you spend enough time practicing this evaluation exercise, you'll be able to identify when, exactly, there simply isn't anything suitable for the gap you're trying to fill. This is your time to write something new.  This is how the ecosystem evolves. Maybe you're new software package will acquire a following and become a huge success.  Maybe it will serve as the basis for a superior project, earning you a reputation.  Or maybe it will be a spectacular failure, in which case you take away some valuable lessons.

Teaching by Learning
One unique property of doing software development in an open environment is the shared roles of teacher and learner.  That is, anyone participating in a software development can, and should, fulfill the role of teacher.  Software development is a nascent field — it's constantly changing because we're constantly building better components.  There is no such thing as a dedicated teaching role because it's impossible to keep abreast with everything new that's happening.  That responsibility is distributed throughout the team — everyone should be making discoveries on their own and sharing them with their peers.

Learning to write software is an  enlightening experience.  It has never been more accessible to anyone, regardless of stature, this ability to acquire new knowledge and to apply it.  Simultaneously.  With software development, theory and practice are tightly integrated.  This is why I love my job — my education didn't end with college — it only just got interesting when I started building real software for real customers.  The open source ecosystem serves as an ideal launchpad for anyone looking to further their experience.  Understanding how this ecosystem evolves and how to best utilize it's inhabitants is a skill no school can teach.  You have to do it yourself.  And it's no trivial investment, but well worth it.  Maybe we'll start seeing educational institutions adopt these new methods of software-based learning in the not-too-distant future.

Wednesday, January 11, 2012

Django Navigation States

I've tried several approaches to implementing Django navigation correctly.  Each approach presents it's own unique challenges and limitations.  The toughest thing to get right is the state.  By state, I mean the menu item that's currently active. Active navigational items need to be conveyed visually - this is easy enough from Django's perspective because it often means inserting the correct CSS class in the template.

Furthering the complexity to designing solid navigation in Django user interfaces is the fact that we can have dynamic variables in the URL path.  This makes a simple equality test in determining the state arduous.

So with this in mind, let me demonstrate the best Django-friendly approach to implementing state management with navigation.  I say Django-friendly because my approach attempts to be of use for any Django application.

Overview
The approach I'm using is similar to this one.  I'm creating a template filter that's applied to the HTTP request object inside a given template.  The filter takes a parameter - an identifier for the item we want state applied to.  So long as the identifier is valid, we can use this filter to emit the appropriate CSS class.

The Template
Here is the navigation template.  Intentionally simple, it shows how the link_state filter is applied.

<ul>
    <li><a class="{{ request|link_state:'home' }}" >Home</a></li>
    <li><a class="{{ request|link_state:'products' }}" >Products</a></li>
    <li><a class="{{ request|link_state:'services' }}" >Services</a></li>
</ul>

The Filter
Here is the link_state template filter used in the template to apply navigation item state.

from django import template
from django.core.urlresolvers import reverse, resolve, NoReverseMatch

register = template.Library()

@register.filter
def link_state(request, key):
    
    keys = dict(
        home = (
            'home',
            'promotion_details',
        ),
        products = (
            'product_list',
            'product_details',
        ),
        services = (
            'service_list',
            'service_details',
        )
    )
    
    url = resolve(request.path)
    
    for candidate in keys.get(key, []):
        try:
            candidate = reverse(
                candidate,
                args=url.args,
                kwargs=url.kwargs
            )
        except NoReverseMatch:
            continue
        if candidate == request.path:
            return 'active'
    return 'default'

Explanation
The link_state filter works by taking the HTTP request path, the navigational item key, and comparing URLs.  If a URL in the set associated with the key matches the request path, the state is active.  Otherwise, the state is default.

The keys dictionary maps navigational item keys to their active state URLs.  Here, there are three keys - home, products, and services.  Notice the relation to these names and arguments passed to link_state in the template.  Each key stores a tuple of URL names - when you define a URL in Django, you can give it a name.

Next, we resolve the request path.  The reason for doing so is that we need any dynamic path values so when we do comparisons, we can match these URLs too. Now we can iterate through each URL in the specified key, checking for a match.

This approach is flexible because it allows for navigational state management even with dynamic path values, without the need for any specialized code.  For example, the product_details URL might look like /products/845/.  This URL would set the products link as active.

Tuesday, January 10, 2012

Cloud SLA

Levels of customer service that go beyond the basics are difficult to achieve. Disaster recovery in the cloud is perhaps the most difficult thing to offer customers. Never mind the myriad other factors that make implementing cloud infrastructure services difficult in the first place — the sheer volume of data to replicate in order to satisfy SLAs is disheartening.  Performing any task, regardless of it's simplicity, becomes complex when the data won't fit on a single hardware node.  Putting it simply, cloud infrastructures are the new, more complex systems of today.

Now imagine saying this to a potential customer — "the technology is new, the ideas are new, the problems are challenging, you understand why I can't support you, right?"  Wave goodbye.  There has to be some level of service you're willing to give customers, at least enough that they're able to operate their business using your services.

Two competing obstacles.  Customers need all the support they can get when facing challenges with your system.  Contrarily, cloud customers are typically new customers.  They're used to operating in more conventional environments, where the problems with implementing a cloud infrastructure don't manifest themselves. That is, disaster recovery isn't why customers choose one cloud provider over another.  That type of SLA has lost some of it's persuasion in a cloud provider context.  Yet, this is a reasonable expectation of the customer.  Are there other solutions?

Clouds and Support
The cloud is different from a public parking lot.  I'm free to pull my car in, but I've got to find an appropriate spot.  I've got to make sure my car will fit in any prospective spots.  If when I want to leave, and someone took the liberty of parking directly behind my car, I'm on my own.  The cloud is probably more like a private parking lot where I need to pay to park.  The difference is that I get at least some guidance on where I can take my car once I've entered.  I can feel relatively at ease that nobody blocking me in.

Support for any software system is essential.  Guaranteed support is essential in some circumstances — as is the case with critical service where downtime and other disasters means losing money to the customer.  The trouble with SLAs, for any given software system, is that they're imaginary.  They say they'll give your software 99% up-time, for example.  If that requirement isn't met, the customer is compensated some how.  But how do you measure lost business opportunity as a result of this SLA violation?  How are you compensated for that?

Obviously it's much safer to put your system, the critical lifeblood of your business, in a place where these types of events simply do not happen.  Operating your application within a cloud service provider definitely helps your chances of survival. Staying responsive, replicating applications and data so they're always available — this is where cloud infrastructures shine.  By their vary nature, everything inside the cloud environment is virtual and transient — they can be shuffled around physical hardware effortlessly.

But just like any other service out there, clouds are susceptible to real disasters. The worst possible scenario is highly unlikely but the end result of it happening are extremely risky.  Remember though, however unlikely for something bad to happen, you're always better off decreasing those odds. An enticing SLA policy might be providers staying open to one another.

Gardens Ajar
There has been much talk lately about walled gardens and how they're harmful. Not just from a vendor lock-in perspective, but it's also bad for the very nature of the web.  Without the freedom to move your data around freely, you're stuck where you are — for better or for worse.  A similar problem presents itself in the cloud domain — sure, it's possible to move your data around from one infrastructure to the next.  But how feasible is it?  Just because there are no hard limitations, such as capabilities or legal ramifications, doesn't mean it's possible for the customer.

Even if it were an easy feat — taking your virtual infrastructure from one provider to the next — practicality dictates that you're better off finding a quality provider and giving them your business.  After all, you're not going to continually shop around for the best local place to eat.  Once you've found something decent, you stick with it.

Unfortunately, this isn't food we're talking about here — it's a lot more complex.  A lot more unpredictable.  Even your favorite restaurant is going to have an off day here or there, but they're your favorite because they're consistently good.  An overdone piece of meat isn't the end of the world.  But we're talking about systems that need better results than that.  Possibly better than any one provider can offer. So is the solution to distribute your infrastructure across multiple providers?  I think so.  I also think this plays a part in the SLA of any given cloud service.

Customers use the cloud because they want to be agile — a mindset of those that care deeply about the availability of their systems.  Part of being agile means having the ability to adapt when the situation calls for it.  So is it up to the service provider to dictate how the customer is able to respond in the face of adversity?  If the provider cannot, it's up to them to accommodate for migrating elsewhere.  Not just as an afterthought, but as a coherent set of APIs that are of practical value and can be utilized on a day-to-day basis.  The best cloud SLA is promising your customers to be open, to give them the freedom they require to operate in true cloud fashion.

Thursday, January 5, 2012

Network Protocol Methods

Computer systems need to communicate with one another.  One computer sends data to another, assuming the other is listening.  Down at the wire, the medium over which network information travels, communications are nothing more than electrons or photons.  At this level, the protocol is governed by the laws of physics. The mechanics of how the information is physically transported from point A to point B isn't relevant from the software perspective.  My system has data it wants to deliver to a remote region of the world.  As far as my software is concerned, the hardware could relay it via horseback.  It might take a year, but it would get there.

Of course, only the fastest delivery of information over networks will satisfy the demands of today's information-hungry applications.  There is so much information to absorb, it could not possibly fit in an isolated environment.  Information moves so fast that the only practical means of staying current is to continuously synchronize with other computers that have newer information.  In this regard, the barrier between stored information and information elicited from foreign sources has been permanently blurred.

How did we get to where we are today, and are we doing it effectively?  Big data is only big because software systems are decoupled, conjoined by cables and airwaves.  Big data translates into big connectivity.  Big connectivity can only mean that software systems that talk to one another also understand one another. There is an agreed-upon protocol that computer systems use to pack and unpack transmitted data.  But there is more to network protocols than how to extract information from data.  The web works the way it does because the protocol has application-level constructs that influence behavior.  What can we expect to see with future network protocols?  Will current protocols evolve into something that can support the ever growing vastness of our connectivity?

Sending and Receiving
Data doesn't traverse over a network spontaneously.  Applications instruct the data, influencing where it goes, how to get there, and what form to assume during it's journey.  These properties of network traffic are controlled through network methods.  A method pertaining to a network is something that an application uses to send and receive data.  Developers have a choice — we can get down to low-level socket details, specifying properties on individual network packets, or we can use higher level protocol methods that are more reflective of the architecture used at the application level.

Before we delve into the stuff applications use to make networks comprehensible from a development perspective, maybe it'll help us to think a little more about why additional semantics are necessary.  That is, we can't we simply use send and receive methods to exchange our data?

On the one hand, send and receive are simple — straightforward.  A handful of properties can tweak how our data is transferred and accepted on the remote end. Contrast this with a dozen methods to choose from, each with their own properties — a matrix of complexity emerges.  Conceptually, two methods means there are relatively few abstractions in the protocol to concern ourselves with.  We've got senders, receivers.  We've got packets, and routes.  We've got destinations and sources.  What this amounts to is point A and point B — with a few added details underneath.

The fact that we're able to use these seemingly low-level methods to control the flow of information over a network is due to even lower-level networking ideas. These ideas go beyond the IP layer of any network protocol stack.  Things that are handled by the operating system in the link layer, take care of a tangled mess for us.  If not for the operating system providing us with abstractions to overcome challenges associated with hardware compatibility, just imagine what the networking code for any application would look like.  So with the lowest-level network protocol details out of the way, the operating system has provided us with two basic methods, at the most fundamental conceptual level.

These two basic methods give applications everything they need to establish a connection and to communicate with remote entities — with meager networking code inside the application.  The challenge introduced by having simplistic network protocol methods is in the data itself.  It's easy to send and receive data.  It's difficult to make sense of that data.

Application Protocols
With the amount of data that needs to be transferred between modern applications over modern networks, the simplistic send and receive methods simply do not suffice.  Even smaller applications that aren't of any significant size in terms of complex features struggle to make sense of the data they're exchanging.  This is simply due to the complexity of the data, and the diversity of it.  Chances are, any given application you're using communicates with another service.  The two parties need to understand one another, the receiver needs to know how to unpack the data upon arrival.  This works well at the operating system level — we can send and receive raw data with ease.  But in the context of an application, there needs to be an agreed-upon format — a standard — before it becomes information.

This is why standardized data formats exist — to make communicating over a network easier for applications.  If two applications want to talk to one another, they might decide to use XML as the exchange format.  This way the sender knows how to pack the data and the receiver knows how to unpack and use that data.  The idea of standardized formats definitely makes life in a network much easier for developers in organizations extrinsic to one another.  One service makes interesting data available, in a particular format, perhaps even a selection of formats.  External entities can then consume that data, knowing how to read it, how to transform that data into information of value.

Standardized formats that applications send over the wire are of a different nature than that of the network method.  The data and it's assumed form is the what of the larger network picture.  The methods are the how.  Part of the problem we're seeing with the ever growing complexity of network-enabled applications is that the how isn't exactly clear-cut.  Why is this data being sent?  How should I respond to it? With standardized formats in place, it's easy to embed these types of semantics in the messages.  But it's difficult to sustain this approach on an Internet scale.

This is where HTTP comes in handy.  It's a protocol web applications and clients can use and readily understand without trying to stuff in new behavior.  That is, HTTP already has a set of methods as part of the specification that allows unambiguous intent to be transferred with each request.  You can GET a resource, POST a new resource, PUT new information on an existing resource, and DELETE a resource.  Like the concept of sending and receiving methods, the HTTP methods are simple, there are only four of them (aside from HEAD and OPTIONS which aren't widely used if at all).  Also like send and receive, HTTP methods are utilitarian — they don't pertain to any one specific application domain.

How well does it work?  How much longer will HTTP be able to support the activities of the web given it's current capabilities?

The Future of Network Methods
What does the future hold for methods that make computer networks functional, and not just a jumbled mess of connected cables?  Is what we have good enough to take us into the next five or ten years?  Well, if we consider how fast the web is growing today, that means a whole lot of new resources that'll come into being. That's many URIs to which HTTP methods can be applied.  Does that mean that we'll finally see a weakness of the protocol exposed, that four methods for interacting with networks in fact wasn't enough to do everything we needed?

It's a difficult question to answer because much of the global network activity isn't necessarily web based.  Not every agent wired to a network is a web browser, and HTTP isn't the silver bullet.  For example, real-time publish-subscribe systems use different standards such as AMQP.  Here we have an entirely different set of protocol methods with their own unique advantages, constraints, and limitations. So which network communications protocol are you going to adopt for your application?  Is it even a choice of one or the other, and can you interchange between two or more sets of defined network methods?

In the fast approaching future, the trouble is going to be dealing with large amounts of data, compounded by the large volume of network activity triggered by the growing online population.  We're shown examples of successful implementations that can handle anything thrown at them.  So you would think that we're safe with everything we have in place, right?  Well, that may not be the case, as we thought we had enough IPV4 addresses ten years ago.  So whats wrong with the current implementations?  If we can just hire the right people who've got the experience in constructing these hugely resilient infrastructures that can survive the apocalypse with minimal downtime, we don't have much to worry about.

Well, not everyone in IT is a rocket surgeon capable of cranking out enterprise-grade networked application suites while blindfolded.  We still need to strive for simplicity in the wake of an ever growing number of variables.  The small number of methods bundled with the HTTP protocol is why it's been such a success.  It's a small improvement over the send and receive methods, small enough to remain lucid yet powerful enough to transfer application operations over a network.

The real danger, I think, is in how some of the more powerful network protocols have a tendency to be misused.  HTTP is a good example, probably because it is so widely used, it is also widely misused.  For instance, sending POST requests to update existing resources, or deleting resources through means other than DELETE requests.  If enough applications continue to evolve in this manor, a lot of the value with HTTP is lost because different applications are inventing their own protocols on top of another.  We're simply inventing methods when they should be part of a standard, such was the case when we decided to improve on the send and receive methods by using a standardized format.  In reality, that's all there is to HTTP, and many other protocols — added data in the transferred network data. But we need to abide by the standards because deviations will only proliferate as the web evolves into something much too large to handle all these broken down contracts of communication.

The end result of such a breakdown?  The networks will always be there because we have such a firm grip on the low-level fundamentals that no developer need touch them.  Will the networks of the future, the web in particular, be all that it can be?  Will it provide the best possible service to all it's inhabitants under an array of circumstances?  It doesn't do that now.  I think it has potential to, but it'll take better cooperation between those who build the most flourishing systems on the web.  To standardize would be simply fantastic, because we could sit down and objectively measure how well our computer networks measure up with the protocols we have in place at the application level.  Maybe they don't.  But the solution isn't to invent on top of existing standards.  Let's make HTTP work the way it's supposed to.  Maybe then we'll see if the methods we have will do just fine in ten years from now.

Sunday, December 18, 2011

Cloud Controllers

The cloud is all about making new resources available to computing consumers. Not hardware consumers, but processing, memory, and storage consumers.  This distinction, I think, is sometimes overlooked by those of us in the industry.  These resources, ultimately, belong to the application — the customer doing the provisioning doesn't necessarily care about these things.  In the end, their job is to make sure the software they're administering runs effectively.

The availability of physical hardware, or in the cloud's case, virtual hardware, is how we're able to achieve optimal usage of deployed software systems.  Of course, as a consumer, I want to give my application everything it needs to perform.  Not just at the barely acceptable level, but at the screaming fast level.

If I'm to get any of these things from a cloud service, I've got to make sure that the resources my application needs are there ahead of time.  So maybe I'll be proactive and give it more memory than it actually needs?  The issue is that I'm looking at the application from outside of the box.  I can peek my head inside to get a general idea of what's happening and how I can improve the situation.  But I get nothing more than a general idea.  The question is, how can I really know what the application is expecting based on current conditions?  What does it need?  And can I automate this process without writing any code?  Maybe, but I think we need to step back and look at cloud services and what they offer to the applications, not just the users who're initiating the environment.

The User Focus
Cloud infrastructure services have friendly control panels for customers.  Control panels, at least in the context of a cloud environment, should hide some of the ugliness involved with provisioning new resources.  A customer sees a limited set of choices in how they can deploy their application — select from a list of different memory profiles.  Select your required bandwidth.  How much storage will you need?  A form not all that different from something typical of any web application we're used to.

The end result of this process?  The application is deployed — with the hardware it needs.  All the work involved with finding the right physical node in which to place this new virtual machine takes place under the covers.

As with any application, this is a sound principle — take a complex task such as provisioning new virtual machine resources and encapsulate the complexity behind a user interface.  This is what successful applications do well — they're successful because they're easy to use.  There is one broad category of user and we're catering to them — to making life easier in how they interact with the cloud.

The problem that I see, or oversight anyway, with this approach is one of priority. When we're designing software systems, one of the first activities is identifying who'll be using the system.  So who uses cloud service providers?  Well, folks who want to provision new applications without the overhead involved with allocating physical hardware to fit their needs.  An opportunity I see with cloud is automation. Not just a simplified interface for system administrators, but a means for deployed applications to start making decisions on what needs to happen in order to perform optimally.

The Application Focus
Some environmental changes that take places are obvious — like the number of registered users jumping from one hundred thousand to five.  These changes are somewhat straightforward to handle by the administrator — they're not exactly critical to how the service will respond to demand over the next few hours.  This type of environmental change takes place over larger amounts of time — a duration suitable for humans to step in a relieve the situation.  If we're seeing a growth trend in terms of registered users, maybe we'd be smart to assume that we'll need a more robust collection of hardware in the near term.

Now, what about when the timeline of these events — the inclining demand of our application's availability — is compressed into something much smaller, like under an hour for example.  If all available resources our applications has to store, compute, and transfer aren't enough to handle the current state of usage, than we'll see a change in behavior.  Sorry, the users will see a change.  But, thankfully, advanced monitoring tools we deploy to the cloud beside our applications can easily tell us when the application is experiencing trouble and the cloud needs to send more virtual hardware to the rescue.

Even if this isn't an automated procedure, it's still something trivial for the application's monitoring utilities to notify the administrator to go and provision another instance of the application server to cope with the request spike.  In this scenario, there may only be a limited window in which users experience unacceptably poor response times.  But this is often automated too — it doesn't take a system administrator to determine that there aren't enough available resources to fulfill the application's requirements based on current situations.

Google App Engine is a good example of how something like this is automated. Each application deployed to app engine has what are called serving instances. These are the decoupled application instances of the application that doesn't share state with other services.  As the load increases, so do the number of serving instances to help cope with the peak.  Just as importantly, as the peak slowly winds down and the pattern of user behavior returns to normal, app engine kills off superfluous serving instances that aren't necessary.

There are many ways to automate application components to help cope with what users are doing — to prevent one user from sucking available CPU cycles away from others.  Provisioning new instances of the serving instance within the cloud environment for example.  But, does this really take into account what the application is really doing and what's likely to change in the eminent future?  To do that, code inside the application needs to take samples of internal state and propagate these changes outward — toward the outer shell of the application — perhaps even into the cloud operating environment in some circumstances.

The trouble isn't that it's not possible to take into account the inner workings of our applications — it's that it isn't a high-priority for cloud service providers.  It's easy to alter applications deployed to the cloud — to take measurements and make them available to other services that could potentially react to those measurements.  The trouble is, there is simply too much code to write — too much of the burden is put on the customer and not the service provider to offer APIs that can help applications operate effectively in the cloud.