[Aiml-programr-developers] Tests and Architecture
Nicholas H.Tollervey
ntoll at ntoll.org
Mon Sep 17 04:07:00 EDT 2007
Guys,
See comments inline... :-)
mauro at cicio.org wrote:
> Hi,
>
> =================
> This is a very long mail, a lot of topics...
> Here you find an afterward written "resume".
>
> I think it was very useful what Nicholas wrote, it points out that
> what he has in mind is not only what the original pR wanted to be (a
> simple request/answer library) but a BOT framework AIML enabled.
>
> I like the idea and I think it is a good and natural evolution of pR.
> Still, they are two separate things:
> - a pure AIML answerer
> - a framework (in large part AIML independent).
>
> I sign in to support both.
> By far, my skills and interests are more in the framework area than in
> the AIML one.
> I think it essential to keep the two parts as distinct as possible.
> Now it is your turn to shoot on all what I said.
>
Totally agree, I also think that AIML answerer should come first before
the framework (but that we should have the framework in mind when
developing the answerer).
> I would suggest to split the answers to this mail: let's open 1 thread
> per topic!
>
Agreed... In future I'll make sure my emails are more specific.
> =================
> here I try to answer to the not yet covered points of
> Nicholas' mail.
>
>
>> We're writing a library and as a result I'll define two sets of tests:
>>
>> * UAT - that define the expected behaviour of the classes that we expect
>> other developers to have to use to write their applications
>> * Unit Tests - that additionally encompass the expected behaviour of the
>> wider classes / methods / areas of the library that we hope other
>> developers will not have to use.
>>
>
> Right. BTW, it looks to me like that the public interface of pR is
> gonna be very simple (there are not too many things a BOT can do...).
> Probably we will have something _like_
> - configure
> - start
> - stop
> - answer(challenge)
>
> Probably a TestFacade would do...
>
>
Yes, totally agree... TestFacade is a good way of describing what I was
calling UAT. I'll use TestFacade from now on.
>> As a result I'll do two things:
>>
>> 1. Specify our "public" classes that third party developers should use
>> to implement our library by means of example "use" cases written in code
>>
>
> "implement our library"
> I assume this is a typo and you meant "use our library". If not, I
> need more explanation.
>
My lazy English / colloquialism - I meant what you assumed. Obviously
third parties use our library - we're going to implement it...
>
>> 2. Define the architecture behind these public classes so we can start
>> to write unit tests.
>>
>
> I have difficulties to match the strategy you suggest with the
> previously discussed one. We just wanted to
>
> - see what pR is not yet doing
> - show it with tests
> - fix/add/refactorize until the program reaches the point we want.
>
> If our goal is still this, the natural steps are:
> - have a full set of challenge/responses testing the program Facade
> (i.e. not caring about the program internals, i.e. black box testing)
> - fix/add/refactorize
> - _along_ the process write UnitTests
>
> New UnitTests will be developed as
> - new Units (classes or small set of classes) are necessary
> - existing Units without existing test are to be modified
>
> Defining the UnitTests in advance means having a strong commitment in
> the early phase on the architectural/design decisions. It is possible,
> but has little to do with TestFirst strategy.
>
> As said: it might well be that your intention matches with what I just
> wrote and I just missed your point.
>
>
>> It is important to remember that I intend to unit test as locally to the
>> implementation of a method / class as possible.
>>
>
> We agree here, of course.o
>
Mauro, I share your concerns about prematurely writing unit tests - we
need to stay as flexible as possible. What I had in mind was the
TestFacade mentioned earlier along with unit tests for *ONLY* those
known internals specified by the AIML standard - specifically tag
handlers and the Graphmaster algorithm. As we're testing locally it
would not be appropriate to place them as part of the test facade.
Also, I think my enthusiasm for my web->bot analogy was getting the
better of me at this point :-). Obviously we should follow our original
plan as stated above, I was definitely thinking of a framework at this
point in my email - something that can wait until the AIML responder is
sorted out.
<snip/>
> The _smallest possible library_ that could be useful to a third party
> is one offering:
>
> @bot = Bot.new
> @bot.configure('aiml_set')
> response = @bot.respond_to(request)
>
> where request.class == response.class == String
>
> When you talk about Request, Response, Conversation, User of course
> you are mixing in much more in the game.
>
> I believe that we need to have all of those, but that the library must
> be modular enough to let the user to the most elementary thing I wrote
> above.
> Do we agree on this?
>
Most definitely, the additional classes *might* be appropriate in a
larger framework but I definitely subscribe to Einstein's "as simple as
possible and no simpler" ethos and agree that the responder should be
developed in this way. However, I think you missed something out of your
example above:
@bot = Bot.new
@bot.configure('aiml_set')
response = @bot.respond_to(request, user_predicate_hash)
Where (I agree that) request.class == response.class = String and
user_predicate_hash.class == Hash
<snip/>
>> I'll UMLify these relationships when I get some time later this week.
>>
>
> Not necessary for me. If also Ben is clear with the relations between
> Bot/User/Conversation/Req/Res you can save the UML time.
> It might be more direct to use small prototypes (like the one I sent before).
> We can UML the key aspects later, once we all agree on the parts
> naming and on the prog aspects.
> Of course if you feel more comfortable UMLing int, it wouldn't harm
> sharing the result :-)
>
>
No need to create work for ourselves then. I'll skip the UML.
<snip/>
> ----------------------------------------------------
> I cut the long story short and introduce my_both (instead of myBot).
> If any of you want the long story, just ask.
> ----------------------------------------------------
>
> It is probably a good idea to have
> my_both.configure(aiml_set)
> or even
> my_both.configure(configuration)
> where
> configuration = Configurator.new(:aiml_sets => [...], :master =>
> '...', :name =>'...')
>
> In this way it is easy to have the hot configuration.
> This technique is used - among others - with chess engines: they do
> not load all the info set as the game begins, but they load the
> modules as they are necessary. If there are only Kings Rooks and Pawns
> left, the RooksEndgames is loaded.
> We can think to use the same: e.g. if the user talks of food, we load
> the 'recipies.aiml'.
>
>
Hmmm... I like the idea of hot configuration but I'm not sure your
example quite works in a circular sort of a way: if the user talks of
food then we need to load recipes.aiml, but to identify that the user is
talking about food the recipes.aiml needs to be loaded already. Or
perhaps you mean that AIML files should be organised by "topic" and when
a topic is set by a template the appropriate file is loaded? Not sure
how you see this working, but I like the idea!
>> # Attributes might include
>> myBot.Name # name of the bot
>> myBot.Botmaster # who the bot-master is
>> myBot.Size # number of categories in the graphmaster
>>
>
> all right. The notation is my_bot.name.
>
>
Actually, I'm having second thoughts on this. IIRC the AIML standard
states each bot should have its own predicate hash. Why not just have:
my_bot.predicates[:name]
my_bot.predicates[:botmaster]
etc... (keeping things simple and flexible here)
>> # loading AIML
>> myBot.Learn(SomeRawAIML) # well formed obviously
>> myBot.Load("pathToAIMLFile(s)") # if an individual AIML file is
>> specified the file is loaded, if a directory all AIML files within it.
>>
>
> Fine, this answers (for the aiml part at least) to my point about hot
> configuration.
> BTW: the current pR should already act like that.
>
>
The <learn/> tag in the AIML specification already defines this behaviour.
> Probably we want to have
> PR::User.new
> PR::User.new(:config => 'userconfig.yaml')
> PR::User.save
> PR::User.find(id)
>
> In this way we offer a Active::Record compliant PR::User.
> In order not to introduce unwanted dependencies, we could use a
> transient DB (marshal or YAML based).
>
> I keep it short because this mail is already pretty long. Probably we
> can depthen the topic.
>
>
Totally agree, I think we should make things, where appropriate,
Active::Record compliant for ease of use and familiarity. Although I
suspect this is more to do with the framework rather than AIML responder
which (as I pointed out above) only requires a user's predicate hash to
work.
>> # Conversation:
>>
>> c = Conversation.new(myUser, myBot) # create a new conversation session
>> with the specified user and bot
>>
>
> Maybe not strictly necessary. The bot and the bot configuration might
> depend on the User. It might be enough to have c =
> Conversation.new(my_user)
>
>
Again, something to be left for the framework. I passed both the user
and the bot to the constructor as it seemed natural to think of a
conversation between two entities, although I think you are correct in
that it isn't necessary.
>
> It might be better to call it Session. It is so spontaneous...
>
>
Actually, I was having second thoughts about this too. "Session" is a
term that is clearly understood and defined within a client/server
context so we should use it.
>> Comments and suggestions would be most welcome. :-)
>>
>
> Done! :-)
>
:-)
> Your turn to shoot!
>
> Mauro
>
>
More information about the Aiml-programr-developers
mailing list