Introduction - Laying the groundwork for a software development project is fundamental to ensuring the quality of an implementation. Whilst setting project objectives will drive the direction of a project, setting coding priorities will drive the implementation of the code for that project. Coding priorities help focus on the factors that have a bearing on the quality of the development and provide context for the coding styles adopted by the developers.
The APL programming language celebrated its 50th anniversary in 2016. Since its inception the APL language has evolved a growing and rich functionality.
An interpreted language with an interactive development environment APL has an immediate fingertip feedback for the developer working with it. Features that combine to provide a fertile and creative environment for its programmers.
In the early days memory and CPU were restricted resources. Writing concise algorithms that performed efficiently was highly prized. Even today the challenge of writing concise code to perform a complex task remains an enjoyable and exciting exercise. These skills in APL stand up quite well in the sporting arena of Code Golf which can be a useful training ground.
However, the requirements of a commercial coding task are very different. Left unchecked a developer will implement code that reflects personal views as to the relative importance of different coding priorities. Not surprisingly where one may produce clean maintainable code; another will write fast highly optimised woodgrain.
This is where defining coding priorities as part of the groundwork for projects can bring benefits.
Qualities for coding priorities
The following suggested list is not definitive and certainly not in any order of importance. It is simply one scenario and it is for the development team to identify and prioritise its own list. Some examples of quality bars have been added for illustration.
Coding priorities will differ for different applications because applications differ by their nature. However, design methods often employ approaches, patterns or templates that differentiate the components that make up an application.
A build can produce code components that may be visualised as arranged vertically and horizontally into packages. A common pattern MVC aims to separate data interfaces (Model); user interfaces (View); and business logic (Controller), into different components.
These different components lend themselves to coding priorities and can resolve conflicts within an application. That the priorities will conflict is inevitable and indeed the whole point of the exercise. The important thing is to consider what are the coding priorities to the component in hand.
Once coding priorities are identified it is important to set a quality bar for each to establish the criteria by which they can be met. A few suggestions have been included as illustrations.
Maintainability is an important feature where code can be expected to change frequently or regularly perhaps in response to external legislation.
Largely maintainability depends on how easily the developer can identify and address the most effective way to implement a solution with the minimum necessary change. One key to this is readability which enhances understanding.
A feature of APL is the use of recognisable idioms composed of the terse primitive functions. Following the principals of “clean code” where meaningful function and variable names may reduce the need for more extensive commenting. But verbose names can obscure idioms making it difficult to see what is happening.
Use of extensive comments should clarify the implementation but will impact on size.
Portability becomes important where releasing code to multiple installs, enabling congruent software across different remote and local platforms. However, portability can conflict with safety because utilities may need to be carefully written or carefully called depending on side effects in different environments.
Robustness becomes a priority where code needs to handle data with erroneous and unreliable data; or it may need to be proof against degrading over time; or scalability is important.
Quality bar: may require that interface classes (Views and Models) should be able to handle garbage data without failing. Interfaces to external data objects may need to be proof against network or service interruptions. For Controllers handling business logic deep in the application it may be enough to require that code should never fail for legal inputs. Whilst in all cases we may require that using deprecated features is avoided.
Re-usability can support size and maintainability of an implementation by reducing the volume of code and reducing the number of functional points that need to be addressed. Another benefit can be speed of development.
Refactoring code is an obvious way to do this where common operations are consolidated into utilities and/or reusable modules is assists in maintenance.
Cloning code or creating multiple versions of active code should be avoided at all costs. It builds up technical debt, can defeat search tools by increasing hits, undermines maintainability, increases size.
Quality bar: Refactoring should be one of the main considerations in pair programming and peer review exercises where code is to be reused. Where common utilities exist, they must be used.
Size may matter where an increased overhead impacting download speeds or data allowances for remote services is important. There may be conflicts with readability where appropriate white space, indentation and commenting will be larger than tightly packed code.
Quality bar: When pair programming or under peer review remove any commented code. Distributed/remote code should be minimised in production environments. Production code could have comments removed when released.
Speed, at first glance it might seem that speed would always be top priority. But performance usually requires more complex logic and optimisation, or even behind the scenes knowledge of how the APL is implemented. There are likely to be conflicts with safety, simplicity or maintainability as optimisations increase complexity.
Consider the component in hand. A start up routine may be time consuming but that assumes a different importance depending on whether it runs once a month or every hour. Bench marking can provide a quantitative measure for assessing areas to address.
Quality bar: Use profiling tools to provide information for peer review exercises. Identify areas that should be targeted for performance enhancements.
Simplicity It seems obvious that one should not try to be clever. Keep it simple stupid (KISS) is a good rule of thumb. Test driven development has a primary goal of passing the tests. Other considerations come later i.e. get it right first optimise later
Testability, where this is a priority then code needs to be designed to be tested. This is difficult where User Interfaces (Views) are involved, these tend to be better handled by explorative testing. So, it makes sense to separate interface processes from business processes.
Components handling business logic (Controllers) and utilities are more easily handled by testcases or in some instances test driven development (TDD). Data interfaces may have predefined data objects available that can help with applying regression testing with suitable tools.
Where testcases or regression tools can be applied then the door is open to automation. The ability to run automated tests supports maintainability.
Quality bar: Utilities and other modular code should have rigorous test cases applied to them. Controllers that handle business logic should have test cases for output resulting from all legal inputs.
Safety, Table driven solutions can help to produce less buggy code but may be slower than logic driven solutions. Holding control parameters externally can also support maintainability as changes are made more easily. Strategies using external storage for table driven code may not offer the speed than logic-driven code but may support maintainability.
Quality bar: May state that system parameters should be stored in appropriate INI files subject to version control. Static lookup tables should be used to control logic for complex processes except where establish benchmarks are compromised.
Setting coding priorities for the desired qualities can be an important contribution to bringing focus to applying coding standards and provide a feedback mechanism to review those standards and keep them relevant to the work in hand.
With focus and clear objectives, it becomes easier to make effective decisions. Pair programming sessions become more productive with relevant goals established up front.
Jake’s working life began as a Field Biologist for Wandsworth Borough Council; collecting, identifying and recording animal and plant life in parks, commons and other habitats; the data was used by the Borough and interested parties such as Friends of the Earth. Jake also used this material to write nature guides in Putney and Wimbledon. More about Jake.