Software engineering, program management The problem Software is expensive to design! – Industry estimates put software development labor costs at 1.5 hours per machine instruction – Software developers are expensive labor – Most "real" programs contain thousands, if not millions of lines of code The quality of much software and most documentation is poor The problem Even after extensive testing, software frequently has bugs – Testing can prove the presence of bugs, but testing can (almost) never prove the absence of bugs! – Testing and debugging software can take as much or more time than the original planning and writing Most new software is completed later than forecast (2x or 3x longer is common) Programming can be tedious, boring work The problem The design process – Software development, as any engineering effort, should be based around a logical design methodology whether for a lab assignment or as part of a large SW design team The problem Need Concept Decomposition Specification Design Test / Validation Production Deployment Maintenance Disposa Programmer's "goals" what's important? Write the shortest program – Uses less memory, so hardware requirements are less – Often trading expensive human effort for inexpensive hardware costs – Encourages programming "tricks" Programmer's "goals" what's important? Write the fastest program – Get the program's execution done as quickly as possible – Not always an important goal in embedded systems – More payoff from developing and implementing an efficient algorithm – Use profiling as a guide to optimizing the already good algorithm Programmer's "goals" what's important? Write an easily understood program – The programmer and others must be able to understand the function of the instructions in the program – Complex programs are hard to modify and maintain – Good documentation – KISS principle Programmer's "goals" what's important? Write an easily modified program – Be able to change it to cope with changing environments – Requires planning and effort during the design phase – Effort is extremely cost effective compared to redesign effort – Focus on long-term success Programmer's "goals" what's important? Meet the schedule – Avoid the vaporware syndrome – Organize and plan for changes – Failure can mean loss of market share Program design The design process lends itself to an iterative problem decomposition in a divide-and-conquer approach Decompose overall task into smaller subtasks that can be written and tested independently Program design Program design Avoid spaghetti code and designs – Each module should have single entry / exit points Program design Structured programming uses 3 basic control structures Documentation Good documentation is mandatory for good code This provides information needed by humans to understand the operation of the program and enable efficient maintenance and modification For a given code segment / block / function , well thought out, detailed comments in the “header” can help reduce the need for line-by-line comments within the code itself Documentation Programs can be over or under documented Examples: – Wrong: LDAA #$56 ; – Right: LDAA #$56 ; load ACCA with $56 initialization word for ; DDRC -- bits 1,2,4,6 ; are outputs Documentation Each code segment / block / function should include comments that … – Identify the routine’s name and function – Who wrote it and when – Describe the algorithm being implemented – Explain the parameters being passed to and from the routine – List other routines that call this routine or are called by this routine CONTD Documentation – Describe register and memory requirements -- which locations are altered? – Give the modification history – Do not overwhelm the reader (particularly in-line comments) Software written for the labs and design projects is expected to follow these guidelines! – For a good example, see the code included with the sample lab report on the WI web page Documentation Main routine should be mostly calls to subroutines – If something takes more than a few instructions, don’t put it directly in the main routine – make it a subroutine – Main routine will usually be an infinite loop – Example: ;******************************** ; Thermometer: This program reads an ; analog value from a temperature sensor ; every 0.5 seconds, and displays the ; temperature on an LCD display. Documentation ORG $B600 Thermometer: lds #$1FF ; initialize stack pointer jsr InitSystem ;initialize the system Loop: jsr GetAnalogValue ; get A/D value from ; temp sensor jsr ConvertTemp ; determine the ; temperature jsr DisplayTemp ; display it on LCD jsr Delay0P5 ; delay for 0.5 seconds bra Loop ; repeat Documentation Include a header with each subroutine: ;******************************** ; Convert_Temp: This routine converts ; an analog value (assumed to be an 8-bit ; binary fraction between 0 and 1) to a ; Fahrenheit temperature using the formula ; temp = (value * 180) + 32 ; Input: ACCA = 8-bit analog value ; Output : ACCA = temperature ; Registers modified: CCR Documentation Convert_Temp: pshb ldab mul adca pulb rts #180 #32 ; save ACCB ; calculate temp ; = (value * 180) + 32 ; ACCA = temp ; restore ACCB ; return Summary Programs should be well-designed and welldocumented Use a modular design – Each subroutine should perform a single function – Subroutine interfaces should be clearly defined Focus on making programs easy to understand and easy to maintain – Bonus: They’re often easier to debug CONTD Summary – Avoid programming “tricks” unless they are truly needed for performance or memory requirements – If you need to use “tricks” -- document them! Time spent on design (before coding) is usually a good investment