Friday, April 25, 2008
Why is this important?
You need to set limits and prioritise.
There isn't enough time to do everything. So you need to focus on what's important and do that!
There isnt' the time to fix every bug. So fix the ones that cause the biggest problems or affect the most people (or whatever criteria you use to prioritse bugs) first. By the time you've made those changes, circumstances may be different.
Make sure you're adding the feature which will bring the most benefit. Not just the one that is easiest to code, or most fun.
Make sure you're creating a new program that is of use, doesn't already exist and will actually benefit others.
What do you do once you know this?
Make sure you're doing something that is worth doing.
Don't do one thing if there's another that is more important.
Understand the costs and benefits of fixing the bug, adding the feature or creating a new program, before you write the code.
"Design and programming are human activities; forget that and all is lost."
From an EDSK point of view I'm gonna start thinking more short term. I had long term plans to extend beyond tips that are generic to all developers and also include content more targeted to developers using specific technologies or targeting specific environments/platforms.
I had starting collecting references to relevant pieces on the web, but to help me focus on what I'm working on right now I'd stop. I also thought I'd post up the link so they don't go to waste.
Linux Developers should know:
Ten Commands Every Linux Developer Should Know
.NET Developers should know:
What Great .NET Developers Ought To Know
MSDN Webcast: What Every Developer Should Know About the .NET Framework, But May Have Missed Along the Way (Session 5) - Level 200
What Every Developer Should Know About the .NET Framework, but May Have Missed Along the Way
Visual Studio Add-Ins Every Developer Should Download Now
Ten Must-Have Tools Every Developer Should Download Now
.NET Framework General Reference - Design Guidelines for Class Library Developers
Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries
Database Developers should know:
... about normalisation. Not just how to do it but why.
Java Developer should know:
Ten Things Every Java Developer Should Know About Unix
Best Java book available
I've been using Java since 1995 and have owned this book since 2001 and it's the only Java text I still turn to. I recommend every Java developer, no matter what level you're at, read this book and read it again every year for the remainder of your career.
Ten Things Every Java Developer Should Know About Unix
PHP Developers should know:
10 Tips That Every PHP Newbie Should Know
10 Tips That Every PHP Developer Should Know, Part 2
make life as a PHP developer a whole lot easier
Web Developers should know:
8 Firefox Add-ons every Web Developer should know about!
Speed up your web pages with YSlow
Color Oracle takes the guesswork out of designing for color blindness by showing you in real time what people with common color vision impairments will see.
What Every Web Developer Should Know
... the differences between REST and SOAP.
Windows Developers should know:
... to avoid using the clipboard programmatically
Eight resources every developer should know about
... about COM
... about User Account Control (UAC)
Tuesday, April 15, 2008
Here's a part of the original grid:
The data relates to these categories:
Immediately there is a duplication of data which could be reduced. The colour and description can be combined as they are show the same thing. That would lead to a grid which looks like:
The category name is supperflous information. The colour indicates the category. This is something that the user will either know or can look up when necessary.
Thursday, April 10, 2008
Tuesday, April 08, 2008
--Size, orientation, resolution, layout
--SIP, keyboard, dedicated buttons, stylus
--Standing up on a moving bus
--Form and Control classes
Do not try to create non-full screen forms
On the screen:
--Don’t hide the title bar
--Use the same title in owned forms
--Don’t use a toolbar control
--Don’t use more than two menus
--Don’t hide the bottom strip
--Place tappable controls near the bottom
--TextBoxes or anything requiring the SIP, near the top
- Touch enabled?
-Stylus or Finger
--Tap and Hold (Avoid)
Aim for single handed operation (ideally stylus free: Designing Pocket PC Application for Stylus-Free Usage (one-handed))
Book based on assumptions:
- Agility/XP essential for profession/industry to improve
- XP offers way to create better developers
- Can't do XP without understanding object thinking
- Won't appreciate the benefits of XP if don't fully understand 'object thinking'
- OT based on problem domain, not potential program
- OT leads to smallest number of things (classes) possible
- Objects doing the least amount of work, in the most direct and simplest way
- Focus on coordination of autonomous objects - not mgmt of unruly modules and passive data structures
- Fewest no. of classes
- Fewest number of methods per class
- Simplest coding of methods
- Avoidance of control, centralization & mgmt classes
- Simple scripts to simulate simple stories
- Allow 'lazy' objects to give work to other objects
The true differences between programming languages are those that reflect philosophical ideals and values
If you think about design using a language - your design will be enhanced or severely restricted by that language
- Collaboration rather than mgmt
- Coordination and cooperation, rather than control
- Rapid prototyping instead of structured development
Prerequisites to OT:
- Everything is an object
- Simulation of problem drives object discovery and definition
- Objects must be composable
- Distributed coordination and communication must replace hierarchical centralized control as an organizational paradigm
Programs may be thought of as data and functions - but the real world isn't
Assuming data and functions:
- Programs are more complicated than need be
- Complex code is difficult to understand and test
- Complex code is brittle and difficult to modify when requirements change
- Resultant code lacks composability - not reusable outside original context
Object principals - software principles:
- Solve complex problems by solving a series of intermediate, simpler problems
- Appreciate human cognitive limitations
- Correctness is unaffected by movement between equivalent contexts
- Correctness is unaffected by replacement with equivalent components
- Modular design
- Portable design
- Provides compositional flexibility
- Appropriate use of abstractions
- Limited set of conceptual forms
Brooks' 4 essential difficulties of software development
- Conformity (to the world, rather than the other way round)
- Changeability (to the world, which changes frequently)
- Help discovery
- Help make design decisions
- Provide handy ways to remember principles of object thinking
- Help avoid non object thinking
It is convenient to build something large from smaller (but not the smallest possible) components
The complexity of object-oriented programs is in the scripting, not the objects themselves
Hierarchical and centralized control is anathema in the object paradigm.
Ants, not autocrats: - do your thing and react to messages from those around you.
Behaviour is the abstraction to use to differentiate between objects and is the criteria to base taxonomy on.
Creating taxonomies based on internal structure leads to numerous problems
The programming language used does not mean that doing object programming
Object vocabulary is first and foremost a technique to help developers avoid the mistake of thinking about solutions using old mental habits
- Responsibility (task)
Computations must be by an object on itself: (e.g. number adds another to itself. rather than an object and two other number objects together)
- Helps enforce simplicity
- Is unnecessary
- There are alternative
- Adds needless complication
Methods and model must:
- Support natural decomposition
- Recognize 2 complementary processes: domain modeling; application assembly
- Aid discovery and evaluation
- Enable measuring progress and 'goodness'
Formal methods do have their value
Blending methods and approaches is hard
Using ideas from both approaches is equally difficult
Need criteria to evaluate:
Need to understand the domain - how computers work is not part of the domain
Starting a journey with one step in the wrong direction can have an enormous impact on the end result
Mistakes at the beginning of a process are more costly:
- Have less knowledge, so more likely to make mistakes
- More tempted to think about what do know (the computer) rather than the domain
Never: think about what the code will look like and then create objects to support that code.
Set aside your own culture when attempting to understand users and user domains
To understand users: (their domain and their tasks)
- Go and spend time with them
- Observe them
- Talk to them
Can't define everything up front - do one thing (story) at a time
- Most critical aspect of discovery
- Define in terms of actual or intended use
- Define within domain, not just application space
- Not the same as object specification
- Specification will involve making design decisions
OT suggests you should generalize responsibilities so that they can be used in any context
Let objects assume responsibility for tasks that are wholly or completely delegated to other objects in cases in which responsibility reflects natural communication patterns in the domain.
Delegate responsibilities to get a better distribution and increase reusability.
Delegation can lead to the temptation of management. - If you delegate, delegate:
- Don't try and control
- Don't guess what the result will be
- Don't do own error checking or evaluation
Responsibilities should be distributed among the community of objects in a balanced manner
Avoid responsibilities that are characteristic specific, that focus on providing a potential user with the value of a single characteristic of the object.
Beware the dangers of GUI-in design!
The two kinds of relationship of interest between objects:
- is a kind of
- collaborates with
Single line of descent based only on the behavior of the object
Collaborations are almost always hard coded - due to complexity of relationship between objects
OT: data is information or knowledge that objects need to complete a task
Traditional data modeling: all the data that a system must remember about objects
Model: - comprises objects engaged in the objectives of the application
View: - hierarchically organized collection of objects
Coordinator: - tasks involved in sending messages to other objects, and notifying subscribed objects of a state change
Objects are not and should not be aware of their clients, even when their clients are not other software objects
Scripts as first class objects:
- Ordered collection of messages
Events as cues to object interaction
Constraints and rules are objects themselves
Rules should not be complex (coz they're objects)
Objects will often have a collection of 'self evaluating rules'
- Error handling/recovery
XP maturity levels:
- Out of the box
Objects are not something you do - objects are something you think
There are circumstances in which it is difficult, if not impossible to apply object thinking
- e.g. RDBMS, GUI
Database philosophy is almost totally inconsistent with the philosophy behind object thinking
Need to remember the functional advantage of databases as well as their persistence services
XP created users who don’t want large monolithic software but a collection of small, targeted applications which do specific tasks.
- In contrast to 80/20 law
Side 1: Responsibilities
Side 2: Description and stereotype
Side 4: Knowledge required
Side 5: Message protocol (methods)
Side 3: Contracts (public or private methods)
Side 6: Events
Friday, April 04, 2008
Update. This memo was written while at a previous job. The IT director had previously claimed there was no value in unit testing and we shouldn't do it. I submitted this memo to all developers at one of the fortnightly update meetings. It did lead to unit tesing being adopted by other developers as part of the development process.
The following is from a memo I wrote:
I have a confession to make. I have been creating unit tests for some of the code I have been writing recently.
The purpose of writing these tests has been to make my task easier and to try and ensure that the code I have written does not contain any preventable errors.
I think it has worked:
- Of the code I have written unit tests for, none has failed testing. (So far.)
- I have saved time by not having to repeatedly perform manual checks.
- I have removed a lot of the opportunity for human error in reviewing my manual testing.
- I have created a resource which will save time in the future, if and when any code in this part of the system is changed and the tests reused.
The calculation of dates and times as part of an SLA is non trivial.
Please note that this is not a criticism of those who have previously written or tested code in this area. I am simply trying to highlight that this is a complicated area which is difficult to test and our current practices have proved inadequate.
There is a lot to consider in SLA calculation:
- Non working days
- 24 hour working days
- Working days for specific hours
- Not working on bank holidays
- Working on bank holidays
- Starting on a non working day
- Starting on midnight on a 24 hour day (beginning and end)
- Starting on a bank holiday
- Starting before the start time on a day with specific working hours
- Starting on the time a specific working period begins
- Starting on the time a specific working period ends
- Starting after a specific working period ends
- Calculations limited to the same day
- Calculations spanning multiple days
- Combinations of the above (E.g. Starting at midnight on a 24 hour working day, adding 112 working hours, but not working the next two days, then having a bank holiday and then working between 9 and 5 on the two days after that, before going back to a 24 hour working day!)
All this adds up to a very large number of possible situations to test.
In making the changes for this CCP, I started out by creating some tests to find out where the errors in the code were. Which calculations were affected, etc.
In total I ended up creating 155 tests which performed a total of 580 checks.
When running these tests against the original code 94 tests failed. A pass rate of just 39%.
The originally reported problem was with using the '24 Hour day' setting in a 'Working week'.
Admittedly, many of these tests are edge cases so it is unlikely that end users would see only 39% of calculations being performed correctly. It is concerning, however, that of all the different situations that need to be accounted for, more than 3 in every 5 will be done incorrectly.
As soon as I started adding tests for dates which are affected by bank holidays it became apparent that the code to determine if a date was a bank holiday was also broken.
(I only checked with up to 18 bank holidays in the system, but there is no way that it would magically start being able to find all dates if there were more.)
Clearly the number of records in the system and which position the one that was being searched for appeared in that list affected whether it would be found, or not.
Obviously the smaller number of bank holidays in the system is less likely to be an issue as we ship with 2 years worth of values in the database, but as the number of records gets bigger, there are still large numbers of records being missed.
To get the above results (on the IsBankHoliday function) I created 172 tests (those listed above plus no bank holidays in the system at all) with each test performing 1 check.
Of all 327 tests created, 197 failed when using the original code. A pass rate of only 39%.
I didn't avoid manual testing altogether though. I did still use the UI to test that the results reported by the tests matched what was displayed in the program. But I only had to do this at the end once I was confident all the calculations were correct.
Well, the process of sitting down and listing all the things (and combination of things) to test caused me to identify a large number of situations to test.
How much time was saved?
To perform these tests manually would involve:
- Log a call entering all details as needed, including setting the SLA start time.
- Save the call.
- Load the form to view the calculated times.
- Check the times are as expected.
To test bank holiday identification:
- Set the right number of bank holiday entries in the database (deleting and adding as required)
- Perform the test (as above) to test the SLA calculation, but over the required bank holiday.
I estimate it would take an average of 1 minute to do each of the above tests.
That adds up to nearly three days of manual testing.
Even if it was only necessary to do half as many tests manually and they could be done twice as fast, it would still take the best part of a day.
There are now 300+ tests to do to make sure the code runs as intended. If you are going to manually test them (at 30 seconds each) it would take at least 2.5 hours.
I have an opinion on which I think is best for the speed and quality of product development. Not to mention tester sanity.
Based on previously shipped software, it is not possible (or practical) to manually test that SLA calculations are performed correctly, in all circumstances, when just using manual testing. (This will inevitably also apply to other parts of the system.)
Performing unit testing is faster then manual testing.
Wednesday, April 02, 2008
Windows Mobile Team Blog
Backstage at MED
Well, my original predictions were a bit off.
But my revised predictions were a bit closer to the mark.
Not as exciting a new version as I would have hoped for, but definitely all good news.