Here’s the free Microsoft Windows software that I can’t live without!
- ArsClip – A very handy clipboard manager… a little bit like vim’s yank ring, but for windows!
- Chrome or Firefox? I don’t know which is better anymore…
- F.lux – change your monitor to match the temperature of the lights in the room
- Foxit Reader – A really fast pdf viewer
- GVIM - Only geeks need apply!
- Notepad++ – a really great free text editor
- Paint.NET – Think Microsoft Paint, but on steroids.
- Synergy – One Keyboard, One Mouse, Multiple Computers.
- Sysinternals Suite – a bunch of great tools including Process Explorer.
- Thunderbird - the only way to read email (besides Mutt of course!)
- WinSCP- FTP, SFTP, Other? Covered.
From the NOT free but worth it department:
- Beyond Compare – If you work with any kind of text file on a regular basis, you need this. Period.
I see this a lot at work – someone puts code in a function. No, that part isn’t unusual :) The part that “bugs” *pun intended!) me is that the code really belongs in the function that they have overridden (in the case of OO languages), or in the functions that they call (in the case of procedural and/or OO languages).
It’s really a variation on the classic theme – don’t repeat yourself; write as little code as possible; keep it simple; don’t make me think.
One of the best ways of accomplishing this is to approach creating software like deer hunting. The best hunters know that there are certain natural funnels – places where deer tend to run. These are the best places to put up a tree stand. You wait for the deer to come to you. You don’t go running around trying to corral the deer. If there’s a river, you find a place that is narrow and shallow to hunt because it is a natural crossing. Over time you’ll see every deer in the surrounding area.
This technique also applies to software development. Find one place in the code to solve your problem. You have an additional advantage too – you can create the bottlenecks – the places where everyone crosses the river so to speak.
At work we have an OO based framework that all of our web apps use. The people who designed it didn’t take full advantage of the natural bottlenecks. Rather than adding code to our Page_Load base method to check if the application should redirect the user to a “sorry, but we’re down while the batch runs” page, they put code in EVERY page of EVERY application. Worse, they put a class in every application that is around 500 lines long. I did a diff between two of these classes. Less than 10 lines of difference. What does this mean? It means that 490 lines of code could be moved into a base class and the 10 lines of code could simply be overridden to provide the appropriate configuration values.
In short, the total amount of code in each application to support this feature could have been less than 10 lines of code instead of 500! In our current situation, if a bug is found in the duplicated code it would take us more than 100 hours of effort to update every application and deploy them. If this code had been put in a base class, we’d just have to update it in one place.
About a year ago, I rewrote it – you see he had coded 4 functions; Sum1, Sum2, Sum3, and Sum4. Sum1, Sum2, and Sum3 were identical except that different bugs had been fixed in each piece of code over time by other developers, so they didn’t “look” identical at first blush. That was confusing. Not to mention it was a little intimidating and scary to fix up each function so that all of the bugs were corrected in a way that didn’t modify the behavior of the framework that depended on these functions. Who knows, maybe someone coded in a way that made Sum3 work correctly for them…
The real surprise though, was Sum4. It presented a completely different problem. One might have assumed that it was simply a fourth sum. Imagine my surprise when I realized that it was not a fourth sum at all! It was in fact, the sum of all sums (Sum1 – Sum3)! A grand total. Even worse, it didn’t use Sum1, Sum2, or Sum3 to do this. Instead, it was simply a (very poor) copy of the code original code for Sum1, Sum2, and Sum3! Of course, completely different bugs had been fixed inside this function when compared to the current versions of Sum1, Sum2, and Sum3. Woah.
Long story short I ended up rewriting the code. We now have a single Sum(x) function that can do the work of sum1, sum2, sum3, etc… and we have a TotalOfAllSums() function that is aware of the number of summations we have on a webpage, and it simply calls sum(x) to determine the total. Simple, and, now we can implement a fourth Sum in the future without having to resort to naming it “Sum5″ and copying and pasting say… Sum3 to get us started.
Too often user interfaces are muddied by this fact that seems lost on software developers. When I install software, I want to answer all of the questions UP FRONT and then let the computer do the dirty work. I should be able to leave without wondering if the computer will need babysitting later on! Not only should user interfaces do this, but they should INDICATE when they are doing this so that I know it’s safe to leave :)
Some prime examples:
- Operating System Install
- New Software Installation
- Redesign debian apt-get to ask any and all configuration questions up-front! I realize there are technical challenges to this, but we’re software developers, and I’m sure there are harder things to figure out…
- FreeBSD could do the same with portupgrade, etc…
- Ironically, Microsoft has this just about right with Windows Update – although Debian is quite similar if you schedule a cron job to download and install the updates.
- Microsoft Windows – Deleting files should be a background process (at least optionally). The file system should be able to mark a tree for deletion so that explorer doesn’t see it, etc… and then the delete should just happen. I don’t really care when it finishes! If the user wants to create a new file that conflicts with a file scheduled for deletion, then the OS should be able to deal with that too …
The goal should be to let the user do as much as possible in as short amount of time as possible. The software should save the time intensive tasks for later and manage them in a way that does not impact the user.
Good OO (object oriented) design is not flat. It is 3d and sometimes even 4d in nature. The problem with most object designs is that they are based on the concept of an object. Objects are too constrained. Too often, an object is demoted to the thing that holds the data. People need to get over that idea. OO is simply a way to organize your code into tools that can be reused. The power of OO is found when you use it to create building blocks and tools. Objects are nice, but you really should be intentionally creating re-usable, modular, code! An object is a byproduct of that organizational style. You are programming related functionality in a multi-dimensional manner.
Consider interfaces that allow “horizontal” relationships. An interface is considered part of good OO design. With it, you can relate things that are not related “vertically” via traditional inheritance. If your “object” has legs, then implement the legs interface. Now everyone else can use them… e.g. Object.Legs.Walk, Object.Legs.Run. Perhaps your animal doesn’t know how to run? Then let it walk instead :) Now your arthropoda spider and your chordata ape can both walk even though they are from different phylums. It’s cross domain functionality.
Excellent programmers understand this distinction. I’ve seen too many good OO designs muddied by people who still live in a functional/procedural world. This is possible because OO simply extends the procedural model. To be an OO programmer does not imply understanding of OO. In fact, it is possible to program as in the past and completely miss the benefits that OO can give!
Warning signs of bad OO programming … hmmm, sounds just like bad procedural programming…
- Repeated blocks code
- A single line of code repeated 10s of times.
- GoTo … LOL :)
Some features of good software design:
Your reasoning is excellent — it’s only your basic assumptions that are wrong.
My most famous code :)
Actually, I “stole” the assembly routine from Samuel and converted it to C. I happened to see it being used on the internet today, and though wow… it’s amazing how long ago I wrote that :) Probably 5+ years ago!
register void *a=HomeExecute;
while(*(unsigned long*)a!=(unsigned long)TE_select)
return (TEXT_EDIT*)(unsigned long)(*(unsigned short*)(a-4));