What is the purpose of having a DataModule in your project? Does it have any special properties compared to a normal class or module? What are the conventions of what it's usually used for?
A datamodule is a non-visual "form" (container) that can contain non-visual components (usually database components, though any component can be added, such as dialogs and Indy components) that can then be shared by many forms.
This wiki explains further: Delphi Wikki.
It is normally used for Dataset and DataSource objects to keep them in a central location. A DataModule can only contain nonvisual components on it but are not just limited to Data Access components. You could put a TTimer on it and SaveDialog etc...
It can be useful when you have multiple forms, needing to change the code only in one place, instead of every form.
A datamodule differs from a simple class that it can be designed within the form designer and its components can be edited with the object inspector. The datamodule has also a resource that is streamed in a DFM file.
Furthermore a datamodule can be used by other datamodules, forms and frames and then its components are available for selection in the object inspector, too.
In my desktop applications, I usually have one data module containing a bunch of TImageLists. If my applications uses TCP/IP, the components are on a separate data module. Of course almost all of my application's logic goes in different data modules. And, if I need to create a service application, I put my logic in a data module so that I can easily create a desktop application around it for debugging. And, last, but least, I put my data access components on data modules most of the time.
Related
Here is a quick comparison of Delphi components and frames and at the end is my question.
Advantages of Delphi components:
They are encapsulated well. A software that uses components can access only public and published properties of components.
All their inner event handlers are available at parent form's design time.
Disadvantages of Delphi components:
They need to be installed with some package
The package is shared between multiple applications even if the components inside are application-specific
Advantages of Delphi frames:
They could be placed on a form just like components
Their published properties also can be adjusted in a form
They are in-app only and aren't available for the rest of apps which they don't belong to
They are quickly available. No need to install.
Disadvantages of Delphi frames:
All of their inner components are directly available in a parent form. If I move the components from published section, design-time customizations are broken in the frame designer too.
If I override the Resize method in a frame all the arrangements are available at run-time only. No arrangements at design-time are made.
If I introduce a new published property, it is not available in object inspector.
What I would like to have is a symbiotic thing:
Good encapsulation. None of the inner components is available from the parent form, but all their inner components are fully functional either at run-time or at their design-time.
Quick availability. No need to install.
In-app only. No sharing with other apps.
Their published properties can be adjusted in a form
All the method overrides (especially Resize method) are available at design-time.
Could you suggest a thing that fulfills these requirements? Or may be some surprising method to work with frames I didn't know about?
It shouldn't be necessarily a frame or a component. If some of other VCL classes fulfills these requirements, I would gratefully accept it.
If its properties have to be editable in the designer the object has to be a descendant of TComponent. TFrame actually is a descendant of TComponent.
Unfortunately, object inspector seems to use structure information from design-time packages only. Thus, you have to compile a design-time package for your custom published properties to show in object inspector.
But that strikes your requirement of Quick availability.
I am planning to move away from BDE and dBase so, while implementing some application I need to stay away from everything that could make the transition more difficult. I wonder, for instance, if data aware components like TDBCtrlGrid is toot tied in some way to the BDE or not.
Db-aware components like the TDBCtrlGrid, TDBGrid, TDBEdit, etc, should all work fine with more modern TDataSet-descendants than TQuery, TTable, etc. So the answer to your q is that they are all generic.
The whole point of the design of Delphi's db-aware components is that the access model they use is abstracted from any particular dataset implementation and so will work with any TDataSet descendant, because TDataSet itself implements an abstracted data-access model.
Delphi's db-aware components work at two steps removed from TDataSet, and interact with it (or any descendant of it) via TDataSource and TDataLink and its descendants. All data interactions occur via TDataLinks - see the source in DB.Pas.
Short answer is no : TDBCtrlGrid is not tied to the BDE.
TDBCtrlGrid is populated by a "dataset" or, if you prefer, by a TDataSet which is an abstract class providing the basic properties, events, and methods for working with data.
There are many implementations of TDataSet which will allow you to use whatever data base engine you want.
From the doc here are some popular TDataSet implementations :
TCustomADODataSet is the base class for datasets that access their
data using ActiveX Data Objects (ADO). TCustomADODataSet descendants
include TADODataSet, TADOTable, TADOQuery, and TADOStoredProc.
Developers who create custom dataset components that use ADO derive
them from CustomADODataSet.
TIBCustomDataSet is the base class for datasets that directly access
the data in InterBase tables. TIBCustomDataSet descendants include
TIBDataSet, TIBTable, TIBQuery, and TIBStoredProc. Developers who
create custom dataset components that directly access data in an
InterBase database derive from TIBCustomDataSet.
TCustomSQLDataSet is the base class for unidirectional datasets.
Unidirectional datasets are read-only datasets that permit only
forward navigation. TCustomSQLDataSet descendants include the
dbExpress datasets TSQLDataSet, TSQLQuery, TSQLTable, and
TSQLStoredProc. Developers who create custom dataset components that
use dbExpress to access their data derive from TCustomSQLDataSet.
TCustomClientDataSet is the base class for in-memory datasets. Client
datasets can work with data from files on disk or with data provided
by another component via a provider. They cache that data in memory,
maintain a record of any changes in a change log, and apply cached
updates at a later point back to the source of the data. Developers
who create custom datasets that store their data in an in-memory cache
derive from TCustomClientDataSet.
I would investigate several databases including some of the latest in the Delphi version you currently use. That includes Mongo if you have the latest.
For productivity Firedac is quite good. It codes like ADO and performs almost as well as GO.
In general I suggest getting Nick Hodges' book and start using Spring4D.
If that is too deep for you then Firedac is a good starting point.
In Delphi 2010...
I am building a reasonably complex application. There are all kinds of non-visual VCL based components, such as TTable, TQuery, etc. I know I can put Data oriented components into a datamodule, so in design time, they don't show up on my main form. I am looking for a way to "hide" the other non-visual components. I know that I can hide them with GExperts, but as soon as you click on the form, they show up again. I seem to recall that there was a 'Component repository' type of component. You dropped it on your form, and then dropped all you other components into it... Can't find it though.
Is anyone aware of a way to accomplish this?
Thanks
Just put your other non-visual components on the DataModule as well. All non-visual controls can be placed there; it's only the visual (TControl/TWinControl) components that can't be (for obvious reasons - the data module has no visual aspect at runtime).
Note that this is useful even in applications that don't access databases of any sort. You can still create a TDataModule to hold all of your non-visual components like image lists, file open/save dialogs, and so forth.
In a moderately complex database application in Delphi it's easy to have dozens of datasets (tables and queries) and associated datasources on a form.
All these clutter up the screen.
It gets worse when your form has a pagecontrol where every page has its own set of datasources et al.
If the Tables and Datasources were visual controls, at least they would only be visible on the Tabsheet where they're applicable.
I've thought about creating some container object that could hold many datasets and datasources, but never got round to it.
I also have cnPack which adds to option to hide non-visual components from view in the designer.
However this is not helpful because it makes it hard to select them.
What's the solution to unclutter the form designer whilst still having the option to select the data access components?
(For what it's worth I'm working in Delphi 2007 and XE2)
You could create a data module for each logical group of non-visual components. Then name the data module accordingly so you can relate it quickly to the page the components belong to.
www.gexperts.org has a IDE plugin for delphi, which contains an option to hide/show all non-visual controls.
It is perfect for hiding all of the datasets etc so you can manipulate your components. You can then show them again when you need to access them.
To make life even easier you can customize the toolbar so you can hide/show them in a single click.
You can write your own small expert or component (like this one) to hide nonvisual components you need and store them in groups.
I've been using Delphi for a little over a month, but I still do not know the proper way of doing things.
If I have methods which I can use on a lot of projects should I put them on a Unit, Form or DataModule?
I have not used a unit (in itself), New-> Unit. Should I put my utility methods there? If so, is there an example I can look at, a tutorial or whatever.
I've used DataModules in the past, though it gives me the impression that it should only be used when I'm dealing with databases and such.
Another thing, I'm customizing some forms (for instance a form with some TEdits that do specific things).
To use this, first I add this to the uses in the .dpr
CustomizedForm in '\CForm\CustomizedForm.pas' ;
then I add CustomizedForm to the uses in my mainform (where I'll be using it).
Is this the correct way to do it? I'm was just guessing, it seems to work though I'm not particularly confident that it's the proper way.
I put all mine in a unit called utils.pas. It works for me.
If you have different segmentations of utilities that some programs use but not others, you may want to create separate units for them.
Look at: Anatomy of a Delphi Unit
It is part of the excellent Beginner's Guide to Delphi Programming by Zarko Gajic that is very worthwhile to go through.
For the best "visual" introduction, see Nick Hodges' Thirty Camtasia Demos in Thirty Days. It is for Turbo Delphi which no longer is offered, but is still very similar to full Delphi and lets you visually get a feel for how to do things in Delphi.
Where you put things depends on what they do. The unit associated with a form should really only contain code that's directly related to the user interface that the form presents. Putting business logic directly into a form unit is considered bad practice for a number of reasons. If your utility methods aren't part of a specific form, it's best to put them in a Unit.
As for Data Modules, they're containers for holding non-visual controls. As the name implies, they were created for database access, but they can hold all sorts of other things. For example, at work we have a handful of data modules that contain TImageList controls, which hold lists of icons that are used in various places throughout the app. If you have any non-visual controls that you need to share with several different forms, a Data Module is the logical place to put them.
And yeah, it looks like you're doing the customized form right. If you have a second form that the first form needs access to, (to make it show up when you hit a button or menu item, for example,) then the first form's unit will need the second form's unit in its uses clause. (There are ways around this involving class registration techniques, but that's an advanced topic.)
You might want to avoid using the global form variable that Delphi likes to set up in a form unit, though. It makes your program start up more slowly, and using globals is another thing that's considered a bad practice. A form is an object like any other Delphi object, and you can create it with its constructor, call Show or ShowModal to make it appear, and then call Release or Free on it (read up on TForm.Release in the helpfile to know when you need to use it) when you're done with it.
For starters, create a few different units based on categories - StringUtils.pas, MathUtils.pas, DateTimeUtils.pas, etc - put your functions into those units according to category and be sure to include all the prototypes in your interface section so they'll be visible to other units (but don't get too caught up in how to categorize things...) and keep all your util units in a separate, dedicated directory. Then, point your Delphi or Project library paths to that directory and you'll be able to use the functions in all your utility units. Eventually, you may want to make the units into classes with class functions or persistent structures etc. I myself generally create a project group that includes a package called MyProjectUtils.bpl and I put all my utility units and classes into that package. I never actually deploy it as a package, but since they are wrapped up together I can always check that they all compile properly and they are all available immediately for browsing in the IDE, etc.