Академический Документы
Профессиональный Документы
Культура Документы
Spider-web
::pck_stream ::lift_account ::pck_stock ::theoretical ::pck_check ::puf ::pck_facility
::pck_flow line
::sep_test
::pck_regression
::pck_cargo
::pck_cargo_doc
::w ell_node
::pck_stream_netw ork
::lagkodeserver
::comp_analysis
::choke
::calc_stream
::units
::value_adjust ::tbp_product
Outline
Understandability High cohesion Loose coupling Code Formatting Consistent Naming Information hiding Valuable Comments
4
Why?
Gives less defects. Easier/cheaper maintenance. Several people may work on and understand the same
html.
5
General rules:
Simplicity Build simple classes and methods.
Keep it as simple as possible, but not simpler (Einstein). Clarity Ensure item has a clear purpose. Explain where, when, why, and how to use each. Completeness Create complete documentation; document all features and functionality.
6
behave the same; dissimilar entities should look and behave differently. Create and apply standards whenever possible. Robustness Provide predictable documented behaviour in response to errors and exceptions. Do not hide errors and do not force clients to detect errors.
7
Do it right the first time ! Your professionalism is expressed by applying code standards ! Document any deviations!
Formatting
Is important for readability, not for the compiler. Use a common standard for code formatting. Do not alter the style of old code to fit new standards.
Examples (1)
class MyClass { void function (int arg) { if (arg < 0) { for (int index = 0; index <= arg; index++) { // Some Action Code } // end for } // end if } // end function } // end MyClass
10
Examples (2)
11
Naming
But: scientific formulas may be better formulated with single characters/words representing symbols instead of descriptive names.
12
Naming
Establish and use a common naming convention. Problems creating a good name purpose of the operation is not clear.
Bad: void get()., better: retrieveDataSamples.
Bad: Time day(Time p_day), better: getDate or
getTruncDate. Bad: void result(), better: createResults. Bad: void gas/oil/water, better: calculateVolumeRate.
13
Package: scope.mypackage Classes: MyClass Methods: myMethod Constants: MY_CONSTANT Attribute: myAttribute Variable: myVariable
14
Parameters
Actual parameters should match the formal Input-modify-output order If several operations use similar parameters, put the similar parameters in a consistent order Use all parameters Document interface assumptions about parameters
access type, unit, ranges, non-valid values
Why: To be able to find out what a operation does after a half, one or two years. Automatic API documentation. When; Document your code before or when you write it; Design before you implement. Put the design in the operation. Where; Before the operation, at specific formulas, decision points etc. What; Document the algorithm, avoid unnecessary comments. Refer to a specification if existing.
16
JavaDoc (1)
Generates HTML-formatted class reference or API documentation. Does only recognise documentation comments that appear immediately before
class Interface constructor, method field declaration.
17
JavaDoc (2)
Purpose: To define a programming contract between a client and a supplier of a service. Keep the documentation synchronised with the code. MAKE DOCUMENTATION FIRST, then code! JavaDoc tags:
@author, @version, @see, @param, @return, @exception.
{@link}.
18
19
JavaDoc (3)
20
22
::Theoretical
::EcDpStream
::EcDpWellReservoir
::EcDpStreamFluid
::calc_stream
23
Information Hiding
Do not expose operations that should be local to a package. Hide data access from the business services.
Create separate packages for performing data services. Define interfaces for data access, like e.g. EJB.
Scoping:
public: classes exposed by interfaces, operations in
interfaces. package: classes and operation not exposed through interface, but used by other classes in package. private: local attributes and methods.
24
Information Hiding
Hide the action part in control structures (functional cohesion) if complex, else delegate to a method. What to hide:
Areas that are likely to change; hardware dependencies,
input/output, non-standard language features, difficult design and implementation areas, data-size constraints, business rules, potential changes. Complex data. Complex logic.
25
Binding
Achieves faster maintenance, and avoids copy-paste errors Makes code better suited for reuse Static methods and/or constants
MyConstants.C1_SPECIFIC_GRAVITY
26
Unchecked run-time exception: serious unexpected errors that may indicate an error in the programs logic Termination. Checked exception: errors that may occur, however rarely, under normal program operation The caller must catch this exception.
27
Only convert exceptions to add information. If the method does not know how to handle an exception it should not be handled. Do not silently absorb a run-time or error exception makes code very hard to debug. Use finally blocks to release resources.
28
in the code. Use a general approach for error handling when erroneous data.
Use exception handling only to draw attention to unexpected cases (Do NOT perform any processing in exception code) (invariants). Anticipate changes; Hide to minimise impact of change.
29
Introduce debugging aids early (logging). Check function return values (post-conditions). Return friendly error messages; Write to a log file any system specific error messages (IO/SQL Exceptions, error codes etc.).
30
Summary
Remember your code should be understandable. Maintenance is often up to 70% of a total project cost. Use quality control.
31
Outline
32
Debugging
Single thread/process.
IDEs with debugger most often sufficient.
An application log is a text history of notable events logged by your application. The logs helps you to figure out what went wrong (and right) during the execution of your application. With the advent of N-tier architectures, Servlets, JSPs, and EJBs, application logging is particularly important to report errors that cannot or should not be surfaced to the user interface.
34
Developed by Todd Lauinger. A significant event happens in your Java code. That event could be any of several different types and conditions. Before you start using a logging framework:
categorize and document your events so that all
35
Levels:
CRITICAL_ERROR. (Highest - 1) ERROR.
WARNING.
INFORMATION. DETAIL. TRACE. (Lowest - 6)
36
Logging Granularity
Agreed and documented set of event categories determine the granularity to log those events. Separate logs for e.g.
thread pool. SQL processor.
37
Logging Events
exception: " + e); SQLLog.info("Executing SQL query: " + statement); AppLog.trace("Entering method getName()");
Notice: the code does not need to have any "if" logic.
38
39
You may select the output logging level. Default is the INFO level. All events logged at a level less than or equal to the log's current logging level will be output to the logging mechanisms. Events logged at a numerically higher level (i.e., a less critical level) will be discarded.
40
At runtime, you can increase or decrease the logging level of any of your logs without affecting your other logs. If you are trying to debug a nasty problem with your thread pool, you can programmatically change the log at runtime :
ThreadLog.getInstance().setLoggingLevel(Log.TRACE_LEVEL);
41
currentLoggingLevel variable. In an application server, you can examine and manipulate log properties with some JSPs. Use RMI to manipulate the log properties of a remote JVM. There are more options you can configure both programmatically and via a properties file.
42
Sample entries from a shared log, a vertical bar ( | ), is used to delimit the various fields of log entries:
RequestLog|L4|09:32:23:769|ExecuteThread-5|Executing request number 4 SQLLog|L4|09:32:23:835|ExecuteThread-5|select * from Customer where id = 35. RequestLog|L4|09:32:23:969|ExecuteThread-5|Request 4 took 200 milliseconds.
43
44
45
Outline
46
Testing
Not closely integrated with development prevents measurement of the progress of development - can't tell when something starts working or when something stops working. JUnit to cheaply and incrementally build a test suite that helps to:
measure your progress, spot unintended side effects. focus your development efforts.
47
JUnit
Unit test.
Reports the number of defects graphically. May create many tests for each method.
48
JUnit Example
that should run, or even better: to write a test that won't run, then write the code that will make it run.
The program presented solves the problem of representing arithmetic with multiple currencies.
49
Example: Money
class Money { private int fAmount; private String fCurrency; public Money(int amount, String currency) { fAmount= amount fCurrency= currency; } public int amount() { return fAmount; } public String currency() { return fCurrency; } }
50
JUnit
JUnit defines how to structure your test cases and provides the tools to run them. You implement a test in a subclass of TestCase.
51
Example: Money
public Money add(Money m) { return new Money(amount()+m.amount(), currency()); }
52
Junit
Define MoneyTest as a subclass of TestCase. Put MoneyTest in the same package as the classes under test access to the package private methods.
Add method testSimpleAdd, that will exercise the
simple version of Money.add() above. A JUnit test method is an ordinary method without any parameters.
53
Example: MoneyTest
public class MoneyTest extends TestCase { // public void testSimpleAdd() { Money m12CHF= new Money(12, "CHF"); // (1) Money m14CHF= new Money(14, "CHF"); Money expected= new Money(26, "CHF"); Money result= m12CHF.add(m14CHF); // (2) assert(expected.equals(result)); // (3) } }
54
Developing Tests
public void testEquals() { Money m12CHF= new Money(12, "CHF"); Money m14CHF= new Money(14, "CHF"); assert(!m12CHF.equals(null)); assertEquals(m12CHF, m12CHF); assertEquals(m12CHF, new Money(12, "CHF")); // (1) assert(!m12CHF.equals(m14CHF)); }
55
Developing Tests
public boolean equals(Object anObject) { if (anObject instanceof Money) { Money aMoney= (Money)anObject; return aMoney.currency().equals(currency()) && amount() == aMoney.amount(); } return false; }
56
Assertions
the argument isn't true. Since assertions for equality are very common, TestCase defines an assertEquals convenience method. Logs the printed value of the two objects if they differ. Shows why a test failed in a JUnit test result report. Logged as a string representation created by toString.
57
Test Fixture
public class MoneyTest extends TestCase { private Money f12CHF; private Money f14CHF; protected void setUp() { f12CHF= new Money(12, "CHF"); f14CHF= new Money(14, "CHF"); } }
58
Tests Refactored
public void testEquals() { assert(!f12CHF.equals(null)); assertEquals(f12CHF, f12CHF); assertEquals(f12CHF, new Money(12, "CHF")); assert(!f12CHF.equals(f14CHF)); } public void testSimpleAdd() { Money expected= new Money(26, "CHF"); Money result= f12CHF.add(f14CHF); assert(expected.equals(result)); }
59
Running of Tests
Two additional steps are needed to run the two test cases:
1. define how to run an individual test case,
Overrides the runTest method inherited from TestCase and call the desired test case.
Convenient way: anonymous inner class. Note: each test must be given a name to identify it if it fails.
TestCase test = new MoneyTest("simple add") { public void runTest() { testSimpleAdd(); } };
Dynamic: TestCase
61
Illustration of the creation of a test suite with the dynamic way to run a test:
You only pass the class with the tests to a TestSuite
62
64
In general: development will go much smoother writing tests a little at a time when developing. When coding the imagination of how the code will work. Capture the thoughts in a test. Test code is just like model code in working best if it is factored well.
65
Keeping old tests running is just as important as making new ones run. The ideal is to always run all of your tests. When you are struck by an idea, defer thinking about the implementation. First write the test. Then run it. Then work on the implementation.
66
Martin Fowler: "Whenever you are tempted to type something into a print statement or a debugger expression, write it as a test instead. Only a fraction of the tests are actually useful.
Write tests that fail even though they should work,
or tests that succeed even though they should fail. Think of it is in cost/benefit terms. You want tests that pay you back with information.
67
Caution:
Once you get them running, make sure they stay running.
Ideally, run every test in the suite every time you change a method. Practically, the suite will soon grow too large to run all the time.
68
Try to optimise your set-up code so you can run all the tests. Or,
create special suites that contain all the tests that might
possibly be affected by your current development. run the suite every time you compile. make sure you run every test at least once a day: overnight, during lunch, during one of those long meetings.
69
References
Code Complete; Steve McConnell, Microsoft Press. The Elements of Java Style; Allan Vermeulen, SIGS Reference Library, Cambridge
70
Questions
71