Yuma Snippet
Yuma Blog: Connecting with the Yuma web development community
RSS
Class Interfaces in Yuma
5 comments
Thursday, April 3, 2008
Joe Strout
A class interface defines a set of methods that other classes may choose to implement. It's a powerful form of generality: code can be written to work with a class interface, and that code will work with ANY class that implements that interface. So today, I'm going to talk about the pre-defined interfaces in the Yuma framework (we'll cover how you can declare and use your own interfaces later).

The current Yuma framework has three interfaces built in. The first is Readable:

Interface Readable
    Function Read( count As Integer ) As String
    Function EOF() As Boolean
    Function ReadError() As Boolean
End Interface

As you can see, Readable defines three methods: Read, EOF, and ReadError. Any class that implements the Readable interface will have (at least) these three methods. That means that you can make a function that works with any Readable.

For example, let's say you need a function that reads a set of fixed-width fields from a file and returns them as a string array, like this:

Function ReadFields( source As Readable ) As String()
  // Read one line of data in our MoldyData format.
  // Each line consists of 5 fields, each containing 20 bytes.
  Dim out() As String
  for i As Integer = 0 to 4
    if source.EOF then exit for
    out.Append source.Read(20)
  next
  call source.Read(1) // (read and discard the line break)
  return out
End Function

Now, here's the cool thing: you can pass any Readable object to your ReadFields method. That includes the built-in classes TextInputStream and BinaryStream, as well as any classes you might define yourself.

This can be especially handy for unit testing. It's inconvenient and slow to have an actual file with which to test something like the function above. But test it you certainly should anyway! So, you can make your own test class that defines Readable, and implements the three Readable methods in order to feed the caller whatever data you want to test with. Then pass an object of that class to your ReadFields method, and sleep well at night knowing that your code works as intended.

The second interface defined in the Yuma framework is Writeable:

Interface Writeable
    Sub Write( data As String )
    Sub Flush()
    Function WriteError() As Boolean
End Interface

Nothing mysterious here; it's pretty much parallel to Readable. The Writeable interface is implemented by TextOutputStream and BinaryStream. Again, you can define your own Writeable class to do whatever you want with the data being written, and pass any of these to any method that works on a Writeable.

(Notice that BinaryStream implements both Readable and Writeable. This illustrates an advantage of interfaces over a regular superclass: a class can have only one superclass, but can implement any number of interfaces.)

Finally, there's one more interface in the current Yuma framework:

Interface Closeable
    Sub Close()
End Interface

This is the simplest interface of all, and it's not actually used by anything publicly exposed (it's used internally by the Session module). But you're welcome to use it yourself on any class you define with a Close method. Here's an example of how this may be useful: you could define a list of closeable objects:

Dim thingsToClose() As Closeable

And then as your Yuma program runs, whenever it creates something that will need to be closed later, it can throw it onto this list. Finally, at the end of the program, it could close everything on the list.

  ...
  // Create a new Whatzit, and remember to close it later
  Dim foo As New Whatzit
  thingsToClose.Append foo

  ...
  // Our work here is done, but remember to close things before we quit
  for each item As Closeable in thingsToClose
    item.Close
  next item

So now you know about class interfaces in Yuma, and why they're so handy. We love them, and will probably be adding more (and implementing them wherever they make sense) in the future. Stay tuned, and if you have any suggestions, please let us know!
Comments
Thursday, April 3, 2008

I am still struggling to grasp OO concepts in RB, and examples really help. So, with the help of your example, I understand how to use Closeable, but your Readable and Writeable examples introduce several concepts that are new to me, making it hard to figure out what is going on. In the line;
if out.EOF then exit for
Is the EOF function coming from the Readable interface? If so, how did the locally defined "out" string get associated with Readable Source? It would make more sense if it were;
if Source.EOF then exit for
but otherwise I am puzzled.

Thursday, April 3, 2008

Oops — good catch, David! That was a typo; it should indeed be "if source.EOF". I'm sorry for the confusion. (I've corrected the post to avoid confusing any future readers.)

Steve Garman
Thursday, April 3, 2008

call out.Read(1) // (read and discard the line break)

This line of code with its bald assumption that a linebreak is one character long ;) reminds me that last time I tried it was not possible to use the lone keyword "endOfLine"
I appreciate that web development makes that a very dubious thing to define, as the server may be on a different OS from the browser but it is a sizeable code-portability issue.
Are there any plans to define an arbitrary meaning for EndOfLine? If not, have you any advice about the issue?

Friday, April 4, 2008

You raise a good point: my simple example not only assumes that all lines are 5 20-byte fields long, but that they're separated with a 1-byte carriage return. If you're dealing with the sort of ancient file format that's likely to have fixed-width fields, you can be fairly confident of knowing what your line endings are too. The example is a bit contrived, but has the benefit of being short.

As to EndOfLine: in b3 you actually can use EndOfLine by itself; what you can't do is add it to a string. That's already fixed for b4 (which we expect to have out soon, perhaps Monday).

Friday, April 4, 2008

Oh, and about the default meaning of EndOfLine: in Yuma, it is equivalent to EndOfLine.HTTP, which is the line break used by the HTTP protocol. This was chosen because perhaps the most common use of it will be with the "Print" command, and that's the line ending you would want to print to get a proper line break in the HTML source seen by the client. If you were writing to a file, you'd probably use something else (perhaps EndOfLine.Unix, or whatever's appropriate for the file format you're writing).

As another teaser, the next beta will also include EndOfLine.HTML, which equals "<br />". This is what you'd use if you wanted to print an HTML line break, i.e. to make a break seen when viewing the page (rather than the source) in the client.

Share Your Comments

Name *

Email Address *

URL

Comment *
Note: If you submit sample code (either HTML, Yuma, or both) in your comments, please enclose it in [code]...[/code] pseudo-tags so that it will be properly formatted. If you'd like to add links or text formatting, please review our brief BBCode reference.

You will receive an email message with a link you need to click to verify your submission.