按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
CH AP T E R 1 1 ■ L E A R N IN G AB O U T 。 N E T G E N E R I CS 291
spreadsheet。Cells(1; 2) = _
CellFactories。DoAdd(spreadsheet。Cells(1; 0); spreadsheet。Cells(0; 1))
spreadsheet。Cells(2; 2) = CellFactories。DoMultiply(spreadsheet。Cells(1; 2); _
CellFactories。FixedValue(2。0))
spreadsheet。Execute()
Console。WriteLine(〃Contents of (1; 2): 〃 & spreadsheet。State(1; 2)。ToString())
Console。WriteLine(〃Contents of (2; 2): 〃 & spreadsheet。State(2; 2)。ToString())
The sample code illustrates a rudimentary example of a spreadsheet and how lambda
expressions can be used。 In this chapter; the focus will be on how to create a spreadsheet
implementation that is effective; mostly object…oriented; and maintainable。
Architecting a Server…Side Spreadsheet
To architect a server spreadsheet; the following requirements must be met:
o Performance: Wherever possible; the design should not sacrifice performance。
o Usability: The server…side spreadsheet must be easy to program from a Visual Basic
perspective。 If the server…side spreadsheet is too plex or difficult to understand; it
will not be used properly; potentially incurring errors。
o Maintainability: The server…side spreadsheet implementation should be somewhat
maintainable。 Otherwise; bugs could creep into the code; impeding the spreadsheet’s
effective use。
Not listed is the requirement for extensibility。 A spreadsheet by itself is not extensible
because it implements a certain paradigm; which is a two…dimensional document of numbers
and calculations。
And if you are wondering where the spreadsheet code es from; it is a subset of the
actual code that I use in my own security trading system。
■Note To code the spreadsheet to do more than it is originally designed for might be an interesting goal;
but not one that is worth pursuing。 Sometimes it is best to solve a problem; and leave paradigm thinking for
another time。 I have seen developers think about paradigms; not finish their code; and then have the code
made obsolete by a paradigm that they did not consider。
Three projects are defined for this example:
o Devspace。Trader。mon: A class library that is a distilled form of my trading library。 I
decided to include such a library to give you a taste of how a production class library
looks and feels。
o ServerSideSpreadsheet: A class library that represents the implementation of a server
side spreadsheet。
o TestServerSideSpreadsheet: A console application that tests the ServerSideSpreadsheet
project。
…………………………………………………………Page 314……………………………………………………………
292 CH AP T E R 1 1 ■ L E A R N I N G A B OU T 。 N E T G E N E R I CS
Designing the Architecture
The original implementation of the spreadsheet code provides a great starting point。 Using
lambda expressions to calculate the state of a cell makes it easy to create a worksheet of numbers。
What is not so great is the fact that the class SpreadSheet is a single worksheet。 Most spreadsheets
applications (like Microsoft Excel) offer the ability to create multiple worksheets。
The server…side spreadsheet that we will create will consist of two concepts: workbook and
worksheet; as illustrated in Figure 11…1。
Figure 11…1。 Spreadsheet design based on workbook and worksheet types
The workbook is a type that acts like a collection class of the worksheet type。 The work
sheet type is an individual spreadsheet of fixed dimension that is responsible for storing the
state; and the cell calculations reference the individual lambda expressions。
The workbook and worksheet could be defined as interfaces or as classes。 Which would be
better? Let’s assume that workbook will be defined as an interface and then implemented by a
class。 The approach is a mitment to a ponent architecture; allowing you to implement
multiple types of workbooks。 However; the likelihood of implementing multiple workbook
types is rather remote; so why use interfaces? Because interfaces fit better into a bigger context。
Let’s say that you have pleted your super…duper server…side application and want
to programmatically share the code with multiple machines。 Having one puter call
functionality on another machine is almost trivial; but to attain the best performance and
resource usage; you should use interfaces。
Defining the Server Spreadsheet Interfaces
Defining the interfaces for the server spreadsheets is actually rather plicated because of
the requirements。 The requirements state performance and usability are important; which; in
this case; is asking quite a bit; as you will see as we work through the example。 Let’s start with a
bottom…up development approach and outline the interfaces。
Defining the Debug Interface
Because the spreadsheet is from a production coding example; included in the discussion will
be pieces of code that demonstrate good programming practices。 The following is the base
interface for all of my interfaces; which is defined in the Devspace。Trader。mon project。
Public Interface IDebug
Property Debug() As Boolean
End Interface
…………………………………………………………Page 315……………………………………………………………
CH AP T E R 1 1 ■ L E A R N IN G AB O U T 。 N E T G E N E R I CS 293
The IDebug interface has a single Boolean property called Debug; which can be assigned and
retrieved。 The idea behind the IDebug interface is to enable a ponent to generate debug
output。 One of the major headaches with debugging applications that process large amounts
of data is finding where the problem is。 Imagine processing several million records; and the
bug happens in record 900;001。 You don’t want to debug 900;000 records before hitting the bug。
Thus; the challenge is figuring out what went wrong without using the debugger。 This is where
IDebug es into play。 It provides a mechanism to let the implementation say what is going
on; so if a bug needs to be deciphered; you do so by looking at the output。
The following example demonstrates how to use the Debug flag。 The class that contains this
code implements the IDebug interface and sets the Debug flag at the beginning of its execution。
Dim baseType As String() = _
typeToInstantiate。Split(New String() { 〃''〃; 〃''〃 }; StringSplitOptions。None)
If baseType。Length = 0 Then
Throw New Exception(〃There is no base type; which is an error〃)
End If
If Debug Then
For Each str As String In baseType
GenerateOutput。Write(〃Workbook。Load〃; 〃baseType(〃 & str & 〃)〃)
Next
End If
The first line of code is used to split up a buffer into individual pieces; where double square
brackets delimit the buffers。 The Debug property is used to output the split…up buffer using the
mand GenerateOutput。Write()。
■Tip Although I have defined my own debugging infrastructure; there is another infrastructure that you can
use; called log4net (http://logging。apache。org/log4net/)。 This is a prehensive infrastructure
that you may want to investigate。
A Debug flag was used to output some text; otherwise; that information is not usually visible。
Without a Debug flag; the only way to get that information is by setting a breakpoint after the
Split() statement; and then individually investigating the result