Avatar of davism
davismFlag for United States of America asked on

Circular reference impact...

Hi,

I have a question...I'm porting something from VB over to VB.NET. My solution is comprised of 1 executable with references to other dll's.

The dll's are categorized based on content of the functions. For example: I have a dll (i.e. DateProcess) that contains seveal date related specific functionality including but not limited to calling another date related dll and the functiona are to be callable from DateProcess. I have another dll (i.e. CoreCommon) that peforms other "common" components such as a file creation.

The problem is - in the CoreCommon I am creating a file and I am using a function in the DateProcess dll.

Since, CoreCommon includes "common" functions the DateProcess has a reference to the CoreCommon.

Now, I understand the reasoning with the memory leak what existed from VB6 but I believe I was handling it appropriately then. Whereas I would set the object created for the function of the DateProcess to nothing. (Basically, destroy it).

However, I cannot even add the reference in DateProcess due to the circular reference item.

Anybody have any thoughts on this?
.NET ProgrammingProgramming Languages-OtherVisual Basic.NET

Avatar of undefined
Last Comment
davism

8/22/2022 - Mon
SolutionsCS

You will have circular reference in project 1 when you reference project2 if project2 already reference project1.  Stop referencing project1 in your project2 and reorganize your code by moving code from project1 to project2.
ASKER
davism

Agreed and understand. What I have is project 1 referencing project 2 for a specific function and project 2 referencing project 1 for several other functions..  Iif I'm having one dll be a categorization of similiar functions; if I split that up then I lose the purpose of the categorization.

Is there another way to handle this whilst retaining the categorization of like functions in a DLL but have a reference it would otherwise defeat a purpose of like functions in a dll and reusability. Isn't there another way?
imladris

I gather you have the executable and the CoreCommon DLL in one project (let's call it A), and the DateProcess DLL in another project (B). So, A references B in order to call date functions; but B also references A for file creation.

If I've got all that right, then would it be viable to split it up into 3 projects? The executable (and all "other" DLL's) in project A, the DateProcess DLL in B, and the CoreCommon DLL in C. Then A would reference B and C, B would reference C, but C wouldn't reference anything else. This would appear to avoid the circularity.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
SolutionsCS

Hi again Davism,

Move it into another DLL.  Keep it simple.  So you will have to DLL to include in your main project.  But for my self, i would review my code organization.  By experience, i know that when i end up in a circular reference, it is an engeneering problem.  Categorization is not an exact science and what we thought is not necessarily what was the best.  For my self i would move it to another DLL.  It would respect your categorization need and respect hierarchical dependency of your subsystem.
ASKER
davism

SolutionCS,

Thanks for the response back. I understand the aspect of an engineering problem. It's not entirely an engineering problem when what was tried and true before no longer works because of something else. There was nothing wrong with the engineering aspect before. The reason why this has changed is due to the underlying architecture.

You're right the aspect of categorization isnt an exact science but logically grouping a set of value-add routines of the same topic may be a better description. That is not new

What I am doing is having a set of DLL's (i.e. CoreCommon and DateProcess, etc) to be utilized by one executable. However, some of the DLL's reference the like aspects of some of the others. (i.e. the CoreCommon using the date routine in the DateProcess) Yet, that are other functions in the DateProcess that are logically associated and therefore part of the DateProcess but they utilitize functions in the CoreCommon. If I move it to anothe DLL that DLL will still have the dependency of Corecommon. So, let's say I have a DLL for configuration validation (let's say XML) called XMLConfig. That DLL will also utilize some of the CoreCommon functions as well as functions in the DateProcess.dll.  I would be ok with the DateProcess because nothing in the DateProcess is dependent upon the XMLConfig. However, the CoreCommon may have some functions that are dependent upon XMLConfig. XMLConfig also has functions dependent upon CoreCommon.

The iontent is synergy between the logically group functions in associated DLL's that have a touch point into the CoreCommon. The CoreCommon *may* have touch points into the other DLL's to capitalize on reusability of functions in different logical groupings of dll's.

The goal is reusability and sharing while isolating like logical grouping of functions in physically separate spaces (i.e. DLL's)

I can think of one way around this by repeating the code in CoreCommon on the File create with the Date logic that I have it trying to call the DateProcess.dll for. I can do that but there is no reusability there. It's redundancy and to me, questions the reusability capabilities.

Am I missing something here? If it's architecture engineering - what am I missing and what is wrong with that pursuit? (Again, I had it before and worked great but now I can't.)

imladris

In my opinion, the architecture engineering aspect is that it is preferable to design software in layers that are used by higher layers, and use lower ones, or, alternatively, in more or less selfcontained objects. Experience has shown that the benefits of this kind of design outweigh the benefits of logical groupings. That's not to say logical groupings have no value; they do. But it is to say that where the two objectives conflict you are usually better off rearranging the logical groupings in favour of layers or objects. It reduces the mutual entanglements in code, which, in general, makes it easier to maintain.

In your last example of XMLConfig using CoreCommon, and CoreCommon being dependant on XMLConfig as well, I would be strongly inclined to take the routine that CoreCommon uses and put it in the CoreCommon DLL (or another one that CoreCommon uses), and attempt to rethink how the functions are grouped, rather than treating the grouping as the most important aspect of the organization.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
davism

imladris,

Help me understand here. How can a hierachcal nature item be introduced rather than a logical group when you have something like...

CoreCommon
   - ErrorReporting
   - FileCreate
         - Calls the DateProcess.DateCalc (This requires the reference to the DateProcess)
   - XML input
        - Calls the XMLConfig.XMLLoad (This requires the reference to the XMLConfig)

DateProcess
   - CalcDate
        Would call the ErrorReporting in a TRY-CATCH block
        (this requires the reference to the CoreCommon)

XMLConfig
  - XMLLoad
        Would call the ErrorReporting in a TRY-CATCH block
        (thjis requires the reference to the CoreCommon.)

If I put the ErrorReporting in each of the DLL's then I have redundancy going on which is something I'm trying to avoid.

How would I go about that one. The are again logically grouped and I'm trying to capabilize on reusability. I had this going on before but it doesn't look like there is a way to do this in this architecture without abandoning the logical grouping concept and introducing redundancy.

What am I missing? What thoughts do you have on this sample of CoreCommon, DateProcess and XMLConfig do you think might work while keeping some form of logical grouping?
ASKER
davism

Would the use of Interfaces and Reflection be the way to go? Although, I see a small form of redundancy still in play there? (Or I'm seeing this correctly).

If that is an approach do either of you have a sample in using the sample situations or example I mentioned previously?

Please let me know.
SOLUTION
SolutionsCS

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
ASKER
davism

SolutionsCS,

Appreciate the visual cue... I'm thinking on the visual cue you have and how an adjustment can be made...

Thinking....
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
ASKER
davism

What I'm trying is something like the CoreCommon is in the middle because all will utilize it.

The main difference here is that the Error was in the CoreCommon and I split it out. I included another DLL (for the sake of concept not of context (i.e. the Compression may not be something I would need).

Would this be more reasonable or a good approach or is Reflection and Interfaces something to evaluate further even though there are some aspects of redundancy?

I'm definitely trying to be generic but at the same token elimiinate redundancy and strengthen reusability.

See the attached:


Drawing1.bmp
imladris

Did you mean to have two way arrows between the various boxes and CoreCommon? Solutions visual cue specifically didn't do that. Allowing CoreCommon to use stuff in "higher" level DLL's is what leads to the circularity.......

As to your example, I think it would be reasonable to stick the XMLInput method into the XML DLL.

I would counsel against Reflection or Interface to manage such organization issues. Interfaces do have a common (different) place in architecture. I think, Reflection on the other hand, is almost always best avoided except for very special purpose kind of uses.
ASKER
davism

So, if I do something like:

Now, if I have an exe that has the references to each of these. CoreCommon, Error, DateProcess, etc They each have references to each other (i.e. CoreCommon has a reference to DateProcess and Error, DateProcess has a reference to Error and Compression but not CoreCommon.

So, in the example: if I were to have the main application (exe) call the FileCreate method in CoreCommon and that method calls the DateCalc in DateProcess I should be ok. IF the TRY-CATCH block throws an exception I can note the exception in the from CoreCommon by calling the Error.

If the DateCalc confronts an exception in the TRY-CATCH block it can trigger the Error.dll as well. (some information redundancy could happen (not bad just more information) if I do not gracefully terminate right there rather than continuing on to the TRY-CATCH of the FileCreate. )

Does this sound like a more reasonable approach? I'm trying to throw darts at it to see if I can make a hole. I might be missing something somewhere.

Thoughts?
Drawing2.bmp
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
SolutionsCS

Now you start having it ;).

ASKER
davism

This changes the dynamic of the intent of the CoreCommon somewhat though. It may be workable, however, with some constraints and some adjustments to existing code.

There is one other DLL that is commensurate with the "Application" - I will have to try and thoroughly break that down to have it function like the CoreCommon, if possible.

I'll work with this and leave this open for now.
ASKER CERTIFIED SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
davism

imladris,

The problem with that is that come are on the same hierarchical level and it can be cyclical in nature:

For instance:

                                                         Application
                                                       CoreCommon
                                     DateProcess XMLConfig Compression
                                                             Error

The DateProcess, XMLConfig. Compression each utilize elements of CoreCommon and/or Error. Application is the orchestrating container.. Application triggers the need to invoke DateProcess or CoreCommon or Compression. For instance with the example I described the Application may trigger the FileCreate in the CoreCommon which then has a touch point into DateProcess with the DateCalc. Both of which may invoke the Error methods in the event of an exception captured in the try catch blocks. The location of where to put the error will be provided by variables defined in CoreCommon that will be privately held with public methods to get the values. Or they may just be public variables. I understand the protection aspect of the scoping and data but it's application when there is a cause for concern and I question whether that will be the case especially when it hasn't been a concern previously.
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
imladris

What I was intending was to simplify the diagram. The diagram does not show an arrow from CoreCommon to Compression. I had to look really hard at the diagram, and trace all the arrows. What the diagram boils down to is the hierarchy I showed.

Perhaps, given your explanation and hierarchy, you meant the arrow between CoreCommon and Compression to be in the other direction. That would correspond to the hierarchy you show.

From your explanation the crux of the problem is to do with ascertaining "where" to "put" the error. This is done, at present, by calling back into CoreCommon to obtain the value of a set of variable. Perhaps it would be possible to have methods in Error (or maybe underneath error) that CoreCommon calls to set the values. Then when Error needs them, it can call into there and get what it needs.
ASKER
davism

imladris,

No, the lines were correct.

I have gone through the pain-staking process of converting the modules to VB.NET. The bad part is that I got it to compile. As we all know, that doesn't imply that it logically works. I have some preliminary step through and it looks good so far but I have more to go through.

I got rid of all the circular references.

I'm going to run through some testing of the most routine aspects and see what my outcome is. I know I'll have to add in some more TRY-CATCH blocks especially with XML due to the ParseError no longer being present.

Is there anything from what you have been involved with on these examples that clearly stands out that I should test?
imladris

The lines show Compression pointing to (using) CoreCommon, DateProcess and Error. The only arrow pointing to Compression (being used by) comes from the application. That would put Compression just below application, by itself, in the hierarchy where I showed it.

No, I have no comment on testing the logic. I have merely been commenting on organization/grouping of methods.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
davism

Wait...you are correct imladris, there is only a line going from compression to CoreCommon. Compression uses CoreCommon, Error and DateProcess and would be invocated by the "Application".

Good news is that I have got this going and I have been testing different situations. I keep running into an issue of a date conversion.

Do you happen to know anything about that?

I'm trying to take like a date string of CCYYMMDD for example: "20080515" and putting in a field defined as DateTime. Or should I just leave that as a string in a field that has a name representing date?

I'm having an issue with a time as well. How can I get the curent time in a 24-hour time format? Right now, it is returning like a string that is "162423" for 4:24:23 PM. Or should I just leave that as a string value as well? I would like to have something like 16:24:23. I know I can do that with regex's but isn't there another way?
imladris

It's best to open a new question for a new topic.
ASKER
davism

Yeah, I was thinking that as well. I'll close this one out and split the points between you and SolutionsCS with the majoriy going to you. :-)
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
ASKER
davism

Thanks SolutionCS. It has helped quit a bit

Thanks imladris, the information you have provided helped.

The information provided by both of you is excellent and very much appreciated!!
ASKER
davism

Whoa...I just hit something that I wasn't expecting of just brain-dead on. Everything else was seemingly working good.

However, if in the CoreCommon.dll I set a variable as public at the class level so I have like:

Public myTest as String

Then let's say in the in the "Application" I set the CoreCommon.myTest = "This test"

Now, if I am in the Error DLL I successfully import the CoreCommon and I instantiate it with:

Public CoreCheck as CoreCommon.

It does NOT identify the CoreCheck.myTest is "This test". It said's it is nothing.

What am I missing here?

Any input is greatly appreciated.
ASKER
davism

Actually, disregard. I got around it by adding a Module to the CoreCommon type dll. Works like a charm.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.