1 / 19

Advanced Programming Guidelines for Efficient and Clean Code

Best practices for writing efficient and clean code using object-oriented programming, polymorphism, and avoiding global variables. Learn to handle exceptions and use reflection wisely.

rhightower
Download Presentation

Advanced Programming Guidelines for Efficient and Clean Code

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Solution MidTerm2017 Advanced Programming Giuseppe Attardi Università di Pisa

  2. General Remarks • Follow good programming guidelines • eg: • https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/styleguide.md • In particular: • NEVER, EVER, EVER USE global variables:they hinder parallelism • Use exceptions sparingly (and handle them) • Use strings sparingly (StringBuffer)

  3. Use Object Oriented Programming • USE Polymorphism, USE Polymorphismmakes your code more modular, more readable, more extensible • Avoid using Reflection (instanceof) • Avoid static methods, aka functions, in OOP • Avoid functions for similar tasks: use polymorphic method in each of the classes where the operation is needed

  4. Bad Example class Utils { static String bytesToString(); static String inputstoString(); static String outputsToString(); … } • Alternative: • Use method serialize() in each class

  5. Exercise 1

  6. Hash class Hash { private static final MessageDigest md = MessageDigest.getInstance(“SHA-256”); public byte[] code; public Hash(byte[] bytes) { code = md.digest(bytes); } boolean isValid() { return code[0] == 0 && … code[2] == 0; } boolean equals(Hash other) { return Arrays.equals(code, other.code); } }

  7. Input class Input extends Pair<Hash, Integer> { // Hash for transaction, Integer for index in outputs public Input(Transaction t, int idx) { super(new Hash(t.serialize()), idx); } public byte[] serialize() { byte[] hash = getKey().code; byte bb = ByteBuffer.allocate(hash.length + 4); bb.put(hash).putInt(getValue()); return bb.array(); } } class Output extends Pair<Integer, PublicKey> { public Output(int v, PublicKey key) { … } public byte[] serialize() { … } }

  8. Transaction class Transaction implements Serializable { private List<Input> inputs; private List<Output> outputs; private byte[] signature; public Transaction() { inputs = new ArrayList<>(); outputs = new ArrayList<>(); } public add(Input i) { inputs.add(i); } public add(Output o) { outputs.add(o); }

  9. Transaction public void sign(PrivateKey key) { Signature s = new Signature(”SHA256withRSA”); s.init(key); for (Input i : inputs) s.update(i.serialize()); for (Output o : outputs) s.update(o.serialize()); signature = s.sign(); } public byte[] serialize() { byte bs = ByteArrayOutputStream(); for (Input i : inputs) bs.write(i.serialize()); for (Output o : outputs) bs.write(o.serialize()); bs.write(signature); return bs.toByteArray(); }

  10. Block class Block implements Serializable { private int seq; private int nonce = -1; private Hash previous; private Transaction t; public Block(int seq, Hash previous, Transaction t) { … } public hash() { return new Hash(serialize()); }   public int mine() { Hash hash; do { nonce++; hash = this.hash();   } while (!hash.isValid())   return nonce; }

  11. Block public byte[] serialize() { byte bs = ByteArrayOutputStream(); bs.write(ByteBuffer.allocate(4).putInt(seq).array()); bs.write(ByteBuffer.allocate(4).putInt(nonce).array()); bs.write(previous.hash()); bs.write(t.serialize()); return bs.toByteArray(); }

  12. Exercise 2

  13. BlockChain class BlockChain {   private List<Block> chain = new LinkedList<>();

  14.  boolean isValidBlockChain() { Map<Hash, BitSet> spentOutputs = new HashMap<>();   Hash current = null; // current block in chain   for (Block next : chain) { // next block in chain Transaction tx = next.transaction; if (current == null) {   spentOutputs.put(new Hash(tx.serialize()), new BitSet(tx.getOutputs().size())); current = next; continue; } Hash previous = current.previous(); Hash hash = next.hash();   if (!hash.isValid() || !hash.equals(previous)) // current block must refer to next one   return false;   for (Input input : tx.getInputs()) {   if (spentOutputs.computeIfPresent(input.getKey(), // update spentOutputs (k, v) -> {   if (v.get(input.getValue())) // already spent output at index input.getValue()   return null;   v.set(input.getValue()); // update return  v; // put back into Map }) == null) return false; }   spentOutputs.put(new Hash(tx.serialize()), new BitSet(tx.getOutputs().size())); current = next;   } return true; }

  15. public int getBalance(PublicKey user) { Map<Hash, BitSet> spentOutputs = new HashMap<>(); Iterator <Block> it = chain.descendingIterator(); // from last to first   while (it.hasNext()) { Block b = it.next(); Transaction tx = b.transaction(); Hash hash =  new Hash(tx); List<Output> outputs = tx.getOutputs();   for (int i = 0; i < outputs.size(); i++) { Output o = outputs.get(i);   if (user.equals(o.getValue()) && (spentOutputs.get(hash) == null || !spentOutputs.get(hash).get(i))) balance += o.getKey(); } // now add the outputs to the map spentOutputs for (Input in : tx.getInputs()) spentOutputs.computeIfAbsent(in.getKey(), v -> new BitSet()).set(in.getValue())); }   return balance; }

  16. Exercise 3

  17.  public static void main(String args[]) { String input; String[] tokens; Scanner reader =  new Scanner(System.in); init();   do {   do { System.out.print("> "); input = reader.nextLine().trim(); } while (input.equals("")); tokens = input.split("\\s+");   switch (tokens[0]) {   case "status": printBlockChain();   break;   case "check":   if (chain.isValidBlockChain()) System.out.println("The block chain is valid!");   else System.out.println("The block chain is not valid.");   break;

  18. Exercise 4

  19. A closure is a functional object that consists of a function and the lexical environment at the time of its creation. The environment contains the bindings for the non local variables visible in the scope of the function. • In C#, a delegate type is a type that represents functions with a given signature. • A delegate instance is created on an object and a method on that object compatible with its signature. • A delegate instance can be used as a function by invoking it with arguments, and this corresponds to invoking the delegate method on the delegate target with the given arguments.

More Related