Let me just start by stating what I mean by a Bug Generator. It's a style of code that is likely to contain bugs or produce bugs in the future as the code is extended. This is of course an anti-pattern. There are corresponding Prevention Patterns, basically less error-prone alternatives. That being said, let's dive into the Bug Generator Use-of-indices.
Use of indexed access is low level, off-by-one errors are very common. Also index out of bounds can happen. Usually we can simply avoid this by using higher level constructs such as for-each-loops and higher-order functions such as map and filter.
Bug: Off-by-one errors
We access the data by some index. The problem can range from some simple error in a loop construct. For instance we use <= instead of < in loop. To harder-to-spot errors like passing the index to some function and using the index while modifying it by a -1 or +1.
A basic example of this. Say we need to find the first cat in a list of animals. The bug will only occur when there is no cat in the collection
Bug: Index-out-of-bounds
Variation of the above bug. This is off-by-one where we actually step outside the array.
Prevention pattern: use lambdas and higher-order-functions
higher order functions like map, filter, some/first, etc have already implemented the looping and we just have to provide a function that the higher order function will use on each element.
Prevention pattern: for-each-loop
If we really must use imperative style
Prevention pattern: link the structure length to the index calculation
E.g. modulo on length. An example would be picking cards from a deck. Lets assume that whenever we get to the end of the deck we're supposed to start from the beginning. A naïve implementation would be to
Prevention pattern: Wrap the array and index in a class (they are nearer).
This is particularly useful when the same calculation is done in several places. Whenever we have a class it is easy to find the code we need to manipulate the date inside. Another advantage is that the behaviour becomes easily testable when isolated in a class.
It'd be very easy and natural (i.e. likely) that we'd test getNextCard both by calling it many times in a row and with large values of someStep.
This solution is related to the Bug generator Primitive-Obsession that will probably be described in the future.
Credits to CodeCop (Peter Kofler) with whom I've worked a lot to explore the concept of Bug Generators. We sketched out this pattern together.
Credits to CodeCop (Peter Kofler) with whom I've worked a lot to explore the concept of Bug Generators. We sketched out this pattern together.
Aucun commentaire:
Enregistrer un commentaire