Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Selling_Maintainability.pdf

Avatar for Tom Hombergs Tom Hombergs
May 31, 2025
13

 Selling_Maintainability.pdf

Avatar for Tom Hombergs

Tom Hombergs

May 31, 2025
Tweet

Transcript

  1. What have I signed up for? What is maintainability? What

    makes software maintainable? Impacts of (lacking) maintainability What happens if our software is maintainable (and what if not)? Tips & Tricks How to argue for spending time on maintainability? How to improve it? … on a Friday at 17:00…
  2. Few dependencies The fewer dependencies a component has … …

    the easier it is to reason about. … the less coupled it is to other components.
  3. Maintainable? static void intern_rec(value *dest) { unsigned int code; tag_t

    tag; mlsize_t size, len, ofs_ind; value v, clos; asize_t ofs; header_t header; char cksum[16]; struct custom_operations * ops; tailcall: code = read8u(); if (code >= PREFIX_SMALL_INT) { if (code >= PREFIX_SMALL_BLOCK) { /* Small block */ tag = code & 0xF; size = (code >> 4) & 0x7; read_block: if (size == 0) { v = Atom(tag); } else { v = Val_hp(intern_dest); *dest = v; if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; dest = (value *) (intern_dest + 1); *intern_dest = Make_header(size, tag, intern_color); intern_dest += 1 + size; for(/*nothing*/; size > 1; size--, dest++) intern_rec(dest); goto tailcall; } } else { /* Small integer */ v = Val_int(code & 0x3F); } } else { if (code >= PREFIX_SMALL_STRING) { /* Small string */ len = (code & 0x1F); read_string: size = (len + sizeof(value)) / sizeof(value); v = Val_hp(intern_dest); if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; *intern_dest = Make_header(size, String_tag, intern_color); intern_dest += 1 + size; Field(v, size - 1) = 0; ofs_ind = Bsize_wsize(size) - 1; Byte(v, ofs_ind) = ofs_ind - len; readblock(String_val(v), len); } else { switch(code) { case CODE_INT8: v = Val_long(read8s()); break; case CODE_INT16: v = Val_long(read16s()); break; case CODE_INT32: v = Val_long(read32s()); break; case CODE_INT64: #ifdef ARCH_SIXTYFOUR v = Val_long(read64s()); break; #else intern_cleanup(); failwith("input_value: integer too large"); break; #endif case CODE_SHARED8: ofs = read8u(); read_shared: Assert (ofs > 0); Assert (ofs <= obj_counter); Assert (intern_obj_table != NULL); v = intern_obj_table[obj_counter - ofs]; break; case CODE_SHARED16: ofs = read16u(); goto read_shared; case CODE_SHARED32: ofs = read32u(); goto read_shared; case CODE_BLOCK32: header = (header_t) read32u(); tag = Tag_hd(header); size = Wosize_hd(header); goto read_block; case CODE_STRING8: len = read8u(); goto read_string; case CODE_STRING32: len = read32u(); goto read_string; case CODE_DOUBLE_LITTLE: case CODE_DOUBLE_BIG: if (sizeof(double) != 8) { intern_cleanup(); invalid_argument("input_value: non-standard floats"); } v = Val_hp(intern_dest); if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; *intern_dest = Make_header(Double_wosize, Double_tag, intern_color); intern_dest += 1 + Double_wosize; readblock((char *) v, 8); #if ARCH_FLOAT_ENDIANNESS == 0x76543210 if (code != CODE_DOUBLE_BIG) Reverse_64(v, v); #elif ARCH_FLOAT_ENDIANNESS == 0x01234567 if (code != CODE_DOUBLE_LITTLE) Reverse_64(v, v); #else if (code == CODE_DOUBLE_LITTLE) Permute_64(v, ARCH_FLOAT_ENDIANNESS, v, 0x01234567) else Permute_64(v, ARCH_FLOAT_ENDIANNESS, v, 0x76543210); #endif break; case CODE_DOUBLE_ARRAY8_LITTLE: case CODE_DOUBLE_ARRAY8_BIG: len = read8u(); read_double_array: if (sizeof(double) != 8) { intern_cleanup(); invalid_argument("input_value: non-standard floats"); } size = len * Double_wosize; v = Val_hp(intern_dest); if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; *intern_dest = Make_header(size, Double_array_tag, intern_color); intern_dest += 1 + size; readblock((char *) v, len * 8 #if ARCH_FLOAT_ENDIANNESS == 0x76543 if (code != CODE_DOUBLE_ARRAY8 code != CODE_DOUBLE_ARRAY3 mlsize_t i; for (i = 0; i < len; i++) Rev } #elif ARCH_FLOAT_ENDIANNESS == 0x012345 if (code != CODE_DOUBLE_ARRAY8_L code != CODE_DOUBLE_ARRAY32_ mlsize_t i; for (i = 0; i < len; i++) Rever } #else if (code == CODE_DOUBLE_ARRAY8_LIT code == CODE_DOUBLE_ARRAY32_LI mlsize_t i; for (i = 0; i < len; i++) Permute_64((value)((double *)v (value)((double *)v + } else { mlsize_t i; for (i = 0; i < len; i++) Permute_64((value)((double *)v + (value)((double *)v + } #endif break; case CODE_DOUBLE_ARRAY32_LITTLE: case CODE_DOUBLE_ARRAY32_BIG: len = read32u(); goto read_double_array; case CODE_CODEPOINTER: ofs = read32u(); readblock(cksum, 16); if (memcmp(cksum, code_checksum(), 16) != intern_cleanup(); failwith("input_value: code mismatch"); } v = (value) (code_area_start + ofs); break; case CODE_INFIXPOINTER: ofs = read32u(); intern_rec(&clos); v = clos + ofs; break; case CODE_CUSTOM: ops = find_custom_operations((char *) intern if (ops == NULL) { intern_cleanup(); failwith("input_value: unknown custom block } while (*intern_src++ != 0) /*nothing*/; /*ski size = ops->deserialize((void *) (intern_dest size = 1 + (size + sizeof(value) - 1) / sizeof v = Val_hp(intern_dest); if (intern_obj_table != NULL) intern_obj_table[ *intern_dest = Make_header(size, Custom_tag, in Custom_ops_val(v) = ops; intern_dest += 1 + size; break; default: intern_clean Few dependencies are not enough to make code maintainable.
  4. Which is more maintainable? B D F E C A

    B F E C A H I J K L G D 12 dependencies 19 dependencies
  5. Few dependencies (in the right direction) 
 and few responsibilities

    
 per component make software maintainable. The system of components will have many dependencies and many responsibilities. Maintainability
  6. Developer productivity positively in fl uences developer joy. Developer joy

    Developer productivity Maintainability “The SPACE of Developer Productivity”: https://dl.acm.org/doi/10.1145/3454122.3454124
  7. Teambuilding analogy If responsibilities in a team are unclear, everyone

    depends on everyone else and the team can’t work productively.
  8. Messy room analogy If a room is already messy, you

    have no inhibitions to make it even messier.
  9. Track the cost of change Observe the cost of change

    over time to make informed decisions.
  10. Cost of change over time Decision we could have made

    at the start of the project This is where we could have been today … (without promotions, though) Decisions we have actually made This where we actually are today
  11. Maintainability by default When making a change, default to the

    more maintainable solution (unless there’s a good reason not to). Record and review decisions impacting maintainability When making a decision that impacts maintainability, record the expected impact on maintainability and compare it against the actual impact. Takeaways Maintainability creates a virtuous (or vicious) cycle Maintainability in fl uences and is in fl uenced by 
 developer joy and productivity.