Here is some code to generate code for raising and getting information about
custom errors in an application. Executing the GenerateXyzErrDefs procedure
generates the code.
<tblXyzError>
ErrorCodeOffset (Long Int) ErrorObjBaseName (Text(50))
ErrorDescription (Text(255))
1 DontDoThat
Hey! Don't do that!
2 NotThatEither Woah!
Don't do that either!
3 AttemptedInstanceReinit
Attempted to reinitialize an instance of an object type that does not allow
multiple initializations per instance.
</tblXyzError>
<clsErrorDefinition>
Option Compare Database
Option Explicit
Private Const mycVBErrMethodNotApplicableInContxt = 444&
Private mlngErrNumber As Long
Private mstrErrDescrip As String
Public Property Get Number() As Long
Number = mlngErrNumber
End Property
Public Property Get Description() As String
Description = mstrErrDescrip
End Property
Public Sub Setup(ByVal lngErrNumber As Long, strDescription As String)
If mlngErrNumber <> 0 Then XyzErrAttemptedInstanceReinit.Raise
mlngErrNumber = lngErrNumber
mstrErrDescrip = strDescription
End Sub
Public Sub Raise()
Err.Raise Number, , Description
End Sub
</clsErrorDefinition>
<basXyzCodeGeneration>
Option Compare Database
Option Explicit
Private Const mycXyzErrDefModuleName = "basXyzErrorDefinitions"
Private Const mycXyzErrorTableName = "tblXyzError"
Private Const mycXyzObjPrefix = "xyz"
Public Const xyzcErrorCodeBase = 1000&
Public Sub GenerateXyzErrDefs()
Dim vbcsProject As VBIDE.VBComponents
Dim vbcModule As VBIDE.VBComponent
Dim db As DAO.Database
Dim rstXyzErrors As DAO.Recordset
Dim strNewFuncName As String
Dim lngErrorNum As Long
Set vbcsProject = VBE.VBProjects(1).VBComponents
RemoveVBComponentIfExists vbcsProject, mycXyzErrDefModuleName
Set vbcModule = CreateNewVBModule(vbcsProject, mycXyzErrDefModuleName)
vbcModule.Name = mycXyzErrDefModuleName
Set db = CurrentDb
Set rstXyzErrors = db.OpenRecordset( _
"SELECT * FROM [" & mycXyzErrorTableName & "] " & _
"ORDER BY ErrorCodeOffset", _
dbOpenDynaset, dbReadOnly)
If rstXyzErrors.RecordCount > 0 Then
While Not rstXyzErrors.EOF
strNewFuncName = _
UpperCaseFirstStringChar(mycXyzObjPrefix) & _
"Err" & rstXyzErrors!ErrorObjBaseName
lngErrorNum = xyzcErrorCodeBase + rstXyzErrors!ErrorCodeOffset
vbcModule.CodeModule.InsertLines _
vbcModule.CodeModule.CountOfLines + 1, _
"Public Function " & strNewFuncName & "() As clsErrorDefinition" & vbCrLf & _
" Static sobjErrDefinition As clsErrorDefinition" & vbCrLf & _
" If sobjErrDefinition Is Nothing Then" & vbCrLf & _
" Set sobjErrDefinition = New clsErrorDefinition" & vbCrLf & _
" sobjErrDefinition.Setup _" & vbCrLf & _
" " & lngErrorNum & ", _" & vbCrLf & _
" """ & rstXyzErrors!ErrorDescription & """" & vbCrLf & _
" End If" & vbCrLf & _
" Set " & strNewFuncName & " = sobjErrDefinition" & vbCrLf & _
"End Function"
rstXyzErrors.MoveNext
Wend
End If
rstXyzErrors.Close: Set rstXyzErrors = Nothing
Set db = Nothing
End Sub
Private Sub RemoveVBComponentIfExists( _
vbcs As VBIDE.VBComponents, _
strModuleName As String _
)
Dim vbcModule As VBIDE.VBComponent
On Error Resume Next
Set vbcModule = vbcs(strModuleName)
On Error GoTo 0
If Not (vbcModule Is Nothing) Then
vbcs.Remove vbcModule
Set vbcModule = Nothing
End If
End Sub
Private Function CreateNewVBModule( _
vbcs As VBIDE.VBComponents, _
strModuleName As String _
) As VBIDE.VBComponent
Dim vbcResultModule As VBIDE.VBComponent
Set vbcResultModule = vbcs.Add(vbext_ct_StdModule)
vbcResultModule.Name = strModuleName
Set CreateNewVBModule = vbcResultModule
End Function
</basXyzCodeGeneration>
Running GenerateXyzErrDefs generates the basXyzErrorDefinitions module as
follows...
<basXyzErrorDefinitions>
Option Compare Database
Option Explicit
Public Function XyzErrDontDoThat() As clsErrorDefinition
Static sobjErrDefinition As clsErrorDefinition
If sobjErrDefinition Is Nothing Then
Set sobjErrDefinition = New clsErrorDefinition
sobjErrDefinition.Setup _
1001, _
"Hey! Don't do that!"
End If
Set XyzErrDontDoThat = sobjErrDefinition
End Function
Public Function XyzErrNotThatEither() As clsErrorDefinition
Static sobjErrDefinition As clsErrorDefinition
If sobjErrDefinition Is Nothing Then
Set sobjErrDefinition = New clsErrorDefinition
sobjErrDefinition.Setup _
1002, _
"Woah! Don't do that either!"
End If
Set XyzErrNotThatEither = sobjErrDefinition
End Function
Public Function XyzErrAttemptedInstanceReinit() As clsErrorDefinition
Static sobjErrDefinition As clsErrorDefinition
If sobjErrDefinition Is Nothing Then
Set sobjErrDefinition = New clsErrorDefinition
sobjErrDefinition.Setup _
1003, _
"Attempted to reinitialize an instance of an object type that does
not allow multiple initializations per instance."
End If
Set XyzErrAttemptedInstanceReinit = sobjErrDefinition
End Function
</basXyzErrorDefinitions> 7 2689
"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:06********************************@4ax.com... Here is some code to generate code for raising and getting information
about custom errors in an application. Executing the GenerateXyzErrDefs
procedure generates the code.
I am completely baffled by this.
Why generate a basXyzErrorDefinitions module that contains nothing but
duplicate functions?
Why not generate a class that not only raises and reports on the error, but
also initializes the pairs?
On Mon, 03 Nov 2003 12:33:47 GMT, "rkc" <rk*@yabba.dabba.do.rochester.rr.bomb>
wrote: "Steve Jorgensen" <no****@nospam.nospam> wrote in message news:06********************************@4ax.com.. . Here is some code to generate code for raising and getting information about custom errors in an application. Executing the GenerateXyzErrDefs procedure generates the code.
I am completely baffled by this.
Why generate a basXyzErrorDefinitions module that contains nothing but duplicate functions?
Why not generate a class that not only raises and reports on the error, but also initializes the pairs?
I'm not sure I understand the question, so I'n not sure if this addresses it,
but...
Instances of clsErrorDefinition represent individual error types. Each of the
functions in basXyzErrorDefinitions accesses an instance of clsErrorDefinition
for a particular type.
I don't want to generate separate class modules for each case because
A. That many class modules would be a big clutter in the VBE.
B. Calling code would have the extra code and extra overhead of creating an
instance of whichever class before using it.
C. It is nice for the calling code to be able to implement functions that
accept or return a value of type clsErrorDefinition, and use early binding
rather than having to use Object type because multiple class types are
possible, and resolve everything else at run-time. An Interface could solve
that, but wouldn't be compatible with Access 97 - which is nice to be.
If I don't generate separate class -modules- for each case, then something has
to initialize them and provide access to the correct one by name. I could
have passed just the ID, and let the class look up the rest from the table,
but the generator is already reading the table, and the resulting code is nto
to be directly maintained anyway, so why not just dump all the info into the
code during code generation?
We're not worried about duplication in the generated code because it's not
manually maintained. The function pattern need only be maintained in one
place in the code generator, and the error details need be maintained in only
one place, the table. I guess it's kind of like doing a mail merge in MS
Word. I probably should have a comment automatically inserted at the top of
the basXyzErrorDefinitions module saying how to maintain and regenerate it, so
it's obvious to anyone maintaining the code.
Note - in my original code, the following line should be removed because it
was part of an experiment that failed, and nothing now uses it...
Private Const mycVBErrMethodNotApplicableInContxt = 444&
"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:6v********************************@4ax.com... On Mon, 03 Nov 2003 12:33:47 GMT, "rkc"
<rk*@yabba.dabba.do.rochester.rr.bomb> wrote:
"Steve Jorgensen" <no****@nospam.nospam> wrote in message news:06********************************@4ax.com.. . Here is some code to generate code for raising and getting informationabout custom errors in an application. Executing the GenerateXyzErrDefs procedure generates the code.
I am completely baffled by this.
Why generate a basXyzErrorDefinitions module that contains nothing but duplicate functions?
Why not generate a class that not only raises and reports on the error,
butalso initializes the pairs?
I'm not sure I understand the question, so I'n not sure if this addresses
it, but...
We've been through this before and I was completely rejected, but here goes.
Now that you have decided that using a class is going to be part of the
process, why not make it THE process.
Instances of clsErrorDefinition represent individual error types. Each of
the functions in basXyzErrorDefinitions accesses an instance of
clsErrorDefinition for a particular type.
You're using the class as just another function in the process instead of
encapsualting the process in the class.
I don't want to generate separate class modules for each case because A. That many class modules would be a big clutter in the VBE.
There would only be one class.
B. Calling code would have the extra code and extra overhead of creating
an instance of whichever class before using it.
Your calling code has to go through the process of calling a function which
has to go through the process of creating an instance of the class. Where's
the extra overhead if the calling code simply creates an instance instead?
C. It is nice for the calling code to be able to implement functions that accept or return a value of type clsErrorDefinition, and use early binding rather than having to use Object type because multiple class types are possible, and resolve everything else at run-time. An Interface could
solve that, but wouldn't be compatible with Access 97 - which is nice to be.
Once again, there only needs to be one class. One class that contains all
the error numbers and descriptions. One class that exposes the error
numbers as property get routines. One class that raises the correct error
through a public method that takes one of the error numbers defined
by itself as a parameter.
If I don't generate separate class -modules- for each case, then something
has to initialize them and provide access to the correct one by name. I could have passed just the ID, and let the class look up the rest from the
table, but the generator is already reading the table, and the resulting code is
nto to be directly maintained anyway, so why not just dump all the info into
the code during code generation?
Dump all the info into the class during code generation.
We're not worried about duplication in the generated code because it's not manually maintained.
It's still duplicate code and it's still ugly and completely un-necessary.
In my view, of course.
The code generation stuff you posted looks interesting and I will be taking
a further look at it. rk*@yabba.dabba.do.rochester.rr.bomb (rkc) wrote in
<3d*******************@twister.nyroc.rr.com>: Once again, there only needs to be one class. One class that contains all the error numbers and descriptions. One class that exposes the error numbers as property get routines. One class that raises the correct error through a public method that takes one of the error numbers defined by itself as a parameter.
Steve's gone in a very different direction than what I foresaw.
He's using a table to store his error definitions, as I suggested,
and his reason is to make it possible to keep multiple attributes
of a single error correlated.
I had suggested that once you do this, you really need only two
things:
1. a module with the constants for your error numbers (generated in
code).
2. a module or class with the functions necessary to raise the
error.
You'd pass the class the error constant and the class would then
raise the error with the appropriate error description and do
whatever else you wanted it to do. The class itself could have as
many methods and properties as you wanted, but I would make them
all generic, rather than generating a class with properties
specific to all your errors.
Steve's objection to the table was that you couldn't enforce it
with compiling. His solution to that was to autogenerate the
constants. My thought is that all you really need are the constants
for the error numbers themselves (which are actually the PK of your
table) as your way of getting to all the other attributes of your
errror. And your class or module for raising your error and
examining its attributes would simply be a lookup of a particular
error code in the error table.
With this solution you get:
1. simple, generic code.
2. as many custom attributes of your errors as you need.
3. with the auto-generated module of error number constants, you
get compile-time enforcement of error codes without needing to
worry about correlating a set of multiple error attributes for each
error, since the error number is itself a pathway into the lookup
for all the other attributes.
You'd only need one instance of your error class (if you went that
route), since you can only raise one error at a time.
--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
On Mon, 03 Nov 2003 20:26:03 GMT, dX********@bway.net.invalid (David W.
Fenton) wrote: rk*@yabba.dabba.do.rochester.rr.bomb (rkc) wrote in <3d*******************@twister.nyroc.rr.com>:
Once again, there only needs to be one class. One class that contains all the error numbers and descriptions. One class that exposes the error numbers as property get routines. One class that raises the correct error through a public method that takes one of the error numbers defined by itself as a parameter.
Steve's gone in a very different direction than what I foresaw.
He's using a table to store his error definitions, as I suggested, and his reason is to make it possible to keep multiple attributes of a single error correlated.
I had suggested that once you do this, you really need only two things:
1. a module with the constants for your error numbers (generated in code).
2. a module or class with the functions necessary to raise the error.
You'd pass the class the error constant and the class would then raise the error with the appropriate error description and do whatever else you wanted it to do. The class itself could have as many methods and properties as you wanted, but I would make them all generic, rather than generating a class with properties specific to all your errors.
Steve's objection to the table was that you couldn't enforce it with compiling. His solution to that was to autogenerate the constants. My thought is that all you really need are the constants for the error numbers themselves (which are actually the PK of your table) as your way of getting to all the other attributes of your errror. And your class or module for raising your error and examining its attributes would simply be a lookup of a particular error code in the error table.
With this solution you get:
1. simple, generic code.
2. as many custom attributes of your errors as you need.
3. with the auto-generated module of error number constants, you get compile-time enforcement of error codes without needing to worry about correlating a set of multiple error attributes for each error, since the error number is itself a pathway into the lookup for all the other attributes.
You'd only need one instance of your error class (if you went that route), since you can only raise one error at a time.
My thinking was that if I'm generating the code anyway, why not take this a
step farther than simply generating a list of constants and a way to look up
the other information about the constants. Why not generate named functions
that directly return class instances that encapsulate all the properties and
methods of the errors.
To raise a "DontDoThat" error, just say XyzErrDontDoThat().Raise. You don't
have to think in terms of looking things up at all, just tell the error to
raise itself. Would you agree or disagree this is an improvement over
generating constants and passing them to one or more lookup functions. no****@nospam.nospam (Steve Jorgensen) wrote in
<j9********************************@4ax.com>: On Mon, 03 Nov 2003 20:26:03 GMT, dX********@bway.net.invalid (David W. Fenton) wrote:
rk*@yabba.dabba.do.rochester.rr.bomb (rkc) wrote in <3d*******************@twister.nyroc.rr.com>:
Once again, there only needs to be one class. One class that contains all the error numbers and descriptions. One class that exposes the error numbers as property get routines. One class that raises the correct error through a public method that takes one of the error numbers defined by itself as a parameter. Steve's gone in a very different direction than what I foresaw.
He's using a table to store his error definitions, as I suggested, and his reason is to make it possible to keep multiple attributes of a single error correlated.
I had suggested that once you do this, you really need only two things:
1. a module with the constants for your error numbers (generated in code).
2. a module or class with the functions necessary to raise the error.
You'd pass the class the error constant and the class would then raise the error with the appropriate error description and do whatever else you wanted it to do. The class itself could have as many methods and properties as you wanted, but I would make them all generic, rather than generating a class with properties specific to all your errors.
Steve's objection to the table was that you couldn't enforce it with compiling. His solution to that was to autogenerate the constants. My thought is that all you really need are the constants for the error numbers themselves (which are actually the PK of your table) as your way of getting to all the other attributes of your errror. And your class or module for raising your error and examining its attributes would simply be a lookup of a particular error code in the error table.
With this solution you get:
1. simple, generic code.
2. as many custom attributes of your errors as you need.
3. with the auto-generated module of error number constants, you get compile-time enforcement of error codes without needing to worry about correlating a set of multiple error attributes for each error, since the error number is itself a pathway into the lookup for all the other attributes.
You'd only need one instance of your error class (if you went that route), since you can only raise one error at a time.
My thinking was that if I'm generating the code anyway, why not take this a step farther than simply generating a list of constants and a way to look up the other information about the constants. Why not generate named functions that directly return class instances that encapsulate all the properties and methods of the errors.
As long as a human being is going to be progamming in the database,
seems to me you want the amount of generated code to be as small
as possible.
To raise a "DontDoThat" error, just say XyzErrDontDoThat().Raise. You don't have to think in terms of looking things up at all, just tell the error to raise itself. Would you agree or disagree this is an improvement over generating constants and passing them to one or more lookup functions.
No, because it proliferates a huge amount of duplicative code.
--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
On Tue, 04 Nov 2003 16:50:30 GMT, dX********@bway.net.invalid (David W.
Fenton) wrote:
.... My thinking was that if I'm generating the code anyway, why not take this a step farther than simply generating a list of constants and a way to look up the other information about the constants. Why not generate named functions that directly return class instances that encapsulate all the properties and methods of the errors. As long as a human being is going to be progamming in the database, seems to me you want the amount of generated code to be as small as possible.
I don't know if that should be a concern. Generated code should be treated as
a black box. Only the metacode and code generator need be dealt with by the
programmer. To raise a "DontDoThat" error, just say XyzErrDontDoThat().Raise. You don't have to think in terms of looking things up at all, just tell the error to raise itself. Would you agree or disagree this is an improvement over generating constants and passing them to one or more lookup functions.
No, because it proliferates a huge amount of duplicative code.
I disagree on this. I do have a problem with my own code, though. Having
part of the code split between the error definition class and the code
generator is not good. Next time I have time, I'll take another stab. I may
decide to do it the way you were suggesting - we'll see what I come up with. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Ziggi |
last post by:
Hi !
I have an ISAPI instalation of PHP over IIS5 server
on Windows 2000. Everything works fine but as I am
under website development I would like to keep
PHP error messages turned on - for my...
|
by: Doug |
last post by:
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Lines: 14
Message-ID: <9DxFc.23833$bs4.23734@newsread3.news.atl.earthlink.net>
Date: Sat, 03 Jul 2004...
|
by: Grant Richard |
last post by:
Using the TcpListener and TcpClient I created a program that just sends and
receives a short string - over and over again. The program is fine until it
gets to around 1500 to 1800 messages. At...
|
by: Mike Hunter |
last post by:
(Please CC me on any replies as I'm not on the list)
Hi,
After a recent power failure, a program that uses a pgsql backend
(netdisco) started to send me nastygrams. I tried the author's...
|
by: Florian G. Pflug |
last post by:
Hi
Since sometime yesterday, my postgresql (7.4.5) reports
"ERROR: cannot compare arrays of different element types",
when I analyze a specific table in my database.
Here is the tables...
|
by: Jarod |
last post by:
Hey
When I put my control into DetailsView in a template I see it and it seems
as working ok. After compile it works on the page. But in normal view in
designer I don't see my detailsView instead...
|
by: Mike Hofer |
last post by:
In my ASP.NET application, *one* page would not render in the
application. All others would show up just fine, but when the user
clicked the button to browse to this one page, I'd get a nasty error...
|
by: Alias |
last post by:
Hi -
I'm trying to implement a custom RoleProvider based on the SqlRoleProvider.
I keep receiving a an error that it can't load type
'MyRoleTest.MyRoleProvider' when trying to load my...
|
by: Kevin Liebowicz |
last post by:
Yes, I wasted the past two days trying to fix this.
Yes, this is on a Win2003 Server.
Yes, this machine is a domain controller.
Yes, I seen the dozens of KB articles like this one:...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
| |