Skip to content

Easily put PDFs on the iPad

Both OS X and Windows support creation and download of PDF documents.  iBookson the iPad provides very good support for reading PDF documents.  The hassle I had was the multiple steps involved to put the PDF on the iPad.  I’m generally in a hurry and feel that technology should make my life easier, so I figure out how to minimize the number of steps.  And, it doesn’t even take much work to set up.  The instructions here are for OS X, although I think you can do something similar in Windows.

Since iTunes 10, there has been a folder buried down in the bowels of iTunes Music.  The exact location is typically something like /Users/your-account/Music/iTunes/iTunes Music/Automatically Add to iTunes/.  Anything you add to this folder will be added to iTunes and can then be synched when you next synch your iPhone, iPod, or iPad, depending on your synch settings.  Because I don’t want to go looking for this folder every time, I created an alias on my desktop.  Now, when I want to save a PDF to my iPad, I just drop it in this folder and the next time I synch it shows up in my iBooks application for reading on the go

Is Twitter Customer Support Encouraging Undesirable Behavior

Today’s post is somewhat off-topic for a technical / M&S site, but it’s something I’ve been thinking about lately and is applicable to all service companies.

I have problems with one of my service provides more frequently that I think I should.  Namely, an expensive service that I rely on drops out unexpectedly and it sometimes doesn’t come back for hours.  Like a good customer, my first call is to the customer support phone line.  And, probably like most callers, I come away disappointed with the support I get or what the nice person at the other end of the phone can actually accomplish.  So, I then do one of two things, sometimes both.  I go to the local service center and complain (another hassle and waste of time) or I post a comment on Twitter.  I generally choose the latter.

Perhaps it’s the visibility of Twitter posts or just that the people who are monitoring Twitter have more authority, but I *always* get my problem fixed and I get it fixed a lot faster than the customer support line says I will.  In one recent case, I got my problem resolved a day earlier!

So, first let me say, “Thanks” to the nice people on Twitter who are able to resolve my issues quickly and efficiently.  However, they have me convinced that if I want to do get something done I should complain on Twitter.  So my choices, from a customer viewpoint are 1) make a private call to customer support and come away unsatisfied or 2) complain publicly on Twitter and get my problem resolved.  I come away happy and the company comes away looking worse for the wear.  I will say that I always follow up with a thanks for the help when the problem is resolved, after all, policy and procedure is set from on-high, not by the folks helping me.

So what’s the solution from a companies viewpoint?  I believe there are two options.  First, they could stop incenting me to complain publicly by providing the same level of service as they do when I call customer support.  The drawback to this approach is that they still get negative comments in a very public forum and I still have a negative opinion.  Or, they could empower customer support to be able to satisfy my problem as well as the folks on Twitter do.  If this were the case I’d be willing to make a private call to get my problem resolved.

Using Scala Functions to Simplify Code

I’ve recently been diving into Scala to create Scarab, a simulation framework I’m developing.  Coming from a Java / Groovy background, I was still in the habit of using classes and inheritance to create functionality.  However, as I was documenting code, I decided it would be cleaner to use functions and pass them as parameters.

One of the things I find useful is to have the ability to write output to different output streams in different formats.  I separated the code to do the formatting from the code to do the writing so that I could easily mix and match writers and formatters.  Originally both the writers and the formatters inherited from a base class.  Writers would then add additional functionality to write and formatters would add additional formatting capabilities.

The base writer contained the following methods (plus more that aren’t relevant to this post):

abstract class AbstractWriter {

  private var formatter : TraceFormatter = SimpleFormat

  // formats, then writes the message
  def trace (trace: String, message: String) = { write (formatter.format(trace, message))  }

  // sets the formatter to use.
  def withFormat (format : TraceFormatter) = {
    formatter = format
    this // for method chaining
  }

  // abstract method writers should implement.
  protected def write (message: String)

}

The base formatting class was defined as such:

abstract class AbstractFormatter {
  // method to be overridden by the formatter to do the formatting.
  def format(trace : String, message: String) : String
}

// Class to format with trace type and date for searching.
class LogFormatter extends AbstractFormat {
  def format(trace: String, message: String) = { "[" + trace + "] [" + new Date() + "] " + message }
}

So, I happily began creating classes to do formatting, but realized that my users might want to create their own formats as well.  Initially I simply said to extend the base formatter and use that with the writer.  However, this has the potential to clutter up the class space and each formatter is at least three lines.  While users could use anonymous classes, it just didn’t feel right.  All I wanted was a function to format a string.

So, after reviewing my Programming In Scala book, I figured out how to make the changes.  First, I changed the AbstractWriter to the following:

abstract class AbstractWriter {

  // Assigns an initial function for the formatter.  The type is implicitly determined.
  private var formatter = TraceFormatters.SimpleFormat

  // formats, then writes the message
  def trace (trace: String, message: String) = {    write (formatter(trace, message))  }

  // sets the formatter to use.  The parameter is now a function.
  def withFormat (format : (String, String) => String) = {
    formatter = format
    this
  }

  // abstract method writers should implement.
  protected def write (message: String)

}

Now, the defined formatters are just functions I placed inside an Object:

object TraceFormatters {

  val SimpleFormat = (trace: String, message: String) => message
  val LogFormat = (trace: String, message: String) => "[" + trace + "] [" + new java.util.Date() + "] " + message

}

I can easily add additional formats as needed with a single line of code.

The major benefit, however, is that now users can create formats on the fly.  Lets say that a user wants to create a formatter that formats messages as comma separated values, then all that is needed is the following:

// ignoring the case of messages or trace names with commas.
val writer = new FileWriter("log.csv") withFormat { _ + ", " + _}

Switching from classes to functions makes the code more readable, reduces the number of classes that need to be created, and provides increased flexibility for users of my class.

 

Forio Online Simulation Tool

I recently viewed a webcast on a tool called Forio that allows users to create simple simulations that run on the web.  So far I’ve only played around with the available simulations, but it is an intriguing concept.  It appears that any simulation you could create in an Excel spreadsheet you can create with their site and then it runs as a Flash application with nice graphics (iPads need not apply).  Mostly I would say that it’s appropriate for games, teaching/training, and some what-if analysis.  I don’t believe it’s very practical for large scale or virtual applications, but that doesn’t appear to be the goal.

In the very near future I’ll create a simulation and give my thoughts on the usability and applicability of the tools.  Until then, take a look at the simulations they have available to try out. If you feel really motivated, go ahead and sign up for a free account and create your own simulation.