Difference between revisions of "Teaching (Computing)"
Line 98: | Line 98: | ||
System.out.printf("in 5 years, you'll be %d years old\n", agePlus5); | System.out.printf("in 5 years, you'll be %d years old\n", agePlus5); | ||
− | '''Problem:''' Holding data in a string necessitates use of awkward | + | '''Problem:''' Holding data in a string necessitates use of methods in awkward ways (such as that of <code>compareTo</code> above) and multiple conversions to more adequate types (e.g. via <code>parseInt</code>). |
'''Solution:''' Apply the classical Input - Processing - Output pattern, noticing that acquiring input does not just mean reading data from an external source (such as a file). Acquiring input frequently means parsing it. With object oriented designs, parsing should normally result in one or more instances of classes that are specific for the application's domain. | '''Solution:''' Apply the classical Input - Processing - Output pattern, noticing that acquiring input does not just mean reading data from an external source (such as a file). Acquiring input frequently means parsing it. With object oriented designs, parsing should normally result in one or more instances of classes that are specific for the application's domain. |
Revision as of 04:54, 6 March 2010
Contents
Misc. Links
- Teaching Mobile Computing has the interesting idea of running exercises using wireless during classes / lectures.
Common Programming Problems and Mistakes
Anti-Patterns
The anti-patterns described are quite basic and thus may be of little interest advanced programmers. I list them here mainly because I seem them repeatedly appearing in beginner's coding. Presumably some of these are widely known and have names other than those I use below. You're welcome to point out these in the discussion page.
Parallel Indexes and Arrays
Synopsis: Several attributes are stored in several arrays, such that attributes with the same index pertain to the same thing.
Problem Example:
String[] name = new String[3]; String[] address = new String[3]; name[0] = "John Doe"; address[0] = "13 Roe Drive"; name[1] = "Jane Deer"; address[2] = "17 Caribou Close"; ...
Problem: If it's one (coherent) thing, then it should be represented as one instance.
Solution: Use one array consisting of instances that each contain several attributes.
Correct Example:
Write a class:
class Person { private String name; private String address; public Person(String name, String address) { this.name = name; this.address = address; } }
and use that:
Person[] person = new Person[3]; person[0] = new Person("John Doe", "13 Roe Drive"); person[1] = new Person("Jane Deer", "17 Caribou Close");
Redundant Representation / De-Normalised Pattern
Synopsis: Multiple instances representing the same entity.
Problem Example:
Example 1:
Person farmer = new Person("John Doe", "13 Roe Drive"); Person tractorDriver = new Person("John Doe", "13 Roe Drive"); // wrong: now there are two instances of Person representing the same real person.
Example 2:
enum WordType = {BLAH, FASEL, BLAPP}; abstract class Word { ... } class Blah extends Word { static final WordType wordType = BLAH; // wrong: wordType redundandly records the fact that this is an instance of Blah }
Note: The second pattern may be somewhat forgivable if a string is declared (rather than an enum), with the intention of using that for producing a human-readable textual representation of Blah instances. It would be better to build the string literal into the toString
method, however.
Problem: The state of the data held in the process can be inconsistent with respect to the problem domain. In database design, normalisation is used to eliminate such redundancy. The same principles can, and should, be applied to the design of data structures used by programs.
Perhaps it seems to some that the more transient nature of variables and instances in a process justifies a more relaxed and less rigorous approach. Normalised data structures may also sometimes appear to be difficult to work with. These arguments only apply in the development of simple software.
Normalised data structures may sometimes limit performance. This can be a good reason for deviating from normalisation. However, this should be based on an informed decision and it should be limited and documented. A generalised concern for performance is not a sufficient reason to justify generalised use of de-normalised data structures.
Solution: Design code so that each entity is represented by exactly one instance.
Everything Is a String
Synopsis: Use of strings instead of adequate types.
Example:
String age = in.readLin(); if (age.compareTo("18") < 0) { System.out.println("you are not yet an adult"); } int agePlus5 = Integer.parseInt(age) + 5; System.out.printf("in 5 years, you'll be %d years old\n", agePlus5);
Problem: Holding data in a string necessitates use of methods in awkward ways (such as that of compareTo
above) and multiple conversions to more adequate types (e.g. via parseInt
).
Solution: Apply the classical Input - Processing - Output pattern, noticing that acquiring input does not just mean reading data from an external source (such as a file). Acquiring input frequently means parsing it. With object oriented designs, parsing should normally result in one or more instances of classes that are specific for the application's domain.
Common Misconceptions
- Code is ok if it works correctly in a test case.
- Trying out what a program / class / method does in a few test cases results in understanding the program / class / method.