個人檔案Nates Stuff相片部落格清單更多 工具 說明

部落格


6月9日

Avoiding Circular Dependencies (Tangles)

The term "circular dependency" may be foreign to some programmers (especially if you do Java as it is a pretty common practice).  However, anyone who has done some scripting for a referential database knows that you have to run scripts in a certain order.  Running scripts out of order causes errors when you run.  The interesting trick is that if you run that same incorrectly-ordered DDL script again and again you will eventually get it to run without errors.  If you were unaware of the order being incorrect and thought to yourself in that moment "Stupid database!" then this blog post is for you!

What is a circular dependency?

It is simply two libraries that use each other (either directly or indirectly) as shown below:

image 

Figure 1: Circular Dependency

 

 

image

Figure 2: Complex Circular Dependency

 

The complexity of a circular dependency may vary.  If you are using Visual Studio and have all of your projects loaded into a single solution AND you add Project References (Right click on project -> Add Reference -> Projects Tab -> {Project Name}) then the IDE will not allow you to create Circular Dependencies.  In fact, this is a good practice as Visual Studio will ensure the correct build order. 

Why are circular dependencies bad?

Just like our Database example above, a circular dependency makes it so you can not guarantee that your application has the latest code.  That is a big deal!  Here is why:

  1. I make changes to Application 1 (in Figure 2)
  2. I build my project, The changes I made in Application 1 may or may not have gotten into Application 2 (depending on build order).  It may have taken a copy of the compiled code that was left over from the last time I built.
  3. Application 2 depends on this new functionality to provide services to Application 3; This functionality will not work correctly with this build.
  4. Application 3 may or may not depend on these same services to provide back to Application 1

As you can see in this scenario, there is no such thing as a "correct" build order when there are these circular dependencies.  The only way you can arrive at the correct version of the code is to build it as many times as there are nodes in our circle.  That would mean for Figure 1 that we would need to build twice and three times for Figure 3.  Some of these dependencies can get really ugly!  Here is some actual code running in an actual company that I did analysis on some time ago using a tool called Structure 101.

image image image image

 

How do I fix circular dependencies?

There are some steps to take to solve even the most complex tangles!  They all involve refactoring your code though.

  1. Refactor common code into a "base" dependency; I usually call this "Common" (figure 3).  BEST SOLUTION
  2. Remove code that is unused.  In the tangles shown above many of them are using deprecated/unused code.
  3. Duplicate the sections of code used.  This should be seen as a last resort but given the choice between code duplication and circular dependencies, I take code duplication ever time!

 

image

Figure 3: Refactor a Common

 

Summary

There are two kinds of design concepts for nTier (and other types of architectures as well) called Logical Layout Design and Physical Layout Design.  The Logical Layout is simply that your software occupies the same project/package but leverage different classes.  In contrast Physical Layout Design forces each tier to be separated into different Projects/Packages.  So long as we are careful to manage the dependencies between these packages from the start this is the preferable way to code.  While the logical layout does not suffer from the dependency problem eventually you may wish to break these classes apart and find that there are a lot of inner-dependency that should not exist simply because they occupied the same project.  Remember to keep it clean!

6月13日

Encrypting Connection Strings in your web.config file

I have run across the need to encrypt some connection strings in a web.config file.  ASP.NET provides a handy way to do this using Protected Sections.  They allow you to encrypt the connection string based on machine or user.  The best part is that it is transparent to the application so if you have an existing application that uses the connection string block you can encrypt the strings without having to add any lines of code or re-test your application. 

Here is what it boils down to:
Encrypting a connection string in a virtual directory using DPAPI (machine specific):
aspnet_regiis -pe "connectionStrings" -app "/MachineDPAPI" -prov "DataProtectionConfigurationProvider"

Encrypting a connection string in a physical directory using DPAPI (machine specific):
aspnet_regiis.exe -pef "connectionStrings" C:\Projects\MachineDPAPI –prov "DataProtectionConfigurationProvider"

Encrypting a connection string in a virtual directory using RSA (user specific):
aspnet_regiis -pe "connectionStrings" -app "/MachineRSA"

Encrypting a connection string in a physical directory using RSA (user specific):
aspnet_regiis.exe -pef "connectionStrings" C:\Projects\MachineRSA
 
--Nathan Zaugg