Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XML

Programming Vs. Software Development

4.95/5 (25 votes)
9 Dec 2013CPOL10 min read 151.7K   513  
An overview of the difference between programming and software development

Introduction

The following is an explanation of the terms "programming" and "Software Development", as I see it. (They are not necessarily the correct language definitions.)

Programming Creating applications to perform a certain task (tools).
Software Development Creating professional applications that are easy to use, expandable and easy to change. IOW - well designed.

That might sound a bit pretentious, which is certainly not my intention. Let's make that clear by saying that "programming" can be useful, and is not "stupid" IOW you can e.g. "program" a very complicated, state-of-the-art algorithm. However, when providing an application to the public, one might think of upgrading or re-writing that programmed application to a software development.

Let me finish the introduction by saying that we are all guilty of some form of (dirty) programming at some point. I certainly am not a saint in this regard. We should however, be aware of this so we can improve if necessary.

This article is not related to any programming language, though the sample is written in C#. It can be applied to any programming language including HTML, XML, SQL, C++, Java, Python, scripting languages, ...

Background

I started thinking about this article when I saw some of the "applications" in our sector and also seeing some of the code snippets here on CodeProject. The real trigger however was when I heard colleagues talk in the hallway, saying that they didn't like software developers because they always work with fancy machines (which the users don't have), they overcomplicate things, ... Needless to say, I was a bit annoyed with this statement (Software developers are obsolete?), certainly because they are these type of people that "program".

A second trigger was when I needed to explain myself to a manager why something took so long or a recruiter on why I am 'better' than the next guy/girl.

The explanations on why they don't improve the application, are things like "not important", "it does what it's supposed too", "not many will use it", "deadline", ...

Basic things that I see as "programming" are:

  • spaghetti code
  • no n-tier design
  • not changing default naming (button1, button1_Click, ... )
  • no thought on UI design (icons, guide text, consistency, control location logic ... )
  • no thought on UI logic (tab order, mouse clicks, ... )
  • no thought about extensibility, re-usability, ...
  • no Exception handling, logging, ...
  • ...

However, "programming" can be very useful in prototyping or personal projects, you could then strip that application from unnecessary bits, clean it up and incorporate it into a larger Software Development. (The hard stuff, finding the correct '20' lines of code that build your fancy algorithm is already done.)

Using the Code

To illustrate what we're trying to clarify, we define a request for an application.

Create an application that will add 2 numbers and present the output.

Before you continue, I propose you build this yourself without reading further. It is a very simple application.

... building code, ..., building code, ..., building code, ...

Done? Probably you didn't do the above. No matter, we'll still continue the article.

The Programming example

In this screenshot, you'll see we've met the request. You enter two numbers and press the add button. Then it calculates the sum of the two terms and displays it in the third textbox.

So what's wrong with it, just by looking at the screenshot?

  • Controls are not aligned (subtle enough to be extra annoying)
  • Window title is "Form1"
  • Window icon is the standard Visual Studio icon

But the difference between "Programming" and "Software Development" goes further than the obvious:

  • The tab order is all wrong
  • There are no tooltips, no guide text, ...
  • There's too much empty space on the window and the controls are placed a bit "at random"
  • It can just add numbers, like requested (nothing more)
  • You can change the actual sum manually

And now, just for fun, try to provide an alphanumeric character:

Unhandled Exception

Oops...

To compare, we'll check out the "Software Development" version of the same request.

Software Development example

Here we see that the same request has been met, with the differences:

  • All fields are aligned
  • You don't need to press a button to perform the calculation (less user action required)
    However, don't overdo this. I personally hate applications that do too much for me, because it becomes hard to determine what is actually going on (and is the application doing it correctly? Didn't I miss something? ...)
  • There is less empty space on the window
  • There is some guide text (and not visible, but also tooltips)
  • Not visible, the tab order is logical
  • Not visible, added tooltips
  • Added icon and changed window title
  • The solution textbox is read-only and calculated when any of the other textboxes or the combobox are changed
  • This example allows +, -, x, / and %. If your argument is, the client doesn't want this, you're right, then build it in and hide the other options for the user. The point is, if you foresee a future request (e.g., please also add subtracting) make sure to foresee to easily modify the code to do this.

Now let's try to break this:

Image 4

The second example itself can also be improved, we could provide textboxes that do not allow any alphanumeric characters, we could limit the textbox contents size to a certain number of characters, we could allow operations on currencies, we could allow decimal, octagonal and binary operations and so on and so forth.

Now we only stated the obvious of what we see on the screen, let's dive deeper into the trenches of our job and have a look at the code.

The programming example's code looks like this:

C#
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
 
    private void button1_Click(object sender, EventArgs e) {
	 textBox3.Text = double.Parse(textBox1.Text) + double.Parse(textBox2.Text) + "";
    }
 
    private void button2_Click(object sender, EventArgs e) {
	 this.Close();
    }
} 

Let's sum up what's wrong here:

  • use of default naming
  • no error checking
  • hardcoded addition
  • no comments

Now let's have a look at the Software Development code:

The GUI class:

C#
public partial class BaseMathOperations : Form
{
    public BaseMathOperations()
    {
        InitializeComponent();
		ToolTip tt = new ToolTip();
		tt.SetToolTip(txtbox_term1, "fill in term 1.");
		tt.SetToolTip(txtbox_term2, "fill in term 2.");
		tt.SetToolTip(txtbox_solution, "the outcome of the math.");
		tt.SetToolTip(combo_operation, "mathematical operation");
		tt.SetToolTip(btn_close, "close this application");
		tt.Active = true; 
	
		combo_operation.SelectedIndex = 0;
	} 
 
    private void txtbox_term_TextChanged(object sender, EventArgs e) {
		Calculate();
    }
 
    private void combo_operation_SelectedIndexChanged(object sender, EventArgs e) {
        Calculate();
    }
 
    private void btn_close_Click(object sender, EventArgs e) {
        this.Close();
    }
 
    private void Calculate(){
        //check if all three necessary fields are filled in.
		if(	!string.IsNullOrEmpty(txtbox_term1.Text) &&
		!string.IsNullOrEmpty(txtbox_term2.Text) && 
		combo_operation.SelectedIndex > -1){
			switch(combo_operation.Text){
				case "+": txtbox_solution.Text = SimpleMath.Add(txtbox_term1.Text, txtbox_term2.Text);
				break;
				case "-": txtbox_solution.Text = 
                          SimpleMath.Substract(txtbox_term1.Text, txtbox_term2.Text);
				break;
				case "x": txtbox_solution.Text = 
                          SimpleMath.Multiply(txtbox_term1.Text, txtbox_term2.Text);
				break;
				case "/": txtbox_solution.Text = 
                          SimpleMath.Divide(txtbox_term1.Text, txtbox_term2.Text);
				break;
				case "%": txtbox_solution.Text = SimpleMath.Mod(txtbox_term1.Text, txtbox_term2.Text);
				break;
			}				//end switch				
		}					//end if
    }
} 

The SimpleMath class:

C#
public class SimpleMath {
	public static string Add(string term1, string term2){
		string retval = "";
		try{
			retval = Double2String(String2Double(term1) + String2Double(term2));
		}				//end try
		catch(Exception ex){
			retval = "not a number";
		}				//end catch
		return retval;
	}
 
	public static string Substract(string term1, string term2){
		string retval = "";
		try{
			retval = Double2String(String2Double(term1) - String2Double(term2));
		}			//end try
		catch(Exception ex){
			retval = "not a number";
		}			//end catch1
		return retval;
	}
 
	public static string Multiply(string term1, string term2){
		string retval = "";
		try{
			retval = Double2String(String2Double(term1) * String2Double(term2));
		}			//end try
		catch(Exception ex){
			retval = "not a number";
		}			//end catch
		return retval;
	}
 
	public static string Divide(string term1, string term2){
		string retval = "";
		try{
			retval = Double2String(String2Double(term1) / String2Double(term2));
		}			//end try
		catch(DivideByZeroException dbzex){
			retval = "cannot divide by 0";
		}			//end catch
		catch(Exception ex){
			retval = "not a number";
		}			//end catch
		return retval;
	}
 
	public static string Mod(string term1, string term2){
		string retval = "";
		try{
			retval = Double2String(String2Double(term1) % String2Double(term2));
		}			//end try
		catch(Exception ex){
			retval = "not a number";
		}			//end catch
		return retval;
	}
 
	private static double String2Double(string val){
		double retval = double.NaN;
		if(!double.TryParse(val, out retval)){
			retval = double.NaN;
		}			//end if
		return retval;
	}
 
	private static string Double2String(double val){
		string retval = "not a number";
		if(val != double.NaN){
			retval = val.ToString("0.00", CultureInfo.InvariantCulture);
		}			//end if
		return retval;
	}
} 

This code is certainly not perfect, but it is certainly a lot better then the first example.

  • Comments - check
  • Error handling - check
  • Division of logic (the arithmetics are handled by another class)
  • No default naming - check
  • Better logic in UI design and can handle more than just adding numbers. It also formats the result.

If you're stating by now that I shouldn't swallow my exceptions, you're right. In the source, I added a comment on top of the SimpleMath class:

C#
/*
 *	Remarks:
 *	Normally you don't swallow the Exceptions as done here, 
 *  but in order to keep the code simple, we don't handle them perse here.
 */  

So indeed, you should never swallow exceptions, but instead write them to a log file or database and/or bubble them up to the user (in some formatted way).

This second example is certainly longer then the programmed version, but if you look a bit closer, you'll see it is not complex at all. The SimpleMath class can be reused, we successfully separated GUI and business logic. (In real applications, you would probably split that into different projects.)

In the end, you spend time to win time (later on).

How to Achieve Higher Standards

When you read this article, you probably didn't have the feeling: "Now this is enlightening!"

Yet it somehow is (I hope so anyway), why, if we're so aware if this, do we repeatedly make mistakes? (Probably because we're lazy).

So here are some pointers on "Software Development":

#1

Do not start coding directly from a requirement, you'll end up with a program. Instead, take a step back and look at all the angles, design your application (and take time for it):

  • Will the requirement likely be expanded in a certain direction?
  • Does it need to plugin to another application?
  • What could be reusable?
  • ...

#2

Keep the K.I.S.S. principle. Don't overcomplicate things. If you start feeling complexity, start re-thinking. Don't be scared to re-write bits of your code to simplify the further development. If you smell trouble coming, fix it before it starts stinking further down the road.

#3

If you need to implement a difficult algorithm, or want to check some features (get to know how a certain class works), create a new project and use "programming" to create a prototype (although "programming" does not imply you throw all the "software development" rules overboard). Only when you are confident in your solution should you incorporate it into the final version. Doing this directly in the final version will result in a mess rather quickly.

#4

Clean up code regularly, take time to browse all classes and remove unnecessary comments or scout for complex code that you could do better and easier. In fact, do so immediately after reading this article.

#5

Very important: dare to question the requirement and/or your boss! If you see problems coming or have a good idea, you SHOULD communicate this. (IMHO, this is what they are paying you for?) The boss/client normally has the final word, but you can say no, and if they really, really want it, well, you warned them.

#6

Test. You and/or someone else. You should not test if something works (it probably will), rather try to make it break! IOW don't test expected behaviour. eg. You can do this by taking the scenario steps of a user test and modifying them slightly. That is how I find the most bugs and we all know users never follow the rules on how something should be used.

#7

I'm all for defensive programming. Don't throw try/catch blocks for fun and try to limit out input from the very start developing "safe gates" along the way. e.g., Integer input can be enforced via the GUI, can be checked in the business - and data access layers and finally can be enforced on the database level.

#8

As commented below, don't allow changes moments before the deadline. Setup a proper period of "code freeze" were (almost) no changes are allowed to the code. Be rigorous about this. It is even a good period to finalize all the other stuff mostly forgotten: documentation.

#9

It is good to automate some work for the user, but never forget that a user still remains the responsible person for his/her work. Never let yourself be drawn in discussions were managers want fully automated systems. Your code becomes exponentially more complex quicker than an improbability drive can take you to the restaurant. In many cases, the end-users start complaining anyway and many changes will have to be reverted.

#10

You don't need to adopt every new shiny feature that comes along.

Conclusion

#1

As explained in the background section, you could use the information of this article towards your manager or recruiter. Furthermore, you can use the information to become more aware of doing things better and certainly simpler. Finally, be aware that applications can always be approved (take time to review your work later on), it can always be better and don't be to fast on your toes when someone asks you "why didn't you do it that way?" (probably because you don't or didn't know or there was some reason for it).

#2

Doing "programming" or "software development" can mean the difference in people using your application or not. Don't take it too lightly.

#3

You can take this concept further into research, presentations (!), documentation, etc...

Points of Interest

When I was writing this article, I started thinking. When is an application "programmed" and when is it "software developed"? The answer: It is a gray area. It comes with experience, it comes from your own point of view. But one thing is clear. Your code can always be improved, you should be critical towards your own work.

History

  • 20/06/2013: First version
  • 09/12/2013: Second version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)