Link to Post about using local jars with leiningen
Posted by Anthony in Uncategorized on November 19, 2011
For my own future reference, here is a link to a blog post about creating a local maven repository and installing a Jar in it in case a dependency required by maven is not available on any of the public clojure repositories: Using local jars with leiningen.
Learning Clojure by Example
Recently I’ve been spending some time learning Clojure and I’ve really been enjoying it. It took me a bit of time to understand functional programming and to begin to grasp how it would help me write better applications. I’m definitely a beginner when it comes to functional languages, but each day I feel that my grasp on it becomes firmer than the day before. I started by going through Stuart’s Programming Clojure book first and then, after making it through the basics there, I started looking at some open source libraries that solve problems that I’m already comfortable with in other languages (such as building web applications).
Yesterday I decided that the next step was to learn my way around the standard functions available in Clojure. I’ve decided to try something new (for me at least) to see if I can work my way through the standard functions rapidly: I’m writing a series of examples for each standard function, based initially on what is in the Clojure cheat sheet. Each example is written as a unit test using the build in clojure.test/is function. I’ll be pushing code up to a repo on Github as I make progress.
I’d love to hear if anyone else has used this technique for learning a standard library. What language did you use it with, did you publish your code and what were the drawbacks, if any? One of the reasons I feel that this is a useful exercise is because it is forcing me to actually write and practice Clojure. I’ve found out things about the language which I might not have otherwise discovered and I have many unanswered questions that I will either answer through further practice or through various Clojure community channels such as the Clojure Google Group or the Freenode #clojure IRC channel.
A few implementation details: I used the fantastically straight-forward Leiningen for generating the project, however I am not running the tests with it. For the tests I have set up a mapping in VIM:
nnoremap .c :!CLASSPATH=lib/* java clojure.main <CR>I haven’t yet done the dance to set up slime.vim but I am sure that time will come. For now I can just type .c while viewing any of the clj files in the repo and that file will execute.
Temporarily Redefine (not stub) Methods for Testing
Today I came across a case where I wanted to temporarily redefine a method’s implementation for purposes of testing. Specifically I want to test with a condition of a large number of records in a database. Since I don’t actually want to load a large number of records into the database I just want to make the system think there is a large number of records for the purposes of the test.
Here’s a gist showing what I ended up doing:
module Count def fake_count words.count + 500 endend
class Thing def words %w(one two three) end def count words.count endend
def assert(value) raise "Assertion failed" unless value == trueend
thing = Thing.newassert thing.count == 3puts thing.count
class Thing include Count alias_method :real_count, :count alias_method :count, :fake_countend
thing = Thing.newassert thing.count == 503puts thing.count
class Thing alias_method :count, :real_countend
thing = Thing.newassert thing.count == 3puts thing.count- Create a module that has the faked version of the method
- Open up the original class and include the module (I want it on all instances – if it were just one I’d use extend)
- While the class is open call alias_method :real_count, :count which creates an alias of real_count that points to the count method
- While still in the open class, call alias_method :count, :fake_count which creates an alias of count to the fake_count method. Note that real_count still points to the original implementation
Once the class has been opened and modified it will return the new value. To undo the change I can just open up the class again and call alias_method :count, :real_count which makes count behave as it did originally.
Why not stub? In this case I wanted to use a method in Thing and just add 500 to it. I probably could have also called real_count + 500 which would have effectively decorated the original count method.
Can you think of alternative approaches? Let me know in the comments.
Experimental Resolution of Gem Dependencies with DNS
Posted by Anthony in Ruby, Technology on July 2, 2011
This week Jeremy Hinegardner (aka @copiousfreetime) was in Montpellier to visit. In addition to enjoying some good meals, good wine and time in the pool we also took this opportunity to work on an experimental gem dependency resolution system using DNS. I’ve written about this before and the latest gist has some new details in it as the result of our work this week.
First of all we’ve outlined how to deal with some of the dependency issues we had not yet dealt with, such as less-than, less-than-or-equals-to and not-equals. Additionally we outlined how to deal with situations where a dependency defines 2 or more requirements (such as ["> 1.0.0", "<= 2.0.0"]). We’ve also added in support for listing all known versions of a specific gem by moving the notion of the latest gem version so it uses a prefix of latest and then putting one PTR for each version of the gem on the gem domain name.
In addition to working on the details of the spec we also got some data loaded! Thanks to the work Jeremy did previously on his Gemology project a lot of the code had already been written. I spent some time working on moving the code we needed into the rubygems-dns project while Jeremy worked on exporting the existing specs we needed from his database and writing an import script. While the implementation is far from complete I’m happy to say that you can actually query the DNS server now and answer questions with it.
First a query to list all of the versions of a gem. We’ll use the Sinatra gem as an example:
dig @ns8.dnsimple.com sinatra.index.rubygems.org PTR
The result will be an unordered list of PTR records, with each record representing a version with the version number in reverse order:
sinatra.index.rubygems.org. 86400 IN PTR 1.3.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 0.1.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 5.1.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 6.1.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 7.1.0.sinatra.index.rubygems.org.
sinatra.index.rubygems.org. 86400 IN PTR 0.2.0.sinatra.index.rubygems.org.
...snip...
So the first line indicates that there was a 0.3.1 version of Sinatra and line 2 indicates there was a 0.1.0 version of Sinatra.
Next, let’s get the latest version:
dig @ns8.dnsimple.com latest.sinatra.index.rubygems.org CNAME
latest.sinatra.index.rubygems.org. 600 IN CNAME e.0.3.1.sinatra.index.rubygems.org.
This shows us that 1.3.0.e is the latest sinatra version published (as of the snapshot).
Next, we can query for PTR records for that same name:
dig @ns8.dnsimple.com latest.sinatra.index.rubygems.org PTR
latest.sinatra.index.rubygems.org. 600 IN CNAME e.0.3.1.sinatra.index.rubygems.org.
e.0.3.1.sinatra.index.rubygems.org. 86400 IN PTR 1.tilt.index.rubygems.org.
e.0.3.1.sinatra.index.rubygems.org. 86400 IN PTR 1.rack.index.rubygems.org.
This shows us that the version 1.3.0.e has two runtime dependencies, tilt and rack, and that they require the latest version of the 1.x releases for each of those. We can then use:
dig @ns8.dnsimple.com 1.tilt.index.rubygems.org PTR
To show us that the latest version:
1.tilt.index.rubygems.org. 600 IN CNAME 2.3.1.tilt.index.rubygems.org
That’s it for now. There is more work to do, like encoding the <, <=, != and dependencies with 2 or more requirements, but this will at least give an example how this all might actually work.
Slides from API Design Matters Talk
Posted by Anthony in Uncategorized on June 18, 2011
I’ve just posted my slides from my API Design Matters talk that I gave yesterday at NordicRuby.
http://dl.dropbox.com/u/3308516/api_design_matters.pdf
Thanks to CJ and ELabs for putting on an awesome conference. Definitely a must-attend conference next year.
Refactoring to Modules
Keeping any application healthy and under control as it grows requires attention to the application’s organization and structure among other things. With DNSimple I’ve been spending some time thinking about how to reduce the size and complexity of some of the larger classes. The impetuous for this refactoring is to make the code easier to understand and easier to test. For the later the goal is to eventually be able to test business logic without needing to load the entire Rails environment.
I currently am trying two approaches to extracting logic into modules. First, I have created a directory in lib where extracted modules will live. I choose to call this directory logic since essentially I’m trying to use it as a place to store logic (as opposed to storing code that describes data models, which will remain in the app/models directory. For simpler classes that only have a small amount of logic I am extracting all of the logic into a single file with the same name as the existing model. For example, for a Contact model the logic would go into a Logic::Contact module. This module is then mixed back into the module. Here is a (somewhat contrived) example:
Before the extraction:
class Contact < ActiveRecord::Base belongs_to :user
def name "#{first_name} #{last_name}" endendAfter the extraction:
class Contact < ActiveRecord::Base include Logic::Contact belongs_to :userend
module Logic module Contact def name "#{first_name} #{last_name}" end endendThis is the simplest form of extraction. Beyond this however is another form of extraction that I am using in cases of larger, more complex classes. In this case I group together some of the logic into a module, usually naming it so it describes the behavior. For example, I have a module in DNSimple called Logic::Domain::Renewable which contains logic for domain renewal.
class Domain < ActiveRecord::Base # ...lots of code... def auto_renew? registry_domain.auto_renew? rescue => e logger.error e false end # ... more code ...endBecomes
class Domain < ActiveRecord::Base include Logic::Domain::Renewableend
module Logic module Domain module Renewable def auto_renew? registry_domain.auto_renew? rescue => e logger.error e false end end endendThe beauty of extracting in this way is that the different behaviors required by the system seem to align nicely into modules which make it much easier to locate code as I continue to develop the system.
So what might the tests look like after these extractions? I already have a fairly comprehensive test suite for DNSimple (yes, there are gaps) so it already is a little bit slow (although not as slow as it would eventually become). With the extractions I can began to test the logic in isolation. For example:
require 'lib/logic/contact'
class FakeContact include Logic::Contact attr_accessor :first_name, :last_nameend
describe Logic::Contact do subject do contact = FakeContact.new contact.first_name = "Anthony" contact.last_name = "Eden" contact end
it "has a name" do subject.name.should eq("#{subject.first_name} #{subject.last_name}") endendWhat I’m doing here is creating a contact class that is not in any way tied to ActiveRecord. This allows me to completely bypass the Rails loading process and these logic tests will run extremely fast. If you take this route you’ll need to make sure to use a modified spec helper that does not load the Rails environment. I call mine lightweight_spec_helper and only load what I need in it.
In closing, all of this is designed to make the application code easier to manage so that I can continue to improve DNSimple and make my customers happier. All of this is really only possible because I have a decent amount of test coverage, allowing me to refactor and not blow up everything in the process. Inevitably during refactorings like this things will break, but my tests cover me and protect me from myself, and thus I can extract and improve without feeling like I’ll shoot myself in the foot.
Service for Subdomains Resolving to URLs
Posted by Anthony in DNSimple, Flotsam, Technology on April 3, 2011
Recently, Dave Winer posted an entry on scripting.com about a need that he sees in the domain market that he thinks presents a good opportunity for a new startup.
The idea is this: make it easy for customers to assign a domain name to a particular resource. Specifically a customer should be able to buy a domain and then give out subdomains to others or allow them to purchase a subdomain. There should be an API of course, and the whole thing should be really easy to use.
As soon as the article was posted I started receiving tweets from people asking if this might be something interesting for DNSimple to consider. From a technical standpoint it makes sense that DNSimple could do this, likely as a separate service. I started thinking about how it could be implemented and came up with the idea of using NAPTR records as the mechanism for software to query to determine what URL a domain name points to. The second thing would be to include a URL forwarding entry so that if you hit the domain with a browser then you’d be redirected to the resource.
Let’s look at an example:
- Assume I have the domain anthony.com delegated to the name servers for this service.
- If I create an entry for twitter.anthony.com and point it to http://twitter.com/aeden then
- If I
`dig twitter.anthonyeden.com naptr`then I would see twitter.anthony.com. 3600 IN NAPTR 0 1 "u" "n2u:uri" "!^.*$!http://twitter.com/aeden!" .- If I browse to twitter.anthony.com then I would be URL forwarded to http://twitter.com/aeden with a 301 Redirect.
The concept is pretty straightforward. I’ve already created a simple prototype, but before I go any further I wanted to find out if there are other people interested in a service like this. Would you be willing to share revenue on sales of subdomains? Would you be willing and interested in integrating NAPTR DNS lookups in your software as a way to resolve a domain name to a URL?
Edit: There seems to be some question as to whether or not NAPTR records are really needed. Here’s why I think they are: A 301 redirect will work, however this means that a redirector server has to be hosted by the service that is providing the delegation, in addition to name servers. NAPTR, with adoption by clients (like browsers) means that the DNS record alone could provide all the details that client needs to make its next move. I think that this is a much more scalable long-term solution and thus I would propose that both a URL forwarding system and NAPTR records are useful for a redirect service.
Why No Wifi at a Tech Conference is a Bad Idea
Posted by Anthony in Technology on March 29, 2011
It seems that SudWeb, a conference near where I live in South France, has made the decision to have no WIFI. Personally I think this is a bad idea and I said so on Twitter, but naturally in 140 characters or less it’s quite difficult to give a lucid argument, so I’m going to try to do that here.
The publicized motive for not having wifi is as follows:
“nowificonferences comes from the desire to give priority to people and interactions. We want people to come listen and share with each other. By removing the WiFi, we remove useless distractions so that the conference really happens between visitors, speakers and staff.”
It’s a reasonable desire but they’ve taken the wrong approach to achieve their goal. Here’s why:
1.) Not having WIFI only punishes those of us who do not have a 3G device, of which there are some, but likely not the majority, especially at a technical conference. Developers with 3G devices will still be online during talks, they will still find a corner to go have a conversation with someone online and likely some of them will even turn their devices into hotspots so others can use their connection.
2.) Not having WIFI means that having hands-on exchanges around specific technical projects or specific web sites becomes much more cumbersome for many and impossible for others. For a conference that is billed as being about the web it’s absurd to not have open and ready access to the web. When I go to a technical conference I often have at least one exchange that involves pulling out a laptop and showing off a site that’s being worked on or code that is interesting. Again, my guess is this will *still* happen, but over 3G.
3.) There are other means that encourage people to talk and share ideas that are more effective. For example, BizConf 2010 used Improv as a means to get the entire conference engaged in an activity that both broke the ice and encouraged attendees to learn the names of those around them. Many technical conferences are now running hacking spaces at the conference so people can get together and program, exchange techniques and ideas and share. Finally more than a few conferences are running parallel unconferences where people can create adhoc groups around topics of their choosing. All of these ideas approach the issue in a creative way rather than a way that penalizes attendees.
Aside from these reasons there are other practical reasons Wifi matters, from the ability to get emergency work done if necessary to the ability to dig deeper into an idea presented by a presenter to the simple act of following an interesting speaker on Twitter during their talk. These things will still happen, but no one will be thanking the organizers of Sudweb for making it happen.
Most likely the outcome of this decision by Sudweb will be that people who are disappointed by the lack of WIFI just won’t come to the conference at all. This is the real tragedy because the goal is to get people to show up and communicate face-to-face yet there’s a good chance that conversations that would have been will now never be.
Update 1: I just realized another aspect of Sudweb’s choice that bothers me. By dictating that there will be no WIFI because they want it to be about people connecting they are essentially treating their audience like children who need to be told how to behave. Rather than assuming that I, as a mature adult and conference attendee, can choose when, how and with whom I interact at a conference, they attempt to dictate this by setting certain conditions.
Presentations in Stockholm
Posted by Anthony in Cucumber, Presentations, Ruby, Technology on March 28, 2011
This month I had the pleasure of traveling up to Stockholm to speak at a couple of events there. First let me just say that Stockholm is an amazing city full of style, character and charm. From classic coffee houses to modern restaurants there is something for anyone. I highly recommend visiting if you have a chance – you won’t regret it.
While I was there I gave a talk called “Why Ruby, Why Now?” at the first dyncon as well as a talk titled Harnessing Cucumber at Valtech Labs. The first talk was an introduction to Ruby. I have been itching to give an introductory talk for a while and I’m glad this gave me the chance. The audience was a bit more knowledgeable about Ruby than I expected, so some of the items weren’t new to them, however I believe there was still enough in the talk to keep people interested. I also blazed through it since it was right before lunch so maybe people were enthralled merely by my lightning-fast presentation skills.
The presentation is available online on Github: https://github.com/aeden/presentation_why_ruby and was created using Scott Chacon’s Show Off.
The second talk I gave was an intermediate to advanced talk on Cucumber where I covered a lot of what I have learned about Cucumber over the last year of using it. Cucumber has become an important part of my test suites because it allows me to test the experience of using my software. This talk covered some of the various command-line switches and cucumber.yml configuration options in the first section and then moves onto testing APIs and CLIs. I’ve found that testing both of these interfaces to my applications has helped tremendously in improving the application and at the same time providing a safety net for refactoring, which is exactly what I want from Cucumber. This talk is available as a PDF and was created using Keynote.
I appreciate the support from both of the audiences and the discussions that followed both talks and I look forward to the opportunity to visit Stockholm again in the not-to-distant future. Thanks as well to Peter Svensson for putting together dyncon and to Peter Lind for opening up the Valtech offices for my talk there.
East Coast Roadtrip
For the month of February I find myself in the US for a stretch of 3 weeks. It all starts with MagicRubyConf and ends with Parallels Summit (both in Orlando). In effort to make the most of this trip I’ve decided to rent a car and drive up the East Coast to Virginia and then back down again, stopping at various dev shops along the way.
I’ll also be stopping at Startup Riot in Orlando as I’ve heard great things about it and I always love to see what other entrepreneurs are working on.
Without further ado, here’s my travel schedule:
Feb 3: Montpellier -> Paris -> Orlando
Feb 4&5: MagicRubyConf @ Disney World
Feb 6&7: Melbourne, FL
Feb 8: Miami, FL
Feb 9: LessEverything, Jacksonville, FL
Feb 10: NC
Feb 11-14: InfoEther, Reston, VA
Feb 15: Relevance, Durham, NC
Feb 16: Startup Riot, Atlanta, GA
Feb 17-18: Hashrocket, Jacksonville, FL
Feb 21: Envy Labs, Orlando, FL
Feb 22-24: Parallels Summit, Orlando, FL
Feb 24: Orlando -> Paris -> Montpellier
In case it’s not obvious, I’m not a winter sort of person, so if the weather craps out then I probably won’t make it any further north than…well, wherever it starts getting icy.
