Coding Techniques

University of Nantes – LS2N, France

Gerson Sunyé

Goals of Coding

column
  • Translate the design of system into a computer language format

  • Reduce the cost of later phases

  • Make the program more readable

Plan

  • Assertive Programming

  • Defensive Programming

  • Logging

  • Automatic Code Generation

Assertive Programming

Assertive Programming

There is a luxury in self-reproach. When we blame ourselves we feel no one else has a right to blame us.

The Picture of Dorian Gray
— Oscar Wilde

Assertive Programming

  • Technique that follows the principle of fail fast and fail visibly

  • It reduces the error propagation because of side-effects.

  • It forbids(kind of sanity-check) the system to enter an inconsistent state because of user-data or by subsequent code changes.

Assertions

  • Assertions are predicates that check conditions that should never occur, and blow up catastrophically if they do.

  • Goals:

    • Ensure the state of variables.

    • Improve code readability.

    • Improve error localization.

  • Can be disabled.

Assertions prevent the impossible!

Java Assertion Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public abstract class Application {
    private Logger logger = Logger.global;
    private List<Service> services = new ArrayList<Service>();
    private Registry registry;
    private MessagingService messaging;

    public Application(Factory factory) {
        registry = factory.createRegistry();
        messaging = factory.createMessaging();

        assert registry != null : "Registry service was not created correctly";
        assert messaging != null : "Messaging service was not created correctly";

        this.addService(registry);
        this.addService(messaging);
    }
}

Improving Assertions with AssertJ

class Assertion {
	public double calculate(int x, int y) {
		assertThat(x).isNotZero();
		assertThat(y).isLessThanOrEqualTo(10);
		// (...)
}

Defensive Programming

Defensive Programming

defensive
Technique for developing maintainable code
  • ensures the code to behave in a correct manner, despite incorrect input.

  • guarantees that a method can be executed only when some requirements are met.

Guard Checking

  • Most spread technique form of Defensive Programming.

  • Guarantee that a method can be executed only when some requirements are met.

Guard Checking in Java
public static void foo(String name, int start, int end) {

    // Guards
    if (null == name) {
        throw new NullPointerException("Name must not be null");
    }
    if (start >= end) {
		throw new IllegalArgumentException("Start (" + start + ") must be " + "smaller than end (" + end + ")");
    }
    // Do something here ...
}

Guards in Apache Commons

public static void foo(String name, int start, int end) {

    // Guards
    Validate.notNull(name, "Name must not be null");
    Validate.isTrue(start < end, "Start (%s) must be smaller than end (%s)", start, end);

    // Do something here ...
}

Guards in Google Guava

public static void foo(String name, int start, int end) {

    // Guards
    Preconditions.checkNotNull(name, "Name must not be null");
    Preconditions.checkArgument(start < end, "Start (%s) must be smaller than end (%s)", start, end);

    // Do something here ...
}

Guards in Atlanmod Commons

public static void foo(String name, int start, int end) {

    // Guards
    Preconditions.checkNotNull(name, "Name must not be null");
    Preconditions.checkArgument(start < end, "Start (%s) must be smaller than end (%s)", start, end);

    // Do something here ...
}

Logging

Logging

Technique for keeping a log of events that occur during the execution of a software:
  • Events are logged according to a severity level hierarchy.

  • For instance: SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST

Logging in Java

Java Logging API Example
import java.util.logging.Logger;

private final static Logger LOG = Logger.getLogger(MyClass.class.getName());

public MyClass {
	public MyCLass() {
		LOG.setLevel(Level.INFO);
	}

	public void foo() {
		LOG.severe("Important Log");
		LOG.warning("Less important Log");
		LOG.info("Not important Log");
		LOG.finest("Really not important");
	}
}

Automatic Code Generation

Automatic Code Generation

automated code generation
Code generation from a higher level language (graphical or textual)
  • Goals:

    • Productivity

    • Simplification

    • Portability

    • Consistency

  • Different Techniques

    • Templates

    • Specific APIs

    • Cross-platform code generation toolkits.

Templates

  • Templates are simple text files enriched with template notation elements in order to work with placeholders.

acceleo example
Figure 1. Acceleo Template Example

JavaPoet

JavaPoet Example

MethodSpec main = MethodSpec.methodBuilder("main")
    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
    .returns(void.class)
    .addParameter(String[].class, "args")
    .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
    .build();

TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
    .addMethod(main)
    .build();

JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
    .build();

javaFile.writeTo(System.out);

Google Protocol Buffer

protobuf logo

Protobuf Example

Definition
message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
}
Usage in Java
Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .build();
output = new FileOutputStream(args[0]);
john.writeTo(output);

Apache Thrift

apache
  • Framework for scalable cross-language services development

  • Code generation engine to build services between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml, and Delphi

Apache Thrift Example

Definition
service Calculator extends shared.SharedService {
   void ping(),

   i32 add(1:i32 num1, 2:i32 num2),

   i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),

   oneway void zip()
}
Python Client
def main():
    # Make socket
    transport = TSocket.TSocket('localhost', 9090)

    # Buffering is critical. Raw sockets are very slow
    transport = TTransport.TBufferedTransport(transport)

    # Wrap in a protocol
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Create a client to use the protocol encoder
    client = Calculator.Client(protocol)

    # Connect!
    transport.open()

    client.ping()
    print('ping()')

    sum_ = client.add(1, 1)