#552 [ANN] flitter

cheeser Mon 27 Apr 2009

Today I pushed my library "flitter" up to http://kenai.com/projects/flitter/. Flitter is a an API to access the twitter API using the fan language. It's by no means complete but you can see your friends/followers and their timelines as well as the status/update methods. Direct messaging is not support quite there yet nor are the account management or search methods but I'll be adding those soon. I haven't pushed any pods up to the download section though if someone would rather have the pod to download rather than building it manually, i can do so.

This is largely a learning project for me to play with the fan language so it may not be quite idiomatic in places. I'm certainly open to feedback as far as that goes. I decided to announce this now rather than later as I wanted to push it up to kenai and figured I might as well announce it myself rather than let someone stumble upon it. :) Feedback/help is welcome of course. I know the code is ugly in places but I'm more focused on working code rather than pretty code at the moment. After I finish up support for the REST portions of the API, I plan on clean up work.

Anyway, if anyone wanted to play with twitter from fan, here's a starting point. Enjoy and please let me know what you think. I'm still trying to break some "bad" Java habits that don't make as much sense in fan.

tactics Mon 27 Apr 2009

Very nice. I will definitely be checking this out when I have a chance this week.

Some random points as I'm glossing over the code. You're using a ton of string-based URLs. In Fan, the URL is a core data type with a very accessible and robust API. It would make sense to make Flitter.baseURL to a Uri object. The Flitter.addParameter method can be replaced by the builtin sys::Uri.plusQuery method.

Also, you probably don't want to be echo'ing in a library. If there's an error, it's better to let it propagate to the top-level.

Other than those two minor points, it looks great.

qualidafial Mon 27 Apr 2009

Also, you probably don't want to be echo'ing in a library. If there's an error, it's better to let it propagate to the top-level.

@cheeser: Whether it's an error or not, the preferred method is to use sys::Log for that. See also docLang::Logging.

cheeser Mon 27 Apr 2009

@tactics: That's a good point. I'll update to use that. I started doing it that way early on and just never stopped to look for a better way. So, thanks! :)

@qualidafial: My goal is to move all that to logging actually. I just haven't quite figured out how to make that all work just yet. I need to actually spend some time on that.

I'll file issues on both points and make sure to clean that up ASAP. Thanks for the feedback.

brian Mon 27 Apr 2009

Really cool cheeser! We may end up using this ourselves.

Couple tips:

  • ditto on tactics suggestion - the URI APIs are pretty nice and handle a lot of that grunt work for you
  • we tend to avoid declaring local variable types and use inference:
    Str url := "http://twitter.com/statuses/show/${id}.json"
    url := "http://twitter.com/statuses/show/${id}.json"  // don't need type
  • in JsonEntity.toStr, take a look at List.join:
    Str value := ""
    type.fields.each | Field s | {
        value += (value.size() == 0 ? "" : ",") + "\n\t${s.name}: ${s.get(this)}"
    }
    
    // can be replaced with
    value := type.fields.join(",") |s| { "\n\t${s.name}: ${s.get(this)}" }

Seems like Kevin could probably enhance our json API to make some of that a little easier. If you have any suggestions please post.

tactics Mon 27 Apr 2009

ditto on tactics suggestion - the URI APIs are pretty nice and handle a lot of that grunt work for you

I had actually never used or seen plusQuery before today. I simply inferred its existence from the enormous reliance Fan has on the things =-)

cheeser Mon 27 Apr 2009

@brian Thanks for the tips. i'll incorporate those. I do see intermittent parsing errors in the json code that I haven't tracked down yet. When I "finish" the API support, i'll dig deeper.

cheeser Tue 28 Apr 2009

Hrm. At first I thought I found a bug (and it might yet be) but I think the docs are just a little vague (for my troglodyte mind at least). From the docs on plusQuery: "If the query param is null or empty, return this instance." I'd read this to mean the values in the maps (keys can't be null anyway apparently). But it would seem to mean that if the map passed in is null. So my recommendation is to either update the docs to reflect that a bit more clearly or to allow [Str:Str?]? there instead. For example, I tried to do this:

uri.plusQuery(["since_id": sinceId?.toStr])

And then I got:

sys::NullErr: java.lang.NullPointerException
  fan.sys.Uri.appendQueryStr (Uri.java:1202)
  fan.sys.Uri.plusQuery (Uri.java:1184)

Which is really unfortunate as now I have to wrap all my calls to plusQuery() anyway... So for now I'll (re)wrap that call off in a method of my own, I guess.

andy Tue 28 Apr 2009

You can probably just do this if want:

uri.plusQuery(["since_id": sinceId?.toStr ?: ""])

cheeser Tue 28 Apr 2009

That's ultimately what I end up doing but off in a method instead.

Login or Signup to reply.