Platforms
In the past, most of my software development happens on and for a Windows 9x platform. The reason is quite simple, I ran Windows 9x, so it's the obvious choice of platform to write for.
However, I aimmed to write code as portably as possible, especially when writing libraries of code and occassionally wrote specifically for UNIX targets. (And was actually brought up on UNIX at school).
These days, I tend to do development in a POSIX environment, whether it be a real UNIX/Linux box, or cygwin. All my C development is done under UNIX shells, using GNU make - I have a complex makefile system which works under both UNIX and Windows (cygwin), configured to support even native Windows compilers such as BorlandC and lcc-win32. The majority of code, unless specifically targetted to Windows runs under both Windows and UNIX.
Most certainly all my web based stuff, whether it be in C, Perl or PHP works on both Windows and UNIX.
After wanting to port some Windows 9x programs to Windows 3x, I've also become to be quite conscious of Win9x/Win3x issues, and writing code with them in mind, even when not planning to port to Win3x, which makes porting at a later time fairly painless.
DOS / Windows 3x Development: I hardly ever do any DOS or Windows 3x development anymore (well, who does? :) ), however I used to do a fair bit, and still when writing Win9x code, do so portably for Win3x, where possible. (I still have some maintained programs that compile for both Win3x and Win9x).
The smartest way to write for either DOS or Windows 3x is to develop under Win32. (For DOS, under Win32 as a console application). Reason being that the Win32 is a lot more stable than Win16 or DOS, and much more tolerable when code has bugs or errors. On the same token, developing a Win16 application under Win32 first can prove to be easier as a Win32 application, even with GUI elements, can be allocated a console, which can be used for debugging printf statements. Although a debugger can be used, I tend to prefer to add printf's to debug code (in most circumstances), which isn't possible under Win16.
Of course, once the development is finished, build with Win16 / DOS tools and test on a Win16 platform. Although most bugs can be tracked down while debugging on Win32, there may very well be bugs that only present themselves on a Win16 platform. This is both true for compiling as Win32 on Win32, and compiling as Win16 on Win32. I've had times where Win16 applications worked fine under Win32, but had problemss on Win16.
Of course, also, when compiling as Win32 on Win32, you MUST be aware of Win16 differences (hence write for Win16), otherwise the code won't compile or link with Win16 tools, or at least won't work properly on Win16. Although Win32 builds on Win32 platforms are most stable development, Win16 builds on Win32 will ensure the code is written the correct way for Win16, while still having most of the saftey net of the Win32 platform.
Tips for portable code: You'll find most of these in any decent programming book or course, but...- Stay away from platform specific calls wherever possible, and choose standard language calls wherever possible. For example, avoid OpenFile(), use fopen() instead etc. This is obviously not always possible, sometimes platform / API specific calls are needed, but generally not the case.
- Abstract portable code from platform specifc code wherever possible. For example, if writing a program for Windows that displays an ID3 tag, write the ID3 code portably and self contained, and write the Windows GUI around the code. In these way, if porting the applicatiom to UNIX, it only involves writing the UNIX GUI around the ID3 code. The ID3 code then does not need to be rewritten, or even modified at all.
- Win16 / Win32. Use message crackers to decode message parameters rather than decoding them explicitly hard coded. These will provide seemless porting between Win16 and Win32 with no physical changes to the source code needed.
- #if WINVER < 0x0400
#else
#endif.
'Nuff said. ;)
The preprocessor is your friend (in languages that have one anyway). - Define your own types. If you need a data size of 16 bits, define
such a type. While in DOS / Win16 an int is 16 bits, under Win32 it's
32 bits. Although the Win API provides BYTE, WORD, DWORD this it's often
not a bad idea to define your own for more control. Changing one line
beats having to change countless lines of code.
Same applies to assuming pointer sizes. Win64 is going to have 64 bit pointers. Any code that assumes DWORD = sizeof(ptr) ain't gonna cut it. - When using winsock, use Berkley type calls over Microsoft extensions (WSAxxx) wherever possible. Reasonably easy to do under Win32, with it's multithread capabilities, however much more difficult to achieve under Win16.
Languages
Compilers
Switch Styles
About Style Switching.