On 27/11/2010 11:01, Frank Church wrote:


On 26 November 2010 20:55, Martin <[email protected] <mailto:[email protected]>> wrote:

    On 26/11/2010 19:56, Frank Church wrote:


        One thing that has always gottem to me when using Delphi and
        now Lazarus is the tedious edit, compile, debug cycle. It has
        been growing worse of late that now I am beginning to dread
        the whole process any time I have to make some changes,
        especially when they are just minor GUI changes.

    ....


        Quite simply I am thinking of a way to create the application
        in parts, so that the parts containing the new functionality
        can be developed separately as standalone programs, perhaps
        even console programs.

        This raises the question of how procedure parameters and
        results can be passed, and these are the options that have
        initially come to mind.

        1. Find a way to automatically translate simple variables,
        record structures, or objects into text and pass them via the
        command line or pipes. Perhaps JSON, XML or simple name-value
        pairs can be used here. Designing the parameters as
        TPersistent objects that are streamed into text form may be a
        better option here.

        2. Rather than using the command line, make them network
        services and pass the parameters that way, or may make them
        RESTful/XML-RPC  with all the new webby stuff( I am getting
        into some of that stuff now)

        3. Design them as DLLs initially - I suspect that will bring
        along a different set of problems.

        Once they are well tested I can incorporate them into the main
        executables.


    Yes splitting your project into parts is a good idea. Quite simple
    use packages.

    Then you still have one application, you still can pass data
    around in the normal pascal way.

    Each package can be tested with a small simple runner application,
    or even better a fully automated testcase.
    Testcase are especially useful, if you can extract the functional
    layer from the visual layer.

    So instead of writing something big into
    TForm.SaveDocumentButtonClick, you just have "TheDocument.Save" in
    there
     => all functionality goes into a none visual object TheDocument
    (or whatever it is in your case).
    - this object takes instruction, if the user clicks something
    - it can be asked what to display.
    - it can be given callbacks, if it requires to notify the visual
    layer.
     for example it can have "OnTitleChange" => which is linked to a
    method changing the forms Caption (Title)
    ....

    Martin


    --



Thanks for the reply, Martin.

Are there some code examples which use this approach, especially the package based one?

I don't know of any examples, but I guess there must be.
It's the same as what Michael Van Canneyt said: "separate the business and gui logic". (you can google this phrase)

In the simplest case:
create a new class (in it's own package) that reflects your form, that has a method for every method that currently exists in your form. Then move all the code (and remove all reference to the form itself). All values are transferred to begin with, all actions applied at the end, or by callback. Of course such a separation will have much better results if you refactor the code more than just copy it in a new class.


Will it also reduce the size of the debugging exe or speed up its creation?

The Size stays the same, therefore also the speed.
But that doesn't matter, because you will create this exe far less often. (could be up to 90% less often)

Let me give you an example. I work on SynEdit.

If I changed something then in order to test it I had to rebuild SynEdit and the IDE. And as you know you need to test often before everything works fine. So I had to rebuild very very often, that has a big impact.
SynEdit already was a package. So I was spared the step of creating one.

I created a test case though. It's still very small, but it helps. If I change something, I run t in the testcase. So all I do is rebuild the package SynEdit (that will only rebuild the files I changed, so I compile 3 or 4 files on average). And compile the testcase. that is a very small and simple application, and is done very very fast too.

I could have just thrown a SynEdit on an empty form and compile this. That would be as fast as the testcase. Then I could try out every feature by hand. But as the amount of features grow (and as each can break on every change), I would have to test more and more scenarios. Doing so by hand is increasingly time consuming.

The testcase does it fully automated. It does not only test the new feature, it alerts me if I break another one.

The GUI itself, the visual interaction, te mouseclick, and canvas drawing, are things that are hard to test in automated testcase (possible but harder).

But what I test, is that the data on which all those actions are done, is correctly calculated, and provided. And that reduces the amount of work I have to do on those GUI/frontend code.


Sometimes I see only one file compiled, then it goes to the linking phase, but it doesn't seem to reduce the exe size or the speed of its creation.

See above. the size of the final exe and the compilation time for that does not matter.

If I change SynEdit, I use the testcase. I may have to recompile th 3 or 4 units affected by my change several dozend times, and rebuild the testcase (another handful units that are recompiled). But thats about one dozend unts, and one small test app. The big IDE I build maybe 2 or 3 times, wher as without the testcase I would have build it several dozen times.

The trick is to find code that can be tested easily, and to extract it into it's on package, and classes.

Martin


--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to