Software Engineering required questions, part 2: Design (Notes)

January 7th, 2008

(Notes) Note subdesign elements requiring additional research, test cases or proofs of concept (poc’s). Make sure to do these items first and factor results or limits back to design or requirements as necessary, to prevent/minimize issues. Example: Main design > sub design 1 (with its own requirements, design research, design and code, test, etc). Note limitations of sub design with respect to feasability of main design, based on reliance of main design on the subcomponent.
1. Are there impacts to the current requirements based on the design? For example, do the requirements cause feasibility issues in design? If so, send these impacts back to requirements phase. The project parts that are not impacted may continue forward, but the release should be adjusted to account for additional necessary changes. If not, then the release can be expected to have a number of predictable problems, costing significant time and money overages as compared with an appropriate design-time adjustment.

2. Research design limitations for workarounds and risks thereof. If there are limitations and risks, send these back to requirements as necessary.

3. Analyze design for overly complex or elements in need of a design refactor, note for phase two, or implement changes to design before coding.

Software Engineering Required Questions, part 1: Requirements

January 6th, 2008

These are the questions that have to get answered in order to successfully deliver a software engineering project, in whole or in part, by an individual or team.

Phases: Requirements, Design, Config, Code, Test, Rollout, Troubleshoot, Other

Requirements questions:

1. Do you have all the requirements collected? If not, collect some more from whomever can supply requirements to you or the team. If there are any unanswered questions re: the existing requirements, then you don’t have all the requirements yet.

2. Are the requirements strong, firm and understandable, and agreed upon in writing by the supplier? Having the requirements in writing is the only way to guarantee that all parties have had a chance to comment on the requirements as they are understood by the developers. If this step is not taken, feature creep will plague your project.

3. Are all the risks for the given requirements spelled out and accounted for? For example, if there is the risk of a project overrun based on an especially difficult requirement, then make sure this is spelled out in the requirements document. If it is not written down, then the client can easily say that they didn’t know the project would cost more or go over. It is the responsibility of the engineering team to make the client aware of these issues up front whenever possible, or to at least indicate where there may be issues, if the issues are not yet entirely apparent.

4. The project should be able to move to the design phase, provided that all of the above questions are answered sufficiently.

Plan to Find Mistakes

January 2nd, 2008

If you plan before acting, you will have a much higher probability of catching mistakes before they actually happen.   I recommend planning out any complicated activity, listing options and possible side effects, before taking action on a project.   The plan becomes the documentation for what was done, so in case something does actually go wrong, the steps to reproduce the problem are apparent.

Maximum Productivity is not Linear to Hours Worked

December 26th, 2007

I was recently referred to the following article:

http://www.igda.org/articles/erobinson_crunch.php

This article discusses why working in “Crunch mode”, i.e. a lot of extra hours per week, sabotages the work environment and almost guarantees significant errors resulting in a loss of any effort gained in the short term by the longer hours.

I additionally would like to contribute that working a set block of hours during the day actually has very little to do with having high output for any creative job. Creative output comes in bursts, and based on every single creative person I’ve ever seen, I’ve never seen anyone that could truly produce an assembly-line like level of creativity evenly all day long. A much more accurate picture of their creative output looks like a wave, with extreme peaks and troughs throughout the day. During the troughs, if they have something non-creative to work on, they tend to work on that during the creative trough. When the creative person is experiencing a creative peak, they can easily accomplish a ton of creative work accurately. To try to force production of creative output during a trough basically won’t work. If there are no non-creative items to work on, the individual may as well not work at all so that their creative energy is recharged.

Imagine that creative energy feeds off of regular energy also, so if regular energy is at 0, creative energy can’t be as strong. If they burn off all their energy and then have to be creative, they aren’t nearly as productive as if they are creative in bursts, recharging energy in between. I argue that the creative person can do 40 hours per week, but it may not be a specific block of 8 hours per day for 5 days in a row.

Strategies for dealing with BBM code, part 2

December 24th, 2007

Fixing temporary invalid state code and ugly code are both difficult and/or time-consuming operations, but there are easy ways to at least protect the existing code until such time that a rewrite can be considered.

To fix temporary invalid state code, simply wrap the offending areas in the appropriate state validations. For example, suppose that you know that A can’t be more than 5 when a certain procedure is called, and yet whenever an A greater than 5 is passed in, bad things happen. Wrap the procedure in a check that A is not greater than 5, and make sure that the check errors out gracefully and prevents the procedure from running, etc. This strategy is a foolproof and simple way to prevent invalid states. Granted, the invalid state shouldn’t be allowed to get entered in the first place, but the goal here is not to reinvent the system, but to inexpensively issue an effective patch. After all, if you were going to do more than this type of patch, wouldn’t you just want to redo the whole thing since it’s all so gross?

Fixing ugly code is next. Suppose that the only thing left now is all these gross patches to the temporary invalid state code, and a bunch of just “ugly” code. Now is when you can carefully refactor a section at a time, so that the code makes sense. Be sure to start in the innermost area, so that the refactorization doesn’t inadvertently introduce bugs. Recompile, test and validate the refactorization like crazy. It does no good to refactorize if it doesn’t still work at least as well as before, without introducing any other errors.

Carefully design and plan out each refactorization, listing any side effects or drawbacks, and then analyze whether those side effects or drawbacks can be prevented w/o more … side effects and drawbacks. If not, then DONT do that particular refactorization. You don’t want to get stuck in a refactorization loop, where each change breaks something somewhere else, and an ugly but functional system turns into a pretty, non-functional system.

Note: This will insult and shock most junior and artistic programmers, but just because code looks “gross”, that doesn’t mean it’s not working or that it’s not good enough for now. The money was already spent to produce it, so replacing it with something that provides no additional benefit other than looking different is wasteful. One person’s crap code can be one person’s great code, although I’ve seen my share of code that is just crap to everyone… this is how to deal with the latter.

Strategies for Dealing with a Big Ball of Mud Application

December 24th, 2007

There has been a lot of discussion around programs that appear to be just a big ball of mud, i.e. very messy code patched together, with functional, architectural and other design and maintenance issues throughout.   I haven’t read much on ways to deal with this other than refactoring, which is a good idea but is a very general solution to a series of specific problems.   In the Strategies for Dealing with a BBM (Big Ball of Mud) application, I will discuss various ways to systematically correct the BBM issues while trying to reduce the overhead associated with a total rewrite or end-to-end brute force refactorization of the code.

The most important thing to do first when confronted with a BBM app or system is to not panic.   Just like in Hitch Hiker’s Guide to the Galaxy, “Don’t Panic” is a mantra for making sure that your state of mind doesn’t lead you to rash conclusions with BBM systems.   No matter how frustrating they may be, things are generally not as bad as they look at first.

Make a list of all the things that look wrong in your BBM system.   Be very specific and enumerate the list just as things appear “off”, whether they are big or small.   You don’t need a complete list at first, but get the major or obvious problems down.   Once you have the list, go back over it and evaluate which of these are issues that just “look bad”, and which actually cause technical problems with the code.

Technical problems with code can be categorized in general as follows:

1. orphaned code problems, meaning code that will never be reached to run.
2. broken code, or code that compiles but doesn’t do what it’s supposed to do, producing a serious problem every single time this particular code is run in the system.
3. invalid temporary state code, code that works until certain state conditions are reached, at which time it temporarily becomes broken code.

4. ugly code, or any code that works “fine”, but is ugly, slow, bulky, etc.

Solving code category #1 is the easiest, because that code can simply be removed.   Code category #2 is also easy to solve, because there is a clear business case for removing or repairing code that simply never works correctly.   Thus, I believe that the vast majority of BBM code issues will fall into categories 3 or 4.     These are issues which are either cost inefficient to repair, or issues that are difficult to diagnose, and both of these reasons are why there are so many of these issues built up over time.   Since they generally aren’t repaired as they are introduced, these errors accumulate over time, causing more and more headache for developers and managers alike.   The managers can’t get the budget to fix the errors, and the programmers struggle with inaccurate specifications from clients, which result in these code issues being knowingly introduced.

So how do you minimize the introduction of category 3 and 4 issues?   How do you remove or repair them at minimal cost?   Find out in part 2.

Mobile Designs part 2: custom buttons and clip text

December 21st, 2007

Mobile GUI Design Diagrams: http://www.flickr.com/photos/devinmoore/2126340769/  

Typing on a handheld or mobile device is hard enough with any sort of keyboard, touch interface, etc. that it shouldn’t be done unless absolutely necessary. To avoid needing to type, I suggest a universal clipboard-like interface, so that any text I’m looking at on my little screen can easily be copied and pasted somewhere else, or saved for later recall into any textbox or text input.

My mobile dashboard design includes custom button macros. I don’t ever want to have to search or operate a manual operation on my phone more than once, so I should be able to save the actions as a custom “icon” to the dashboard. Instead of an “open spreadsheet” icon, i can have “open the work spreadsheet and skip to sheet 4, and re-run sheet 4 to display the latest data”. Why would I need a general launch icon out on the dashboard if I can have custom ones?

I additionally want calendar and other alerts to always be available. If I have to have my calendar open in order to get the event notifications, then I can’t see or easily get to other functions on the phone.

Mobile Dashboard Design

December 21st, 2007

I tried out a windows 6.0 device, and the standard screen is good but not great. The screen looks way too busy, and it’s hard to interpret all the information because of the excess graphical decoration. The main screen says a lot of things that are important but aren’t relevant to what I’d want to know on first glance at my phone. For example, the main screen shows the presence of SIM card, whether wi-fi is on or off, and has a number of links to launch general applications. The sim card and wi-fi stuff are obvious enough from the device output itself, so those items don’t need to be listed. The general app launches are all available from the start menu, so they aren’t necessary and simply take up a ton of space.

My re-engineered mobile dashboard has the following components: calendar events with add option, tasks to do with add option, new message indicator (email, text, voicemail, etc), weather forecast and other web updates if wi-fi is present to download and update the content.

Game Design 4: Breakthrough Game Design

December 19th, 2007

Many games have similar features, but there are also great games that exhibit none of those predictable elements. For example, games don’t need any of the following:

humanoid character sprites / enemies or “bosses”
levels / a scripted beginning and/or ending to gameplay
first-person action / side-scrolling action / etc.
game time tracking / real-time game cycle / etc.

And so on. A great example of a game that has few of these elements is the original Tetris. Tetris has one giant “level”, where the difficulty gradually increases until the player is forced to lose by way of human reaction limits. There are no characters or enemies, and yet with all of these familiar elements gone, Tetris is still one of the most popular games of all time.

Game Design part 3: cheats

December 18th, 2007

Almost every game has some form of cheat in it, so there are two schools of thought on including cheats in the game.

First, remember that many games inadvertently include “cheats” by way of having easy ways to beat supposedly difficult enemies or player characters. These are all incredibly unfair to other gamers and can ruin the gameplay for everyone. Great care should be taken to extrude any such cheats in advance with good beta testing programs and judicious gameplay range settings. Watch for edges of items, and whether or not a plaer can get unexpected behavior while exploring the limits of the game environment or game control parameters.

Second, are the built-in obvious cheats, such as save codes. Save codes are useful for returning a player to a certain point in a game, but they can be abused through incorrect implementation. Games such as the original Metroid on NES used a cryptographic save code that included various parameters for the player’s position. This allowed for the first type of cheats, where clever players determined how to interpret the game save codes, and were able to produce undefined save positions. For example, a correctly hacked save code would let the player start at the end of the game but with no weapons or items, thereby rendering the player helpless. These situations are easily avoidable through the use of appropriately predefined save points, plus a system of passwords to reach these points. These passwords may be published at some point as part of game walkthroughs, but they will all yield playable locations within the game.

Finally, there are easter egg type cheats. These are cheats that the designer builds into the game to make the gameplay either less linear or more interesting. In either case, these cheats can be considered as part of feature overload, and as an avoidance of poorly designed sections of the game. Cheats should be considered as an integral part of the game — for example, if one section is skipped, then some other obstacle may be presented. In the classic game Megaman 2 for NES, the game had built-in cheats such as extremely difficult-to-reach items on alternate paths throughout the game. Players had to be willing to risk the difficult obstacles to get the “cheat” (i.e. another obstacle presented as a “penalty” for the cheat).