Professional Programming: Case Study Using C#

Introduction

Demand for shrewd Programming skills of software professional is quiet heavy. The programming industry is setup in such a way that the junior developers never know what the finished product of their hard work is going to look like. This article is not for the developer who simply creates a few hundred lines of code as assigned by the team leader. This is for a programmer who wishes to manage a large project all by himself. The analogy goes like this: The developer working at the lowest end of the software industry is like the worker in building constructions, who simply takes a few bricks, mixes mortar or brings some water. He does not know how the project will evolve. Even if he knows, he is not the master of the situation. On the other hand, the single programmer or a small group of programmers who work for their own projects are like the engineer who plans the building layout, designs all of its components and then comes out with a team of his own for its construction. He visualizes the fullness of his work, even before it actually commences.

This article offers tips for creating professional quality software aimed at individuals who are not part of a large software firm but do want to develop a few products of their own. This article explains creation of a simple text editor as a case study. Each topic is divided into two portions: first is the conceptual part, second is the case study part.

Define the Problem

Conceptual part: All programmers are good. The difference lies in the eagerness with which the programmer wants to solve the problem at hand. The first work for a programmer is to fully understand problem at hand. A deep understanding of the problem results in the natural evolution of a software for solving it. Hence, the first thing for beginning a software project is to have full scale discussion with the clients regarding the problems to be solved with the help of the new software. Then, a few searches on the net for similar software will help understand the quality of other solutions, convenient layout of front end etc. Some free software products may also be available along with source code. Just have a look at the source code.
Once the problem is fully understood, it is possible to create a list of specifications (i.e. the criteria to be fulfilled), which describe the functions to be fulfilled by the product. This specification list is the base document. Compliance with specifications should be measured with suitable tests. Hence, tests are prepared with a view to fully ensure compliance with specifications.

Application part: The editor we plan is expected to handle rich text format and plain text files. It should be capable of providing support for different fonts, colours and alignments. It has to save files in rich text format or plain text format. It should be capable of providing basic editing support like undo, cut, copy, paste, search and replace. The editor is named SimEdit (SIMple EDITor). The language chosen for the project is C#. 

The testing is to be done by creating a formatted letter addressed to the editor of DeveloperIQ Magazine communicating the article and software. This test is to be followed by rigorous tests to ensure proper search-replace, cut-copy-paste, save-open, font-color-alignment and printing related functionalities. SimEdit will have File menu containing New, Open, Close, Save, Save As, Page Setup, Print Preview, Print and Exit items, Edit menu having Undo, Cut, Copy, Paste and Select All items, Search Menu having Find, Replace, Book Mark and Go to Book Mark items, Format menu having Font, Color, Alignments (Left, Right and Center) and a Help menu containing About SimEdit item. The main component is a RichTextBox available in System.Windows.Forms assembly.

Divide and Conquer

Conceptual Part: Any large project is to be divided into smaller components, so that the entire work is divided into manageable chunks. Look at a beautiful motor bike riding wholesome on the road. Although it performs as a large unit, it is made up of many components like shafts, forks, wheels, engine etc.. This type of design is called modular design. Each module is produced separately according to specifications and assembled to form the entire thing. This is true of any large software. One cannot keep large software as a monolithic unit contained in a single file. It should be divided into suitable modules and each module must have a means of integrating with other modules.

What if the divided pieces have to operate with components in other modules, e.g. the search module of an editor, which requires parameters from the main editor, which itself is not yet ready. This is accomplished by creating suitable interface for getting search parameters like selected text search direction, text box etc.. The interface name shall be used within the search module whenever any data from the main module is required. The main module must implement the interface in order to enable communication from the search. The moral of the story is: modules communicate with each other using interfaces.

Application Part: The Editor is divided into five separate modules, viz., i) SimEdit – the base module, ii) Finder – for performing search, iii) Replacer – for text replacement, iv) Print – for printing the document, v) AboutMessage – for displaying small message about the program; in actual programming a separate module for help related items takes the place of this trivial about message.
The responsibilities of each module are described here: SimEdit module contains the RichTextBox (the hero of our show), the menu bar, functions for handling menu events and functions for file opening and saving, cut, copy, paste, font, color and alignment of text. This module is the king pin of our project. Finder is responsible for searching text. It requires search text and access to the RichTextBox instance from the SimEdit module. This is accomplished by creating an interface named SearchClient, which contains the methods void SetForward(bool x); bool GetForward();void SetReplacing(bool x); bool GetReplacing(); void SetSearchText(String s); String GetSearchText(); void SetReplacementText(String s); String GetReplacementText(); RichTextBox GetRTB(). These methods are enough for both searching and replacement. Hence, the constructor for Finder takes SearchClient as argument. This makes it compulsory on the part of SimEdit to implement the interface SearchClient. Replacer is similar to finder except that it does replacement as well. Hence, it is enough for its constructor to take SearchClient as argument. Print module takes the RichTextBox as argument, since it requires both text and the formatting information for printing the pages. This module extends System.Drawing.Print.PrintDocument class and overrides OnPrintPage(PrintPageEventArgs ev) method. This method receives the paper margins and dimensions from the event argument. This method simply goes on to select text from the RichTextBox and prints the text using the same font and color. But the location on screen deviates from that on print. This could be overcome by directly printing the RichTextBox in suitable pieces to fit the paper. Whereas, that is left for further developments on the editor. AboutMessage simply displays a message box.



Fig. 1 Organization and Interaction of Modules in SimEdit Project (Note that Finder, Replacer and SimEdit interact through SearchClient interface)

Code the Modules
Conceptual Part: Coding for the modules begins by defining the interfaces. When the interfaces are ready, development work is allotted to different teams, or a single developer proceeds to code the modules one by one. The advantage of the modular approach is, the project is ready to work just on completion of the base module. The project lacks only a few extra features when a module is still not ready. Hence, the modular projects evolve just as a child grows from infancy to adolescence. Version numbers for the project may be fixed based on extent to which the work is complete, such that version number 1.0 corresponds to completed project. Numbers like 0.3, 0.5 reflect the current status. Sub version numbers and build numbers are also permitted after further dots. Once the base module is ready, the software can be sent out to work within closely known circles and it is not ready for public distribution until all modules are ready and tested for proper performance. 

Application Part: Since we have only one interface named SearchClient, this interface is defined and compiled using the command csc /t:library SearchClient.cs to produce SearchClient.dll. A modular project may have many dynamic loaded libraries but only one executable file. The rest is related to coding the modules. Names of functions should clearly convey the work they do. People sometimes use names like func, func1, func2 in their coding. This is going to land them into trouble when they look at the coding after a few months. It is not possible to understand which function does which job just by looking at the name of the function. The contents of SearchClient.cs are shown below:

using System;

public interface SearchClient
{
void SetForward(bool x);
bool GetForward();
void SetReplacing(bool x);
bool GetReplacing();
void SetSearchText(String s);
String GetSearchText();
void SetReplacementText(String s);
String GetReplacementText();
System.Windows.Forms.RichTextBox GetRTB();
}

The search and replacement modules are coded in Finder.cs and Replacer.cs files. Printing portion is implemented in Print.cs file. About dialog is implemented in AboutMessage.cs file. The SimEdit.cs file contains the core editor providing support for the major operations like font, color, file selection, editing and implementing SearchClient interface. Since the coding is bit too large for inclusion into the text of this article, a summary of the methods and their purposes is provided in table 1. The actual source code is contained in the folder SimEdit\src folder in the accompanying CDROM.

Table 1 Summary of methods in source code files

Sl. No.

Name of Class

Method

Purpose

1

SimEdit

SimEdit (Constructor)

Initializes the GUI and sets up the RichTextBox

2

SimEdit

SetupFileDialog

Sets file name filters on file dialogs for opening and saving files

3

SimEdit

SetMenu

Sets up the menu for SimEdit. This is called by the constructor

4

SimEdit

MenuHandler

Handles the events related to all menu items. It calls other methods or takes action itself based on the selected menu

5

SimEdit

FindText

Finds the text chosen through the search or replacement dialog. It does the search or replacement according to the options set by the dialogs.

6

SimEdit

KeyReleased

This handles key up events on the rich text box. If F3 key is released, previous search or replacement operation is continued.

7

SimEdit

PrintDocument

Prints the document displayed by the editor. Passes the rich text box as argument to the Print class and sets the page size. Then, it displays a PrintDialog, results of which are used for printing

8

SimEdit

GeneratePrintPreview

Generates print preview for the document. The working is similar to the previous method except that the Print object is attached with a PrintPreviewDialog (available in System.Windows.Forms namespace) instead of PrintDialog used in the previous case

9

SimEdit

OpenFile

Displays open file dialog, reads the file from disk and loads the document into the rich text box. The LoadFile method of rich text box is used

10

SimEdit

CloseFile

Closes the current file. Clears the contents of rich text box and forgets the file name. It clears the title and sets “SimEdit” as title, omitting the file name part

11

SimEdit

SaveFile

Displays the save file dialog if file name is not already chosen. Saves the contents of rich text box by calling SaveFile method of rich text box

12

SimEdit

PageSettingsDialog

Displays PageSetupDialog (contained in System.Windows.Forms namespace). Attaches PageSettings object (available in System.Drawing.Printing) to reflect previous page settings

13

SimEdit

ClipSelection

Sends the selected text to  clip board. It SetDataObject  method of ClipBoard class. It takes DataObject class as the argument. DataObject is constructed with format and selected contents of the text box

14

SimEdit

PasteClipContents

Gets the DataObject associated with ClipBoard and extracts any data having RTF format from it. This text data is used to replace the selection region of rich text box

15

SimEdit

SetForeground

Displays color dialog and sets the text color according to selection

16

SimEdit

SetFont

Displays font dialog and sets the selection font accordingly

17

SimEdit

Main

Runs the SimEdit application. STAThread attribute is specified before Main method in order allow clip board related actions like copy and paste. Otherwise, an exception is thrown, since normal thread mode does not permit access to com objects (clip board is accessed using com object)

18

SimEdit

Methods of SearchClient interface

Nine methods belonging to SearchClient interface are implemented

19

Finder

Finder, InitializeComponents, SetComponents

Initialize the visual interface for searching text. The constructor calls the other two methods to complete the GUI.

20

Finder

TextChosen

This method actually handles the clicking of Ok and Cancel buttons. If Ok button is clicked, it calls the SetSearchText method of SearchClient interface, which is implemented by SimEdit

21

Replacer

Finder, InitializeComponents, SetComponents

Initialize the visual interface for searching text. The constructor calls the other two methods to complete the GUI.

22

Replacer

TextChosen

This method actually handles the clicking of Ok and Cancel buttons. If Ok button is clicked, it calls the SetSearchText method of SearchClient interface, which is implemented by SimEdit

23

Print

Print

Constructor

24

Print

TranslateAlignment

Translates the alignment of the rich text box into StringAlignment object of appropriate value. This translation is essential for rendering text on the Graphics object of printer.

25

Print

OnPrintPage

Prints the page on Graphics object associated with the printer.

26

Print

GetXPosition

Since our print class renders text by setting location, font, color and alignment on its own, the location of text in the horizontal direction needs to be decided based on the above parameters. This method returns the starting position for the text in the horizontal direction.

27

AboutMessage

AboutMessage, FixLabels

The constructor and the method create the GUI associated with the message to be displayed by SimEdit program.

Go through the source code files. Read the method names first. Then seek a line by line explanation of the methods. As a developer, the job is to generate code for these methods on getting specification of the work for each one of them.

Compile and Distribute

Conceptual Part: Compilation of the programs requires the appropriate development tools. The job of the compiler is to translate the source file provided by the developer into executable, DLL or other binary forms (such as byte code class files of Java). Languages like C, C++, FORTRAN, Java and C# have compilers. Some Languages like PERL, python, older implementations of BASIC, TCL (Tool Command Language) have interpreters. Cross bread Languages like Java are both comiled and interpreted, i.e., the code is compiled into a quasi executable form and then interpreted on the machine in which they run. It is better to automate process of building the software with the help of a simple batch file, shell script or make file (if you are already a mature programmer). This is essential to avoid repetition of certain command sequences for completing a build. This is important because no software is built to error free functioning on the first build. It takes a lot of builds to get a stable release of the software.
Why so much story about compilation and interpretation? When the programs are meant for public distribution, there is no guarantee that the end user knows what dependencies are required for the program in hand to run. Hence, the developer has to take care to pack dependencies along with the program. For fully compiled languages like C, C++ and FORTRAN, if the executable file is created with static linkage (i.e. all library subroutines are packed into the executable), no dependencies are required on the users machine. But the developer has to recompile the code to suite different operating systems and processor architectures.

Programs developed on visual studio for Windows require runtime DLL files (such as VB runtime) on the user machine. Programs developed on Linux or Unix platform need some shared object files (having .so extension) to be available on the user machine. Hence, the developer should know what dependencies are needed for his program to run on the worst updated system, assuming that the client does not have any of the dependencies.
Programs developed using Java language require JRE to be available on the user machine. Software developed in any of the languages of .NET platform (like C#, VB.NET, VC++.NET, J#, ASP.NET) require the .NET Framework (the libraries and environment settings specific to .NET) to be available. Programs developed using PERL, PYTHON or TCL require the language implementation to be available on the client's machine.
Hence, the developer has to take care to pack all requirements along with his software. Moreover, he should not try too much to pack third party software without knowing the license liabilities. Most of the run time dependencies like VB runtime, .NET framework, JRE, interpretors for PERL, PYTHON and TCL are free. But most of them insist that the user must read the terms and conditions associated with their software before it is installed on the user's machine. Hence, try to understand the mode of preferred installation of dependencies without unnecessary work for your client.

Finally, creating a setup file is of really good value. Free setup creation tools like NSIS from NullSoft and InnoSetup Compiler (down loadable from www.innosetup.com) exist apart from the tools packed with large software suite like Visual Studio .NET. Professional developers requiring key based authentication and other security features may purchase setup tools available from several sources. Distributing a software in a setup file relieves the end user from a lot of irritating copying other registry related operations.

Application Part: SimEdit requires .NET SDK for compilation and .NET framework for execution. The build process is automated with a simple batch file called compile.bat, which takes care to compile the required DLL files and make the final executable file. The contents of the batch file are shown below:

csc /t:library SearchClient.cs
csc /t:library AboutMessage.cs
csc /t:library Print.cs
csc /t:library /r:SearchClient.dll Finder.cs
csc /t:library /r:SearchClient.dll Replacer.cs
csc /t:winexe /r:AboutMessage.dll,Finder.dll,Print.dll,Replacer.dll,SearchClient.dll SimEdit.cs

Running this batch file compiles all the executables from the source code. With regard to packing into a setup file, it takes a lot of space explain even one of the tools in detail. It shall be taken up in a separate article. For our application, it is enough to pack all DLL files along with SimEdit.exe file, may be packed into a self extracting zip executable file. The .NET framework should also be distributed along with the package.

Testing the Project

After building the project, it should be subjected a meticulous testing schedule to ensure its fitness. Any bugs are noted down and promptly rectified, build process is repeated followed by packing. The screen shots taken during testing of the SimEdit program are shown in figures 1 to 12. Remember the goals set for the project when it was started.


 

Conclusions
Managing a project is a really demanding task, requiring a lot of foresight and intuition to visualize the solutions before they are created. Although the sample problem solved here is a simple one, the essence of problem solving remains the same, whether it is a trivial project or a large project. Managing projects is done more through hands on experience than through studying a lot of material. Hence, start your own projects. Experience the joy when your brain child becomes an essential part of the daily lives of others!

The author is a civil engineer by qualification but a software engineer by passion and can be reached on nagaradjanev@rediffmail.com




Added on August 11, 2008 Comment

Comments

Post a comment