Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 12 total
Thread Best Startup approach
Thu, May 10 2007 2:21 PMPermanent Link

Mark C
Is there a correct or efficient way of starting an applications session/database/tables reagrding opened or closed.

At design-time compile is it best to have everything in-active and then on the main application formCreate, activate session / database then...

1. open ALL the tables and leave open throughout system until application terminates
2. Have NO tables open, but open them use them THEN close them.
3. Or any other methods.

The application I am using is a 5 user works order system using one main form that drives all other input forms
All my datasets and session/database componets are in one datamodule.

Just was hoping for some BEST PRACTICE advice.

Regards
Mark.
Fri, May 11 2007 1:08 AMPermanent Link

Dave M
Mark C wrote:
> Just was hoping for some BEST PRACTICE advice.

At the risk of sounding like a wise guy, it might be a little after the fact to ask for
best practice.Smiley

It seems to me that your questions stem from treating data as global and once your data is
no longer treated as global, your questions are answered.

If you are using datamodules (which OOP wise aren't really best practice anyway), you can
first design what you want. Then remove the var declaration (and remove from the
autocreate list) and create in code. You can have the form, (which is removed from the
autocreate list and created in code) create the datamodule in code. For instance, the
customer form creates a customer datamodule, which could create job datamodules, etc. Only
the form or creating datamodule can access a datamodule, since all var declarations are
removed. (This also allows the creation, for instance, of many customer or job windows.)

If you actually mean just one unit for the whole app, keeping everything in one datamodule
or unit means the unit could eventually become thousands or tens of thousands of lines.
Each time you edit something, how do you know you haven't broken something else? I have
many times done so. It's true you can start off an app this way, but you may eventually
have to rip it apart and do it over, if it gets big enough.

Also, depending on the complexity of your app, globally accessible vars may end up making
some other problems. For instance, you may end up assuming a table is on one record one
place and on on another elsewhere. (Yes, I have done this and it makes for hard to find
bugs and an undependable app.)

This approach means when all forms (other than the main) are closed, all tables are closed.

BTW, you can put your database and session in one globally available unit and have various
datamodules use it.

Dave M
Fri, May 11 2007 2:44 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Mark

>Is there a correct or efficient way of starting an applications session/database/tables reagrding opened or closed.

No Smiley

>At design-time compile is it best to have everything in-active and then on the main application formCreate, activate session / database then...

Its best to have all tables, sessions, databases etc closed before you compile - this prevents some potential problems.

>1. open ALL the tables and leave open throughout system until application terminates

That's how one of my apps works. The only problem is the time taken to open all the tables.

>2. Have NO tables open, but open them use them THEN close them.
>3. Or any other methods.

I would go with open when needed and leave open until the app closes. The overhead is low and its probably the most efficient. The only potential danger is corruption if a pc crashes with the tables open and before the OS has written stuff to disk, but with DBISAM I've very rarely encountered this..

Roy Lambert
Fri, May 11 2007 3:34 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Dave

>If you are using datamodules (which OOP wise aren't really best practice anyway), you can
>first design what you want. Then remove the var declaration (and remove from the
>autocreate list) and create in code. You can have the form, (which is removed from the
>autocreate list and created in code) create the datamodule in code. For instance, the
>customer form creates a customer datamodule, which could create job datamodules, etc. Only
>the form or creating datamodule can access a datamodule, since all var declarations are
>removed. (This also allows the creation, for instance, of many customer or job windows.)

I leave the var declaration in, have the datamodule autocreated BUT with all the tables closed. There is a public procedure which I call from my main form to open the tables. Apart from the time spent opening tables it works very well and hasn't yet caused a problem.


>If you actually mean just one unit for the whole app, keeping everything in one datamodule
>or unit means the unit could eventually become thousands or tens of thousands of lines.

Many of which will be simple table or field declarations unless there are some very complex business rules which have to live in the datamodule. I don't know about others but the vast (and I do mean vast) majority of my code deals with user interaction and is distributed over the forms in the app that the user works with, there are some generic procedures that are called from several apps which live in various units. I've just had a look in one app. The data module is 2259 lines but the declarations are 1207 lines.


>Each time you edit something, how do you know you haven't broken something else? I have
>many times done so.

Same applies where ever the code lives.

I>Also, depending on the complexity of your app, globally accessible vars may end up making
>some other problems. For instance, you may end up assuming a table is on one record one
>place and on on another elsewhere. (Yes, I have done this and it makes for hard to find
>bugs and an undependable app.)

But there's nothing to prevent several instances of a table on a datamodule. Also,depending on the design of the app it can be far better to have just one instance of the table and manage the cursor, especially if you define the fields in the ide and use the persistent variables rather than fieldbyname to access them.

Roy Lambert


Fri, May 11 2007 10:25 AMPermanent Link

Mark C
Thanks For your comments.
Fri, May 11 2007 8:48 PMPermanent Link

Dave M
Roy Lambert  wrote:

>it works very well and hasn't yet caused a problem.

The question I tried to answer was about best practice. There exists lots of ways of doing
things that may not create problems for some and are also not best practice.  I tried to
answer working within the existing Delphi datamodule framework, which itself is not best
practice. Therefore my answer also isn't best practice. So I guess if someone is going to
use datamodules, it is a matter of how close one wants to get to best practice in a
framework that isn't engineered for best practice.

>The data module is 2259 lines but the declarations are 1207 lines.

I would call that size hard to manage. I have a number of files that size and larger and I
don't even like to open them.  If it is big, it's hard to follow. It then involves
retesting pretty much everything in the file, especially if you have set properties in the
designer. Basically, you may end up with a situation where you are never sure if things
that you have already debugged work. Of course if all testing is completely automated and
thorough, then no problem, sort of.

>>Each time you edit something, how do you know you haven't broken something else?

>Same applies where ever the code lives.

Generally not true, because when organized correctly, very seldom will you be editing all
of the code. Isn't this is one of the reasons for organizing debugged routines in
libraries and removing them from source code, so as to provide for some kind of reliable
version? The issue here is reducing complexity of code maintenance by removing as much
code as possible from a given editing cycle or event.

>But there's nothing to prevent several instances of a table on a datamodule.

This reminds me of having repeating data in a tuple, sometimes it works, sometimes it
comes back to haunt you. In some situations, no problem. The way I recommended, you can
for instance have 1 job or 100. You can use the datamodule (or an ancestor) for lookup,
display, or data entry. No side effects, other than normal multiple user issues. On the
other hand, for a simple app, it can be overkill.

>Also,depending on the design of the app it can be far better to have just one instance of
the table and manage the cursor, especially if you define the fields in the ide and use
the persistent variables rather than fieldbyname to access them.

Isn't the need to manage the cursor the result of an undesirable side effect? I used to do
this with Clipper years ago. At the time, it always seemed wrong or lacking, and that
there should have been a better way.

The whole persistent variable/fieldbyname issue is part of the problems with Delphi's
native code database access. It should have been changed years ago to allow binding to
objects. That would be much better than what I suggested. As it is, the whole datamodule
implementation breaks encapsulation.

Years ago I had questions like what the OP had. It seems to me that the questions are a
symptom of an antiquated design and that these questions will resolve once the design is
updated.


Dave M


Sat, May 12 2007 3:55 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Dave

>The question I tried to answer was about best practice.

Often that's a matter of opinion

>I tried to
>answer working within the existing Delphi datamodule framework, which itself is not best
>practice.

I'm always willing to learn - why isn't it best practice?

>>The data module is 2259 lines but the declarations are 1207 lines.
>
>I would call that size hard to manage.

I wouldn't <vbg>

>>Same applies where ever the code lives.
>
>Generally not true, because when organized correctly, very seldom will you be editing all
>of the code. Isn't this is one of the reasons for organizing debugged routines in
>libraries and removing them from source code, so as to provide for some kind of reliable
>version? The issue here is reducing complexity of code maintenance by removing as much
>code as possible from a given editing cycle or event.

That one reads to me like total gibberish. Maybe we're talking at cross purposes. I don't have any procedures that are 1000 lines long. If I'm editing a simple standalone procedure in a unit no matter how large the unit is why should it have any impact on other procedures or fuctions eg

procedure TDM.CompaniesNewRecord(DataSet: TDataSet);
begin
Companies_Turnover.Value := '?';
Companies_Staffing.Value := '?';
Companies_Created.AsDateTime := Date;
end;

This is going to impact the companies table, and will do so even if I put it in a unit all its own. More importantly it will impact the companies table wherever its used. I don't want to have to stick it on every form. Editing it is rather unlikely to affect any other code don't you think even though the unit is 2259 lines long?

>>But there's nothing to prevent several instances of a table on a datamodule.
>
>This reminds me of having repeating data in a tuple, sometimes it works, sometimes it
>comes back to haunt you.

We obviously program in different styles it certainly doesn't haunt me - a whip and a chair are all you need to tame it Smiley


>Isn't the need to manage the cursor the result of an undesirable side effect? I used to do
>this with Clipper years ago. At the time, it always seemed wrong or lacking, and that
>there should have been a better way.

I would say that all you're doing is an alternative way of managing the cursor. I (in some apps) use a single table, you're using multiple tables. Using a single table is a bit more tricky, but for an app that started life under Paradox & W95 I had to use every trick I could to keep the number of file handles in use down. As I change it for ElevateDB I'm altering the architecture to some degree.

>The whole persistent variable/fieldbyname issue is part of the problems with Delphi's
>native code database access.

Don't see that please educate me.


>Years ago I had questions like what the OP had. It seems to me that the questions are a
>symptom of an antiquated design and that these questions will resolve once the design is
>updated.

Just cos its newer don't mean its better! I have major issues with coding and development practices that require ever more CPU and RAM just to work at an acceptable speed.

Roy Lambert
Sat, May 12 2007 7:56 AMPermanent Link

Dave M
Roy Lambert wrote:

>Often that's a matter of opinion
>I'm always willing to learn - why isn't it best practice?

Unfortunately you'll have to read to the end of this post.

>That one reads to me like total gibberish. Maybe we're talking at cross purposes. I don't
have any
>procedures that are 1000 lines long. If I'm editing a simple standalone procedure in a
unit no matter
>how large the unit is why should it have any impact on other procedures or fuctions eg

Ideally it wouldn't but...first of all, we were talking about Delphi datamodules. This
includes the visual designer which is subject to accidental changes (not to mention bugs).
Have you ever accidentally deleted events from a table when editing? Haven't you ever
introduced bugs by global search and replace? Unless you check differences in the pas and
dfm, you can't be sure of what is changed. The more things in the file, the more things
called into question. Again, this is one of the reasons code is place in a library. Code I
don't have access to (or haven't accessed),  I can't mess up. How is this gibberish?    

>procedure TDM.CompaniesNewRecord(DataSet: TDataSet);
>begin
>Companies_Turnover.Value := '?';
>Companies_Staffing.Value := '?';
>Companies_Created.AsDateTime := Date;
>end;

>This is going to impact the companies table, and will do so even if I put it in a unit
all its own. More
>importantly it will impact the companies table wherever its used. I don't want to have to
stick it on
>every form.

Your above comments and related code look to me like an illustration of the effects of
passing around global data. It's also one of the same problems that datamodules have.
Wouldn't it be better to have the company create its own new record? That might lead to a
company object and would cause you to bump up against a native Delphi “data access issue”,
specifically, how do you bind your objects to controls? It's either directly binding to
datasets (and bypassing the objects), doing it manually, or coming up with a workaround.  

>We obviously program in different styles

Maybe, but I have lots of “less than best practice” code of the type I have criticized.
Right now I am considering rewriting some of it. Part of Delphi's native code database
access architecture doesn't lend itself to easily writing good OO code. Maybe a year ago,
I read somewhere that changes in data binding were planned for vcl.net in Highlander. I
had hoped that it might also end up in native, but I'm not too sure it will.

>Don't see that please educate me.

See above. It's all part of the “how do you bind controls if you want to build business
objects problem.” Also, how about the inability to maintain a clear delineation between
UI, business objects, and data access? Having Tfields/fieldbyname show up in your forms
doesn't help with this. These issues have been written about many times over the years.

Maybe you don't see a need for what I have discussed. These issues have become more
prominent as the code I am maintaining has gotten larger and harder to maintain.

Dave M
Sat, May 12 2007 8:23 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Dave

>Unfortunately you'll have to read to the end of this post.

Nothing unfortunate about it - just a fact of life - and I did.

>Ideally it wouldn't but...first of all, we were talking about Delphi datamodules. This
>includes the visual designer which is subject to accidental changes (not to mention bugs).
>Have you ever accidentally deleted events from a table when editing? Haven't you ever
>introduced bugs by global search and replace?

OK I see where you're coming from now. I first learnt (the hard way) about global search and replace when programming in APL back around 1978 and also learnt that its not a two way street.

>Your above comments and related code look to me like an illustration of the effects of
>passing around global data. It's also one of the same problems that datamodules have.
>Wouldn't it be better to have the company create its own new record? That might lead to a
>company object and would cause you to bump up against a native Delphi “data access issue”,
>specifically, how do you bind your objects to controls? It's either directly binding to
>datasets (and bypassing the objects), doing it manually, or coming up with a workaround.

This is obviously where we start to differ. I'm sufficiently old school not to care overmuch (I was going to use a stronger expression but this is a public NG and I wouldn't want to embarrass Tim) about the purities of OO. I am as happy, probably happier, writing a function and passing it a few parameters as I am creating a class and altering its properties. I'm old enough to have seen a lot of passing ideas all of which were going to mean bug free and easy to maintain code. In the words of Catweasel "nothing works"

>Maybe, but I have lots of “less than best practice” code of the type

Again I would make the point that this is often a matter of opinion. One thing that seems to have fallen out of favour in judging how good code is is its performance. The attitude now is sling more hardware at it. Someday pure OO will reach an acceptable performance level, databases will move on from flat file or relational to OO. Not sure if I'll be alive to see that though.

>See above. It's all part of the “how do you bind controls if you want to build business
>objects problem.” Also, how about the inability to maintain a clear delineation between
>UI, business objects, and data access? Having Tfields/fieldbyname show up in your forms
>doesn't help with this. These issues have been written about many times over the years.
>
>Maybe you don't see a need for what I have discussed. These issues have become more
>prominent as the code I am maintaining has gotten larger and harder to maintain.

You've guessed right there Smiley However, one thing I've learnt over the years is that code you're happy with is easier to maintain and anyone else's code not matter how well written is a nightmare.

Thanks for sharing your views, but as you can tell no convert Smiley

Roy Lambert
Mon, May 14 2007 5:58 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Dave,

<< Isn't the need to manage the cursor the result of an undesirable side
effect? I used to do this with Clipper years ago. At the time, it always
seemed wrong or lacking, and that there should have been a better way. >>

It depends upon what you mean by "manage the cursor".  If you mean
navigation, searching, etc. then there really isn't any way around that.
Every access to a cursor on any dataset is going to require cursor
management to some degree.  MS has tried to remove this type of access with
respect to .NET and the way that they handle data retrieval, but it is
really counter-intuitive in many ways because it tries to make datasets that
are from a database (and can be quite large) behave like in-memory datasets.
This basically eliminates the ability to ever look at the dataset in its
entirety for any practical purpose without resorting to pagination schemes
that effectively force the end developer to recreate the code that the
client interface layer has managed *for them* for years.  IOW, eliminating
the pagination and scrollable cursor support that ODBC and other standard
CLI access layers have always had in the past didn't get rid of the
requirements for such things, it simply moved the responsibility out of the
hands of the database engine developers and into those with the least amount
of experience in coping with such issues - the application developer.  Now
with .NET the application developer has to come up with all sorts of
pagination schemes to work around the fact that the data access layer does
not provide scrollable cursors.

--
Tim Young
Elevate Software
www.elevatesoft.com

Page 1 of 2Next Page »
Jump to Page:  1 2
Image