AngularJS Tutorial: If You Have Circular Dependencies, You’re Doing Something Wrong
Codementor AngularJS expert and founder of the Angular UI organization, Dean Sofer, joined us during open office hours for an open Q&A session. One of our viewers had a scenario where he had circular references and didn’t realize there was a problem until the compiler base was reset. What he wanted to do was have a user object and have the user get loaded with a bunch of link data from different services over time, so he first loaded the application, the user object, the portfolio data and other objects. However, all those objects needed access to the user object, and they ended up pointing at each other and didn’t work. The viewer asked Dean if the problem could be solved by creating a data objects a user takes and then having everybody working off it.
Dean’s answers are as below:
The text below is a summary done by the Codementor team and may vary from the original video and if you see any issues, please let us know!
I had this same exact issue when I was building the project Angular ORM was inspired by, and I talked to my CTO, as I find it helpful to talk out general programming problems with people who know lots of design patterns. The response I got from him was: “If you have circular dependencies, you’re doing something wrong. There are a lot of ways to clean things up and fix these circular dependencies.”
In our project, we had a socket system, a user class, and an authentication class. When you open up a socket, you had to be authenticated with a user object, so I created this weird triangle. Deciding what fell under where was kind of arbitrary, as there was no real reason why I chose this guy fell under this and that guy had access to that. Here’s how I got around the circular dependency:
Let’s say my authentication class could not have a user inside of it, but the user can have an authentication class, but the authentication class needed a validation function, which is all about validating the user, and I put that inside the user class. So Auth is inside of user, but it needs something inside user, which is surrounding Auth. I spun up an instance of Auth inside of user and used a singleton, like a factory. Then I put past in a piece of information about the user. So I have “validate user” in my authentication as an undefined function. I inject Auth into user, then user calls Auth.setvalidator, and I pass in a reference to the validation function.
I’m kind of monkey patching the authentication to have a piece of body of logic that’s actually residing inside the user, and that body of logic has access to all the information inside the user class, but I can still call it up from within. So essentially, spin an object and add in a function onto the object after it has been constructed. That’s one way of doing it to make it more API-esque and more like a contract. I think the pattern might be “decorator”, where I was thinking of adding something into the Auth. Decorator might be a good thing to check out because you had one utility decorating another utility with extra capability.
Another thing we tried to do was a “state manager”, which is a global service that injects all the guys and information around them. It works and we tried that first but it got really convoluted and we got rid of it with decorator.
Other posts in this series with Dean Sofer:
- AngularJS Office Hours: Best Practices, UI-Router, and ORM
- What Should Beginners Choose: Angular, Ember, or Backbone?
- Angular Tutorial: Solving Asynchronous Problems with Resolve
- Tips from AngularUI Founder: How to persuade non-coder clients to adopt Angular
Or Become a Codementor!
Codementor is your live 1:1 expert mentor helping you in real time.