Simpler dependency injection
In my last post, I wrote about how Java’s final modifier could be replaced with a mutable modifier, helping us to follow modern coding practices.
Another feature Java and other languages lack is a built-in understanding of dependency injection. I’ve been using Spring and Guice for a few years now, and it’s so clear to me that dependency injection is absolutely essential to writing a complex application. Even more than separating code into classes, we must avoid mixing the wiring with the logic. It makes code much more testable – if you look at the Testability explorer metric, it is partly based on the expense you incur in testing when a dependency cannot be injected – you are bound to test the object with that particular collaborator.
In Java, a typical incantation of constructor injection looks like this:
class Foo { private final Dependency1 d1; private final Dependency2 d2; public Foo(Dependency1 d1, Dependency2 d2) { this.d1 = d1; this.d2 = d2; } }
The only information we are providing here is that to construct this class, we’ll need access to two dependencies, and we’ve given them names. This is how most classes should start, and the list of dependencies can be long. Why not treat this just like arguments to a method? We just provide the types and names of the arguments, and then they become new variables in method scope.
What we need to improve this is Properties. Just ask Java Posse co-host Joe Nuxoll – Java needs properties. If you don’t know, a property is just like a public member variable, except that you can write a set or get method for it later if you like. It replaces the silly Javabeans spec – to client code, it looks just like a public member, you just use object.property = 1 to set and object.property to get. I like how they are implemented in ActionScript, with set and get keywords to override the assignment/dereference:
public var one:int; private var _two:int; public function get two():int { return _two + 1; } public function set two(i:int):void { _two = i - 1; }
Now we can dream up an example:
class Foo(Dependency1 d1, Dependency2 d2) { void doThing() { d1.print(); d2 = null; // not allowed - the property is read-only } Foo foo = new Foo(new Dependency1(), new Dependency2()); foo.d1; // also not allowed - the properties are private
This would create private read-only properties d1 and d2, and a default constructor that requires both to be passed in. It’s important that the values are final – we want to reduce the mutable state at runtime, and assigning the properties during construction allows this.
Ok, now setter injection: if the dependency is optional, meaning we could have a Foo in a valid state without it, then it might be appropriate to inject the dependency with a setter instead. (For some reason, setter injection seems to be the preferred way in Spring – which is wrong.) We could allow a convenience for setter injection as well, simply by adding a default value for that dependency in our “class arguments”:
class Foo(Dependency1 d1, Dependency2 d2 = null) { } Foo foo = new Foo(new Dependency1()); foo.d2 = new Dependency2();
Now the default constructor takes only one argument, of type Dependency1, which populates the readonly property d1, and the read/write public property d2 starts off as null. Because it’s a property, outside code can set it. The only aspect that’s missing here is if you want to have additional constructors – but with no additional syntax, you could just write those constructors out in the class body.
The more I have thought about this, the more obvious it seems that injected dependencies of a class are analogous to method parameters, at one scope higher. Why not make the syntax the same, so that this good practice is the easy way? I’d love to hear whether you think this is a good idea.
Java’s final modifier is backwards
In Java, there’s a modifier that can be applied to a variable, and it’s called final. Final can also be applied to classes and methods, to prevent overriding, which is kind of overloading the word. I don’t have a problem with that kind of final, except that I don’t agree that it’s good to use it liberally where you don’t design for inheritance up-front. This post is about final variables and immutable objects.
Good practice dictates that variables should always be marked final, except where the reference needs to be changed. This is true for class members, which should be assigned in instance initialization or a constructor, and can therefore be marked final. It’s true for method parameters, where it prevents you mistakenly thinking that Java is pass-by-value. And of course block-scoped variables should be final. All of this is good because it reduces mutable state at runtime, making your app less complex, more testable, and expresses your intent in compiler-enforceable constraints.
class Bear { final DateFormat df = new SimpleDateFormat("MMddyy"); final SalmonService ss; Bear() { ss = new HuntSalmonService(); } void eat(final Stream s) { final Integer hungerLevel = 10; ss.takeFish(s, hungerLevel); } }
The problem is, I only know one coder who is religious about declaring everything possible as final. Which sucks: if a variable is NOT marked final, this tells you nothing. Most likely, the coder didn’t write it because they were in a hurry or didn’t think it was needed, but they never modify the reference. The fact that Java makes you write this modifier everywhere is backwards, because you are rarely forced to use it (for use in anonymous inner classes). It would make more sense to use a modifier to note the exception rather than the rule, so we should have a mutable modifier instead. Now if you see a mutable List foo, you can bet the reference is really changed to another List later, since the developer bothered to mark it as mutable.
In Scala, you are forced to think about this, by marking your identifiers as a var or a val. Val’s are final, var’s are not. That’s good, Java should do that too. Now our Bear example is:
class Bear { DateFormat df = new SimpleDateFormat("MMddyy"); // non-mutable SalmonService ss; Bear() { // Without this, compiler complains that ss must be marked mutable ss = new HuntSalmonService(); } void eat(Stream s) { // re-assigning s here would be a compiler error mutable Integer hungerLevel; hungerLevel = 10; ss.takeFish(s, hungerLevel); } }
So far, this would be an easy change to the Java language, or something a new language could model.
There’s a second problem, however. I love to ask this in interviews: if something is marked final, can it be changed? It’s intentionally vague, and of course the answer is that the reference cannot change, but the value can. Immutability is important for the referenced object even more than for the reference, since immutable objects are thread-safe, can cache expensive operations, may be pooled, and it’s easier to reason about their state. They also have the same benefits as final variables – less mutable state at runtime is a Good Thing. Is there anything to be done at the language level to support the maxim, “Favor Immutability”?
Let’s imagine what it could look like. We’ll add the mutable modifier to a class that is mutable:
mutable class MyList<E> implements java.util.List<E> { List delegate = new ArrayList<E>(); public void add(E item) { delegate.add(item); } public E get(int index) { return delegate.get(index); } // More implementation for List methods ... } class YourList<E> implements java.util.List<E> { // We don't even want a mutator, but have to satisfy our interface void add(E item) { throw new UnsupportedOperationException(); } public E get(int index) { return delegate.get(index); } // More implementation for List methods ... } //reference and value are both mutable mutable List<Object> foo = new MyList<Object>(); foo = new YourList<Object>(); // now the value is immutable
This is no different from what Java does already: you have two classes, one that is mutable, and one that isn’t, or a method like Collections.unmodifiableList() that returns a wrapper around a list with exceptions thrown by the mutator methods – in the latter case, you don’t find out until runtime that mutation was attempted. Just like with the final modifier, the status quo is that everything is mutable, and thoughtful programmers sometimes use a utility method to produce immutable instances or have to write a second copy of their classes that lacks or hides the mutator methods. Note that there are lots of classes named “Immutable*” out there – maybe that’s backwards too. Again, we’d like the language to give us immutable objects unless we specifically ask for a mutable instance.
So we’ll just have the one MyList class, and we’ll need to mark the methods that are mutators. Those methods are only available, at compile time, if a mutable instance of the object was constructed. Since the mutable keyword is already in use for the referencing variable, we’ll need some other way to request mutable instances, maybe a mutable version of the new() operator. We can also mark methods as returning mutable instances, since we have made mutability part of our type system, and we don’t want callers to be able to cast an immutable return value into a mutable instance.
class MyList<E> implements java.util.List<E> { List delegate = new ArrayList<E>(); mutator void add(E item) { delegate.add(item); } public E get(int index) { return delegate.get(index); } // Return a mutable copy: public mutable MyList copy() { // call the copy constructor, // using the mutable() keyword instead of new() return mutable MyList(this); } // More implementation for List methods ... } mutable List<Object> foo = new MyList<Object>(); // Compile-time error: This instance of MyList is immutable foo.add("Not allowed"); foo.copy().add("Can do this"); foo = mutable MyList<Object>(); foo.add("Good");
Is this possible? I’m still pondering the implications. Here are a few:
- Can a non-mutator method call a mutator method? Probably that should be compile-time error.
- Should support reflection on whether an instance is mutable.
- Can the compiler figure out what are mutators without marking the method? Right now, if we forget to mark a method, it violates the immutability of our object. Or it could be reversed: a modifier could be required for the methods that are legal on immutable instances.
- Maybe if a newly created object is assigned to a mutable variable, it should be mutable? Then we could avoid this new brother of the new() operator.
I’d love to hear your comments.
Structuring Java code that assembles a UI
I’m dong some GWT coding today, which is a lot like writing Swing. It’s very procedural. Create a new UI element, then call methods on it to set up the state. Even when you do the right thing and split your UI into many Composite classes, you get something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 | StackPanel stackPanel = new StackPanel(); stackPanel.add(new Label("Recently Eaten")); stackPanel.add(new Label("Manual Entry")); stackPanel.add(new Label("Search the database")); DockPanel panel = new DockPanel(); panel.add(stackPanel, DockPanel.CENTER); FlowPanel buttonsPanel = new FlowPanel(); buttonsPanel.add(new Button("Done")); buttonsPanel.add(new Button("Next")); panel.add(buttonsPanel, DockPanel.SOUTH); |
This is really annoying. The order of assembly is important, but it’s also very arbitrary. I’m creating my DockPanel before my FlowPanel, but you should always declare variables in the narrowest scope possible (item 45 in Effective Java). On the other hand, maybe I want to finish referring to my StackPanel, adding it to the parent, before I create my FlowPanel. Also, it’s easy to make a mistake here. I might accidentally add something to the wrong parent container, if the variable names are similar, and there isn’t a good way to test this code aside from inspecting the UI visually.
Maybe Java is just not a good language to express this UI layout, but for now I considered an under-used construct, inline instance initialization blocks:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | final StackPanel stackPanel = new StackPanel() {{ add(new RecentlyEatenPanel(), "Recently Eaten"); add(new ManualEntryPanel(), "Manual Entry"); add(new DatabaseSearchPanel(), "Search the database"); }}; final FlowPanel buttonsPanel = new FlowPanel() {{ add(nextButton); add(doneButton); }}; DockPanel panel = new DockPanel() {{ add(stackPanel, DockPanel.CENTER); add(buttonsPanel, DockPanel.SOUTH); }}; |
This is kind of cool – the structure is certainly more evident in this code. The extra braces define an initializer that is copied into each constructor – see the Sun tutorial. I assume that the code in the initializer block executes after the constructor has finished its work, so we can depend on the add() method having a place to do its work.
The limitations: this creates a subclass, so you can’t use it to initialize fields in a final class. Also, as you see, any variables must be declared final to be used in the initializer block, just like with any anonymous inner class.
Links:
Here’s a clever DSL to build the GUI in a “fluent” way: http://www.pathf.com/blogs/2007/09/expressing-rich/
And a project to use Flex-style XML to configure the layout: http://code.google.com/p/gwt-ui/
Chrome, the first mainstream Site-Specific Browser
In a previous post, I got into my passion about the misuse of web browsers. They’re intended for browsing content on the web, and not really intended for running applications like we do so much of today.
The problems with normal browsers can be summed up:
- The back button. In general, the browser’s controls only make sense in a browsing context.
- Apps running inside the browser don’t show up in Alt-Tab/Cmd-Tab, they’re hidden in a browser tab.
- Webapps can’t interact with the desktop in the usual ways, such as drag-and-drop, system tray/menubar integration, and running processes in the background like notifications.
- Dialogs and pop-ups lose the association with the application that originated them.
- One misbehaving webapp can take down the browser, along with other non-related apps.
- Offline storage is not generally available, other than what can fit in cookies.
- Security is a lot harder when state like your current session is expoitable by a site in another tab.
Speaking truth to HD FUD
So pretty much everyone knows about the big switch to digital TV that’s coming in February. You know why? It’s been advertised heavily by companies that think they can sell you something you don’t need, by misleading you about what’s really going to happen on Feb 17. I’ve seen ads for it, and I don’t usually see a lot of ads in the course of my daily activities, so I’m guessing most people have seen them too.
It makes me mad when my poor grandmother thinks she has to buy an HDTV because they are shutting down the old TV. No one has to buy a new TV, and no one has to buy a new antenna, and in fact
You probably don’t have to buy anything.
Really, you don’t. Maybe you’d like to go buy something, after all, this is America (unless you live somewhere else). But this big digital switchover only affects you if you’re watching analog broadcast TV right now.
If you pay a cable or satellite bill for your TV, you don’t need to buy anything.
That’s assuming that your cable company hasn’t decided to change your service on you to take advantage of the confusion right now. There’s no reason your cable company can’t give you the same thing they have been.
If you have an antenna, and you get bad reception all the time, but you got your TV after March 2007, then you don’t need to buy anything!
That’s how you know you have broadcast TV now. You probably get up to adjust the antenna now and then, or there’s a big one on your roof. But your antenna is just fine, and your TV is just fine, too! There’s perfectly good digital TV coming over those same airwaves, exactly the same way as HD radio is overlayed on regular analog radio.
You can get that digital signal on your TV, because there has been a mandate from the FCC that:
If you have only thirteen channels, and you get bad reception all the time, and that bad reception looks like snow on your TV, and your TV is a few years old, then you may have to pay around $30 max.
All you need is a digital-to-analog converter at $40-$70 – and you can get a coupon from the government for $40 of that.
So please, if your grandmother is like mine, please help to clear up the fear, uncertainty, and doubt that’s being spread around the digital TV switch.
(On a side note, it makes me crazy that PCs still only have analog video on them. That’s 40-year old scan-refresh technology out of TVs. Your grandma is replacing it by February, but you just got it in your new Lenovo ThinkPad? Outrageous.)
Inbox full? Not your fault!
I’ve never been good at managing my email. My inbox is very large; I have some folders but I don’t use them consistently. My OCD need to collect things makes it hard to delete, and GMail is teaching us not to anyway. Worse, I fail to reply to mail because it is quickly buried on a busy day, and I know there are some emails on page 43 of my inbox that I ought to have replied to. I’m pretty sure everyone has the same problems.
So, like most other people, I need to develop a better “system” for myself, using flags/stars and folders/labels, and I need to learn better discipline for using my system, and also gradually improve it. OR DO I?????
Maybe the fault here is not mine, or yours. This bold notion first occurred to me after reading The Design of Everyday Things. In the book, Donald A Norman writes that many people blame themselves for not being able to understand how to program their VCR. The author insists that we must point the blame at the designer of the device, it should be simple to use by emulating characteristics of physical things that we understand how to operate. One such characteristic is affordances, which are most easily explained by analogy to a doorknob: it provides a clear place to grasp and operate the device. Another is quick feedback, which helps you quickly learn if your actions are having the desired effect. The VCR doesn’t tell you if the programming was right until you check the contents of your videocassette (the book is a little old). This book is really good for tuning your ability to understand human interaction with design. I think most user experience professionals keep a copy on their nightstand.
So what of email? It’s a very old system, developed around the same time as the web, and based on “snail mail” as a paradigm. You could now use your computer to send letters, and they are delivered quickly. But you would never have imagined in each day getting hundreds of letters from the mailman, giving him dozens, and expecting him to carry it all! In terms of the user experience, email is very similar to writing letters.
As a result, there’s too much busy work in email. We have too little automation, and the basic paradigm is just wrong. I don’t want to deal with conversations on a single-reply basis – and GMail helped a lot by getting us used to conversations as the fundamental unit of email. But, there are still times when a text message conversation moves to IM or an email conversation turns into a meeting, and email doesn’t understand these other ways of communicating. The attachment paradigm is terrible for old-school offices that use it to transfer documents as work-in-progress – the messages may contain some comments about the work in progress, which aren’t in the document itself. My email doesn’t actually help me either – I want to know which friends I haven’t heard from in a long time.
I think a new way of doing things will come, and people will probably have trouble making a transition. They’ll stick to sending emails, just like they create lots of Word documents on their hard drive and try to collaborate with other authors, and they’ll continue to confuse babysitting their collections of mails with doing work. Please do your part to point out to these people that email was just an awkward transition period in communication, and that silly electronic equivalent of a mailbox never worked very well. I don’t want to get any more emails from them.
Site-specific Browsers
To start, an announcement: I’m going to start work at Google in September! I’m in California now, and partly moved to Sunnyvale, one town south of Mountain View, home of the Googleplex. Google is kind of like a college campus, where I can do awesome coding without feeling political pressure to deal with bosses, or pressure to get into the business side of things to have a viable career path. Yet as terrific as that is, I have a dark secret that makes it an unlikely place for me to work: I don’t like web applications.
At first, I wondered if webapps were just the fashion. They’re easy to code (at first), trivial to deploy to many client computers, updates are mandatory so you pretty much don’t have old clients still running. The fashion shifted to creating web applications and now that’s what we get. Even for internal company systems, where you have control of the client machines, and your app is intended to be used as the primary work interface for a good chunk of a person’s day, I see a lot of big organizations writing a web app without considering a rich-client app. And now I’m not sure it’s just fashion – it seems to be the way we’re headed.
The browser is built for browsing
One problem with web applications is that they all run in this web browser program, which is a Multi-Document Interface. (More specifically, a TDI) Inside that browser, you have a number of documents going on. You’re reading some news, you’re logged into a company IT system, you’re shopping for a t-shirt, you have a couple pages you were reading but lost interest in, and of course your webmail. On IE7, Safari, or Firefox, you’re probably managing those documents using tabs, all within one browser window.
Now, you also have some other programs open, and you have developed whatever mechanism you’re comfortable with for switching – maybe the mouse, maybe ⌘-Tab. This works well, you have icons that represent each program so that your brain’s exceptional image-processing can figure out where you want to go without adding any reading tasks in the middle of your task-switching.
All those tabs in your browser don’t cooperate with your app-switching mechanism, that’s the problem. For the documents you were just browsing, this isn’t a big deal – your browser is good for browsing. But your webmail and your corporate IT system – what are those doing in there? Those are web applications, and should be in the same context-switch with the rich client applications. I don’t want to remember that Firefox is the first thing to switch to, then use a different means (I recently found ⌘0-⌘9 for choosing the active tab) to get back to my webmail.
Then there are the other issues with MDI’s: they don’t play with Expose, and it’s not always possible to drag a tab out onto another screen if you’re actively using two of the documents at once. Popup windows don’t get associated with the document that opened them.
Launching and quitting the Web Application
If I want to do banking, I’d like to launch my bank’s application from my Dock (actually I use Overflow) just like my other apps. When I’m done, I’d like to exit my banking application with ⌘Q.
In the browser, there is a very different way to accomplish this. I’d either find a bookmark (which would be mixed in with browsed pages) ar I’d put something in my toolbar, or just start typing a URL. I usually find the latter is the quickest, which is kind of dumb because I’m typing a lot of characters to get to this place I go all the time. Then I probably have to navigate to my personal account login, which is another dreaded pageload or two. When I’m done, I have to log out.
Security
A big problem with my online banking is that my bank’s session is stored as state in my browser. If I load a URI from my bank site, it’s treated as authenticated. But what if I’m browsing a page with an image in it like
http://mybank.com/account/transferMoney?toAcct=012345&amount=100.00
and my browser requests that? It will send along my session cookie and give you $100 from my account. That’s dumb. My bank’s application shouldn’t be running in a shared environment with untrusted stuff I’m reading online, it should be a separate app and if it wants to use cookies and HTTP, great, but they should live in the banking app only.
Interacting with the rest of the computer
This is a problem Adobe AIR and others are trying to address with the “Rich Internet Application” concept. I should be able to drag files into GMail to attach them, have my webapps give me Growl notifications, have them add things to the MenuBar, and so on. Maybe they should be user-scriptable in Greasemonkey, like you’d do with Applescript on a Cocoa app. To me, this is actually the least compelling problem with web applications, mostly because apps that need to do these things are delivered as Rich-client apps already.
There’s also the issues that Mark Finkle writes about: the web application should probably run in its own process, and doesn’t need all that extra chrome or toolbars. I get most emphatic when I talk about the Back button. It’s based on this idea that you’d like to return to the document you were viewing when you followed the link that brought you here. Web developers go to lots of trouble to try to make the back button do something reasonable in a web application. Why is it even there???
The Solution
Site-specific browsers are the best way to resolve all this. The web application doesn’t have to change – my bank doesn’t need to be involved to fix this problem. We just need a convenient way to spin up a Webkit into a little standalone app.
Here are a few approaches:
- Gabe’s Browsair turns a site into an Adobe AIR application
- Some Google apps have been turned into Mac apps: Mailplane, GCal.app
- Mozilla’s Prism (previously WebRunner)
None of this has really caught on, as far as I can tell. I have been on this bandwagon for several months and I haven’t seen it go anywhere. This needs to get solved!
New version of Reason
This is one thing I really like about electronic music: you have to be a super-dork to think this looks like a fun instrument to play:
I installed Reason 4 last night, which Gabe and I used among our tools in our laptop band. Reason 4 add this enormously complicated looking instrument called the Thor, which I know basically nothing about. So let me blog about it anyway.
The Thor is a synth of an analog waveform generator with such complicated options that there are arrows showing the flowchart and a table at the bottom listing part of the configuration. The knobs are a lot of fun – you can play one note on your keyboard and then just perform on the knobs. Best of all, it comes with patches from some electronic music savants, most notably, Plaid! It was a blast to play with a couple of their instruments.
December 16, 2007 was a big day for me, as longtime readers know. The great Dvorak switch, which hobbled my typing for quite a while, is finally over the hump, and I think it will end up being a success. Success in this case means lack of regret. I am back to a pretty reasonable speed on the zebra test: Accuracy: 100%, Gross Speed: 47 WPM. It’s about where I was with Qwerty before going to the Das Keyboard. After getting married at the end of this month, I’ll switch back to blank keys and I expect to get over the touch typing hump a lot faster, since I can already type a fair amount without looking.
Now, maybe this blog won’t be the Dvorak blog anymore, but I will give a few parting thoughts to the topic. Dvorak is great if you like to be a one-man novelty act. This is partly because people tend to be conformist, and enforce that tendency on others by mocking differences. You’ll get some blank stares from people who assume (probably correctly) that you’d have to be crazy to move around all the keys on your keyboard.
But also, although Dvorak feels better and is faster to learn, you’re competing with 20 years (in my case) of qwerty. It took me 5 months to feel really comfortable with typing again. Now, mind you, I don’t have a lot of discipline, so I didn’t practice. I’m sure if I used a typing program (instead of deciding to write my own), it could have gone faster, but really, this has been a hard, hard thing to make myself do.
That said, it is now a major accomplishment, and I can move forward into the world even more special than I was before
Arrival times on DC Subway

So awesome! I found that you can get the Metro’s next train arrival times on your phone! It’s exactly the same data you see on those electronic boards on the platform – I checked it for the Courthouse station, and saw that I had two minutes to make the train, and I ran down to the platform and just barely caught it.
It’s extra nice that the page is intended to be displayed in a popup – so it’s a tiny download.
1. Google “wmata <name of your stop>”
2.The second link (usually) goes to a small page showing the train arrival board. You can also find it on the station’s page.
Like this: Clarendon
If you have an iPhone with the Jan08 update, add that sucker to your home screen!
Typing speed update
I’m still on Dvorak. I guess that’s really the big news, because it has been occasionally infuriating that I can’t get words onto “paper” as fast as I think. But the more I get mad at this shortcoming, the more I’m reminded of how great it is to be a fast typist, and that’s tho whole goal here.
I have taken the labels off five keys now, returning to their glorious and blank Das Keyboard state. I’m also still working on TypingHero, my Flex app that’s supposed to make it fun to type faster. Gabe helped me out over the weekend to improve the wiring of my mxml views to their backing controller classes. It’s great to work with true components, but it’s frustrating that using best practices in Flex is so contrary to the examples and sometimes the language makes it awkward.
Sadly my speed has leveled out over this month, and is stuck at half my QWERTY speed…
1/7
Net Speed: 33 WPM
Accuracy: 97%
Gross Speed: 34 WPM
1/21
Net Speed: 33 WPM
Accuracy: 97%
Gross Speed: 34 WPM
I’ll get a more useful and fun version of TypingHero soon, and of course I’ll speed up my typing considerably using it. Of course!
About Me
Tweets
- @iamauthentic Look at it on the bright side. You're in the last generation that will know what a "busy signal" is. in reply to iamauthentic 12 hrs ago
- I played the ice hockey for the second time in about 8 years. I was about as good as ever, I guess. Which was fairly bad. 1 day ago
- I finally jailbroke an iPhone. Now I feel like I have decent geek cred again. 3 days ago
- Lost a bolt on my lower control arm. Found out about it when the wheel came partly off. http://twitgoo.com/fw9e0 4 days ago
- Wow we have the craziest channel 1.6 on broadcast TV where I live, that runs this show: http://intensit.tv/ 6 days ago
- Dorfmeister is playing Zurich the day after I leave. Worst! 1 week ago
- 70 fresh, organic oranges from our tree were sitting on the table this morning. So, marmalade had to be canned. It's tasty! 1 week ago
- Moles, cousins, and unattended baggage #10kpyramid 1 week ago
- More updates...
Powered by Twitter Tools
