进度:第七周
讲义 E6
在开始本练习之前,我们建议你仔细阅读整个问题。
介绍
在练习
5中,你确定了你的FolioTracker程序的基本功能,为它设计了一个图形用户接口(GUI);指定了一个应用程序接口(API),GUI
可以通过它访问获取投资报价的代码,等等。但是除指定接口和功能之外,你并没有做多少后端设计和实现的工作。练习6的焦点就是后端的设计和实现。你并不需要学习任何新东西,但是你将重新练习你所学过的技术:抽象数据类型的设计、对象模型、等等。你不需要实现获取投资报价的代码,我们将为你提供一个类,这个类中提供了一个简单的方法,它需要一个字符串型的订单符号作为输入并返回一个价格。
练习 6
在本练习中,你的任务是通过实现你在练习5中定义的API来完成你的投资跟踪器程序。你需要设计你的投资跟踪器后端的内部结构,并测试整个程序。这个程序的测试是很困难的,因为它包含一个GUI,而且股票价格的不断变化使得测试很难被重复。因此你需要设计一个可行的测试方案来保证你的应用程序是可靠的,而且股票价格、资产和
投资评估是值得信赖的。你可能需要利用你在练习5中设计的总体接口,并且对GUI使用特殊的方式进行单独测试。
你应该提交以下项目:
(a) 代码对象模型 [一页]:一个列举应用程序内部状态的对象模型。它应该包含主要的GUI对象以及用来实现API的对象。
(b) 模块依赖图
[一页]:整个应用程序的一个模块依赖图。用它来解释你所设计的用来分解问题或达成其他目的的特殊技术或抽象,添加一个简短说明。
(c) 代码:你的API的后端实现代码,以及你所写的测试代码。还应该包括对于实现中各个模块的合适说明(也就是,对于公有方法和难以理解的私有方法应该添加说明)。
(d) 测试 [一页或更少]:对于你的测试策略的一个简洁明了的概述:你进行了什么样的测试,使用了什么测试用例。
勘误
- QuoteServer (报价服务器)数值格式检查
QuoteServer的代码错误的尝试检查返回值的格式。如果返回值中包含逗号(例如NASDAQ
=> "2,494.00")这将导致问题。我们已经移除了检查代码,并修改了getLastValue() 方法的规格说明以允许逗号的存在。
问题&回答
这部分将对练习中一些常见问题进行澄清和回答。我们将尽力保持对这部分的更新,因此,当你遇到问题时这部分应该是你最先查看的地方(在仔细的阅读问题描述讲义和规格说明之后)。
- 问题:如果拥有一个订单符号,我们该怎样得到公司名称?
-
回答:对于此问题Reuben Sterling提出了一个很好的解决方案。多谢Reuben!
信息:getNameFromTicker2()是实际和网站交互的方法。getNameFromTicker()是应该调用的方法,它保存一个先前查出的订单符号的记录,因此它的运行速度可能更快一些。
添加到QuoteServer中:
protected static final String _NAME_LOOKUP_URL = "http://quote.fool.com/lookup.asp?company=";
protected static final String _TOKEN3 = "currticker=";
protected static final String _TOKEN4 = "&symbols=";
protected static final String _TOKEN5 = "mw_symbollookup_standard";
protected static HashMap names = new HashMap();
public static String getNameFromTicker(String tickerSymbol) throws WebsiteDataException, NoSuchTickerException {
String name = (String)QuoteServer.names.get(tickerSymbol);
if (name == null) {
name = QuoteServer.getNameFromTicker2(tickerSymbol);
QuoteServer.names.put(tickerSymbol, name);
}
return name;
}
private static String getNameFromTicker2(String tickerSymbol) throws WebsiteDataException, NoSuchTickerException {
tickerSymbol = tickerSymbol.toUpperCase();
String strURLStart = _NAME_LOOKUP_URL;
URL urlWebPage = null;
InputStreamReader isr = null;
BufferedReader brWebPage = null;
String nameLookupToken = _TOKEN3+tickerSymbol+_TOKEN4+tickerSymbol;
String strStockName;
// 打开网页以阅读
try {
urlWebPage = new URL(strURLStart + tickerSymbol);
isr = new InputStreamReader(urlWebPage.openStream());
brWebPage = new BufferedReader(isr);
} catch(Exception e) {
throw new WebsiteDataException();
}
// 查找有股票报价的行
String strLine = null;
try {
while(true) {
strLine = brWebPage.readLine();
if(strLine == null) {
throw new WebsiteDataException("Parse failed!");
}
if(strLine.indexOf(nameLookupToken) != -1)
break;
}
}
catch(IOException e) {
throw new WebsiteDataException();
}
// 查找行中的股票报价
StringTokenizer strtok = new StringTokenizer(strLine, _DELIMITER);
while(true) {
if(strtok.hasMoreTokens() == false) {
throw new NoSuchTickerException();
}
if(strtok.nextToken().compareTo(_TOKEN5) == 0) {
strStockName = strtok.nextToken();
if (strStockName.substring(0, 5).compareTo("nbsp;") == 0)
break;
}
}
strStockName = strStockName.substring(5);
return strStockName;
}