Imposing Design (was Re: [TDD] Re: Wandering through layers of software)
[snipstart] --- In testdrivendevelopment@yahoogroups.com, "Kelly Anderson" <kellycoinguy@...> wrote: > > My TDD code throws more exceptions generally... so I'd really like to > hear more about your thoughts on this subject. > [snipend] Using the example as shown in: What is Exceptional? [126], The Pragmatic Programmer (converted from java to C#).
private TextReader ipstream;
public void open_passwd() { try { ipstream = new StreamReader(@"..\etc\passwd"); } catch(Exception) { throw new FileNotFoundException("No Password File Found"); } }
public bool open_user_file(string fname) { if (!File.Exists(fname)) return false;
ipstream = new StreamReader(fname);
return true; }
public void OpenUserFile(string fname) { if (!File.Exists(fname)) { Fire_FileDoesNotExistEvent(); return; }
ipstream = new StreamReader(fname); }
The method open_passwd has a dependency on passwd file. The second method is not dependent on a specific file. (In my opinion both methods are ripe to be refactored). Would you have written either of these methods with TDD/Refactoring. The point is that because of that dependency on the first method it has to have some way to communicate to the client that the part of the contract it is responsible for cannot be fulfilled. Also I am not saying that when you write code you shouldn't ever throw an exception.
As far as I have been able to determine there are only three standard ways objects can communicate in an OOP methodology.
- Exception Message (first method)
- Command Message (second method).
- Event Message (third method).
using System; using System.IO; using NUnit.Framework;
namespace UnitTestAlarmSystem { [TestFixture] public class Test_FileOpener_NoExceptions { private const string FILE_NAME = "Tester"; private TextFileOpener textFileOpener; private ShutDownSystem shutDownSystem; private bool isNoFile;
[TestFixtureSetUp] public void TestFixtureSetUp() { textFileOpener = new TextFileOpener(); shutDownSystem = new ShutDownSystem(); }
[TestFixtureTearDown] public void TestFixtureTearDown() { shutDownSystem = null; textFileOpener = null; }
[Test] public void TestExceptionMessagesNoFile() { LoadFileForm form = new LoadFileForm(textFileOpener, shutDownSystem); form.ButtonClickException(); Assert.IsTrue(form.IsException); }
[Test] public void TestCommandMessageNoFile() { LoadFileForm form = new LoadFileForm(textFileOpener, shutDownSystem); form.SetFileName(FILE_NAME); form.ButtonClickCommand(); Assert.IsTrue(form.IsCommand); }
[Test] public void TestEventMessageNoFile() { isNoFile = false; textFileOpener.WhenLoadFile += new EventHandler(shutDownSystem.WhenNoFileHandler); textFileOpener.WhenLoadFile += new EventHandler(WhenNoFileHandler);
LoadFileForm form = new LoadFileForm(textFileOpener); form.SetFileName(FILE_NAME); form.ButtonClickEvent(); Assert.IsTrue(isNoFile); }
private void WhenNoFileHandler(object sender, EventArgs e) { isNoFile = true; } }
public class LoadFileForm { private TextFileOpener textFileOpener; private ShutDownSystem shutDownSystem; private string mFileName; private bool isCommand = false; private bool isException = false;
public LoadFileForm(TextFileOpener opener, ShutDownSystem shutDown) { textFileOpener = opener; shutDownSystem = shutDown; }
public LoadFileForm(TextFileOpener opener) { textFileOpener = opener; }
public bool IsException { get { return isException; } }
public bool IsCommand { get { return isCommand; } }
public void ButtonClickException() { try { textFileOpener.open_passwd(); //Process file } catch (Exception ex) { isException = true; shutDownSystem.SetException(ex.Message);
shutDownSystem.Execute(); } }
public void ButtonClickCommand() { bool fileOpenResult = textFileOpener.open_user_file(mFileName);
if (fileOpenResult) { //Process file } else { isCommand = true; shutDownSystem.SetException("No File Found {Command}"); shutDownSystem.Execute(); } }
public void ButtonClickEvent() { textFileOpener.OpenUserFile(mFileName); //Process file }
public void SetFileName(string file_NAME) { mFileName = file_NAME; } }
public class ShutDownSystem { private string mException;
public void Execute() { Console.WriteLine(mException); //Shut Down Logic }
public void WhenNoFileHandler(object sender, EventArgs e) { Console.WriteLine("No File Found {Event}"); //Shut Down Logic }
public void SetException(string exceptionMessage) { mException = exceptionMessage; } }
public class TextFileOpener { public event EventHandler WhenLoadFile;
private TextReader ipstream;
public TextReader Ipstream { get { return ipstream; } }
public void open_passwd() { try { ipstream = new StreamReader(@"..\etc\passwd"); } catch (Exception) { throw new FileNotFoundException("No File Found {Exception}"); } }
public bool open_user_file(string fname) { if (!File.Exists(fname)) return false;
ipstream = new StreamReader(fname);
return true; }
public void OpenUserFile(string fname) { if (!File.Exists(fname)) { Fire_FileDoesNotExistEvent(); return; }
ipstream = new StreamReader(fname); }
private void Fire_FileDoesNotExistEvent() { if (WhenLoadFile != null) WhenLoadFile.Invoke(null, null); } } }