What’s wrong with this code? A bit of background for this example; `driver` is a Selenium::WebDriver object, the Selenium server is remote. Also, this technique is applicable to all expensive code that does the same thing over and over.
1 2 3 4 5 6 7 8 9 10 11
def first_name_field (driver.find_elements:id, "name") end
unless first_name_field.nil? if first_name_field.displayed? if first_name_field.enabled?
first_name_field.send_keys"Dylan" end end end
Apart from being terribly contrived, this code is bad because every single interaction with first_name_field causes a call to find_elements, which in turn reaches out to the Selenium server. You’re adding a network round trip every single time, and for no reason. Instead of asking the browser to do this:
Find the “name” element (line 5)
Check if the name element is displayed (line 6)
Check if the name element is enabled (line 7)
Send the string “Dylan” to the name element (line 8)
You’re asking it to do this:
Find the “name” element (line 5)
Find the “name” element (line 6)
Check if the name element is displayed (line 6)
Find the “name” element (line 7)
Check if the name element is enabled (line 7)
Find the “name” element (line 8)
Send the string “Dylan” to the name element (line 8)
This doesn’t just occur through Selenium commands (although Page Object Model code and libraries are often prone working this way). Loading configurations, accessing web services, validating data. There’s many places where you’ll burn up cycles (and correspondingly incinerate coal and warm the planet dooming us all just a liiiiitle sooner. Yeah, I actually do think wasted compute matters.) and, maybe more sellable to your Product Owner (who clearly doesn’t care about the environment), this will make your code faster.
Are you writing this down, and taking a memo?
No, like, literally. Take a memo. This kind of memo. Memoization is where you save the result of an expensive operation and return the saved result every time the operation is requested. Like responding to everything your Mum says on the phone with “Uhuh”, Memoization swaps one resource (computing time or brain-cells) for another (memory or engagement). Memory is cheap. You can probably throw more into your server if you need it. (But you don’t need it. Just… You don’t, trust me.)
If you use Ruby, you’re probably already taking advantage of Memoization:
def proscuitto_pizza @proscuitto_pizza||= Pizza.new(:delicious) end
That’s right, the ||= operator in Ruby effectively does Memoization; If the variable exists, it does nothing, else it sets it to the code on on the right of the operator. Wrap the whole lot up in a method name and you’ve got a memoized value.
For example, we could re-write the code above as so: def first_name_field @first_name_field||= (driver.find_elements:id, "name") end
That single line change means that Ruby will remember the field in question and we won’t need to ask the Selenium server for it again, saving us a heap of time.
(Selenium Sidenote – Unless the page changes of course. How do you know if the page changes? Well, every navigation will do it (including those involving submitting forms) and some AJAX requests do it. You need to understand how your site is implemented… But then, you should anyway so you know what you’re actually testing).
Git (and its ilk) are tools for working collaboratively (especially with hostedservices). Your commit messages are your best weapon for communicating context, and every collaborator, including Future You, depends on context to be productive. It’s not opinion, it’s Science!
See, human memory is so bad it can be erased by passing through a doorway. We can defeat doorway-induced time wasting (not to mention the change of screaming “what the hell is this?!” at code someone, maybe Past You, wrote) with great commit messages.
(Image courtesy of XKCD because Randall is a champ.)
A great commit message:
Is never ‘left behind’ by code changes (unlike comments)
Gives all the info you need (ticket numbers, reasons for change, expected behaviour changes)
Shows relevant changes around your change
Summarises everything in 50 characters or less as the ‘subject line’
All this info, the context of the change, makes problem solving (read: coding) more efficient. Good context helps any collaborator; there’s evidence that context-based approaches to problem solving are more effective.
They’re occasionally a useful source of discussion (usually in curated communities or niche content) but mostly, they’re a swirling cesspoll. The comments are where people write hateful, toxic vitriol.
On YouTube this is often in the form of attacks on the presenter. Open Source projects, though, tend to get more… religious. Your product isn’t their favourite product and thus must be purged. They want a feature from the thing you made and gave them for free and DAMN HOWDY if you aren’t the worst person alive for not giving it to them. They don’t understand how to use it and so you must perish.
If you leave pointlessly negative comments on Open Source projects, screaming demands or trashing the free work people have done for you, then as far as I’m concerned you suck as a developer and you’re a bad person. I have more respect for the noobiest of noobs then I do for people who piss all over others in Open Source.
I’d never hire anyone who made their team-mates feel bad when they wouldn’t do something optional for them. I’d never hire someone who yells at others rather then fixing bugs, who acts like they’re entitled to things, who can’t interact professionally in public situations. As far as I’m concerned, you’re not a good developer if you do those things, you’re a terrible staff member who happens to be OK with development.
Being a good Open Source citizen in the venues you use it is, in my mind, a defining characteristic of good devs. “GitHub Resumes” aren’t useful just because they show your work style but because they show your workplace style. How you’ll get along with others. Whether I can trust you to not ruin my team. If you’re helpful and good at communicating and compromising and not a complete dickhead.
(Corollary: If you defend people who do this because they’re productive or talented or useful for the project, you’re also a sucky developer and a bad person. We don’t let famous surgeons ignore ethics no matter how brilliant.)
Even print media about rich people making more money is still a thing, which probably says something about who those people are and their attitudes to change. Yes, that’s an Old White Men joke.
But print media knows the end is nigh and has moved online as well as being available in print, and Fortune magazine is no exception! It’s even writing articles about these shiny new technical whatzcalits, like a recent article, ‘Why APIs will save your business from getting “Uber-ed”‘.
Oh, sweet fish sauce, that article. It’s… you don’t… I started making fun of it on Twitter then quickly realised there was just too much and you, Dear Reader, would be better served by a blow-by-blow commentary. Fair Use Away!
Why APIs will save your business from getting “Uber-ed”
It’s no longer about what you build alone. It’s about how you smartly incorporate what others have built.
I am seeing a technology shift that only happens every 10 to 15 years – one in which companies will become “composites” of other companies.
(Like how, 10 years ago, Apple become a composite of Swarovski, Swatch and 90s era Sony, or how Alta Vista became a composite of Betamax and Crystal Pepsi)
Uber is a perfect example. It didn’t have to build its own mapping, payment, or communications services. Instead, Uber is a composite of what it considers the best of those programs and more — Google Maps, Braintree (payment), Twilio (for mobile SMS), Oracle, etc. Uber was able to quickly connect to these systems using little pieces of code called APIs.
(Yes, the API itself is a tiny chunk of code you just put in your own code and magically, billing happens)
MuleSoft is in the business of APIs, and today’s announcement of MuleSoft’s latest $128 million financing round at a $1.5 billion valuation is evidence that this trend is more than gathering steam. [Disclosure: I am an early venture investor in MuleSoft.]
(Disclosure: The only way I can made money from my API middleware As A Service investment is convincing you all that your existing APIs are in fact legacy ‘integrations’ instead)
Companies pursuing API-led connectivity strategies include MasterCard, Unilever, Nestle, Tesla, Intuit, BSkyB, Verizon, News Corp and Sutter Health. This shift it is only possible because of a once-in-a-generation convergence of megatrends: cloud, mobile, and the “Internet of things.”
(API-led connectivity strategies: much better then those old ‘protocol’ and ‘carrier’ based ones. Also mega is _last_ generation’s slang. The hipster generation prefer ‘whatevertrends’)
If you’re not taking full advantage of this trend, your organization could be “Uber-ed” and out-innovated, just like the taxi companies have been. Uber has upended the global taxi industry in large part by using APIs masterfully. In just a few short years, Uber has become seemingly ubiquitous and is reportedly valued at $50 billion. The old-world taxi companies are struggling to compete with this API-savvy juggernaut. You don’t have to be in the transportation industry to be Uber-ed. Any business without a viable API strategy stands to be altered on this scale.
(This is so blatantly wrong it’s being funny _for_ me. Taxi services weren’t out-innovated because of Uber’s mystical oneness with the API universe. They were out-innovated because they didn’t try to innovate at all. They still don’t; Their reaction has been to try to legislate, sue and bully Uber out, not try to fix their product and compete. This is like saying a greasy sidewalk hotdog grill gets less customers on a date then a fancy restaurant because the restaurant’s supply chain is faster)
Why CEOs Should Care
Companies are currently spending more than $590 billion per year to integrate existing, disparate systems. Traditional businesses rely on large sales forces, paperwork, and fax machines to generate revenue with customers and through partners. This is expensive, time consuming, and scales only as fast as the sales force grows. Today’s startups eliminate much of this friction, time, and cost by building their solutions with best-of-breed components, which they access via APIs, or “application program interfaces.”
(So existing disparate systems, they don’t have APIs, they have ‘integrations’. Because they’re old, see? APIs are jazzy and sexy and new. So new, we only literally just now got a definition for them, halfway through this article! Until APIs were invented last year, absolutely every business was unscalable and did everything with FAX.)
Using APIs as building blocks, Uber was able to go to market far more quickly and nimbly than its competitors. What’s more, in August 2014, Uber launched a publicly-accessible API that would become the foundation for their digital ecosystem, allowing companies like OpenTable, Google and United Airlines to embed Uber into their apps.It’s a mutually beneficial arrangement: Uber reaches more customers and establishes new revenue streams, while app providers like United Airlines, Open Table, Google Maps and others can offer a transportation service to their customers and profit from it at the same time.
(Again the fallacy that sexy startup VC backed API based data-viagra, and not being thoroughly better, are what made Uber work. This time, thought, it’s because you can get a pizza on the way to the airport. What’s the deal with Airline food AM I RIGHT?)
Contrast this with Hertz, Avis, and other rental car agencies that have been United Airlines partners for decades, but are nowhere to be found in the United mobile app. That’s because these rental car companies don’t have an API (or at least not one that’s public). OpenTable, Google Maps, Starbucks, and dozens of other apps offer the Uber service — but not services from Uber competitors like Lyft — so there is definitely a first-mover advantage in each market.
(…You literally just said that lack of an API is why United’s business partners aren’t in their mobile app)
Another simple but enormously successful example is UPS, founded 108 years ago. UPS has captured a large share of the parcel-shipping market for the burgeoning online commerce sector by publishing an API – just a few lines of code – which makes it easy for shopping sites to integrate shipping seamlessly into their online check-out process.
(Again this ‘few lines of code’ thing. Every word in the phrase ‘an API – just a few lines of code –’ is bullshit. APIs can take thousands of lines of code to write and powerful ones, hundreds of lines to consume. That’s completely ignoring that APIs aren’t actually code, any more then a delicious cooked steak is DNA)
The “Connected Era” is Happening Now
There are progressive management teams productizing their company’s value-add as a service via APIs now, allowing any connected business to instantly become a customer or partner.
(I think I just went partially blind from buzzword poisoning)
Everything and everyone will be connected digitally – including customers, employees, partners, and even “things” like appliances and cars – all through APIs. How a business wins or loses is increasingly dependent on how well they connect to external third party apps, devices and services.
(Connecting to things now acceptable as a substitute for competence, performance, price, utility or human rights)
News Corp Australia’s CIO Tom Quinn last year declared a “cloud first” strategy that gets rid of hundreds of applications residing in the company’s data centers. This shift requires big changes in the way IT is delivered. Said Quinn: “Technologies are changing so fast, and new systems are coming onboard so often, that you don’t want to be locked into a big monster piece of tech. We are not holding the business ransom to detailed, intricate, costly in-house development in order to get things hooked together.”
(No, now you’re holding it to ransom with services you can’t customise, by forcing (possibly good) process change on unwilling staff and by risking services being sold, absorbed or shut down.)
With APIs, you can hook, and unhook, to the best available software and services on your own timetable.
(Making in house systems talk uses ‘big monster piece of tech’, is very hard, messy. Making cloud services talk uses APIs, is somehow much easier despite doing the same thing, simple. Providing those services don’t go bankrupt, don’t have downtime, support the operations you want via API, are reliable, don’t break the API randomly, don’t communicate insecurely, have well managed downtime, support request caching and retries…)
Sutter Health is a large hospital network in California serving more than 10 million patients each year. It created an app in three months with APIs,
(Did they build an app which they built an API for, or did they build an app that used existing APIs?)
versus nine months without, to help diagnose and better treat an autoimmune disease.
(Were the time savings due to actions Sutter Health took, or just made possible by the systems they’re using being more modern? Also, how do you know how long it would take them without the APIs? Do you have an API to contact the parallel universe where they don’t use APIs to ask Sutter Health how long their app took to develop, and if so, how do the people in that universe communicate with your API, given they don’t use APIs?)
Previously, accessing information across multiple data sources used to be a huge challenge. Now it’s possible to get real-time access to healthcare data. The Sutter Health app connects disparate data—from EMRs to administrative systems—and can display this data on any device.
(Some false correlations here. News Corp moved its support software into the cloud to avoid lock in and APIs let you connect different apps which might avoid lock in SO NEWS CORP USED APIS! It used to be hard to access multiple sources of data (apparently) and now you can get real-time access to data and Sutter Health’s app was delivered 6 months faster (apparently) SO APIS LET YOU MAGICALLY ACCESS ANY DATA IN REALTIME!)
So whether you’re the CEO of a Fortune-500 company or small business, building a company from scratch or reinvigorating a well-established one, you owe it to your stakeholders to explore what APIs can do for your business.
(So please go shout at your CTO to buy the first _enterprise grade_ API-based product he can find: mine)
Gary Little is a general partner at Canvas Venture Fund, an early-stage venture-capital firm based in Menlo Park, CA. He serves on the boards of Adara, Evernote, MuleSoft, PeopleMatter, Sonatype, and Totango.
(And yet he still doesn’t seem to fully grasp what an API is.)
This article, man. It seems to fundamentally misunderstand what an API is, treating them like a chunk of code that can be applied to any system to make it vomit money. All of the effort of making or implementing to an API is handwaved away. It draws this imaginary distinction between system integration of older & non-cloud products (which apparently don’t use APIs for some reason) and integration with cloud products (which do).
Plenty of older systems have APIs. They’re just shitty. Even if you use a modern service it’s not like lego; you have to tell the API what to do, and if you are linking cloud products you often need a 3rd party system to host the glue code linking them together and implementing your business rules. And there’s going to be just as much business rule logic for a new API as an old one; It’s only things like data marshalling and synchronisation that most truly non-API based legacy integrations are bloated by. There’s just often a LOT of that.
That’s disregarding that you need to have APIs offered by the systems you want to integrate. If your core business app is from a 3rd party and has no API you’re screwed. If your billing system isn’t out of contract for 15 more years and doesn’t have an API you can’t exactly add one without assistance. There’s no magic panacea for crap systems. Good systems have good APIs, but lots of otherwise perfect systems don’t. You can’t forcefully add them. The better version of this article avoids treating APIs like a miracle (and all the logical fallacies). It focuses on flexible and well-written systems, with open APIs and data formats forming one part. But it also focuses on using industry standard business processes, the importance of offering an API to, at least, your business partners, and providing enough value through it that people want to consume it.
The entire article reads to me like a PR piece, trying to get CEOs in a buying mood for ‘APIs’ like they’re pieces of hardware, in the hopes that they’ll investigate the author’s VC baby as an ‘Enterprise’ option. Even if this isn’t the case… It’s just a load of bollucks.
From the beginning of my career, I’ve been tending smaller and smaller. From consulting gig, to Government enterprise, to 300 person company, to smaller Government enterprise (never again) to a publishing company… Each one getting smaller in size, and feel. Agile, dynamic companies full of smart people is where it’s at.
I’ve also realised that I want to make things that matter to me, and one thing I’m really passionate about is developers. I *love* helping people and I love making cool shit, so being able to help people make cool shit is really exciting to me. I also think that people need time to think, to work and act… Doing things manually that aren’t valuable wastes the most valuable thing any given person has, their mind. I want to help free them.
Both of these put me on a trajectory to one single possible outcome, which I’ve chosen to put in interpretive danceeasily digestible image format:
(This is San Francisco)
(I am here. Over my right shoulder is the Bridge)
(I am Ruby Developer Evangelist)
(I am Employee Number 16 Here)
(They even gave me a hoodie)
(My job involves a lot of trips on these)
(I’m also required to drink a lot of these. It’s a burden)
(Sauce Labs do Selenium Testing in the Cloud)
(It’s fucking AWESOME)
(You get Screenshots for every action and video of the entire test)
(And if you’re not able to deploy development to the outside world, we provide Sauce Connect, an awesome VPN tunnelling solution)
(Sauce Labs runs our own cloud)
(Instances run in seconds and last only as long as you need. Our CEO calls it Efervescent Computing)
(I am insanely excited to be able to work with such smart people on such a cool product)
My bailiwick is to make it better for Ruby developers to use the product, including improving the gems, writing better documentation and building the community. Plus, a unique opportunity to use my personality to insult people all over the world! If you want to offend your manager, disrupt your office and get kicked out of your favorite bar for getting shouty about whether RSpec shits all over Test::Unit (It does), let me know. Hell, even if you just want help with the Sauce Gem or tests from Ruby land, hit me up.
So I worked all weekend this week. I won’t get paid. I won’t even get a nod from my boss, although I was there for even longer for a standard work day. Jerks. Time to burn the office down. Get my stapler back.
The idea is that you spend a day focusing on implementing the same thing over and over, so you can hone your professional skills. In the same way as a sculptor might practice straight lines over and over, we implemented Conway’s Game of Life using TDD techniques in 45 minutes. Every 45 minutes you had to delete your code and tests, debrief, and start again with a new constraint. Some of the constraints felt more annoying then educational, but on the whole I felt I got something out of every session. I also got to teach a couple of people something about TDD & RSpec, and I love helping others improve, so I got a kick out of being able to contribute like that.
I’m going to post how I found each session today, then mull over the others and post some observations a little bit later. I think it’s best to see how learning effects you in other contexts (like actually at work) before you jump into critiquing it, so I’m going to see how the next work week goes.
Language: Ruby Testing Framework: RSpec
This session just booted people off into implementing Conway’s life. I worked with a young Thoughtworker whose name eluded me, and we got about halfway into an implementation before time was up.
We spent the majority of this session just discussing what way to do things. I was a big fan of using a “Cell” object which maintained a list of its own neighbours, without directional information because it doesn’t matter. Doing it like this allows for arbitrary topologies (And I suspected that might be one of the constraints.)
Potentially tricky issues with this approach include implementing the tick for every cell at once(If you duplicate the cells, you have to duplicate the network and ensure you’ve duplicated every cell with its new state. If you mutate the network in place, each cell needs to know if it’s neighbours have ticked, and if so, what their state was last tick.
At the end of the session we had a discussion about what techniques people tried. Having a “Cell” object was quite popular (OO is like herpes, it spreads with contact), there was one “have a universe holding an array of cells” solution, and the one which I liked most, which was using the co-ordinates of the cells as a key for a hash of booleans, representing whether the cell is alive or dead. I really liked this… It’s unbounded (unlike an array in many languages) and *doesn’t* require a hojillion objects.
Session 2 – Ping Pong
Language: Ruby Testing Framework: RSpec Constraint: Each time you write a test, you ensure it tests properly, then you pass it to your pair and they have to do all the implementation. Then they write the next test, and you implement that
This session we decided to try the hash technique one of the groups suggested last time. I say”we decided” but actually mean “I decided”, because prevarication frustrates me, my partner had no strong opinions and I thought it sounded interesting so I made a snap decision.
The Ping Pong criteria is how I’d probably prefer to do pairing in the future, although usually it irks me (I need to be doing something and my “I’m not doing anything” behaviors usually irritate my pair). It meant that your tests had to be higher quality, and there was a defined place where you had to hand over to the other member of your pair — No long stints at the keyboard or just watching.
We didn’t get an implementation finished though, although I worked out how I’d like to derive neighbours. I proceeded to teach people a tiny bit of matrix math all day (more on that later)
Session 3 – Silent Ping Pong
Language: Ruby Testing Framework: RSpec Constraint: The same Ping Pong TDD as before, but this time you’re not allowed to talk
I paired again with a Thoughtworker this time, a gent from China called Hiyun (I hope, sorry if I’m wrong mate >.>). Wow. Dude was a shortcut pro. I learned a shittonne of RubyMine shortcuts and tricks I’d always wanted too but never devoted time to (Which is obviously my fault). It was really cool, probably my favorite session of the day.
We went back to the “Cell as self aware object” paradigm (drink). With the exception of a couple of inadequate tests, this session worked remarkably well. The inadequate tests required a lot of gesticulating. Once you’ve written something it’s hard to prove that the test is wrong rather then the code.
I think not being able to talk focused our attentions on communicating *only* our requirements through tests. There was no discussions of where you worked, what you thought of Test::Unit VS RSpec, why’s DHH’s hair like that; it was purely a “get shit done” event.
I think the most surprising thing was that we finished. It was almost like being unable to design architecture by consensus made one arise naturally out of requirements, which I am… skeptical of. I’m not sure how well our solution would have accommodated change, but maybe most software projects are simple enough that it doesn’t matter.
Session Four – No Primatives
Language: Ruby Testing Framework: RSpec Constraint: Rather then using native types to store results, cells and so on, use a wrapper class or object. No Arrays of cells, no Object.live? returns true
Oh god so hard. Getting away from primitives in Ruby is hard. Every time I wanted to wrap something I heard a tiny voice in my head stop talking about bees, games, cooking and Alice in Wonderland for a minute to scream “NEEdleSS ComPleXItY!“. All I wanted to do was use built in objects so I could rely on methods that Someone Else Has Tested™.
This session, we did something horrific. We decided that, if we weren’t going to use primitives, we’d use something as far removed as possible. Something so non-primative it’d make your eyes haemorrhage. Files.
Yup. Files. To check if there was a cell at (4,5), you checked the directory ./data/4 for file 5.cell. If it existed, it was alive. Touch a location to make a cell alive, rm to delete it. We were planning to store the current generation number in the file to allow for ticking.
How’s that for non-primitives, bitches?
Session Five – Tests must pass in 3 minutes
Language: Java Testing Framework: JUnit Constraint: Once you start writing a test, you must write code to make it fail in three minutes or less. If you get to three minutes without it passing, you must revert all you changes and delete your test
The intent of this constraint, I believe, was to force you to test small amounts of functionality rather then huge sweeping changes. The idea is that small tests are good tests, and it’s tempting to write large tests that try to do too much. When they fail, you’re not actually sure why, and you lose much of the advantage of a full test suite.
My pair (Hi, Mike!) and I chose Java because it was our lingua franca (Scala was preferred but it’s quite hard to use a language without a dev environment, oddly enough). This may not have been the wisest choice, because of one simple truism:
Fuck me Java is Verbose!
It’s not just the punchline to the “what’s wrong with other people’s languages” joke. It was never really bought home to me just how verbose Java was until I had to spend so much time setting up each test. I’d just spent most of the day writing Ruby and now I’m having to give all my tests annotations and a typed, static method signature, and set up my variables types, and then set up and type the method and ensure to return the right sort of thing, and just making so much boilerplate it nearly made my eyes bleed (I propose we call this Stigjava.)
Even Mike, who writes Java for a living, was surprised. He said it bought Java’s verbosity into stark relief after a day of writing Ruby and Haskell. It forced us into doing true TDD because otherwise we simply couldn’t make a test that tested anythingin time. We had to implement the minimal amount every single test pass. Here’s how we had to test that we could get a list of neighbours for a cell:
Write a test to ensure that there is a “getNeighbours” method. Just that one exists. Pass it
Write a test to ensure the method returns an (empty) ArrayList. Pass it.
Write a test to ensure the method returns an ArrayList containing eight things
Run out of time because it took so long to learn how much code we could write at once
It was just astonishing. I’m not Java bashing (so passé), just really surprised. Writing the code to pass things, and even the tests, wash’t too hard, just getting to a point where we could do something took forever. And Mike is an IntelliJ wizard – Otherwise we’d have been screwed. He was making sweet combo love to the keyboard to bust out methods and variables and implement the signatures correctly and we were still fighting the clock.
Session Six – No Returns
Language: Ruby Testing Framework: RSpec Constraint: None of our methods could return values.
Woah. OK. Globalling it up. During this session I had a bit of an idea how to use events to generate a grid of neighbors, but didn’t implement it cleanly. Actually, this session was embarrassing because I forgot that Ruby is pass-by-reference, so resorted to using Globals. Don’t tell my mother. The solution wasn’t really productive, just because every time I manipulated the global objects I felt dirty and wanted to cry.
During this session, the pair using Haskell gave up on the constraint and just started trying to get it working at all. Globals were popular (at least we weren’t alone wallowing in filth) and only one group used callbacks. The idea I’d had was callback/eventing based, but wasn’t async, so obviously I need to do a bit more work about doing that kind of programming at need, rather then when forced.
Then, we had beer, a debrief and a powwow. Roughly half the room left straight away and the rest wanted to hang for a bit, which I always enjoy. I’m looking forward to the next one. I’m thinking this time, we use the presence of machines on a network as live cells….
(If you just want the solution, check out the “Solution” section below)
My parents have a Linksys SPA-3102 ATA for making long distance and international calls (family in Victoria, daughter in Austin) because the idea of using a headset and a desktop program is weird and disturbing. Well, and it’s easier. Hi dad!
Recently the VOIP server (Privately operated) was broken into and used, no doubt, for one of those cheap phone cards or to power some sketchy “Hello this is Microsoft what is your credit card you have a virus in your cheese” scammer. The server admin reset the DNS binding, security and username policy so the ATA had to have its settings updated, which proved a challenge for my parent because the bloody thing wasn’t responding to its web interface.
So since I’m vising them at the moment I’ve been taking a look at the adapter and found that indeed, it’s not responding, and I’ve checked every device on the network to find out if it’s one of them (Which first involved finding the IP of the router because apparently 192.168.1.138 is a ‘proper’ address for a router. Which is security in the same way that hiding a key under the doormat is: You deserve to be broken into).
The problem was, I figured out, that its web interface was disabled (somehow). You can fix that, thankfully, with the magic of DTMF tones.
It turns out these particular ATAs have a DTMF interface usable from any connected handset. So, as long as you’ve got a handset, you can dial numbers into it and get the information (and perform any configuration) you need.
Finding your ATA’s IP address
Enter the DTMF administration console by entering * * * * into the phone and waiting for the lovely British Robot Lady at the other end of the phone (I’m going to call her Estelle) to tell you you’ve entered the “Linksys Configuration Menu“.
Enter 1 1 0 # and Estelle will read out the device’s IP address.
Enabling the Web Interface
From the main menu (Just after Estelle welcomes you to the configuration system):
Enter 1 #
Wait to be asked to save
You should now be able to head to the IP address quoted, on port 80 (the standard HTTP Port) to access the web interface, which is what I recommend for most tasks (If only for reasons of speed). Oh, and don’t forget you’ll probably find Advanced Admin mode more useful… Click on “Admin Login” then “Advanced on the right hand side of the web admin console’s header to enable it. And, just because it’s not *overly* clear, all the VOIP settings are under the “Voice” tab.
JQueryUI has updated, and I want to take advantage of one of the new features (the response event for auto complete, fired after a search result is returned but before the menu is displayed), which means updating to the new version of JQuery… And re-creating my theme.
Now, “Luckily” I’m constrained in the colours I can use by another developer’s choices (I have to look pretty in their page, and was directed to use their colour scheme exactly), but that still left me with the prospect of trying to remember all the damn colour values, shades, effects and additional wunkery to apply, a prospect of slow revision over several hours, and not one I was looking forward too anymore then I’d look forward to being repeatedly slammed up against a large, moist, shaved yak covered in flaming mashed bananas. Bananas are fucking repulsive.
Reading through the CSS file produced last time, though, I don’t have too! Line 50 of jquery-ui-1.8.23.custom.css contains this gem:
To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,%20Arial,%20sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=444444&blahblahblah.......
That link takes you to the theme roller, with all your previous settings, ready to download suitable for the latest version of JQueryUI.
If you, like me, are a mass of doughy flesh and don’t particularly have an interest in sport (see post-script 1) then you may be trying to find things to do for the next month or so. I’m going to try to spend the time training for the things I *am* qualified for, the intellectual, lazy practice of programming. (Don’t bitch, laziness is good).
I want to be world class. Everyone wants to be world class, because it’s nice to be famous and it’s deeply satisfying to be very good at something you create. I’d say, if you don’t want to be very good at the job you enjoy, maybe you should be doing something less involved, useful and creative then programming. Like, say, becoming a BA, or something more important, a barista. I’m not good at sitting still, I hate not achieving things, I loathe being passive and I need something to do, and that’s going to be learning and making. I haven’t enough life to not spend it making shit.
World Class means practice. You need to apply yourself to improving constantly, you need to record and manage your performance and you need to try again and again and again to get better, bringing in new challenges, new work and experts. One way to incorporate new ideas and experts into your day is to watch videos *by* experts. I watch stuff while eating dinner because playing videogames is too hard with a handful of chicken and the mouse gets sticky. Gross. So videos, specifically lectures and conference talks, are the order of the day.
is that gut instinct is wrong, so code inspections can fail. Fall-through case statements get a beating, as do assignments, brace alignment, with and other things I didn’t follow because I was busy writing this post. A really enjoyable presentation, y’all should go check it out. Do you some learnin’, rather then being a lardarse. Two Piece and A Biscuit does not a good hacker make, unless you’re watching something enlightening.
Post Script 1
(Seriously, you like something but rather then play you want to sit on your arse and watch it? Not to mention that some people are so xenophobic or so uninspiring that you they to stake their ego on whether the best of their country can beat the best of other countries at an arbitrary game?)
My ego, being almost as big as my manhood, ensures me that JetBrains have released RubyMine 4.5 today simply to correct the error which I publicly shamed them about in my last post. Shaming may be as imaginary as my own sense of the same.
Please don’t correct me.
Regardless, go fetch the new version posthaste, take the version restriction out of your gemfile and you’re good to go.
Well done JetBrains, you have Pleased your Master.