760 likes | 1.1k Views
Code Quality, Maintainability, Reusability, Debugging , Testing. SIF8080, Sep. 27th 2001 Customer-driven project Carl-Fredrik Sørensen mailto:carlfrs@idi.ntnu.no. Spider-web. Outline. Code Quality & Standards . Debugging, logging etc. Testing. Key Principles; Coding. Understandability
E N D
Code Quality, Maintainability, Reusability, Debugging, Testing SIF8080, Sep. 27th 2001 Customer-driven project Carl-Fredrik Sørensenmailto:carlfrs@idi.ntnu.no
Outline • Code Quality & Standards. • Debugging, logging etc. • Testing.
Key Principles; Coding • Understandability • High cohesion • Loose coupling • Code Formatting • Consistent Naming • Information hiding • Valuable Comments
Code Standards (1) • Why? • Gives less defects. • Easier/cheaper maintenance. • Several people may work on and understand the same code. • Code to be read, not only written. • Java coding standards: • The Elements of Java Style; Vermeulen et.al. SIGS Books. • http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html.
Code Standards (2) • 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.
Code Standards (3) • General rules (continued): • Consistency – Similar entities should look and 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.
Code Standards (4) • 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 notalter 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
Examples (2) • Include white space: • Bad: double length=Math.sqrt(x*x+y*y); • Better: double length = Math.sqrt(x * x + y * y); • Use blank lines to separate. • Do not use hard tabs.
Naming • Clear, unambiguous, readable, meaningful.Describe the purpose of the item: • Bad: X1, X2, mth, get, tmp, temp, result. • Give a descriptive name to temporary variables. • But: scientific formulas may be better formulated with single characters/words representing symbols instead of descriptive names.
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: calculate…VolumeRate.
Java Naming Convention • Package: scope.mypackage • Classes: MyClass • Methods: myMethod • Constants: MY_CONSTANT • Attribute: myAttribute • Variable: myVariable
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 • Limit the number of parameters to about seven
Comments; Why, when, where, what • 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.
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.
JavaDoc (2) • Purpose: To define a programmingcontract 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}.
JavaDoc Example: Class /** * <code> MyConstants </code> is the base class for all the constants and * implements any general constant responsibilities. * * @author Carl-Fredrik Sørensen * @version $Revision: 1.0$ * @invariants p > 0 * * @see MySpecificConstants */
JavaDoc (3) • Document pre-, post- and invariant conditions (OCL…). • @pre-condition, @post-condition, @invariants. • Document known defects and deficiencies. • @defect. • Document synchronisation semantics.
JavaDoc Example: Method /** * Method description * * @param paramName Name of the mechanism to search for, * one of the constants in the <code>MyClass</code> class. * @return The concrete instance of an <code>MyClass</code> * that is currently in effect if one found, null if not. * @exception Throwable Default finalizer exception. * @pre-condition valid paramName. * @post-condition (… described in @return here…) */
Architecture; How to Avoid Spider-web • Class/package organisation (loose coupling, high cohesion): • Split classes in (package/service) layers (user, data and business). Use package scoping (no.ntnu.idi…..). • Uni-directional dependencies.
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.
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.
Binding • Bind constants as late as possible • Do not use magic Numbers, avoid hard-coded values totalFooDay = totalFooHour * 24; if (me.equals(”thirsty”)) return ”water”; • Avoid global variables (constants OK) • Use separate classes/methods to hide hard-coded values • Achieves faster maintenance, and avoids copy-paste errors • Makes code better suited for reuse • Static methods and/or constants MyConstants.C1_SPECIFIC_GRAVITY
Java Exceptions (1) • Uncheckedrun-time exception: serious unexpected errors that may indicate an error in the program’s logic Termination. • Checkedexception: errors that may occur, however rarely, under normal program operation The caller must catch this exception.
Java Exceptions (2) • 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.
Code Defensively (1) • Check input data for validity (Pre-conditions). • Range, comment assumptions about acceptable input ranges 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.
Code Defensively (2) • 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.).
Summary • Remember your code should be understandable. • Maintenance is often up to 70% of a total project cost. • Use quality control.
Outline • Code quality and Code Standards. • Debugging, logging etc. • Testing.
Debugging • Single thread/process. • IDE’s with debugger most often sufficient. • Multiple clients, threads, distributed applications. • Synchronisation issues to protect the state of objects. • IDE’s (most often) lack good support. • Pre-instrumentation of code is often necessary. • Non-visual services (e.g. Real-time data conversions). • May debug single runs in IDE’s. • Hard to debug in real settings: system runs continuously or discretely at fixed times
Application Logging: What and Why? • 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.
JLog – Java Logging Framework • 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 users of the framework will log events consistently.
System Event Categories • Levels: • CRITICAL_ERROR. (Highest - 1) • ERROR. • WARNING. • INFORMATION. • DETAIL. • TRACE. (Lowest - 6)
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.
Logging Events • Instrument code with logging statements: • AppLog.criticalError("Caught unexpected exception: " + e); • SQLLog.info("Executing SQL query: " + statement); • AppLog.trace("Entering method getName()"); • Notice: the code does not need to have any "if" logic.
Configuring the Logs (1) • Configuration from a properties file. LogFileExtension = log LogFilePath = c:\\temp\\ LoggingLevel = 2 LoggingMechanism = log.StandardErrLoggingMechanism LogFieldSeparator = |
Configuring the Logs (2) • 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.
Configuring the Logs (3) • 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);
Configuring the Logs (4) • Other ways to dynamically reset the logging level at runtime: • In a debugger, you can change the value of the log's 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.
Reading the Logs (1) • 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.
Reading the Logs (2) • Import the log into a spreadsheet: • ASCII text import with a vertical bar as a field delimiter. • Sort or filter the log using various spreadsheet capabilities.
Outline • Code quality and Code Standards. • Debugging, logging etc. • Testing.
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. • JUnitto cheaply and incrementally build a test suite that helps to: • measure your progress, • spot unintended side effects. • focus your development efforts.
JUnit • Automatic testing framework. • Acceptance tests. • Integration test. • Unit test. • Reports the number of defects graphically. • May create many tests for each method.
JUnit Example • Pay attention to the interplay of the code and the tests. • The style: to write a few lines of code, then a test 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.
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; } }