It seems like every single time I go to write any code that deals with fetch, push, read, or write operations, the entire swath of code is ad hoc, ugly, and completely unusable outside the context of that exact application. Worse yet, it fells like I have to reinvent the wheel every time I design these things. It seems to me that the nature of I/O operations is very functional, and not well suited to modular or object-oriented patterns.
I'm really hoping somebody can tell me I'm wrong here. Are there techniques/patterns for object-oriented or modular file and data I/O? Is there some convention I can follow to add some code re-usability? I know that various tools exist to make reading individual files easier, like XML parser and the like, but referring to the larger designs which use those tools.
The best thing I've been able to come up with is a facade pattern... but holy smokes is the code in that facade ugly.
I'm not looking for help with the following code, I'm just using it to illustrate the issue I always run into. The problem isn't limited to Java; I hit the same wall in C, Matlab, and Python.
Here's an example in Java. This is psuedocode for some the method definitions of class IOControl, which is a singleton:
public getZohoFiles(...);
public pullFromZoho(...);
public reloadZohoData(...);
private dumpHttpToFile(...);
private primeHttpCommand(...);
private primeZohoFileRead(...);
private primeZohoFileReadWrite(...);
private readClientsFromFile(...);
private writeZohoFile(...);
The only method that is used in more than one point is readClientsFromFile(), which is used twice! Yippie.
Most of these methods are solely for the purpose of avoiding a several-hundred-line try-catch-finally block.
pullFromZoho() is the method invoked from the outside work to do most of the work. Almost all I/O code I write encounters the same problem: its entire structure and the methods it calls had to be custom designed to meet this specific application. It is completely ad hoc, unless I happen to use this API again. Its psudeocode:
public FetchResult pullFromZoho() {
// Code: clear old client list
// Code: Initialize HTTP client
// Code: Move local files to backup
try {
int index = 0;
boolean fetchNext;
do {
// Possible IOException
File xmlFile = primeZohoFileReadWrite(index);
// Possible IOException
// Uses an HTTP Post package
boolean readNext = result.addHttpResult(
dumpHttpToFile(httpClient, xmlFile, index));
if( readNext ) {
/*
* Possible ParserConfigurationException, SAXException,
* IOException
* Uses an XML parser package
*/
fetchNext = result.addXmlReadResult(
readClientsFromFile(xmlFile));
} else {
fetchNext = false;
}
if( fetchNext )
index++;
} while(fetchNext);
} catch (UnsupportedEncodingException ex) {
result.triggerFail(ex);
} catch (IOException ex) {
result.triggerFail(ex);
} catch (ParserConfigurationException | SAXException ex) {
result.triggerFail(ex);
} finally {
try {
httpClient.close();
} catch (IOException ex) {
result.addWarning(ex);
}
}
// Code: add loaded clients to list
return result;
}
Even this try-catch-finally block arrangement is unique to this particular operation. Any different application would definitely use a different structure. (Side note: because of a peculiarity of the external API I'm using, I have to parse each dataset before fetching another.)
The code for this set of operations spans about 700 lines, and this doesn't include a similar cluster of methods needed for local file saving, and another set for pushing data to another database. That's about 2,100 lines of single-purpose code. Not one of these methods could be used for any other application.
Somebody please tell me a pattern exists wherein I could either re-use some of my code, or at least follow a template for future read-writes.
Somebody asked about Modular Design here, but the answers are specific to that asker's problem, and aren't altogether useful.
Aucun commentaire:
Enregistrer un commentaire