views:

74

answers:

4

Let's say you want to construct an Iterator that spits out File objects. What type of data do you usually provide to the constructor of such an Iterator?

  • an array of pre-constructed File objects, or
  • simply raw data (multidimensional array for instance), and let the Iterator create File objects on the fly when Iterated through?

Edit:
Although my question was actually ment to be as general a possible, it seems my example is a bit to broad to tackle general, so I'll elaborate a bit more. The File objects I'm talking about are actually file references from a database. See these two tables:

folder
| id | folderId | name             |
------------------------------------
|  1 |     null | downloads        |

file
| id | folderId | name             |
------------------------------------
|  1 |        1 | instructions.pdf |

They reference actual folders and files on a filesystem.

Now, I created a FileManager object. This will be able to return a listing of folders and files. For instance:

FileManager::listFiles( Folder $folder );

... would return an Iterator of File objects (or, come to think of it, rather FileReference objects) from the database.

So what my question boils down to is: If the FileManager object constructs the Iterator in listFiles() would you do something like this (pseudo code):

listFiles( Folder $folder )
{
    // let's assume the following returns an multidimensional array of rows
    $filesData = $db->fetch( $sqlForFetchingFilesFromFolder );
    // let the Iterator take care of constructing the FileReference objects with each iteration
    return FileIterator( $filesData );

}

or (pseudo code):

listFiles( Folder $folder )
{
    // let's assume the following returns an multidimensional array of rows
    $filesData = $db->fetch( $sqlForFetchingFilesFromFolder );
    $files = array();
    for each( $filesData as $fileData )
    {
        $files.push ( new FileReference( $fileData ) );
    }
    // provide the Iterator with precomposed FileReference objects
    return FileIterator( $files );

}

Hope this clarifies things a bit.

+1  A: 

What exactly is your iterator supposed to do? Write data to files? Create them?

An iterator is a pattern for iterating through data, which means providing sequential data in a uniformous way, not mutating them.

Dario
I've updated my question. Please see my extended question for more information. Thanks.
fireeyedboy
+1  A: 

What is your "File" object meant to be? An open handle to a file, or a representation of a file system path which can be opened in turn?

It would generally be a bad idea to open all the files at once - after all, part of the point of using an iterator is that you only access one object at a time. Your iterator could yield one open file at a time, and let the caller take responsibility for closing it, although again that might be slightly odd to use.

Your requirements aren't clear, to be honest - in my experience, most iterators which yield a series of files use something like Directory.GetFiles(pattern) - you don't pass them the raw data at all, you pass them something which they can use to find the data for you.

It's not obvious what you're trying to get at - it feels like you're trying to ask a general question, but you haven't provided enough information to let us advise you. It's like asking, "Do I want to use a string or an integer?" without giving any context.

EDIT: I would probably push all of that logic into FileIterator, personally. Otherwise it's hard to see what value it's really providing. In a language like C# or Python you wouldn't need a separate class in the first place - you'd just use a generator of some description. In that sense this question isn't language agnostic :(

Jon Skeet
The File object is actually ment to represent a file system path. You're right in saying opening the physical files all at once would be a bad idea. That was indeed not my intention.I've updated my question. Please see my extended question for more information. Thanks.
fireeyedboy
A: 

It depends what you need. For example, you could have:

  • a collection / list of filenames to iterate over;
  • the name of a directory through which you want to iterate;
  • your iterator could decide itself what files it wants to return;
  • ...

You could design an underlying class, e.g. FilenameCollection or Directory that has a method which returns an appropriate iterator for this type of object (i.e. an iterator "factory method"), instead of requiring that a parameter be passed to your iterator's constructor.

stakx
+1  A: 

I find the question to be unclear.

Are we talking Iterator or Factory?

To me an Iterator is operating on a pre-existing collection of things and allows the caller to work on each thing in turn.

When you say "Spits Out" do you mean allows the client to work with one file from a pre-existing set of files or do you mean that you are iterating some data and intend to store that data in files you are generting. If we are geneating, then we've got a File factory.

My guess is that you are intending to process some files in a file sytstem. I think that your Iterator is akin to a Directory, it can give you the next file it knows about. So I construct the "Driectory" by passing enough data to allow it to know which files you mean (could be just an OS path, could be some kind of "find" enxpression, a list of ftp-like references, etc.) and expect it to give me the next File as I iterate.

----updated following question clarification

I think that the key question here is when the individual files should be opened. The Iterator itself will reasonably return a File object corresponding to an open file handle, the caller can then just work with the file. But iternally should the iterator be working against a list of pre-opened files or a list of file references, the files being opened as the iterator next() is used.

I think we should do the latter, because there is overhead in having an open file, hence we should open the files only when we need them.

That leads to one other point: who closes the file? We can't afford to keep them all open. Perhaps the iterator should close each file as next() is called. This implies that that the iterator itself needs a close() method to allow tidy up of the currently open file. Alterntaivelywe need to explictily document that closing is the client's responsibility.

djna
Hmmm, you're making a very good point there, with saying the Directory itself could be the Iterator. Hadn't thought about it that way. Thanks!
fireeyedboy
Although you make valid points, my concern wasn't about opening the actual physical files yet. The Iterator, at first, is only ment to display the names of files in a view of a MVC app. Later on I want the File(Reference) objects to give me the actual physical file for downloading for instance. But that wasn't my concern yet. My concern is more with how to generate the Iterator. But since you gave a whole other perspective on the Iterator, I think I'll rethink my design. I like your "let the Directory itself act as an Iterator" idea.
fireeyedboy