a5c513add4b1e4b0bd068f1b60251520.ppt
- Количество слайдов: 24
Component-Based Software Engineering Designing the Remote Interface Paul Krause
Lecture 8 Contents
Why is it important? “Every program has (at least) two purposes: the one for which it was written, and another for which it wasn’t” Alan Perlis
Ariane 4 Ariane 5
First cut at Account public interface Account extends Remote { public Money get. Balance() throws Remote. Exception; public void Make. Deposit(Money amount) throws Remote. Exception, Negative. Amount. Exception; public void Make. Withdrawal(Money amount) throws Remote. Exception, Negative. Amount. Exception, Overdraft. Exception; }
Or, use “method objects” public interface Account extends Remote { public Money get. Balance() throws Remote. Exception; public void post. Transaction(Transaction transaction) throws Remote. Exception, Transaction. Exception; } Transaction Withdrawal Deposit … ? ?
Caution Ø Using method objects without thinking carefully about the security implications can be dangerous Ø If not you this approach becomes an open invitation to load a virus into the missioncritical part of the application
Discount this for now: Ø Consider adding a method to transfer money between accounts public void transfer. Money. To(Account account, Money amount) throws Remote. Exception, Overdraft. Exception, Negative. Amount. Exception, Invalid. Account. Exception; account 1. transfer. Money. To(account 2, money); Ø Or: Transfer. Money transfer. Money = new Transfer. Money(account 2, money); account 1. post. Transaction(transfer. Money);
General rule Ø “If it isn’t an object on the Client side, then it shouldn’t be an object on the interface” Ø Otherwise, in this case we have to: l l Display a form to get data from the user Enter data to build the transaction object Send the Transaction object to the Server Clear the reference to the Transaction object
Passing values or objects? public void make. Deposit(Money amount) throws Remote. Exception, Negative. Amount. Exception Ø The choice is between sending a primitive argument: float or int. Ø Or wrapping up the value as an object: Money. Ø Pro: flexibility Ø Con: bandwidth
E. g. Money as an integer An integer is 4 bytes long Ø Consider: Ø l l Naive. Money – straightforward wrapper Smart. Money – more efficient use of serialisation Serializing first instance of Naive. Money 235 bytes Serializing subsequent instances … 40 per instance Serializing first instance of Smart. Money 162 bytes Serializing subsequent instances … 15 per instance
Who wins now? Ø “If it isn’t an object on the client side, it shouldn’t be an object in the interface” Ø Change to: Ø “If it isn’t an object on the client side, it shouldn’t be an object in the interface … Ø unless the object is a natural collection of a set of related values” “If you have a procedure with ten parameters, you probably missed some. ”
Money as an object? Ø Money as a float: dddd. cccc l Very bad news as this introduces potential for floating point errors into accounting Ø Money as a String: “dddd Dolars and cc Cents” l Needs a parser to extract each part, and this may need to be changed if we change currency Ø Answer: Allow a range of Money classes
Return values? Ø Should we receive objects or primitive values? Ø Generally, this is easy as we only have a single return value l So make it an object Ø Possible exception if returning a boolean success flag: public boolean do. This(); l But can be better to return void and throw an exception if the operation fails
Applying to Account Ø get. Balance() returns an object (Money) Ø make. Deposit() and make. Withdrawal() return void l With informative exceptions if they fail
Do method calls waste bandwidth? Ø Warning with serialisation l Deep copies
Returning multiple values public interface Mortgage. Sales. Helper extends Remote { public Array. List get. All. Accountswith. Balance. Over(Money amount) throws Remote. Exception; // … } Ø Could return any number of accounts greater than the specified amount l All in one go
Problems Degrades perceived client performance Ø Increases performance variance Ø Large all-at-once network hit Ø Large commitment to a single client by server Ø Penalizes client mistakes Solution: Ø Use an iterator in this case to return manageable (and interruptible) chunks of data Ø
Conceptual Operations Ø Is each conceptual operation a single method call? Ø Consider a Printer service: public … int int get. Number. Of. Sheets. In. Paper. Feeder() throws… get. Toner. Level() throws… get. Time. Till. Paper. Runs. Out() throws… Ø Much better to group together frequently performed sequences of commands
Revised Printer example public class public int // … } Printer. Status extends Serializable { number. Of. Sheet. In. Paper. Feeder; toner. Level; estimated. Time. To. Paper. Run. Out(); public interface Printer extends Remote { public Printer. Status get. Status() throws Remote. Exception; // … }
Applied to Account Ø This favours including transfer. Money() in the interface in preference to just using the sequence l l make. Withdrawal(); make. Deposit();
Exposing Metadata Ø Does the interface expose the right amount of metadata? l l Functional methods Descriptive methods Ø E. g. with a printer, can you find out: l l l Types and sizes of paper handled Does it handle foils? Can it print in colour?
Applied to Account Ø No problem here. Individual accounts are registered in the naming service l The client must already know the server’s metadata
Accounting for Partial Failure
a5c513add4b1e4b0bd068f1b60251520.ppt