Better Faster Lighter Java [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Better Faster Lighter Java [Electronic resources] - نسخه متنی

Justin Gehtland; Bruce A. Tate

نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
افزودن یادداشت
افزودن یادداشت جدید

9.8 The Console Interface

Console interfaces generally share a common usage idiom: provide a method for invoking the interface without arguments, but also allow for runtime decisions by providing for command flags. If the number of arguments does not match your expectations, return a usage statement.

If a user provides no command flags to our console interface, it launches into search mode. We'll allow users to enter search terms on the command line and return results. To quit, they just press Enter.

In order to launch an indexing event, the user passes in a flag in this format: /i: http://www.somedomain.com/. This simply provides the starting URL from which the rest of the indexable pages are eventually discovered. If the user invokes the indexer, we'll bypass the search. If not, we go into search mode.

According to typical standards, we should allow the user to enter a help flag (we'll use /?) that produces the usage message. Any other number of or type of flag cause us to write out the usage message and quit.

Here are the utility methods:

private static void writeUsage( )
{
System.out.println("Usage: java ConsoleSearch");
System.out.println(" -- /i:http://YOUR_INITIAL_INDEX_PATH");
System.out.println(" -- /?:show this message");
}
private static boolean checkArgs(String[] args)
{
if(args.length < 2 && args.length > 0 && args != null)
{
if(args[0].startsWith("/i") || args[0].startsWith("/?"))
{
return true;
}
}
return false;
}
private static String getIndexFlag(String[] args)
{
for(int i=0;i<args.length;i++)
{
if(args[i].startsWith("/i:"))
{
return args[i].substring(3, args[i].length( ));
}
}
return ";
}

The last method, getIndexFlag, examines the args collection to see if the user passed in the /i flag. If so, it returns the URL that is passed in after the flag.

That only leaves the entry point to the application:

public static void main(String[] args)
{
// get configured index path from IndexPathBean
ConfigBean config = new ConfigBean( );
String indexPath = config.getCurIndexPath( );
if(indexPath == ") return;
// check args for index flag, retrieve initial page, execute index
if(!checkArgs(args)) {
writeUsage( );
return;
}
String indexInitialPage = getIndexFlag(args);
if(indexInitialPage != ")
{
doIndex(indexInitialPage);
return;
}
// Allow multiple queries from command line
BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in));
try {
while (true) {
System.out.print("Query: ");
String line = rdr.readLine( );
if (line.length( ) == 0) {
break;
}
QueryBean query = new QueryBean("contents", indexPath, line);
query.execute( );
HitBean[] hits = query.getResults( );
for(int i = 0;i<hits.length;i++)
{
System.out.println(hits[i].getScoreAsString( ) + " " + 
hits[i].getUrl( ));
}
}
}
catch(Exception e)
{
e.printStackTrace( );
}
}

This single method provides everything our human and machine users could want. The live users can execute the main method and start interactively querying the index. Conversely, they can pass in the /i: flag and operate just the indexing/crawling functionality.

First, make sure the arguments are correct; if they're not, call writeUsage and then break. Check to see if the user is asking for an index instead of a search. If she is, call doIndex, then return. If not, allow the user to enter a query and execute the search, returning a simply-formatted result set. If anything goes wrong, print out the stack trace.

Here's the doIndex method:

private static void doIndex(String indexflag)
{
try
{
ConfigBean config = new ConfigBean( );
String nextIndex;
try
{
nextIndex = config.getNextIndexPath( );
}
catch(Exception ex)
{
return;
}
IndexLinks lts = new IndexLinks(nextIndex, config.getMaxLinks( ), 
config.getSkippedLinksFile( ));
lts.initFollowPrefixesFromSystemProperties( );
lts.initAvoidPrefixesFromSystemProperties( );
lts.setInitialLink(indexflag);
config.flipIndexPath( );
}
catch(Exception e)
{
// handle error
}
}

First, we retrieve the alternate index path from the ConfigBean. Remember, we need to create the index, but still allow other users to coninue to search it. Create a new instance of our IndexLinks class, passing in the alternate index path plus the MaxLinks and SkippedLinksFile values from our ConfigBean. Set up the avoid and follow link collections and kick off the index process. If everything succeeds, flip the indexes via the ConfigBean.flipIndexPath( ) method.

The console interface is simple enough that it doesn't need a controller layer between it and our business logic. In fact, the console interface looks a lot like a simple controller layer. It pieces together all three services without knowing anything about their internal configuration, demonstrating good interface separation. It is entirely focused on providing entry points to the application services to our users and returning results.

9.8.1 Principles in Action

Keep it simple: no configurable schedule for invoking services, allow indexing output to show through to user

Choose the right tools: JUnit

Do one thing, and do it well: just read from command lines and return search results

Strive for transparency: no internal knowledge of services

Allow for extension: none

/ 111