Amazon.com Widgets

Life is Too Short To Call Create

clock January 27, 2012 18:52 by author Nick |

Introduction

Okay, so the whole FreeAndNil thing has been going on for a while.  Some folks are understandably sick of it, but I’m not.  Winking smile I think it is an important discussion that actually reveals a much deeper issue – sort of like how a fight with your spouse over the toothpaste tube is usually really a fight over something deeper and more serious.

I think in this case, the “fight” (I don’t like that word for this particular case, but we’ll roll with the metaphor…) is really about the approach one takes towards memory management – specifically, how one views the role of class creation (and thus memory allocation) when writing code.  In my Dependency Injection Series (which I really need to continue…), I spoke about the notion of creating classes without constructors (other than the default one, of course).  In a sense, this post might be considered part of my DI series, because in this post I am basically making the case for using a Dependency Injection container.  In this post, I’m going to argue that for the most part, you should not call Create.  And you should design your code in such a way that you don’t need to call Create

Life Too Short?

Okay, so I was watching a terrific video by Neal Ford (a former Delphi guy, actually – ) in which he introduces the notions of and “way of thinking” behind Functional Programming.  It’s a great video, and you should watch it.  Near the end of it, Neal says something that I’ve been pondering a while:  “Life is to short to call malloc”. He doesn’t think he should have to worry about memory management anymore.   This somewhat provocative thought stream-lined with a notion I ran across as I was investigating and thinking about unit testing – the idea from Misko Hevery where he is deeply suspicious of the new operator, Java’s equivalent of .Create.  At first, this seems like a really weird notion, particularly since Delphi is a native language, and many Delphi developers appreciate the ability to control the lifetime of their objects and directly manage memory .  But I started to see the wisdom in it, and have finally come to agree with Neal – Life is too short to call .Create.  I don’t want to be spending my limited thinking and coding time worrying about memory, particularly since there are now frameworks and language features that can do this automatically.  In languages like Java and C# (among others), developers use garbage collection to manage memory.  We don’t have garbage collection in Delphi, but we do have ways of making memory management something that isn’t a huge concern. 

And hey, if you are a Delphi developer, and you want to completely control your objects lifetime manually, they hey, you can. More power to you.  But again, I’m going to show you how you can spend less time worrying about that and more time doing the things that we developers really are trying to do -- which is come up with solutions and products. 

This isn’t the first time that I’ve thought or mentioned all of this stuff:

I’m Lazy

First, I am not the sharpest knife in the drawer and I have a limited number of CPU cycles in my brain.  If I don’t have to, I don’t want to spend them doing repetitive “busy work”.  And calling the Create/Free cycle is, to a large degree, busy work.  We all do it – we carefully ensure that if we call Create, we code the try…finally block and call .Free.  If we create an instance class variable in a constructor, we immediately call .Free in the destructor.  Those are all good practices, and bravo to you for following them, but I think we’ve now gotten to the point where we don’t always have to do these kinds of tedious, wrote coding activities anymore.  If we can spend time thinking more about higher level solutions and less about lower-level intricacies, we are more productive.  (One could argue that the entire field of computer science has been nothing other than a giant march towards spending time on higher level solutions and away from tedious, low-level coding…)

Don’t Cause Dependencies

But that is more of a basic, low-level reason in itself -- the idea that you can save brain power.  There are some deeper technical and practical  reasons why you should eschew creating anything.  The first is that calling .Create creates more than just an object instance -- it creates a dependency.  If you actually create a class instance your self and use that class via a direct class reference, that is, do something like this:

procedure TMyWidget.DoSomeSprocketWork;
var
  SomeSprocket: TSprocket
begin
  SomeSprocket := TSprocket.Create
  try
    SomeSprocket.DoSprocketyStuff
  finally
    SomeSprocket.Free
  end;
end;

you are dependent on that class and that class alone.  You’ve created an unbreakable dependency on that particular implementation.  You have to include that classes unit in your uses clause.  You’ve very tightly coupled yourself to a specific means of getting something done.   If you want to change it, you actually have to go and alter the code itself.  Yikes! If you want to test it, your tests have to rely on the entire dependency chain of TSprocket, and who  knows what the heck that entails?  And I hope we can all agree that tightly coupling yourself to specific implementations is bad, right?  (If we can’t, I’m afraid that we can’t be friends anymore.  Alas.)

As I’ve been preaching for a while now, you should reference classes and functionality via interfaces.  Interfaces allow you to, at the very least, reference specific a functionality rather than a specific implementation of that functionality.  But even in you use interfaces exclusively -- that is do something like the below instead of the above --

procedure TMyWidget.DoSomeSprocketWork;
var
  SomeSprocket: ISprocket
begin
  SomeSprocket := TSprocket.Create
  SomeSprocket.DoSprocketyStuff
end;

you are still creating a dependency on that particular class. Your uses clause still has to include the unit for that class, and your code is explicitly tied to that particular implementation.  Using the interface is a step in the right direction – using an interface makes you not have to worry about memory management – but you still end up with dependency on a specific implementation.  And we agree that a dependency on a specific implementation should be avoided, right? 

So, we agree that calling Create causes a hard-coded dependency and that it is bad.  And if you think about it, anytime you call create in one class, you create a dependency.  One reason such dependencies are bad is that it makes your code hard to test.  True and proper unit testing means that each class should be able to be tested in isolation.  If ClassA is irrevocably dependent on ClassB, then you cannot test ClassA without invoking ClassB.  You can’t easily provide a mock class for ClassB either.  Thus, a call to Create can make your code hard to test. 

Following SOLID

But there’s yet another reason to avoid calling Create – the ‘S’ in the SOLID principles.  The ‘S’  stands for the “Single Responsibility Principle” which is “the notion that an object should have only a single responsibility.”  If your class has a mission and it is creating stuff to do that mission, then it actually has multiple responsibilities – doing its mission and  creating stuff.  That’s two things, not one.  Instead, let your class do it’s main mission, and leave creating stuff up to another class whose main mission it is to create stuff.   Plus,  if you have dug into the SOLID principles, you know that the ‘D’ stands for the “Dependency Inversion Principle” which is the notion that “one should depend upon abstractions [and] not depend upon concretions.”  Or, as you might have heard me say say “Program against abstractions, not against implementations”.  (And of course, it wasn’t me that said that – it was Erich Gamma of  “Gang of Four ” fame.)

And where does that leave us?  Well, right back with not calling Create, and having a class whose specific, single purpose in life is to create stuff for you.  Sound familiar?  It should, we just described either a class based on the Factory pattern, or a Dependency Injection container. 

So, in the end, the code you’d write would end up looking like:

procedure TMyWidget.DoSomeSprocketWork;
var
  SomeSprocket: ISprocket
begin
  SomeSprocket := SprocketFactory.GetSprocket;
  // Or maybe something like
  // SomeSprocket := MyDIContainer.GetImplementation<ISprocket>('Basic');
  SomeSprocket.DoSprocketyStuff
end;

That way, there is no Create call, and thus you aren’t creating any dependency other than on the interface.  You get instances of your objects from a Factory or from a Dependency Injection container  -- and either one can produce any implementation you want or ask for without creating a dependency.   Either way, it gives you control over how the interface is implemented without coupling to that implementation. You could even add a parameter to the GetSprocket call to ask for a specific kind of Sprocket implementation, and even that wouldn’t cause you to be dependent on that implementation.  

In the end, calling Create merely causes a dependency, takes brain cycles, and violates the SOLID principle.  No wonder you shouldn’t use it much!

So then the question becomes, When should you call Create? Well, I’m glad you asked. I’ll answer that in a future post.  Winking smile



Delphi Mocks: The Basics

clock October 16, 2011 21:41 by author Nick |

Introduction

As you may have noticed, I’ve kind of started to become a championship caliber pain in the butt about unit testing.  I walk the halls of Gateway Ticketing saying “If your code isn’t easy to test, you are doing it wrong”.  I keep giving my Unit Testing presentation to anyone that will listen.  But I feel justified – unit testing is critical to writing clean, maintainable code.

One of the reasons people seem to frequently give for not doing unit testing is that “My code requires <some external dependency> and it’s too hard to configure for simple unit tests” or something like that.  Okay, fair enough.  I won’t point out how you should be using Dependency Injection to decouple that code and enable you to insert a mock or a stub or a different class for testing purposes.  (Okay, I lied – technically I guess I did mention that.  Sorry.)  But I get that sometimes implementing a complete, formal TMockXXXX version of your interface (and you are coding against interfaces and not implementations, right?) is not something you want to do. 

Mocks

In their simplest form, a mock object is simply an alternate implementation of a class that provides “fake” responses to method calls.  For example, you have a class TCustomer that has a method GetCustomerName, and normally, that call goes to the production database and gets the name (a simple, unlikely example, I know, but you get the idea).  So to avoid the call to the database, you just create TMockCustomer, and implement it’s call to GetCustomerName and have it return “George Jetson” every time.  This enables you to test the class that is using TCustomer without having to hit the database at all.

But that can get a bit clumsy.  What if you want to return different values based on different inputs?  What if you find a bug based on specific input or output, and you want to create a unit test for that specific case?  Then a mock class as described above gets harried, complicated, and hard to maintain.

Enter a Mocking Framework

What if we could have a framework that would allow us to implement any interface, and define easily and exactly what the inputs and outputs should be?  That would be cool.  This would enable you to easily create a mock object that can respond to method calls in defined ways in a flexible, easy to set up manner.  This is what a mocking framework does.

Obviously something this flexible needs some powerful language features.  Such a framework would have to be able to flex to dynamically implement an interface.  It would have to be able to dynamically recognize method calls and respond accordingly.  Fortunately, Delphi XE2 is up to the task.  Delphi XE2 introduces the TVirtualInterface class that lets you dynamically implement any interface at runtime.  Combine that with the new RTTI, and you have the ability to build a very powerful mocking framework.

And that is just what Vince Parrett of VSoft Technologies, author of the wonderful FinalBuilder, did.  He has built a very cool and very powerful library called Delphi Mocks and released it as open source for all of us.  Very cool – thanks, Vince.   Delphi Mocks is available on GitHub under the very developer friendly Apache 2.0 License.  Vince has written a nice “Getting Started” guide, but I wanted to write  this article to build a very simple example of a pretty simple use case for mock objects.  So let’s do that.

An Expensive Service

A typical use case for using a mock object is to replace a service that is “expensive”.  Sometimes that means expensive as in “actually costs money”, but it will more likely mean expensive in CPU cycles, database connectivity, or anything else that requires an external dependency that causes your class under test to stop being tested in isolation and start being integrated with something else.   Since a unit test should always test something atomically and leave nothing (database entries, files, charges on a credit card) lying around, any time that will happen when running a unit test, you probably should consider a stub or a mock object instead.

By “stub” I mean “a class that implements a particular interface but doesn’t really do anything”.  It’s not exactly the same as a mock object in that the interface in question will normally not return anything but merely do things external to the class.  A typical example is a logging class.  If you are running unit tests, you don’t want your logging system writing logs all over the place every time you run your tests, so you create a Logger stub class that acts like your regular logger, but which actually doesn’t do anything.  You can call it in your code, but you get nothing from it – which is what you want. 

So let’s look at a simple, but “expensive” service.  Consider the following code:

unit uCreditCardValidator;

interface

uses
      SysUtils;

type

  ICreditCardValidator = interface(IInvokable)
  ['{68553321-248C-4FD4-9881-C6B6B92B95AD}']
    function IsCreditCardValid(aCreditCardNumber: string): Boolean;
    procedure DoNotCallThisEver;
  end;

  TCreditCardValidator = class(TInterfacedObject, ICreditCardValidator)
    function IsCreditCardValid(aCreditCardNumber: string): Boolean;
    procedure DoNotCallThisEver;
  end;

implementation

uses
     Dialogs;

{ TAdder }

function TCreditCardValidator.IsCreditCardValid(aCreditCardNumber: string): Boolean;
begin
  // Let's pretend this calls a SOAP server that charges $0.25 everytim
  // you use it.

  // For Demo purposes, we'll have the card be invalid if it the number 7 in it
  Result := Pos('7', aCreditCardNumber) <= 0;

  ShowMessage('You were just charged $0.25');
end;

procedure TCreditCardValidator.DoNotCallThisEver;
begin
  // This one will charge the company $500!  We should never
  // call this!
end;

end.

This unit declares two things, an ICreditCardValidator and a class that implements it, TCreditCardValidator.  It simulates deciding a credit card is bad by saying any card number that has the number ‘7’ in it is bad.  Otherwise, any string will be acceptable. It’s a demo class, obviously, but it illustrates a class that would be used only in production, as you get charged by a credit card validating service every time you call IsCreditCardValid.    Clearly, you don’t want to be calling that whenever you run your tests.  Thus, it seems likely that any collection of unit tests that wants to use this service would likely want to use a mock class.

A Class to Use the ICreditCardValidator

Mock classes really become useful when you are testing a class that consumes an expensive service.  Thus, we’ll declare the following class, TCreditCardManager, which consumes ICreditCardValidator:

unit uCreditCardManager;

interface

uses
      uCreditCardValidator
    ;

type
  TCreditCardManager = class
  private
    FCCValidator: ICreditCardValidator;
  public
    constructor Create(aCCValidator: ICreditCardValidator);
    function CreditCardIsValid(aCCString: string): Boolean;
  end;

implementation

{ TAddingMachine }

function TCreditCardManager.CreditCardIsValid(aCCString: string): Boolean;
begin
  Result := FCCValidator.IsCreditCardValid(aCCString);
end;

constructor TCreditCardManager.Create(aCCValidator: ICreditCardValidator);
begin
  inherited Create;
  FCCValidator := aCCValidator;
end;

end.

This class is really simple – it just takes an ICreditCardValidator in it’s constructor and uses it to validate credit cards.  As a demo class it is really simple, but a more complete class would have methods to make payments against the card, etc.  But if, when testing this class, you pass it in an implementation of the ICreditCardValidator above, you’ll get charged $0.25 for every test you run.  That’s not something you’d really want to do, so this class seems like a good candidate for using a mock object to replace the implementation of ICreditCardValidator

Testing TCreditCardManager Can Be Expensive

So, the typical way to test TCreditCardManager might look like this:

procedure TestTCCValidator.TestValidateCreditCard;
var
  ReturnValue: Boolean;
  ExpensiveCCValidator: ICreditCardValidator;
  ValidCard: string;
  BadCard: string;
begin
  ExpensiveCCValidator := TCreditCardValidator.Create;
  FCCValidator := TCreditCardManager.Create(ExpensiveCCValidator);

  ValidCard := '1112221'; // Rule is that a bad card has a '7' in it
  BadCard   := '6667666'; // ..so this one is bad

  ReturnValue := FCCValidator.CreditCardIsValid(ValidCard);
  CheckTrue(ReturnValue);

  ReturnValue := FCCValidator.CreditCardIsValid(BadCard);
  CheckFalse(ReturnValue);
end;

However, if you run this in the GUI test runner for DUnit, you’ll see this:

image

 

And of course, if you keep this up, the bill you get will not make your boss happy.

Testing with a Mock

So, to avoid the wrath of your boss, you should create a mock object that behaves like you want it to but that doesn’t end up costing anything.  The first way you might do it is to create a new class that implements the ICreditCardValidator interface, but that does nothing or returns set values.  But that is kind of clunky, and hard to customize.  What you really want is what I mentioned earlier, an extensible mock that can be created an configured on the fly.  That’s where Delphi Mocks comes in.

The Delphi.Mocks.pas unit declares a type TMock which takes a parameterized type, and which then can sort of morph itself into an implementation of that interface using the cool new-to-XE2 class called TVirtualInterfaceTVirtualInterface basically allows you to implement an interface on the fly at runtime.  Thus, you can create a generic class (or record, in the case of TMock) that can appear to be any interface you want it to be. 

Thus, we can create a TMock that looks and acts like an ICreditCardValidator:

var
  CCMock: TMock<ICreditCardValidator>;
 begin
  CCMock := TMock<ICreditCardValidator>.Create;
  ...
end;

Once we have that mock, we can tell it how to behave:

  ValidCard := '1112221'; // Rule is that a bad card has a '7' in it
  BadCard   := '6667666'; // ..so this one is bad

  CCMock.Setup.WillReturn(True).When.IsCreditCardValid(ValidCard);
  CCMock.Setup.WillReturn(False).When.IsCreditCardValid(BadCard);

This code uses a nice fluent interface to be somewhat self-explanatory.  It basically sets the mock up as follows: “When I pass in the valid string, return True.  When I pass in the bad string, return False.”  This is a basic definition that will allow your TCreditCardManager class to exercise itself with both good and bad input, allowing you to test your code with both kinds of responses.  We can determine exactly what the inputs and outputs are and ensure that the mock displays the correct behavior and follows the business rules set out in the “real” implementation.  Notice, too, that the When call, through the delightful magic of generics, is actually an implementation of the ICreditCardValidator interface, and thus is able to execute a real method call to the method from that interface.  You even get support from Code Completion in the IDE. 

Now, you can create the Credit Card Manager, pass it your mock object, and run tests with your mock input and output:

  FCCValidator := TCreditCardManager.Create(CCMock);

  ReturnValue := FCCValidator.CreditCardIsValid(ValidCard);
  CheckTrue(ReturnValue);

  ReturnValue := FCCValidator.CreditCardIsValid(BadCard);
  CheckFalse(ReturnValue);

This way, you can exercise the instance and test it  to your hearts content without incurring any of the expense associated with your “regular” implementation.  If you need to add additional tests, you can simply tell the mock class what the new input and outputs are, and then run the appropriate tests.

Ensuring Code Is (or Is Not) Called

When writing tests, there may be times when you want to ensure that a given method is called with a frequency that you want to specify.  Thus, you can write things like:

  CCMock.Setup.Expect.AtLeastOnce.When.IsCreditCardValid(ValidCard);

  // Ensure that the tests never call this.  It costs $500!!
  CCMock.Setup.Expect.Never.When.DoNotCallThisEver;

And then, when all the test are run, call:

CCMock.Verify;

on the mock object, and it will validate that the calls that you required were indeed called. 

So, in the above example, if I were to call:

CCMock.Instance.DoNotCallThisEver;

I would get the following dialog:

image

…which of course tells me that I called a method in my tests that should not have ever been called.

There are also methods on the call to Expect interface that ensure that a certain call is made a minimum or maximum number of times, between a specified  number of times, at least or at most a certain number of times, and as we saw, even never.  Also, you can specify that one method be called before or after other methods.  This enables you to dictate exactly how your object methods are called, and what should or should not happen when you run your tests.

Conclusion

So the Delphi Mock library is a very powerful tool for making it easy to write concise unit tests that don’t connect to “expensive” classes that could make testing difficult.  The goal of writing testable code is a worthy one, and Delphi Mocks definitely can make it easier to reach that goal.



Getting Giddy #4 Fixed

clock July 10, 2011 20:52 by author Nick |

Okay, so I was getting all these emails about the fourth article in my “Getting Giddy” series of articles.  You guys kept saying it was missing and I kept saying “Hey, it’s right here!”.  And then finally I noticed – #4 and #5 were identical.  I must have done something stupid somewhere.  Well, I was able to track down the original article on my hard drive and restore it.  So now, the fourth article is as it should be, and all seems well with the universe.

Sorry for the confusion, and I appreciate the interest that these articles have generated.



Getting Giddy with Dependency Injection and Delphi Spring #3 – Writing Testable Code

clock June 5, 2011 22:05 by author Nick |

Okay, so in Part #2 we talked about the Law of Demeter, and how you should think about it and follow it as if it were the Word of God when building classes. 

One of the main reasons to follow the Law of Demeter is to write code and code modules that are loosely coupled.  Loosely coupled modules have minimal interactions with other modules and thus have minimal affect on those other modules.   Change something in a loosely coupled module and the chances of breaking something in another module are slim.  If you have a minimal connection to another module, then you can only cause minimal bugs in that module.

And “minimal bugs” is a phrase to warm the heart of us all, no? 

But the Law of Demeter even goes farther than that.  Using the LOD principles means that you can write “testable code”.

So I think we’d all agree that  the best way to avoid bugs in your application is to never check them in to your source control system in the first place. (And you are using a source control system, aren’t you?)  And the best way to do that is to write lots and lots of unit tests.  Unit tests are the first line of defense against bugs, as they can root out problems in your code as you write them.  They can discover trouble at the very lowest level before it becomes a system level problem.  Writing unit tests is the profound and solemn duty of every software developer.  If you do “true” test-driven development, you’ll write your test first so that the bugs never even show up at all as you write your code to make your tests pass. 

But when it comes to writing unit tests, a common refrain I hear is “I can’t test my code” or “My code is too complicated to test.”  And my response to that is this:

If your code can’t be easily unit tested, you’re doing it wrong.

In fact, this is kind of getting to be our mantra around here at Gateway Ticketing.

Now there are exceptions, of course, such as code for directly manipulating your GUI, etc. But if you are writing anything other than that -- i.e. the vast majority of the code you do write -- then you should be writing code that is testable.  But I’ll make the point again – if you can’t write unit tests for your code, then you need to change the way you are writing your code.   That is, you should be writing code that is “testable”.

Code that is “testable” has a number of familiar qualities.  The most noticeable of those is – surprise! – code that adheres to the Law of Demeter.  LOD code is easy to test because the classes you write stand alone and have limited dependencies.  Code with limited dependencies is easy to test.

A common refrain is this – “My code isn’t testable because it hooks up to too many other things like a database or a scanner or some other thing that can’t be attached to the test suite”.  And my answer to this is:  change your code to remove those dependencies and write mock objects for the instances that you can’t.

Code that is hard to test has dependencies.  Creating an instance of a given class can result in the creating of a host of other classes – even classes that you don’t know about or can’t foresee.  As noted above, heavily coupled code creates these dependencies. Consider the diagram below:

image

Here, you have a class that you want to test, but when you create it, it creates, in turn, three other classes that then  can create yet more classes, including dependencies on external devices and other systems.  Such classes are hard to test, because testing them brings in all those dependencies. 

What we need is a way to limit and even remove those dependencies in order to make a class easily testable.  And the way you do that is to find the “seam” in your class.  The seam is the point where the dependencies are “attached” to the class to be tested.  Once you find that “seam”, you can reduce and/or eliminate those dependencies.  In the diagram below, the Class Under Test is made more testable by creating classes that don’t create dependencies – a better designed class that itself uses the LOD, a “stub” class that does nothing (say, a logging class that actually doesn’t log anything) or a Mock class that merely pretends to be the external dependency without actually being the external dependency. 

image

Creating classes for which you can find this “seam” and substitute classes that don’t create the dependencies is key to creating a “testable” class.  Remember, it is hard to introduce bugs into systems that are made of up easy-to-test classes.  So, we should write easy to test classes, right?

The critical thing to remember here is that the class need not completely avoid the dependency – at some point your code is going to have to connect up and talk to that Oscillation Over-thruster – but rather your classes should be able to limit those dependencies as much as possible, and where they can’t, they should be easily able to “fake” having the dependency so the class can be tested without the real dependency.

And just how will that be done? You’ll have to tune in for the next episode!



Flotsam and Jetsam #20

clock January 14, 2011 05:25 by author Nick |
  • My Dad got me this clock for Christmas and I now have it hanging on my wall at the office here at the World-wide Headquarters of Gateway Ticketing.  It is definitely an eye catcher and a conversation starter.  I was able to figure out some of the numbers (12, 6, 7, 8, and 11), but the rest I had to get from a blog post that explains them all. 
  • I happy and honored to say that the Delphi Feed for my blog is now part of DelphiFeeds. Hopefully this will mean that these amazing pearls of wisdom will benefit a broader audience than just you fine people.
  • We here at Gateway are in the process of migrating to Mercurial for our source control (I’ve probably mentioned that before….) and we are considering using bitbucket.org to host our repository.  Thus, I’ve created a small Delphi project there called DelphiClean. It’s not much right now, but it is serving the purpose of letting me see how things work on BitBucket.  I will update it in the future, particularly with the ability to provide a custom list of extensions to be “cleaned”.
  • Now that Delphi has cool language features like Generics and Anonymous Methods, there is a lot of very cool code being written. Combine that with the ease of sharing code on places like GoogleCode, BitBucket, SourceForge, etc., and it ‘s a pretty cool time to be a developer.  The indefatigable Alex Ciobanu is a guy who is producing some amazing code.  Alex create the DeHL project, and now he’s created out of that a project called Collections.  Well worth a look.  The fun part is that Alex creates a full suite of unit tests for his code, so you can use it with confidence, and if you find a bug, you can write a failing unit test for him, and he can fix it, incorporate the now passing test, and we’ll all know if that bug appears again.  (There’s my daily pitch for unit testing….) In any event, Alex’s code is quite remarkable, and he’s a valuable member of the Delphi RTL team.  Here’s hoping some of this great code finds its way into the RTL.
  • Danny Magin posts about the Developer Solutions Conference.  I wish I could go – alas, duty calls – but you can. (I’m particularly interested in the Android development stuff.  Alas)  Plus, it’s in Vegas, baby!


Even More Changes to HTMLWriter

clock January 9, 2011 14:19 by author Nick |

Okay, so if you are actually using THTMLWriter, I’m sorry – but I made another pretty major change to it, one that will require you to again make changes to any existing code that you have.  Such are the perils of using pre-1.0 software I suppose.

These changes are made at the suggestion of a number of you fine people, and I’m grateful for your wisdom and for taking the time to critique my work and make such good suggestions. 

Interface Only Access

If you have an interface you want people to use, then you should provide a way for them to use it.  In fact, the really cool thing to do is to make it so that it is the only way to do it.  One iron-clad rule of interfaces is that you should never mix interfaces and instances of the classes that implement them.  The interface is the important thing, not how the interface is implemented. 

An interface is a “promise” of a specific service, and a consumer of an interface shouldn’t care about the implementation details of an interface.  Indeed, that is one of the main advantages of interfaces – that you can “switch out” what you use to actually implement the interface.  If one of you guys things my implementation sucks and want to create a new one, you can simply create a class that implements IHTMLWriter and use that instead without changing any of the code that you have using IHTMLWriter.

So What Did I Do This Time?

Okay, so here’s what I did.

  • I created three standalone functions that return a reference to the IHTMLWriter interface.  They correspond to the three constructors that are included in the THTMLWriterclass.  This is the only way to “get at” the IHTMLWriter interface. 
  • I “hid” the entire THTMLWriterclass in the implementation section of the uHTMLWriter.pas unit.  Now, you can’t even get at the class even if you wanted to.  You must deal exclusively with the interface. 
  • I put the two interfaces I created – IHTMLWriter and ILoadSave -- in their own units.  This way, they aren’t coupled together and can be used separately if desired. 
  • I put all the /// comments in the interface unit instead of on the class. 
  • I had to make changes to the tests to support the new way of grabbing an interface reference.  I made the names of the functions similar enough to the code you current have that it will just be a matter of deleting a few characters.  Of course, all the tests still pass.

What’s Left?

I have a few more things to implement – mostly support for some less common tags that go in specific places inside a <table> tag.  After I do that, I think then I’ll declare THTMLWriter to be an official 1.0 release.



Update on THTMLWriter

clock January 6, 2011 12:56 by author Nick |

I’ve made a fairly significant change to THTMLWriter.  (Even if you aren’t a use of THTMLWriter, please keep reading, there’s a valuable lesson at the end.)

What Did I Do?

I created an interface – IHTMLWriter – which simply lists the public interface of the class – and then had THTMLWriter implement that interface.  Not a big deal.  The big deal is that now the Fluent Interface is done with the IHTMLWriter interface instead of the class itself.  This shouldn’t be a big deal if you are using the class – you merely need to change the variable declaration to IHTMLWriter, and remove any code that destroys/frees the class you may have created. 

Why did I do this?  Well, I have to confess that it was partly because I could.  But I also think that in general, interfaces are better to deal with, particularly with the fluent interface.  I’ve noticed that interfaces appear to be the typical way that such things are implemented.  In addition, an interface limits the scope available to the consumer of a class.  If  you can only use a class via the interface, I as the developer can decouple the implementation from the interface – something that is always good. Plus, if one of you fine people feels like there is a better way to crank out HTML, now you can do it, too, using the same interface. 

The Valuable Lesson

Here’s the part that you all need to read:  I was able to make this rather large change with a lot of confidence because I had a pretty extensive set of unit tests to back me up. 

The initial change – creating the IHTMLWriter interface and changing the class to implement and use it – broke everything.  No test would pass, and the test program did nothing but raise access violations.  So, of course, I went to work and fixed things up.  I had to change a little architecture, alter the way a few things were done, and generally fix things up. 

All of my debugging was done on the test project.  It provided a perfect, simple reproduction of the bugs.  The unit tests enabled me to easily step through simple examples and find the places where the bugs were and where things weren’t working right.  And eventually the tests all “turned green”. 

GoingGreen

And let me tell you, turning green is sweet!  First, it feels really good. I kept running the tests and watching that little green bar slide across because it felt great.  Why did it feel great?  Because I knew that my changes were complete and  because I had confidence that things were all working as they were supposed to.   The only way that was possible was because of the existence of the unit tests.  Without them, I’d never really ever be sure that things were back to normal and working.

Time Well Spent

So the unit tests allowed me to forge ahead with confidence, provided me with a useful and powerful vehicle for testing and debugging my changes, ensured that I would know when I was done, and enabled me to prove that things were working as they should – all while making a fairly substantial change to a fairly complex code library. 

And some people say they don’t have the time to write unit tests.  I say you don’t have the time not to.