tag:blogger.com,1999:blog-64630442497074689932025-12-12T15:29:23.784-08:00Experiments in publicAlec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-6463044249707468993.post-11196366335031162722021-02-23T12:36:00.000-08:002021-02-23T12:36:12.990-08:00The twist on the experiment<h2 style="text-align: left;"><span style="font-family: helvetica;">Preface</span></h2><p><span style="font-family: helvetica;">Having resurrected this blog for the purpose of helping find myself a job (again), some things are going to be different.</span></p><p><span style="font-family: helvetica;">The principle thing is a switch in focus, less on the technical and more on the people side, corresponding with how my career has evolved over the past decade. I probably will still dig into some technical topics, both out of interest and because it's easier to find opportunities to solve technical problems in the wilds of the internet, but it's important I also demonstrate, as best as I am able, that I have some understanding of organizational dynamics and human issues.</span></p><p><span style="font-family: helvetica;">The secondary thing that's different is nearly a consequence of the first thing. In short, I will try to use this space to promote the efforts of those less well-represented in tech than myself. I will still surely include some of my own opinions, but my experience is that my opinion is much less likely to provide unique value than that of, say, a black woman.</span></p><p><span style="font-family: helvetica;">Compared to the last 5-7 years, where in general I've sought to avoid injecting myself into discussions, I am going to use this space to highlight and discuss relevant events. Again, where I can I will populate those discussions by including quotes from and links to others thoughts on the subjects, but when I believe I can provide value by collating and commenting on these subjects, I will.</span></p><p><span style="font-family: helvetica;">I will be writing about:</span></p><h2 style="text-align: left;"><span style="font-family: helvetica;">People - Process - Product</span></h2><p style="text-align: left;"><span style="font-family: helvetica;">When I was working on my resume recently, I shrunk it down about 75%, and I wanted a pithy way to convey where my priorities were at this point. Both to put it out into the world, as an expression of what I was looking for, but also because it represented a clear shift in how I approached "work" over the past decade. While process has always been a significant part of the work I do in the tech world, it's generally been in service of the delivery of a particular product. Yes, I spent plenty of time optimizing processes for people, but that wasn't where the focus was. So a big part of resurrecting this blog is also about representing that shift to a focus on people.</span></p><h3 style="text-align: left;"><span style="font-family: helvetica;">People</span></h3><p><span style="font-family: helvetica;">Writing about people here is likely to be the most difficult, in some ways. I don't think there's a bug tracker for people problems, where I could just volunteer to try to help them, then write about it. But one of the ways that I think I can incorporate writing about people into my efforts here is through the relatively introspective manner that I tend to approach problems. That is, through documented analysis of my own process and behaviour in approaching problems, I can demonstrate at least some personal understanding of the dynamics involved.</span></p><p><span style="font-family: helvetica;">Besides that, I will write about patterns and individual instances of workplace people problems that I encounter, primarily on Twitter. I will do my best to gather evidence demonstrating the harms that are occurring, and highlighting opportunities to mitigate those harms. I expect to lean heavily on the work of others here, and if I allow the focus of this type of writing to be on me, please call me out on it. That said, I will incorporate examples and stories from my own experience, as appropriate.</span></p><h3 style="text-align: left;"><span style="font-family: helvetica;">Process</span></h3><p style="text-align: left;"><span style="font-family: helvetica;">Writing about process is something I generally enjoy, and while I'm used to doing that in a professional setting where I have long-term plans for the processes in question, I don't think I'll have a problem finding many, many relevant opportunities when writing about people or products.</span></p><h3 style="text-align: left;"><span style="font-family: helvetica;">Product</span></h3><p><span style="font-family: helvetica;">While definitely the lesser focus overall in how I'm approaching work, I will demonstrate delivery of high quality products throughout here. Both in the written work, and any accompanying projects, completeness and correctness will be held to a high standard. </span></p><p><span style="font-family: helvetica;"><br /></span></p><h2 style="text-align: left;"><span style="font-family: helvetica;">Enhancing Google Keep</span></h2><div><span style="font-family: helvetica;">To that end, my first project here is going to be building an opinionated task management tool on top of Google Keep. It will allow me to write about many of the topics relevant to the kind of work I'm seeking, while also scratching a very old itch for me. :)</span></div>Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-86895593592938930102021-02-22T12:18:00.003-08:002021-02-23T10:21:09.518-08:00The Automator's Manifesto, Part TwoThis was written quite a while ago, but I never got around to publishing it. So here you go!<br /><br />Proactive Transparency<br />
<br />
One of the most important things any automator can do is provide confidence to stakeholders in the project. Confidence can only develop if stakeholders understand the project, and see meaningful improvement. As such, it behooves the automator to make it easy to understand the state of the project. This is particularly relevant when it comes to actual test results, as even successful results that have no audience are essentially useless.<br />
<br />
The term I came up with for this aspect of an automators role is "proactive transparency", based on the idea that it's not enough to simply run tests and call it a day. It's a good start, but publishing the results of those tests in a way so as to maximize their audience is where real value starts to develop.<div><br />
<br />
Entropy Factors<br />
<br />
The most challenging automation task of my career came at Research in Motion, where I put together a device lab to test over the air OS software updates (RIM was actually the first to have this available, as I understand). This was a hugely complex endeavour, covering a range of devices with different capabilities, moving between OS versions that could vary greatly. But even more significant to our testing were the externalities we were dependent on.<br />
<br />
For instance, knowing what builds were available for updating required manual scraping of a development version of an application maintained by a different team, with no formal connection. This application, in turn, was loosely connected to the servers which devices would contact to identify what updates might apply to them. We frequently encountered issues where a test was queued, but when the device navigated to the update screen, the desired build wasn't found.<br />
<br />
These, and many others, came to be known as our "entropy factors". I'm probably misusing entropy, but here the phrase means things outside of your control that could impact the results of your tests. Understanding what these are for a given automation project is one of the most important planning exercises you can do.<br />
<br />
<br />
Measuring Everything<br />
<br />
At my first GTAC, Patrick Copeland said "measure everything" (he probably said "at Google we measure everything", but that wasn't what I wrote down.) This was an inspiring credo for a then new-to-the-field automator, and I spent many years trying to live up to it. But it's wrong, or at least deceptive.<br />
<br />
Assuming you have the resources to make it possible, measuring everything is still going to require implementation time. But what is much more important is that it is going to increase the scale of measuring output, while doing nothing to identify which metrics mean success. It might feel great to have every system metric, API call, user session and what-have-you carefully collected, but it does nothing on it's own to make your project better. That's an oversimplification, as having this all can increase stakeholder confidence initially, but after a couple of scares, that will fade.</div><div><br /></div><div>You need to commit to measurements that correspond to your desired outcomes for the automation project. That doesn't mean you shouldn't collect a ton of other metrics if your tooling can do it for free, but you shouldn't surface them by default. Keep clear what you are measuring and why, and add cases to that as you grow.<br />
<br /></div>Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-69835323955585546502021-02-22T04:59:00.002-08:002021-02-22T08:18:10.156-08:00Renewing the Experiment<p> I started this blog about a decade ago to help me find work.</p><p>Once I found work, it began to atrophy rather quickly.</p><p>Now, I need to find work again. :)<br /><br />So here's a placeholder, saying that this blog is coming back to life. I've got a handful of unpublished drafts from the past several years that I may polish and publish, and I'll write about my job search otherwise.</p>Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-75041952626779933492017-03-12T18:01:00.001-07:002017-03-12T18:11:41.219-07:00My fling with iOS, or "I like my gardens unwalled"Somewhat of a digression from the usual content of this blog (either programming or nothing), and ground that has been well-trod in many other places. But here I am, writing it anyway.<br />
<br />
<h3>
TL;DR</h3>
<br />
I switched to an iPhone 7 2 months ago. It was really cool, but I don't like it and am switching back.<br />
<br />
<h3>
Origin</h3>
<br />
I've never owned an iPhone. My wife has had a 4, 5, 6, and 7, and other family members have had many others.<br />
<br />
I worked at BlackBerry back when it was called Research in Motion, starting in 2008, around the launch of the Bold 9000. Before then, I didn't even own a cellphone (I had an awesome Sanyo in 2001, but it broke and I never replaced it).<br />
<br />
While at RIM I changed phones every 6 months or so. Luckily, I got to more or less avoid the Storm and follow-ups (though I was responsible for implementing touch support in our test automation framework), so I got very used to the BlackBerry keyboards. I still think the keyboard in the original Bold is a work of art.<br />
<br />
From when RIM and I parted ways in 2011 until the end of last year, I used almost entirely Androids, except for a while where I enjoyed the LG Quantum on Windows. I actually really liked that phone, and Windows there worked really well. Like the commercials emphasized, you could very quickly get things done and put your phone back down. Part of this was because there was no reason to keep looking at your phone, because it couldn't do much more than essential communication functions, but at the time I found that simplicity quite charming.<br />
<br />
But Android...<br />
<br />
Well, my first experience with Android was a week with the Galaxy Nexus. It was pretty cool at the time, but I returned it due to the expense.<br />
<br />
But when the Nexus 4 came-a-callin, I was smitten. It was a beautiful piece of hardware that ran all kinds of cool things, did very little to get in my way, and cost half of what my wife's phone did. Sure, the camera was mostly crap and the battery wasn't great, but I loved that thing.<br />
<br />
The Nexus 4 was followed by the Moto X. I picked mine up on Kijiji, and loved the active display and passable camera.<br />
<br />
I followed the Moto X with the Droid Turbo, which was nearly a perfect phone. Swiping my hand over to check notifications is still one of my favourite phone interactions, and the battery would go two days before needing a charge (which only took 90 minutes anyway). The camera, despite the resolution, was bad most of the time, and as a Verizon exclusive that I exported to Canada, I had to put up with useless apps and slooooow updates. Still, it lasted me nearly two years before the screen got damaged (which was supposed to be under warranty, but Verizon and Moto figured they could get away with screwing a Canadian).<br />
<br />
<br />
Which brings me to my last (and near future) Android, the LG G4. Battery life was a big let down from the Droid, but the camera was very good, and it had some other neat features. I cracked the screen on it in 3 months. I ordered a replacement screen, but while I was waiting for it to arrive, an opportunity to go iPhone arose.<br />
<h3>
<br />The iPhone</h3>
<br />
For all that my phones have rarely been top-of-the-line, I read multiple reviews of every flagship, and the pace at which Apple has pushed forward their CPU was amazing. With the 6S I was tempted to jump ship just for that reason, and seeing how far they pushed it further in the 7 made it impossible to resist.<br />
<br />
The iPhone 7 is the most attractive piece of hardware to touch, ever. The weight is perfect, it's sleek, and it responds to you in a very physical way.<br />
<br />
It is blazing fast at practically everything, and the screen is second-to-none.<br />
<br />
The camera is super-fast, and generally very good, though I would argue it trades blows with the G4 in some areas.<br />
<br />
Force touch is cool, and makes some things nicer to do.<br />
<br />
I like being able to ask Siri to time things for me. Very cool.<br />
<br />
I get through a day with 40% left on the battery, easily. But that's not the whole story...<br />
<br />
My wife can't get through the day without having to recharge, with the same phone. Because she uses it for Facebook. I generally don't use mine for anything like that. In fact, I use my iPhone the way I used my Windows Phone. When I need it, it's there, and then I put it away.<br />
<br />
But it's the only piece of Apple in my ecosystem, and that means a lot of the things I want to do are just a little bit inconvenient, so I don't do them. My life is on Google's cloud, and my work is on Microsoft's. These things are available in a pinch from my iPhone, but my Surface is substantially better for either of them, and not that much harder to tote around.<br />
<br />
Specific examples of annoying things:<br />
- I must use a case, because it's $$$, which detracts substantially from the aesthetic appeal. I've never used a case before<br />
- Google maps navigation cuts out over bluetooth<br />
- Notifications are among the worst on any phone I've ever had. Better since I disabled the volume switches affecting them, but some apps just fail to notify me consistently (might be on the apps, but they worked fine on Android)<br />
- I've got relatively large hands, and I cannot seem to get comfortable with the keyboard. Some of this might be the case, some might be that I've developed a preference for Swype, who knows.<br />
- Siri is really dumb. I don't know if it's somehow related to my lack of Apple ecosystem, but other than timing things or prank questions, I've given up talking to her<br />
- No headphone jack is just stupid. Yes I have two dongles in the house, but mostly I just carry two sets of headphones now. Especially stupid if they're going to move to USB-C.<br />
- Chromecast (the only input to my TVs) control is inconsistent. Some apps I can change volume with buttons, others within the app, others I need to open Google Home to control volume. Probably an app issue, but not a problem I had before.<br />
- My fitbit stopped pairing with it, and one of my vehicles will only pair for a day or so before needing to removed, bluetooth toggled off and on, and re-added.<br />
- The UI on some of Apples apps is surprisingly bad. Sometimes when I change settings, I click "back" in the top left, other times I hit "save" in the top right. Some apps require you to do both these things to effect a change.<br />
<br />
<h3>
Summary</h3>
<br />
Subjectively, the feeling is that I need to do things Apple's way, and I'm not interested in that approach. So all that lovely power never gets called upon. A lot of my issues are little things, many of which there may be fixes for, but my experience is that unlike Android, there's not a lot you can do to fix these little things.<br />
<br />
So it's back to the G4 for me, with its fresh screen. I won't use a case, and I'll probably break it again. But it's not getting Nougat anyway, so maybe it will be time to trade up again by then. :)Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com1tag:blogger.com,1999:blog-6463044249707468993.post-49527544709036124842015-10-17T03:29:00.000-07:002015-10-17T03:29:31.024-07:00Software Gardening in practiceSoftware gardening, as expressed by <a href="http://www.artima.com/intv/gardenP.html" target="_blank">Hunt/Thomas</a>, <a href="http://www.codinghorror.com/blog/2008/11/tending-your-software-garden.html" target="_blank">Atwood</a>, <a href="http://www.chrisaitchison.com/2011/05/03/you-are-not-a-software-engineer/" target="_blank">etc</a> uses the metaphor to deal with how a software project is alive, and is constantly being changed by factors outside of the control of the developers. You can plant a seed, and water it, but you can’t control the sunlight, the bugs, bees, etc. As it grows, you can weed the garden, removing features that are not used but taking up resources, add fertilizer, change the plants to better reflect your needs (why didn’t someone tell me Joe was allergic to cucumbers!?).<br />
<br />
I want to expand on this idea, as I believe there are several valuable insights that can be derived from adopting this view. In this post I will explore this concept from three different perspectives: the project itself, a software developer, and a client that wants to get some software developed.<br />
<br />
<h3>
The Unseen Environment</h3>
As a particular software environment is like a garden, there are many factors that the garden grows out of. There are obvious factors, like the composition of the soil, and the likely availability of water, and sunlight. But there are also more subtle, “living” factors, that are going to be part of the environment of your garden, yet generally operate independently.<br />
<br />
One of the most fascinating things I’ve learned recently is the concept of <a href="http://en.wikipedia.org/wiki/Mycorrhizal_networks" target="_blank">mycorrhizal networks</a>. These are fungal layers that exist within the soil that serve to break down waste matter and distribute molecules that plants depend on for nutrition. It is generally unseen, but is a huge factor in the ability of plant ecosystems to thrive. Generally much better known, but still somewhat unseen, are the pollinators. Birds, bees, and butterflies allow plants to reproduce, and thus stimulate genetic diversity.<br />
<br />
So, above and below, there is an environment that allows plant life to thrive. A similar role is played in software development by the ecosystem that exists <b>around</b> both the software, and the developers.<br />
All developers and software libraries come to a project with a history that is shaped through the absorption of “byproducts” from previous projects. These can take the form of learned code snippets, software structure conventions, and many other things. I would liken this to the way the mycorrhizal network digests the output from various past biological processes and produces raw nutrients to begin new ones.<br />
<br />
In a similar way, open/shared source cultures could be compared to pollinators. Moving from project to project with very few barriers, a developer can distribute efficient techniques rapidly, effecting the projects and other developers. This has resulted in the establishment of numerous best practices, to the point where high-profile open source projects are the gold standards for software quality. Another interesting way in which open source diversity is like genetic diversity is in the trend of multiple competing software projects springing up with different attributes tailored to their environments. These can continue for very long periods, sharing “genes” with each other but still continuing as distinct “species”.<br />
<br />
In some large organizations, the software ecosystem is distinct enough to effect the software that is produced there, but at this point, almost everyone is dependent on Open Source. It produces specific codebases that underly most every modern project, such as Linux, Apache, OpenSSL, GCC, Boost, Python, etc. But it also establishes the best practices and standards for software development that are used by individual developers, whatever they are working on. Conversely, bug reports come from commercial projects that make Open Source stronger, and developer experiences there continue to inform and refine the state of the art. There are also cases where it is beneficial for commercial development to open source certain pieces of their software, to expose them to that wider diversity, and encourage contributions that will help meet business goals (though like natural evolution, predicting the future of an open source project is far from a science).<br />
<br />
Tying that back together, that means that for a developer, every project you work on contributes to this larger community, even when the code itself is closed. Because it changes you, and it changes the conversations you have with others, and how you work to solve problems in the future. As a former user of the Zope Web Application Server, I have watched other users and contributors define the cutting edge of web software (<a href="https://github.com/tarekziade" target="_blank">Tarek Ziade</a>, <a href="https://github.com/mcdonc" target="_blank">Chris McDonough</a>, <a href="https://github.com/alex" target="_blank">Alex Gaynor</a>, and <a href="https://github.com/faassen" target="_blank">Martijn Faasen</a>, among <a href="http://www.python.org/~guido/" target="_blank">others</a>).<br />
<br />
<h3>
Garden Development as a Service</h3>
As someone who works on software, your value is not the creation and delivery of a product, but rather the cultivation of an environment. Even when you are employed delivering products, there’s no such thing as a final release, just something that is able to meet the needs of the moment. Needs will change, the ecosystem will change, you will change, and new opportunities will arise. How might this change how you approach a single project, and your career?<br />
<br />
In terms of approaching a particular project, it means you need to understand the landscape in order to effectively execute on the vision. You need to know what kind of software is already there, and what the state of third party libraries are in that particular domain. You need to plan for the inevitable bugs and maintenance. The actual implementation flows out of these concerns, not the other way around.<br />
<br />
From a career standpoint, I should first confess that, well, I’m not a gardener. However the image I have of them is that they don’t get annoyed that all the cool gardens are already cultivated. As long as you have a willingness to work, gardens are going to need cultivation. Likewise, as long as you have a willingness to develop it, there will always be available work developing software. Under this philosophy, nothing ever reaches the point that it cannot be improved or does not require maintenance.<br />
<br />
<h3>
Gardening Agency</h3>
When we have a need for some software, and we attempt to consider the effort that will be required, we usually think about the features that we want the software to have. The gardening metaphor suggests this is a very limited way to view this. If we think of the features of a particular garden as “has Roses and Violets, and produces Tomatoes”, we can quickly understand that a good deal more information is required to get a reasonable estimate of the effort that will be necessary.<br />
<br />
Is the garden in Hawaii, Alaska, or the Central Park Zoo? What if there’s already a garden there? What's the condition of the soil, or local animal life?<br />
<br />
Translating these questions over to software, we can see that the environment a piece of software needs to "live" in can impact the effort required to develop it as much or more than the features it needs to have. For instance, if you are looking to add accounting features for exporting financial data to your partners, the effort could vary tremendously depending on the existence and maturity of the open source software that exists to work with data in the formats they use.<br />
<br />
Just as working with a professional landscaper will produce dramatically different results than simply purchasing plants, establishing a relationship with someone who can look at your situation holistically is key to a successful software project. They know the questions that need to be asked, the process for finding the answers, and they know how to build out a development team that will take that reality into account.Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com5tag:blogger.com,1999:blog-6463044249707468993.post-37354687259570060992014-08-29T16:31:00.000-07:002014-08-29T16:31:49.895-07:00It's yer data! - how Google secured its future, and everyone else'sDear Google,<br />
<br />
This is a love letter and a call to action.<br />
<br />
I believe we stand at a place where there is a unique opportunity in managing personal data.<br />
<br />
There is a limited range of data types in the universe, and practically speaking, the vast majority of software works with a particularly tiny fraction of them.<br />
<br />
People, for example. We know things about them.<br />
<br />
Names, pictures of, people known, statements made, etc.<br />
<br />
Tons of web applications conceive of these objects. Maybe not all, but probably most have some crossover. For many of the most trafficked apps, this personal data represents a very central currency. But unfortunately, up until now we've more or less been content with each app having it's own currency, that is not recognized elsewhere.<br />
<br />
You can change that. You can establish a central, independent bank of data, owned by users and lent to applications in exchange for functionality. The format of the data itself will be defined and evolved by an independent agency of some sort.<br />
<br />
There are two core things this will accomplish.<br />
<br />
1) It will open up a whole new world of application development free from ties to you, Facebook, Twitter, etc.<br />
<br />
2) It will give people back ownership of their data. They will be able to establish and evolve an online identity that carries forward as they change what applications they use.<br />
<br />
Both of these have a dramatic impact on Google, as they allow you to do what you do best, building applications that work with large datasets, while at the same time freeing from you concerns that you are monopolizing people's data.<br />
<br />
<h3>A new application world</h3>When developing a new application, you start with an idea, and then you spend a lot of time defining a data model and the logic required to implement that idea on that data model. If you have any success with your application, you will need to invest further in your data model, fleshing it out, and implementing search, caching, and other optimizations.<br />
<br />
In this new world, all you would do is include a library and point it at an existing data model. For the small fraction of data that was unique to your application, you could extend the existing model. For example:<br />
<pre>from new_world import Model, Field
BaseUser = Model("https://new_world.org/users/1.0")
class OurUser(BaseUser):
our_field = Field("our_field", type=String)
</pre><br />
That's it. No persistence (though you could set args somewhere to define how to synchronize), no search, no caching. Now you can get to actually building what makes your application great.<br />
<br />
Conceivably, you can do it all in Javascript, other than identifying the application uniquely to the data store.<br />
<br />
And you can be guaranteed data interoperability with Facebook, Google, etc. So if you make a photo editing app, you can edit photos uploaded with any of those, and they can display the photos that are edited.<br />
<br />
<h3>Securing our future</h3>People have good reason to be suspicious of Google, Facebook, or any other organization that is able to derive value through the "ownership" of their data. Regardless of the intent of the organization today, history has shown that profit is a very powerful motivator for bad behaviour, and these caches of personal data represent a store of potential profit that we all expect will at some point prove too tempting to avoid abusing.<br />
<br />
Providing explicit ownership and license of said data via a third-party won't take away the temptation to abuse the data, but will make it more difficult in a number of ways:<br />
<br />
<ul><li>Clear ownership will make unfair use claims much more cut-and-dried</li>
<li>A common data format will make it much easier to abandon rogue applications</li>
<li>Reduced application development overhead will increase the competitive pressure, lowering the chance of a single application monopolizing a market and needing to grow through exploitation of its users data</li>
</ul><h3>A gooder, more-productive, Google</h3>By putting people's data back in their hands, and merely borrowing it from them for specific applications, the opportunities for evil are dramatically reduced.<br />
<br />
But what I think is even more compelling for Google here is that it will make you more productive. Internally, I believe you already operate similar to how I've described here, but you constantly bump up against limitations imposed by trying not to be evil. Without having to worry about the perceptions of how you are using people's data, what could you accomplish?<br />
<br />
<h3>Conclusion</h3>Google wants to do no evil. Facebook is perhaps less explicit, but from what I know of its culture, I believe it aspires to be competent enough that there's no need to exploit users data. The future will bring new leadership and changes in culture to both companies, but if they act soon, they can secure their moral aspirations and provide a great gift to the world.<br />
<br />
(Interesting aside, Amazon's recently announced Cognito appears to be in some ways a relative of this idea, at least as a developer looking to build things. <a href="http://aws.amazon.com/cognito/">Check it out</a>.)Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com1tag:blogger.com,1999:blog-6463044249707468993.post-9909000780246262242014-04-24T07:43:00.000-07:002014-04-24T07:43:00.647-07:00PyCon 2014I've now been back from PyCon for a week, and I've got some thoughts to share.<br />
<br />
<h3>
Scope</h3>
It was huge.<br /><br />I usually try to memorize everyone's names, and I have some habits that help me with that. But there were so many people, I think that may have fallen apart. :)<br /><br />A lot of hero worship, as I met, or at least observed from a distance, many people who helped shape my views on software <a class="g-profile" href="https://plus.google.com/108647550086762894581" target="_blank">(+Tres Seaver</a> in particular). <br />
<br />
Conversely, I managed to avoid running into those attending from my employers (I'm looking at you, <a class="g-profile" href="https://plus.google.com/103147017122717028284" target="_blank">+Kenneth Reitz</a>, Sandy Walsh, and probably someone from RIM/BlackBerry).<br />
<br />
<h3>
Diversity</h3>
All the promotion of the diversity was terrific. At the same time that it's great to be part of a movement that is markedly more female-friendly then the tech community at large, Jessica McKellar made it clear that we have so much farther to go. As the father of two girls, it's very important to me that we change the culture around technology to emphasize that there's no particular skillset or aptitude that's required for entry.<br />
<br />
Software is our world, and we can empower EVERYONE to play a part in shaping it.<br />
<br />
<h3>
Content Overview</h3>
I enjoyed the talks that I went to, but I did skip more than I was intending to. I had trouble letting go of work, and there was a lot of content that was relatively beginner focused, or represented tutorials that I knew had high-quality online counterparts, should I need them. I feel like this was a deficiency of my own, and one I hope I handle better if I come back next year.<br />
<br />
<h3>
Meta programming</h3>
I've been flirting with creating my own language for a while now, and if I were to do so, it would probably be on top of Python. Thanks to talks by <a class="g-profile" href="https://plus.google.com/102811351942608564358" target="_blank">+Allison Kaptur</a> and <a class="g-profile" href="https://plus.google.com/105972614387206099837" target="_blank">+Paul Tagliamonte</a>, I feel much more prepared to do so.<br />
<br />
Allison provided a brilliant guide to implementing the import mechanism from scratch. Having read <a class="g-profile" href="https://plus.google.com/115362263245161504841" target="_blank">+Brett Cannon</a>'s blog when he created importlib, I knew there was a huge amount of work that went into getting it right, so it was an intimidating area. Yet in 20 minutes Allison walked us through getting something functional.<br />
<br />
Paul's talk on Hy was not quite so accessible, but perhaps even more inspiring. The relative ease with which Hy and Python can co-exist within the same project is just awesome, though mucking around with ASTs remains a bit of a scary idea.<br />
<br />
<h3>
Sprints</h3>
While I was skipping talks, I consoled myself in the thought that I would really engage during the Sprints (I had a day and half scheduled for these). But I didn't, and while I think that had more to do with me (once again, I worked), I'll share what I think could have been done better, in case anyone else felt the same way.<br />
<br />
Technically Sprints started Sunday evening, but I get the feeling that no one was actually interested in running them Sunday evening (or maybe my timing was off). There were a handful of people there, but no clear organization or plan about what was to be worked on.<br />
<br />
Monday morning, it was certainly better attended, but it still wasn't inviting. There was a central chart of what rooms contained what projects, but within the rooms there was no indication of who was working on what. From my limited time being involved in or running other short coding sessions, I was also surprised not to see much use of flipcharts or whiteboards.<br />
<br />
I guess how I would do it, if I ran it next year (I'm not volunteering, yet), is provide signs for each project to put at their table, and encourage each of them to write out a list of goals for the sprint in a place where it can be publicly examined and crossed off. Perhaps also provide special shirts/hats/badges to the "leader" of each sprint. The experience I would like is for someone to be able to wander in, examine what each project is doing without actually bothering anybody, and then if they find something they think could fit them, to know who to ask.<br />
<br />
<h3>
Misc.</h3>
<ul>
<li><a href="http://www.ansible.com/home">Ansible</a> is what we're using at SFX, and while I've had some experience with it, I have a much more robust appreciation for it, thanks to <a class="g-profile" href="https://plus.google.com/101704241454464802713" target="_blank">+Michael DeHaan</a> </li>
<li><a href="https://pypi.python.org/pypi/peep">Peep</a> should be included in the standard library. Seriously.</li>
<li><a href="https://docs.python.org/3.4/library/asyncio.html">Asyncio</a> makes things most people do easier. Bravo!</li>
<li><a href="http://ipython.org/install.html">iPython Notebook</a> is cool, and <a class="g-profile" href="https://plus.google.com/109297632387313990923" target="_blank">+Catherine Devlin</a>s talk about executable documentation has me itching to try it out.</li>
</ul>
<br />
<h3>
Conclusion</h3>
As someone who has been around the block but doesn't find much time to actually code anymore, I may not be the code audience for PyCon. But I'm still delighted to have finally made it to one, and I'm really tempted to make it a family trip next year. Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-64955340076810507752013-10-11T19:19:00.001-07:002013-10-11T19:19:55.082-07:00Rethinking my excuses about hiring for Test Automation<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."</div>
<div style="text-align: right;">
--Brian Kernighan</div>
<div>
<br /></div>
<div>
For a long time, I've made the excuse that it's hard to hire QA Engineers, etc. because of stigma based on the desired career path going from testing to development, not the other way around. That may be part of it, but I'm beginning to realize that there might be something much more significant.</div>
<div>
<br /></div>
<div>
Being a good Automator is HARD. As <span style="text-align: right;">Kernighan</span> says, debugging is hard, and automation is all debugging.</div>
<div>
<br /></div>
<div>
Practically speaking, the act of debugging is the investigation of a behaviour to determine it's cause. You know the software does a thing, but you don't know why, and you need to figure out how to stop it (usually). So you run it in a controlled environment and try to get that behaviour to happen.</div>
<div>
<br /></div>
<div>
What Automators do, most of the time, is write software that interfaces with other software. Automation is it's own integration point, but generally speaking, it's a low-priority client, so you frequently have to exploit one or more other integration points in order to get the software to behave as desired for your automation. Usually, what you want the software to do is on the margins of what it was expected to do, so you do a lot of debugging to identify and simulate the conditions that might generate the desired behaviour.</div>
<div>
<br /></div>
<div>
Ok, so that's a lot of horn tooting, but I've met nearly a dozen good Automators, and without exception they are fantastic software developers. That's not to say there aren't other factors that drive people away from automation, but consider this a call to action for those who want to prove their mettle as software craftspeople. </div>
<div>
<br /></div>
<div>
Be an Automator, spend your days debugging everyone else's software, drive the art forward, and enjoy (in the long run) incredible job security!</div>
<div>
<br /></div>
<div>
As an aside, I think the headline quote is also what binds me to the Python community. The Zen of Python guides us to avoid "clever" solutions whenever possible, out of the shared recognizance that in the long run, software spends a lot more time being debugged than developed.</div>
Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-30682369437637952402013-08-21T06:50:00.001-07:002013-08-21T06:55:08.817-07:00The Automator's Manifesto, Part One<div>
In my career in the software field, I've had to teach myself about what quality software was. What the differences were between successful software projects, and unsuccessful ones. It's been a long and often frustrating journey, but I feel like I've come out of it with some principles that could be helpful in guiding people in the field.</div>
<br />
My principle strength in software development is pattern recognition, especially behavioural. I've used this over the years to refine my approach to software development, by analyzing my own behaviour and that of those around me. For this topic, I've tried to apply that at a higher level to my experience with test automation. What is it about automation that most consistently delivers value? What consistently doesn't? Are there practices can guide us towards the former and away from the latter?<br />
<br />
Certainly, to a degree, everything here is derived from common software best practices, but I believe I am able to tailor them in a way that is uniquely suited to the automator. That's why this part is sub-titled…<br />
<br />
<h3>
Automation is Software</h3>
<div>
(I use the term "automator" as a generalization of test automation developer, quality engineer, software engineer in test, and a dozen other titles).</div>
<h4>
</h4>
<h4>
Apply Best Practices, as best you can</h4>
I'm sure we've all heard the statistics about how 50%, 75% or 90% of all software projects fail in some way. If we've been around the block, we may even understand some of the steps to take to improve our chances, commonly called "best practices". Automation projects are almost always directly dependent on some other software project, and when they go down, the automation often goes with them.<br />
<br />
So from the start, the odds aren't good with your automation. But then consider that of all software projects, automation seems to be the place where best practices are least… practiced. I'm talking about things like:<br />
<ul>
<li>Requirements gathering</li>
<li>Structured development process</li>
<li>Documentation</li>
<li>Unit, etc. tests</li>
<li>Source control (I've seen this missing several times)</li>
</ul>
Not to say that every piece of automation needs all of these, just that an automation project is like any other software project, and if we fail to apply common knowledge about software projects to it, we are shooting ourselves in the foot.<br />
What's more, by practicing these things, you become better equipped to ensure they get applied to the project you are developing automation for, primarily because it can help you establish credibility with the developers working on it. Walking the walk, and all that.<br />
<br />
<h4>
Have a Client</h4>
A key aspect of most successful software projects is the presence of an engaged client. As in most aspects, Automation is no different. Someone who understands the value that you are supposed to be delivering is in the best position to help you understand what needs to be done to deliver that value. Do not simply write tests because there was a decree "we need tests for X". <br />
<br />
Instead, you need to understand where the desire for tests comes from? Is it that developers are hesitant to make changes because they have no safety net? Is it that there are lots of regressions in production? Is it that there's a performance optimization project underway, and metrics are needed? Each case would suggest a different focus, and there are many more cases.<br />
<br />
But in order to get to this point where you have identified the need, and make progress against meeting it, you need a partner who will vet requirements and validate progress. You need a client. This can be a team of developers, a particular developer, someone in management, or others. But they need to understand the value you are expected to deliver, and have the time to confirm that you are doing so.<br />
<br />
<h4>
Fight on the best terrain available to you</h4>
As I believe is common to anyone who has been in this field for a while, actually automating tests is not always the best way you can improve the quality of the software. As described in "<a href="http://www.youtube.com/watch?v=X1jWe5rOu3g">Test is Dead</a>", many companies have user bases that accept being used for beta testing. Sure, it might not always be so, but if that is the situation you find yourself in, attempting to keep bugs from those beta testers will not be an ideal use of your time.<br />
<br />
A robust functional test suite for a rapidly changing product might cost more in maintenance then it delivers in the first few years. A development team without a mature development process will gain little by forcing them to write unit tests. Sometimes there's more value to be gained in doing SysAdmin or DevOps type work, such as creating continuous integration infrastructure. The important thing about being an automator is establishing processes that will make producing higher quality software easier. Whether those are actual automated tests run against software, or merely conventions established to improve communication during development is not important. What is important is that you make producing quality software the easiest thing for the developers.<br />
<br />
In order of priority, I would suggest:<br />
<ul>
<li>Establish a development process</li>
<li>Establish a development environment </li>
<li>Automate tests</li>
<li>Automate monitoring</li>
</ul>
Each of these makes the following item easier and more valuable.<br />
<br />
<h3>
Summary</h3>
Automation is Software, so:<br />
<ul>
<li>Follow best practices, as best you can</li>
<li>Have a client, who can validate the value you deliver</li>
<li>Understand the terrain of the project you are automating against, and tailor your focus to that</li>
</ul>
Join me next time as I dive into the value of Proactive Transparency, the danger of Entropy Factors, and the deceptive bliss of Measuring Everything.Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com1tag:blogger.com,1999:blog-6463044249707468993.post-70618089534083888082013-04-29T08:45:00.000-07:002013-04-29T08:45:26.702-07:00Beyond GTACIn 2013, in the twilight of my "testing" career, I was able to attend Google Test Automation Conference for the third time. Once again, I was impressed by (and jealous of) many of the solutions presented. But for me at least, I'm not sure I'm the target audience anymore.<br />
<h3>
About me</h3>
Before I get into that, let me expand on what I said above about twilight. The arc of my career is the story of trying to figure out how to use technology to improve people's lives. This began as computer and then network support, making sure people were able to use the tech they already had. From there, I began to write software, for myself and then those who would pay me to do it.<br />
<br />
Throughout this process, I have had to constantly analyze and refine my own processes. I made mistakes, researched best practices, and tried again. Everything I do comes from continual experimentation and optimization. My career transitions also come out of this drive for self-improvement.<br />
<br />
As I wrote and used more software, and especially assisted others in using it, it became (gradually) clear that the only useful measure of quality was whether it made it easier for users to accomplish their goals.<br />
<br />
Most recently, that career has led me to look beyond myself in terms of delivering quality software. I'm now responsible for optimizing the output of a team of fantastic developers. In the majority of situations we currently encounter, writing tests is not the most efficient path towards this.<br />
<h3>
But enough about me</h3>
So, to a certain degree, GTAC may not be for me because I need to take a wider view then many of the participants, even though we share the same goals. But I think there's more to it then that. The people at GTAC are on average likely to be the best test engineers on the planet. Yet with few exceptions, the work they presented would have fit right in with GTAC from 4 or 6 years ago. As a community, we are failing to establish and exploit institutional memory, so we keep having to re-solve the same problems.<br />
<br />
As a specific example, Google themselves have an incredible build and release system, as the result of a huge ongoing investment. From what we saw of every non-Google presentation, other companies capabilities for automated testing are hampered by the lack of this kind of infrastructure. Not to imply that Google has any obligation to provide it, but it seems to me that everyone could benefit substantially from more direct collaboration on it. Not to say the tooling in this area doesn't hasn't improved, but it still seems like a problem that every company continues to try to solve in their own way.<br />
<br />
Don't get the impression from this that GTAC itself is anything less than fantastic. It has helped me grow so much, and likely raised my expectations for what should be possible. If you have any sort of passion for automated testing, there would be few things more valuable than connecting with this community. Also, despite my gripings, there are some things happening today that simply wouldn't have been possible in the recent past.<br />
<h3>
About those exceptions</h3>
<b>Selenium</b>. Not to be trite about it, but the Selenium project is the biggest change to the test automation community over the past 6 years. It's gone from being a nifty tool for somewhat flaky web automation to a standard (<a href="http://www.w3.org/TR/2012/WD-webdriver-20120710/">literally</a>) platform upon which we can converse about automation and build other tools. Some examples of this include <a href="http://appium.io/">Appium</a>, which is leveraging it to provide cross-platform mobile app testing, and <a href="https://developer.mozilla.org/en-US/docs/Marionette">Marionette</a>, which is integrating Selenium into builds of Firefox OS. It's not the end of the story by a long shot, but having Selenium allows us to elevate our dialogue around test automation.<br />
<br />
<b>Misc</b>. <a href="http://facebook.github.io/buck/">Buck</a>, by Facebook, seems like a nifty solution to a problem I almost have (though I'm not sure when <a class="g-profile" href="http://plus.google.com/104565969450039850531" target="_blank">+Simon Stewart</a> finds time to stop being funny and start writing software). Almost everyone agrees you should just kill flaky tests, which is good, but I'm not sure it's the endpoint in that conversation. Getting developers to write tests was also a near-unanimous sentiment (and why wouldn't it be in this group?), though unlike <a href="http://www.datalord.dk/gtac-2013.html">Thomas Petersen</a>, I didn't get the impression that it was intended to exclude testers from the development process. <a href="http://pex4fun.com/">Pex4Fun</a> is just cool. The Android UI testing team embedding their automation commands in the build thread seems a bit crazy, but still a really clever way to avoid the whole click-and-sleep cycle that plagues most UI automation.<br />
<br />
<b>Organization</b>. Despite having a more limited experience of the Google office, I feel like this was by far the best run conference I have ever been to. Things were on schedule, very smooth, and <a class="g-profile" href="http://plus.google.com/118386507756073290855" target="_blank">+Anthony Voellm</a> is one heck of an MC.<br />
<h3>
Summary</h3>
GTAC remains in my mind the place to be if you are interested in <b>doing</b> test automation. I believe there's more that the test automation/software quality community needs to do to grow together, but the fact that this conference isn't all about that is mostly a reflection of my changing priorities, rather than any failings on their part.<br />
<br />
Full disclosure, I spent 3 years in automation at <strike>RIM</strike> BlackBerry, and this was a mobile testing conference, so I'm probably just jaded.Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com5tag:blogger.com,1999:blog-6463044249707468993.post-49734979969918579492012-03-09T06:19:00.000-08:002012-03-09T06:52:17.758-08:00Recursively formatting a dictionary of stringsI have a use-case where I'm using a dictionary as a basis for generating a configuration file, and many of the values in the file share pieces, such as URL bases or credentials. I will also be generating configuration files for several different instances from the same dictionary.<br />
<div>I wanted a simple way to define replaceable parts of the dictionary. I made a couple of Google searches, didn't find anything on the first page, so I wrote this:</div><div><script src="https://gist.github.com/2006829.js"> </script><br />
<a href="https://gist.github.com/2006829">gist for dict_format.py</a><br />
</div><div>I hope it's useful to someone else, or that I find it next time I have this use-case. :)</div>Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com3tag:blogger.com,1999:blog-6463044249707468993.post-47580152080496509222012-03-08T07:23:00.001-08:002012-03-08T07:23:05.541-08:00Shoutout to PyDevI've been using <a href="http://pydev.org/">PyDev</a> for many years, for Python and Jython development of all kinds. The more recent releases have made some big usability improvements. Specifically, autocompletion works in many more cases, and the built-in refactoring support is proving handy. Rough edges that have bugged me for years are being steadily smoothed away.<br />
So thanks for all the free stuff <a href="http://pydev.blogspot.com/">Fabio</a>! If I was at PyCon I would buy you a drink.Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-73716158513224139752011-12-29T07:33:00.000-08:002011-12-31T08:51:45.657-08:00New Year's Python Meme<span style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; text-align: justify;">As suggested by Tarek, and done by so many others.</span><br />
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<strong style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">1. What’s the coolest Python application, framework or library you have discovered in 2011 ?</strong></div>
<div style="background-color: white; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<b style="color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px;"><a href="http://pypi.python.org/pypi/requests">Requests</a>. </b><span style="color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: x-small;"><span style="line-height: 20px;">I've dealt with Python's HTTP handling on numerous occasions, and most times found myself constructing an abstraction layer to deal with it. Requests provides this abstraction layer for pretty much all of my use cases. I'll give an honourable mention to <b><a href="http://www.pylonsproject.org/">Pyramid</a></b>, because it allowed me to bring together my current use of Pylons and my past experience with Zope.</span></span></div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<strong style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">2. What new programming technique did you learn in 2011 ?</strong></div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<strong style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><a href="http://alecmunro.blogspot.com/2011/09/sorting-out.html">Sorting algorithms</a> ;). </strong><span style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">On a more serious note,</span><span style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"> I started actually getting benefit out of Scrum, which is not quite a programming technique but definitely help my programming. On a related note, I learned the benefits of continuous deployment, and some of the techniques one can use to support that.</span></div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<strong style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">3. What’s the name of the open source project you contributed the most in 2011 ? What did you do ?</strong></div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<b><a href="https://github.com/alecmunro/Experiments-in-Public/tree/master/python_web_client/pwc">Python Web Client</a>. </b>But I built that myself. I did file an accepted (and quickly fixed) bug in <a href="http://pydev.org/">PyDev</a>.</div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<strong style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">4. What was the Python blog or website you read the most in 2011 ?</strong></div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<a href="http://planet.python.org/">Planet Python</a>. Pretty much my go to for Python, though I'm tempted to start reading Python Reddit (I've never used Reddit before).</div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<strong style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">5. What are the three top things you want to learn in 2012 ?</strong></div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<a href="http://wiki.opscode.com/display/chef/Home">Chef</a> (and related tools), <a href="http://www.gevent.org/">gevent</a>, <a href="http://golang.org/">Go</a>. I'm also interested in (and more likely to learn) <a href="http://coffeescript.org/">CoffeeScript</a> and <a href="http://nodejs.org/">Node JS</a>.</div>
<div style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify;">
<strong style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">6. What are the top software, app or lib you wish someone would write in 2012 ?</strong></div>
<div>
<ul>
<li><span style="color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: x-small;"><span style="line-height: 20px;">A web service mocking library. I've seen some promising signs in this direction, and I have cause to contribute myself to the effort.</span></span></li>
<li><span style="color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: x-small;"><span style="line-height: 20px;">A self-replicating Python platform, that can deploy itself from device-to-device relatively transparently. I want to be able to say "run code X on instance Y", and not worry about any of the details of preparing Y or moving X to it.</span></span></li>
</ul>
</div>
<div>
<span style="color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: x-small;"><span style="line-height: 20px;">If you want to participate:</span></span></div>
<ul style="background-color: white; margin-bottom: 0px; margin-left: 3em; margin-right: 0px; margin-top: 1.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
<li style="color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">copy-paste the questions and answer to them in your blog</li>
<li style="color: #333333; font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 13px; line-height: 20px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">tweet it with the <a href="https://twitter.com/#!/search/%232012pythonmeme" style="color: #cc6b47; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">#2012pythonmeme</a> hashtag</li>
</ul>Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-29877928930740590822011-10-27T06:10:00.000-07:002011-10-27T06:10:44.239-07:00An end to the experiments (for now)Well, it's been 3 months, and I've gotten a decent number of things written. It took much longer than I was expecting, but I learned a lot of things, and made some good contacts. But most excitingly, I got a job! Last week I accepted a position working for <a href="http://arc90.com/">Arc90</a>, most prominently of <a href="http://www.readability.com/">Readability</a> fame, but they've got plenty of other things going on.<div>
I first heard about them when <a href="http://kennethreitz.com/">Kenneth Reitz</a> started working there, and <a href="http://kennethreitz.com/joining-arc90-readability.html">blogged</a> about it. As it turns out, they were looking for someone with test automation experience just about the time I started getting serious about sending my resume around.</div>
<div>
I'll be working with the <a href="http://arc90.com/work/#insight">Insight</a> project team, building test automation and reporting tools to ensure confidence in the quality of every release. It's a very different scale from my work at RIM, and I think a very good opportunity for me to succeed or fail entirely on my own merits (I'm going to succeed, btw).</div>
<div>
Which brings us to this blog. For the next few months, I don't expect to have much time to commit to writing here. Kenneth has certainly done an admirable job of keeping up blogging (and working on <a href="http://python-requests.org/en/latest/index.html">Requests</a>!), so perhaps I will be able to as well. I've done a bit of research on some of the other topics I wanted to write about, and there's a post I think I owe someone for the help they have given me, but Arc90 is going to be my focus.</div>
<div>
So this is an end, to this blog as it was. But one of the reasons I chose Arc90 as an employer is their support for blogging and open source work, so I do expect to be back writing before too long. Thanks to everyone who has read and commented on any of this!</div>Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com2tag:blogger.com,1999:blog-6463044249707468993.post-36357734191460524422011-10-12T09:04:00.000-07:002011-10-12T09:04:23.213-07:00Python Web Client 0.2 Release<br />
I'm pleased to announce the 0.2 release of the Python Web Client. It now meets a bare minimum of functionality to be useful. Specifically, it provides a web UI to allow you to put together and submit HTTP requests, specifying request type, URL, parameters and headers.<br />
<br />
You can view a <a href="http://208.111.39.117:6543/">demo here</a>.<br />
<br />
Oh, and it's hosted on <a href="https://github.com/alecmunro/Experiments-in-Public/tree/master/python_web_client">Github here</a>.<br />
<br />
<b>What's new in 0.2?</b><br />
<br />
- Added display of response body<br />
- Added option to select request method<br />
- Added field to add parameters<br />
- Added field to add headers<br />
<br />
<b>What does the future hold?</b><br />
<br />
Well, there are a lot of potential ideas for where this could go, both in the <a href="https://bitbucket.org/socal.piggies/pwc/wiki/Home">original SoCal piggies proposal</a>, and on the <a href="https://community.rallydev.com/slm/rally.sp?">Rally site where I've been tracking this</a> (log in with alecmunro+public@gmail.com:Experiments). However, I expect to resume my place among the employed soon, and thus far I haven't had any feedback on this. So barring extreme boredom on my part, this is probably the end of the line until someone forks it.<br />Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-26838663841598159542011-10-04T12:18:00.000-07:002011-10-04T12:18:21.840-07:00Python Web Client 0.1<b>The release</b><br />
I've polished a few rough edges, and I'm now (somewhat) proud to release Python Web Client 0.1. It's still lacking in features, but it's got docs and an easy way to start it, and what's more, its pieces work on non-Windows platforms. I've also handicapped it a bit to allow me to put up a hosted version for people to try out, <a href="http://208.111.39.117:6543/">here</a>.<br />
<br />
<b>What's next</b><br />
Well, with this "release", the foundation of the project should be more or less complete (though I don't have it in continuous integration yet). That should make it pretty safe to add features. I'll see what I can put into it over the next few days and get a 0.2 release out, that will hopefully be more useful. If I people are interested, we might make it to 0.3, at which point I'll try to get it on PyPi (it would be nice to have a project up there).<br />
<br />
<b>Sidenote</b><br />
I'm not sure there's a good solution, but I find all the context-switching that goes along with setting up a new project to be a real drain on productivity.Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com2tag:blogger.com,1999:blog-6463044249707468993.post-1408293913047183132011-09-26T20:24:00.000-07:002011-09-26T20:24:54.395-07:00Python Web Client 0.1.dev1<b>tl;dr</b><br />
I built a preliminary version of the <a href="https://bitbucket.org/socal.piggies/pwc/wiki/Home">Socal Piggies</a> Python Web Client. Take a look at the code and methodology, suggest features/fixes, and otherwise enjoy! There's no live demo because of a gaping security hole.<br />
<br />
<b>Intro</b><br />
First off, I would just like to express my sincere appreciation for everyone who responded to my <a href="http://alecmunro.blogspot.com/2011/09/let-me-build-you-web-appservice.html">request for ideas</a>. There were a number of interesting options, but for now, I've decided to build an implementation of the Python Web Client described on the <a href="https://bitbucket.org/socal.piggies/pwc/wiki/Home">Socal Piggies</a> site. I made this choice because it's a comfortable area for me to work in, it's a tool I can see using, and probably most important, I think I can build a simple version fairly quickly. :)<br />
<br />
<b>Design</b><br />
The first thing I usually do with a new project is retreat to a quiet corner with a notebook and a writing implement. It would be nice to find an electronic way to do this, but so far nothing has come close to what I need in terms of offering a combination or structured and free-form input, along with instant availability.<br />
<br />
In this case, I was trying to strip the concept down to the bare essentials. In this case that means:<br />
<ul><li>One page, with two widgets:</li>
<ul><li>Create request (Enter a URL)</li>
<li>Display response (Status Code + Headers)</li>
</ul><li>Startup script that launches a browser to the service</li>
</ul>That last one may seem non-essential, but speaks to my philosophy that "delivery is as important as development". In practice, that means that how a client is introduced to functionality is just as important as how well that functionality works. Make it really easy to start using.<br />
<br />
Because this is somewhat of a showcase project, there's a couple of other things I pinned on my design list:<br />
<ul><li>Testing (unit, functional, system, jsunit)</li>
<li>Docs (UI + API, published in Sphinx)</li>
</ul>While I was putting this together, I also wrote down a whole lot of nice-to-have features for later. You can check them out on the<a href="https://community.rallydev.com/slm/rally.sp?"> Rally site</a> I am (kind of) using to manage this project. You will need to log in:<br />
alecmunro+public@gmail.com:Experiments<br />
<br />
<b>Testing</b><br />
Because I'm a TDD advocate, let's do that. So first I need to decide what tests I want to have. Since I don't know my code structure at all yet, I'm going to start with system level tests, which I usually define as something that tests the system at the UI level, running very close to how it will run in production:<br />
<ul><li>Visit site, enter URL, press submit, verify results.</li>
</ul><a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/python_web_client/pwc/tests/test_ui.py">Gist-It for test_ui.py</a><br />
<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/tests/test_ui.py">
</script><br />
<div>That pretty much does it, and can be done with something like <a href="http://seleniumhq.org/">Selenium</a>, unless I also wanted to test the startup script. Doing so would involve using something like <a href="http://sikuli.org/">Sikuli</a>(which I do love), to observe the state of the desktop, but that might balloon the scope of this project a bit too much. So we are on to functional testing, in this case defined as testing the API of the web service, in as isolated an environment as we can create. So what are we looking at there?</div><div><ul><li>Submit URL, verify response</li>
<ul><li>Probably some variants of this, to test error handling or redirect responses (we are handling those, right?).</li>
<li>What happens if the URL to retrieve is the URL of the webservice itself? Could we experience some nastiness there?</li>
</ul></ul>So both of the test types we have addressed so far require an actual connection to another server. We could use something that's always going to be available, like www.google.com, but we aren't really guaranteed a network connection. So for this, I'll write a small web server that can be set to return whatever you want it to.<br />
<a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/python_web_client/pwc/tests/echo_server.py">Gist-It for echo_server.py</a><br />
<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/tests/echo_server.py">
</script><br />
This was actually a bit trickier than I anticipated, due to the need to run the server in a separate thread/process, and <a href="http://bugs.python.org/issue11969">this bug</a>. Anyway, here's the API tests:</div><a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/python_web_client/pwc/tests/test_apis.py">Gist-It for test_apis.py</a><br />
<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/tests/test_apis.py">
</script><br />
<br />
Ok, so unit tests now. From our earlier tests, it's become pretty clear that the API will have one view, which accepts the details to construct a request (just a URL to start), submits that request, and returns the status code and headers from the response.<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/tests/test_views.py">
</script><br />
<div>Well, that was all really boring. Maybe the jsunit tests will be more interesting? In practice, I probably won't write these before the code, because it still takes me a while to get into the rhythm of writing tests for javascript. I need a bit of trial-and-error.</div><div><ul><li>Create Request Widget:</li>
<ul><li>Enter text and press submit. A call should be made to create the request, and the deferred for that call should be passed to the page.</li>
</ul></ul><a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/python_web_client/pwc/static/script/tests/test_create_request.js">Gist-It for test_create_request.js</a><br />
<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/static/script/tests/test_create_request.js">
</script><br />
<ul><li>Display Response Widget:</li>
<ul><li>Supply it with various responses, and confirm that they display properly. Probably the most interesting bit of testing of the whole lot.</li>
</ul></ul><a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/python_web_client/pwc/static/script/tests/test_display_response.js">Gist-It for test_display_response.js</a><br />
<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/static/script/tests/test_display_response.js">
</script><br />
<div><b>Implementation</b></div></div><div>Ok, so we have our tests, perhaps. Now, on to the implementation. This part is actually really simple.<br />
<br />
There's the Python view:<br />
<a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/python_web_client/pwc/views.py">Gist-It for views.py</a><br />
<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/views.py">
</script><br />
and the two Javascript widgets:<br />
<a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/python_web_client/pwc/static/script/create_request.js">Gist-It for create_request.js</a><br />
<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/static/script/create_request.js">
</script><br />
<a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/python_web_client/pwc/static/script/display_response.js">Gist-It for display_response.js</a><br />
<script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/python_web_client/pwc/static/script/display_response.js">
</script><br />
<br />
Feel free to <a href="https://github.com/alecmunro/Experiments-in-Public/tree/master/python_web_client/pwc">take a look at the GitHub repository</a> for more details (or check it out to run it). </div><br />
<b>Documentation</b><br />
I've left off the documentation for now, both because I wanted to get this up soon, and it's been a while since I started anything with Sphinx, and also because it really doesn't do much yet. I'm also still missing the launch script.<br />
<br />
<b>Conclusion</b><br />
There's lots more work to be done here to make something useful, so I'm taking suggestions. But hopefully this gives you an idea of how you can build a simple and somewhat tested web-app using Pyramid and JQuery. You will notice that it is very testing heavy, probably significantly more than real-world deadlines would allow for. But once you get these tests in place (and a system to run them), they are fairly easy to build on, and can provide a safe container in which to experiment.<br />
For the moment, I'm planning two distinct iterations:<br />
<br />
<ul><li>Add docs and launch script, as well as displaying the response body. That will be 0.1</li>
<li>Flesh out the request creation ability, to allow settings headers and parameters. Along with hopefully some fixes/refinements, that will be 0.2</li>
</ul><div>Beyond that, development will depend on whether this is interesting to anyone, so let me know.</div>Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com0tag:blogger.com,1999:blog-6463044249707468993.post-56022632179740809992011-09-17T19:16:00.000-07:002011-09-18T10:49:09.547-07:00Sorting outAs someone who almost exclusively uses high-level languages, the idea of writing my own sorting algorithm seems a bit silly. However, I can certainly appreciate the algorithms used for sorting, and it's a neat opportunity to try to document and implement these algorithms using methods I am familiar with.<br />
<div><br />
<b>Preface</b><br />
<br />
These implementations are likely to be extremely naive. If you went CS school, you probably learned better implementations in your first year. There is absolutely no reason to use these in production code anywhere. The built-in python sorting is 10-50 times faster than anything I've produced (I'm actually surprised it's not more). If you've got tips about how to speed these up just by changing the code around, feel free to comment, or you can try forking <a href="https://github.com/alecmunro/Experiments-in-Public/tree/master/sorting">my repository</a> and sending a pull? request. I can't promise to spend much time on it, because this is pretty well-trod territory, but it would be a bit entertaining to see how close we can get.<br />
<br />
</div><div><b>Quick Sort</b></div><div>My understanding of quicksort is still developing, but based on what I've read on Wikipedia, it can work something like this:</div><div><ol><li>Grab an item in the list, called the "pivot".</li>
<li>Create two lists, representing everything greater than the pivot, and everything less then the pivot.</li>
<li>Repeat steps 1 and 2 on the two sub-lists, returning the a list comprised of the smaller list items, then the pivot, then the larger list items.</li>
</ol><div>In this way, the entire list should get sorted. It's my understanding there are various optimizations that can be done, such as swapping elements instead of creating new lists. It seems to be one of the "best" all around algorithms, though for certain cases, it's performance can be beaten by others.</div><a href="http://gist-it.appspot.com/">Gist-it</a> for <a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/sorting/src/quick_sort.py">quick_sort.py</a></div><script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/sorting/src/quick_sort.py">
</script><br />
<div><br />
This was the second fastest list implementation I created, at about 1/12th the performance of the built-in sorting.<br />
<br />
</div><div><b>Merge Sort</b><br />
Merge sort relies on splitting the list recursively until you have an ordered hierarchy of l item item lists. Then you compare each list with it's neighbour, and return a combined list of the two merged together. Now you have 2-item sorted lists, which you work through, comparing the left-most element to its neighbour's left-most element, and moving the lowest one to a new list, eventually creating a 4-item list.<br />
<br />
<a href="http://gist-it.appspot.com/">Gist-it</a> for <a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/sorting/src/merge_sort.py">merge_sort.py</a></div><script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/sorting/src/merge_sort.py">
</script><br />
<div><b>Heap Sort</b></div><div>Heap sort relies on understanding what a "heap" is, in this context. So let's do that.<br />
<br />
A heap is a data structure that is tree based, and follows the rule that all children of a node will have a value that is lower than or equal to the value of that node (for a max-heap, for a min-heap the rule is reversed). In practice, heaps are usually implemented within arrays, with the first or last item of the array being the root of the tree.<br />
<br />
Now, why do we do have a heap? What's the advantage? Apparently sorting things. :)<br />
<br />
In a heap sort, we first build the heap from the list we've been given. Once we have our heap, we know the item with the highest value is at the root of the heap, which is position 0 in the list representing the heap. So now we swap the first and last elements in that list, and either move the last element from the list, or simply treat that part of the heap as already sorted (which means our heap needs to know to ignore it somehow). Then we take the first item, and trickle it down through the heap until the heap is proper again. This consists of comparing it's value with it's children, and swapping it with the higher one of these, until one of these is not higher.<br />
<br />
<a href="http://gist-it.appspot.com/">Gist-it</a> for <a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/sorting/src/heap_sort.py">heap_sort.py</a></div><script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/sorting/src/heap_sort.py">
</script><br />
<div>Python apparently does have a <a href="http://docs.python.org/library/heapq.html">built-in heap library</a>, which might be worth benchmarking, as heap was my slowest sort implementation.<br />
<br />
</div><div><b>Bubble Sort</b></div><div>Bubble sort is fairly trivial.<br />
<br />
Iterate through the items, except the last one, if an item is greater than the next one, swap their positions. When you reach the end of the list, do it again, unless there were zero swaps.<br />
<br />
<a href="http://gist-it.appspot.com/">Gist-it</a> for <a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/sorting/src/bubble_sort.py">bubble_sort.py</a></div><script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/sorting/src/bubble_sort.py">
</script><br />
<div><b>Insertion Sort</b></div><div>Insertion sort is another trivial sort. I'm really only including it because I think my (unwitting) choice of an insertion sort in an interview may have cost me a job.<br />
<br />
<a href="http://gist-it.appspot.com/">Gist-it</a> for <a href="https://github.com/alecmunro/Experiments-in-Public/blob/master/sorting/src/insertion_sort.py">insertion_sort.py</a></div><script src="http://gist-it.appspot.com/github/alecmunro/Experiments-in-Public/raw/master/sorting/src/insertion_sort.py">
</script><br />
<div>Interestingly enough, for my stupid example of sorting a small list of characters, insertion sort is the fastest implementation I created.<br />
<br />
<b>Acknowledgements and Conclusion</b><br />
<b><br />
</b><br />
Not really much to conclude, except that I now have a better understanding how to write a sorting algorithm, and some of the pros and cons of different algorithms. I certainly can't look at a data set and give you the big O case for a given algorithm.<br />
<br />
But one thing I do want to draw special attention to is Wikipedia's pages on this subject. They vary a bit in information density, but they were incredibly informative, and make use of numerous methods to help communicate how each sort works. If you really want to understand this stuff, I would definitely start with these pages:<br />
<br />
<ul><li><a href="http://en.wikipedia.org/wiki/Quicksort">Quicksort</a></li>
<li><a href="http://en.wikipedia.org/wiki/Merge_sort">Merge sort</a></li>
<li><a href="http://en.wikipedia.org/wiki/Heapsort">Heap sort</a></li>
<li><a href="http://en.wikipedia.org/wiki/Bubble_sort">Bubble sort</a></li>
<li><a href="http://en.wikipedia.org/wiki/Insertion_sort">Insertion sort</a></li>
</ul><div>Also, my thought to do this post was sparked by another post on Planet Python that mentioned Insertion Sort, where I recognized the algorithm. I'm not entirely sure, but <a href="http://lionel.textmalaysia.com/insertion-sort.html">this</a> may be that post.</div></div>Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com5tag:blogger.com,1999:blog-6463044249707468993.post-54245428116563609942011-09-15T08:25:00.000-07:002011-09-15T08:25:39.272-07:00Let me build you a web app/service!So, according to my <a href="http://alecmunro.blogspot.com/2011/07/introductions.html">introduction</a>, one of my goals for this project is to build a web app or service to demonstrate my skillset in that area. Unfortunately, it's turns out my idea for a web app has already been done, and is quite well-known (on the plus side, I now understand what 4Chan is). At the moment, I'm drawing blanks about what I should build, so I thought perhaps I could crowdsource that job.<br />
<br />
So if you have an idea for a web app or service, but not the time or skills to get it started, or if you would simply like to collaborate with someone on it, post a comment describing your idea.<br />
<br />
In general, I'm game for pretty much anything, as I'm confident I can learn whatever I need to. Some general parameters though:<br />
<br />
<ul>
<li>It's going to be in Python, built on Pyramid, using SQLAlchemy for models</li>
<li>I will try to strip the idea to it's core, and leave others to make it full-featured</li>
<li>I will try to make an appealing and usable UI, but again, it will be pretty barebones</li>
<li>I'm going to blog about it, host it in github and make the code viewable by everyone</li>
<li>If you want to collaborate:</li>
<ul>
<li>I'm open to hosting it elsewhere, as long as it's publicly accessible</li>
<li>I will be a stickler in design discussion and code reviews</li>
</ul>
</ul>
<div>
Finally, I will happily put it under any license you want and grant you and copyright or whatnot, as long as it doesn't prevent me from achieving my objectives vis-a-vis skill demonstration.</div>
Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com9tag:blogger.com,1999:blog-6463044249707468993.post-12005189537399608352011-09-13T11:17:00.000-07:002011-09-13T11:17:07.301-07:00Design patternsDesign patterns are a very broad subject, but as far as I can tell, they are primarily common conventions for structuring software. I've never been taught them, and as far as I can tell, I've used nearly all of them, repeatedly. So for an experienced software developer, I don't believe studying design patterns is likely to improve your coding skills much, if at all. However, it could certainly improve your collaboration skills.<br />
<br />
<b>Words Matter</b><br />
If there's one downside to being self-taught in the field of computer programming (there are several), it would be the difficulty of communicating your ideas with those who have a "standard" education. However good my code may be doesn't matter if I spend all my time trying to explain how I'm going to implement something. Formal computer science comes with a whole boatload of terminology, design patterns among them. Being able to say "use the template method pattern to defer processing to subclasses" is much more concise than "in the superclass method, call methods that are overridden in the subclass, but have only stub implementations in the superclass". Even that verbose description is concise compared to what usually comes up with discussing actual project code.<br />
<br />
<b>Template Method</b><br />
The template method pattern is something that eventually comes in handy to anyone who does a fair amount of object oriented design. It's a response to the problem of how to mix specialized behaviour of subclasses with general behaviour of superclasses. The basic idea is that the superclass implementation of a method will contain mostly calls to other methods of the object, which will be mostly abstract in the superclass, and implemented in the subclasses, which won't implement the method being called.<br />
I recently used this on an email reporting system, which used either HTML or text email depending on the job being reported on. There was a fair amount of commonality between both types, in that they dealt with collecting data from the environment and stuffing it into some kind of template (the use of the word template here is unrelated), then formatting that template into an email and sending it along.<br />
The actual email sending was almost the same for both HTML and text, so with just a condition or two we could handle that entirely in the superclass. However, the data that was sent out varied a bit between the two types, as did the emails themselves.<br />
<br />
<div>
<a href="https://gist.github.com/1214125">Gist: "Template Method example"</a></div>
<script src="https://gist.github.com/1214125.js?file=gistfile1.py">
</script><br />
<div>
Note that the implementation above is not ideal, because the subclasses do need a certain awareness of the superclass implementation in order to behave properly.<br />
<br />
<b>Mediator</b></div>
<div>
The mediator pattern, in my understanding, mostly deals with managing the flow of communication between objects. It puts a layer between your object and it's intended communication target. I use this pattern frequently for building UIs, most of which I build in JQuery, so that's where I use it.</div>
<div>
The way I build UIs in JQuery has been a constantly evolving pattern, so this may change, but right now it gives me the flexibility I need. What I usually do is create an object representing the page itself, as well as objects to represent each of the distinct interface areas, which I am going to call widgets (thought that might be too specific of a term in this context). Each of the widgets takes zero or more callback functions, depending on what they do, and the page object is responsible for seeing that these point to the same things. In some cases, they are methods of other widgets (though in typical javascript fashion, they are anonymous functions that call those methods), but more often they are methods of the page object, which accept the communication and see it dispatched to any other widget(s) that are interested. The page object is almost never more than wiring between the widgets.<br />
<br />
The following is probably not syntactically correct. It frequently takes a bit of trial and error before I get into the swing of JavaScript OOP.<br />
<br />
<a href="https://gist.github.com/1214446">Gist: "Mediator Pattern example"</a></div>
<script src="https://gist.github.com/1214446.js?file=gistfile1.js">
</script><br />
<div>
<b>Strategy</b></div>
<div>
The strategy pattern deals with abstracting away algorithms. In situations where a different context might require a different algorithm to achieve the desired results, you apply the strategy pattern. This might sounds complex, but in practice, it is as simple as using different validation functions on different data types, as long as you have a common interface to those functions.<br />
<br />
<a href="https://gist.github.com/1214513">Gist: "Strategy Pattern example"</a></div>
<script src="https://gist.github.com/1214513.js?file=gistfile1.py">
</script><br />
<b>Adapter</b><br />
<div>
The adapter pattern is one that, thanks to Zope 3, I've been familiar with for a long time. An adapter is an object that "wraps" another object to provide a desired interface. Designing a system based on the adapter pattern requires using capital-I Interfaces for establishing object communication. Then, as necessary, adapters are created to allow the available objects to satisfy those interfaces.<br />
To a certain degree, the adapter pattern takes the concept of polymorphism, traditionally understood as being able to use a superclass' interface to interact with instances of subclasses, and expands it. So you can use the specification of an Interface to interact with any objects that are adaptable to that Interface. To use the traditional Bicycle example, Bicycle might extend Vehicle, and have traditional vehicular methods. However, maybe we want to check what color the bike is, or paint it. Vehicle may not have methods for this, but IPaintable might. Then, with a BicyclePainter adapter, we can adapter our Bicycle instance to this interface. (For the record, I've never found the Bicycle example very useful, and I'm not sure if I'm doing you any favours by using it here).<br />
<br />
<a href="https://gist.github.com/1214536">Gist: "Adapter Pattern example"</a></div>
<script src="https://gist.github.com/1214536.js?file=gistfile1.py">
</script><br />
<div>
<b>Conclusion</b></div>
<div>
So there's some design patterns, and their usage. It's by no means comprehensive, and I'm sure many of you will have encountered these in other contexts where my definitions aren't entirely accurate. That's just fine, because the value of these is not in having rigid development patterns, it's having useful ways to elevate the discussion of your development. I've almost never encountered clearly recognizable design patterns in code I inherited, because patterns are theory, and when applied, the real world makes things start to get messy.<br />
<br />
<b>References</b><br />
<br />
<ul>
<li><a href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)">Wikipedia</a>: I relied on this for design patterns and their basic descriptions.</li>
<li><a href="http://grok.zope.org/documentation/tutorial/grok-poller-tutorial/adapters">"Adapters" chapter from Grok tutorial</a></li>
</ul>
</div>
Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com4tag:blogger.com,1999:blog-6463044249707468993.post-50087428270753217982011-09-08T11:34:00.000-07:002011-09-13T06:06:15.022-07:00Mocking snakesMany years ago, I was tasked with improving the performance of a suite of unit tests. They were taking ever longer to run, and were beyond 20 minutes when I started working with them. Needless to say, this meant people rarely ran them.<br />
<div>
<div>
<a href="http://misko.hevery.com/2009/05/07/configure-your-ide-to-run-your-tests-automatically/">From Miško Hevery</a>:<br />
<blockquote>
What I want is for my IDE to run my tests every time I save the code. To do this my tests need to be fast, because my patience after hitting Cntl-S is about two seconds. Anything longer than that and I will get annoyed. If you start running your tests after every save from test zero you will automatically make sure that your test will never become slow, since as soon as your tests start to run slow you will be forced to refactor your tests to make them faster.</blockquote>
</div>
</div>
<div>
The problem was that every test was descended from a common base class, and that class brought up fake versions of most of the application. Well, mostly fake versions. There was still a lot of I/O and network activity involved in bringing up these fakes.</div>
<div>
<br /></div>
<div>
The solution turned out to be mock objects, JMock in this particular case. For those unfamiliar, mock objects are objects that can stand in for your dependencies, and can be programmed to respond in the particular manner necessary for whatever it is you are testing. So if your network client is supposed to return "oops" every time the network connection times out, you can use a mock to stand in for the network connection, rather than relying on lady fortune to drop the network for you (or doing something terrible, like having code in your test that disables your network interface).</div>
<div>
<br /></div>
<div>
There are a couple of general drawbacks to using mock objects, but the primary one is that a mock object only knows what you tell it. If the interface of your dependencies change, your mock object will not know this, and your tests will continue to pass. This is why it is key to have higher level tests, run less frequently, that exercise the actual interfaces between objects, not just the interfaces you have trained your mocks to have.</div>
<div>
<br /></div>
<div>
The other drawbacks have more to do with verbosity and code structure than anything else. In order for a mock to be useful, you need a way to tell your code under test what dependency it is standing in for. In my code, this tends to lead to far more verbose constructors, that detail every dependency of the object. But there are other mechanisms, which I will explore here.</div>
<div>
<br /></div>
<div>
For a more verbose comparison of mock libraries in a variety of use cases, check this out:</div>
<div>
<br /></div>
<div>
<a href="http://garybernhardt.github.com/python-mock-comparison/">http://garybernhardt.github.com/python-mock-comparison/</a></div>
<div>
<br /></div>
<div>
Hopefully this post will be a more opinionated supplement to that.</div>
<div>
<br /></div>
<div>
There are a couple of categories of things to mock:</div>
<div>
<ul>
<li>Unreliable dependencies (network, file system)</li>
<li>Inconsistent dependencies (time-dependent functionality)</li>
<li>Performance-impacting dependencies (pickling, hashing functions, perhaps)</li>
<li>Calls to the object under test</li>
</ul>
<div>
The last item is certainly not a necessity to mock, but it does come in handy when testing an object with a bunch of methods that call each other. I'll refer to it as <em>"partial mocking"</em> here.</div>
</div>
<div>
<br /></div>
<div>
For this article, I'm going to focus on 4 mock object libraries, <a href="http://labix.org/mocker">Mocker</a>, <a href="http://has207.github.com/flexmock/index.html">Flexmock</a>, and <a href="http://farmdev.com/projects/fudge/">Fudge</a>, chosen primarily because they are the ones I have experience with. I also added in <a href="http://www.voidspace.org.uk/python/mock/">Mock</a>, but I don't have much experience with it yet. I believe, from my more limited experience with other libraries, that these provide a decent representation of different approaches to mocking challenges.</div>
<div>
<br /></div>
<div>
I'm going to go through common use cases, how each library handles them, and my comments on that. One important note is that I generally don't (and won't here) differentiate between mocks, stubs, spies, etc.</div>
<div>
<h3>
Getting a mock</h3>
</div>
<div>
<a href="https://gist.github.com/1149878">Gist: "Getting mock objects from different libraries"</a></div>
<br />
<script src="https://gist.github.com/1149878.js?file=gistfile1.py">
</script><br />
<div>
<br /></div>
<div>
<br /></div>
<div>
Dependencies are usually injected in the constructor, in a form like the following:<br />
<a href="https://gist.github.com/1149767">Gist "Verbose dependency specification for mocking"</a></div>
<div>
<br /></div>
<br />
<script src="https://gist.github.com/1149767.js?file=gistfile1.py">
</script><br />
<div>
<br /></div>
<div>
This is verbose, especially as we build real objects, which tend to have many dependencies, once you start to consider standard library modules as dependencies. :)</div>
<div>
<br /></div>
<div>
NOTE: Not all standard library modules need to be mocked out. Things like os.path.join or date formatting operations are entirely self contained, and shouldn't introduce significant performance penalties. As such, I tend not to mock them out. That does introduce the unfortunate situation where I will have a call to a mocked out os.path on one line, and call to the real os.path on the next:<br />
<a href="https://gist.github.com/1149773">Gist: "Confusion when not everything is mocked"</a></div>
<div>
<br /></div>
<br />
<script src="https://gist.github.com/1149773.js?file=gistfile1.py">
</script><br />
<div>
<br /></div>
<div>
This can certainly be a bit confusing at times, but I don't yet have a better solution.</div>
<div>
<br /></div>
<div>
However, it is quite explicit, and avoids the need for a dependency injection framework. Not that there's anything wrong with using such a framework, but doing so steepens the learning curve for your code.</div>
<br />
<div>
<h3>
Verifying Expectations</h3>
</div>
<br />
<div>
One key aspect of using mock objects is ensuring that they are called in the ways you expect. Understanding how to use this functionality can make test driven development very straightforward, because by understanding how your object will need to work with it's dependencies, you can be sure that the interface you are implementing on those dependencies reflects the reality of how it will be used. For this and more, read <a href="http://www.mockobjects.com/files/mockrolesnotobjects.pdf"><em>Mock Roles Not Objects>, by Steve Freeman and Nat Pryce</em></a>.</div>
<br />
<div>
...anyway, verification takes different forms across libraries.<br />
<a href="https://gist.github.com/1150664">Gist: "Verifying mock expectations"</a></div>
<br />
<script src="https://gist.github.com/1150664.js">
</script><br />
<br />
<h3>
Partial Mocks</h3>
<div>
Partial mocking is a pretty useful way to ensure your methods are tested independently from each other, and while it is supported by all of the libraries tested here, some make it much easier to work with than others.<br />
<a href="https://gist.github.com/1198698">Gist "Partial mocks"</a></div>
<script src="https://gist.github.com/1198698.js?file=gistfile1.py">
</script> <br />
<h3>
</h3>
<h3>
Chaining Attributes and Methods</h3>
<div>
I'm of the opinion that chained attributes are generally indicative of poor separation of concerns, so I don't place too much weight on how the different libraries handle them. That said, I've certainly had need of this functionality when dealing with a settings tree, where it can be much easier to just create a mock if you need to access settings.a.b.c.</div>
<div>
Chained methods are sometimes useful (especially if you use SQLAlchemy), as long as they don't impair readability.<br />
<a href="https://gist.github.com/1203804">Gist "Chaining methods and attributes"</a></div>
<script src="https://gist.github.com/1203804.js?file=gistfile1.py">
</script> <br />
<div>
<br /></div>
<div>
<br /></div>
<h3>
Failures</h3>
<div>
An important part of any testing tool is how informative it is when things break down. I'm talking about detail of error messages, tracability, etc. There's a couple of errors I can think of that are pretty common. For brevity, I'm only going to show the actual error message, not the entire traceback.<br />
<br />
<b>Note</b>: Mock is a bit of an odd duck in these cases, because it lets you do literally anything with a mock. It does have assertions you can use afterwards for most cases, but if an unexpected call is made on your mock, you will not receive any errors. There's probably a way around this.<br />
<br />
Arguments don't match expectations, such as when we call time.sleep(4) when our expectation was set up for 6 seconds:<br />
<blockquote>
<b>Mocker</b>: MatchError: [Mocker] Unexpected expression: m_time.sleep(4)<br />
<b>Flexmock</b>: InvalidMethodSignature: sleep(4)<br />
<b>Fudge</b>: AssertionError: fake:time.sleep(6) was called unexpectedly with args (4)<br />
<b>Mock</b>: AssertionError: Expected call: sleep(6)<br />
Actual call: sleep(4)</blockquote>
When I first encountered Flexmock's InvalidMethodSignature, it threw me off. I think it could certainly be expanded upon. Otherwise, Mock and Fudge have very nice messages, and as long as you know what was supposed to happen, Mockers is perfectly sufficient.<br />
<br />
Unexpected method called, such as when you misspell "sleep":<br />
<blockquote>
<b>Mocker</b>: MatchError: [Mocker] Unexpected expression: m_time.sloop<br />
<b>Flexmock</b>: AttributeError: 'Mock' object has no attribute 'sloop'<br />
<b>Fudge </b>(patched time.sleep): AttributeError: 'module' object has no attribute 'sloop'<br />
<b>Fudge</b>: AttributeError: fake:unnamed object does not allow call or attribute 'sloop' (maybe you want Fake.is_a_stub() ?)<br />
<b>Mock</b>: AssertionError: Expected call: sleep(6)<br />
Not called</blockquote>
Mock doesn't tell you that an unexpected method was called. Mocker has what I consider the best implementation here, because it names the mock the call was made on. The second Fudge variant is good, but because you might encounter it or the first variant depending on context, Fudge overall is my least favourite for this. Flexmock simply defers handling this to Python.<br />
<br />
Expected method not called:<br />
<blockquote>
<b>Mocker</b>: AssertionError: [Mocker] Unmet expectations:<br />
=> m_time.sleep(6)<br />
- Performed fewer times than expected.<br />
<b>Flexmock</b>: MethodNotCalled: sleep(6) expected to be called 1 times, called 0 times<br />
<b>Fudge</b>: AssertionError: fake:time.sleep(6) was not called<br />
<b>Mock</b>: AssertionError: Expected call: sleep(6)<br />
Not called</blockquote>
I think they all do pretty well for this case, which is good, because it's probably the most fundamental.</div>
<h3>
Roundup</h3>
<div>
So, having spent a bit of time with all of these libraries, how do I feel about them? Let's bullet point it!</div>
<h4>
Mocker</h4>
<div>
<ul>
<li>Pros</li>
<ul>
<li>Very explicit syntax</li>
<li>Verbose error messages</li>
<li>Very flexible</li>
</ul>
<li>Cons</li>
<ul>
<li>Doesn't support Python 3 and not under active development</li>
<li>Performance sometimes isn't very good, especially with patch()</li>
<li>Quite verbose</li>
</ul>
</ul>
<h4>
Flexmock</h4>
</div>
<div>
<ul>
<li>Pros</li>
<ul>
<li>Clean, readable syntax for most operations</li>
</ul>
<li>Cons</li>
<ul>
<li>Syntax for chained methods can be very complex</li>
<li>Error messages could be improved</li>
</ul>
</ul>
<h4>
Fudge</h4>
</div>
<div>
<ul>
<li>Pros</li>
<ul>
<li>Using @patch is really nice, syntactically</li>
<li>Examples showing web app testing is nice touch</li>
</ul>
<li>Cons</li>
<ul>
<li>@patch can interfere with test runner operations (because it affects the entire interpreter?)</li>
<li>Partial mocking is difficult</li>
</ul>
</ul>
<h4>
Mock (preliminary)</h4>
</div>
<div>
<ul>
<li>Pros</li>
<ul>
<li>Very flexible</li>
</ul>
<li>Cons</li>
<ul>
<li>Almost too flexible. All-accepting mocks make it easy to think you have better coverage then you do (so use <a href="http://nedbatchelder.com/code/coverage/">coverage.py</a>!)</li>
</ul>
</ul>
</div>
<h3>
Acknowledgements</h3>
<div>
Clearly, a lot of work has been put into these mock libraries and others. So I would like extend some thanks:<br />
<ul>
<li>Gustavo Niemeyer, for his work on Mocker.</li>
<li>Kumar MacMillan, for his work on Fudge, and for helping me in preparing material for this post.</li>
<li>Herman Sheremetyev, for his work on Flexmock</li>
<li>Michael Foord, for his work on Mock, and for getting me on Planet Python</li>
</ul>
<div>
Additionally, while I didn't work with them for this post, there are a number of other mock libraries worth looking at:</div>
<div>
<ul>
<li><a href="http://pypi.python.org/pypi/dingus">Dingus</a></li>
<li><a href="http://pypi.python.org/pypi/mox">Mox</a></li>
<li><a href="http://pypi.python.org/pypi/MiniMock">MiniMock</a>, which I've used quite a bit in the past, and I'm delighted to learn that development is continuing on it!</li>
</ul>
</div>
</div>
Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com4tag:blogger.com,1999:blog-6463044249707468993.post-35897432655306717032011-09-07T15:31:00.000-07:002011-09-07T15:31:09.717-07:00Blogging and not bloggingIt's been a month since I started working on this blog, and the only thing I have gotten up is my introductory post, which talks about all the other stuff I want to write. Not quite the start I wanted to get off to, admittedly, but August managed to be much busier than I would have thought, me lacking a job and all.<br />
<br />
That said, I do have a bone to pick with Blogger. It's convenient, free, interfaces with all my stuff, but writing things that include code has been a real pain in the butt. I could inline it as a quote, but I don't get syntax highlighting. It seems I can modify my template to include plugins for syntax highlighting, but given that I would like these bits to be copy-pastable, including the actual code in the HTML seems like a recipe for trouble.<br />
<br />
So I am currently using "gist" for my samples, and embedding them with script tags. This is nifty, certainly, but I'm guessing it doesn't come across well in RSS, and probably to aggregators like Planet Python (which is probably where you are reading this). Furthermore, if I'm already maintaining a github account to get the gists, and for the larger project work, it seems like it would be much more straightforward if I could embed snippets directly from github, so I could do my editing and testing in PyDev.<br />
<br />
I'm sure I'm not the first person to run up against this, so we will see if my Planet Python syndication can bring any knowledgeable commentators my way. If you have any suggestions, especially ones where you can link to examples, that would be very much appreciated.Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com5tag:blogger.com,1999:blog-6463044249707468993.post-63430445046564981972011-07-29T10:21:00.000-07:002011-09-08T11:42:37.942-07:00IntroductionsHi there, I'm Alec Munro. For various reasons, I've been unable to engage online for the last several years. That is no longer true, and I find myself with time, so here I am, engaging (well, I hope so).<br />
<div>
<br /></div>
<br />
<div>
So what am I trying to engage with? Well, I'm a software developer, interested in refining the process of software development to produce higher quality software. In practice, my skills and experience tend towards Python and Web Development, with the last 5 years being spent in the realm of test automation. Let's break that down...</div>
<div>
<br /></div>
<div>
When I say I want to produce higher quality software, I'm defining quality as "that which meets or exceeds my customer's expectations". This is a definition I'm stealing from someone, but which feels correct to me. There are two implicit conditions in that definition that go beyond simply writing good code: that you know who your customers are, and that you understand their expectations. So for me, developing quality software is a very holistic process, that encompasses the entire lifecycle of a desired piece of functionality.</div>
<div>
<br /></div>
<div>
I've been developing web sites for 14 years, starting with static HTML and JavaScript, moving through Flash and PHP, and finally "settling" on Python about 8 years ago. Since then, web development has almost never been my primary occupation, but it has almost always been a tool I could use to improve the projects I was working on. In the Python world, I started with Zope 2, moved to Zope 3, then Grok, and most recently Pylons and Pyramid. I'm biased towards building everything as a REST-ish web service, with a UI built in JQuery.</div>
<div>
<br /></div>
<div>
I came to test automation because I saw a need. I saw (seemingly) automatable tasks being performed by manual testers, and I took action to address this. I learned, with great difficulty, that many things I had assumed could be easily automated were actually terrible candidates for automation, often due to the development process that produced them. I learned about "testability" (thanks <a href="http://misko.hevery.com/code-reviewers-guide/">Misko</a>!), and the role that test automation must play in driving development process improvements. I also gained an appreciation for what I call "proactive transparency", which is the philosophy that much of the information people need is too difficult to find, because those producing it don't know how to publicize it (or don't appreciate the need to do so). In test automation, this applies to results of testing, but I've found it applicable to many other areas.</div>
<div>
<br /></div>
<div>
So that's a rough overview of who I am, and what I can do. But where's the engagement? Well, I find myself without a job, but with a bit of a margin before I <b>need</b> a job. So I thought I would take this time to write on subjects I know about, as well as to study and report on those that I don't. This will hopefully give me the opportunity to broaden my skills (specifically for interviewing purposes, I will admit), while also re-engaging with the development community that I have been absent from for several years. For you, the reader, hopefully some of these topics will interest you, and you will participate in my discussions, to correct me where I err, or weasel further answers out of me when I am unclear.</div>
<div>
<br /></div>
<div>
What kind of topics? Well, I have no formal computer science training, so there's a couple of areas that tend to come up in interviews that I don't think I give satisfactory answers on. These include:</div>
<div>
<ul>
<li>Design patterns. I know many of their names, and I know I use them often in my work, albeit uncredited. I will research the most common ones, and invent problems where they are applicable, and explain why one over the other.</li>
<li>Sorting. Quick sort, merge sort, etc. Using Python for web development, I've never been held back by the performance of a sorting operation, but I understand that these algorithms are considered quite foundational, and I know I've suffered in interviews due to the lack of them.</li>
</ul>
<div>
I will also go into some topics that are interesting to me, and play to the strengths I have developed during my career.</div>
</div>
<div>
<ul>
<li><a href="http://alecmunro.blogspot.com/2011/07/mocking-snakes.html">Mock library comparison</a>. I consider the use of mock objects to be an essential (and often neglected) part of almost any software development project. I also think there are too many Python mock object libraries. :) I will discuss this in more detail, and show examples of the use of each library, and try to illustrate the strengths and weaknesses of each.</li>
<li>Web application development. Because of my recent work history, I have virtually no public code to share with potential interviewers. So, purely as a vanity project, I will create what I consider to be a properly tested and documented web application, and write about the process. I'll try to make a useful application, but I can't promise that.</li>
<li><a href="http://www.rabbitmq.com/">RabbitMQ</a>, <a href="http://www.zeromq.org/">ZeroMQ</a>, <a href="http://www.gevent.org/">Gevent</a>. I keep running across these things, but I've never had an occasion to do much beyond skim their docs. They seem interesting and well regarded by those who are well regarded by me, so I'll look into them.</li>
<li><a href="http://golang.org/">Go</a> (the language, I'll leave the game to my father, at least for now). I've heard being laid off is a great time to learn a new language, and two of the jobs I've seen that would be most interesting mention Go, so I think that will probably be it for me.</li>
</ul>
<div>
To further my ideal of engagement, I will post any code I write for any of these in <a href="https://github.com/alecmunro/Experiments-in-Public">github</a> (also new to me), and encourage contributions from the community. Hopefully, the community will find enough useful in what I create to do so.</div>
</div>
Alec Munrohttp://www.blogger.com/profile/13172977631007255821noreply@blogger.com2