Method Sharing in Angular

What started as me saying "let's give Angular a try" has now turned into an experiment that has been going on for a few years now. And being this far in, I still enjoy it.

Since first diving in, I have adopted some solid design principles. Many of these them can be found in @toddmotto's Angular Styleguide for teams or in @John_Papa's Angular Styleguide. Todd and John are both masters with Angular. Their style guides are both great for large teams. They have many similarities, as well as some differences. You have to read them both and pick the one that makes the most sense to you.

Today, however, I wanted to share one of my own. It has to do with sharing methods between parent and children scopes. I don't usually get worked-up enough to share my thoughts about how code ought to be written. However, today was different, and I decided to write this one down.

It isn't really fair for me to describe this as "It has something to do with sharing code between parent and children scopes", because I don't think that you should ever do this. Unfortunately, it is something that I have seen too often, as Angular makes it very easy to do. Let me explain a bit more about what I mean.

SAD PANDA

Consider you have a controller with two children controllers inside of it.

In the example here, you can see a parent controller with two children controllers inside of it. The parent controller's scope has a handleClick method on it. Because the children scopes inherit from the parent scope, both of them (ChildAController and ChildBController) can call $scope.handleClick(), as they inherit from the parent. In the above example, when the button from each child controller is clicked, the handler that will handle those two events is located inside the parent controller.

While the above example is trivial, as controllers get bigger and more complex, this example quickly becomes non-trivial. While maintaining code, when you see an event handler in your angular view, you begin to look for the handler on your view's controller. When you don't see it there, you have to walk up the scope inheritance to find where the method actually resides. This is not the worst thing ever, but not cool. But then, if you need to make any changes to the handler on the parent scope, the change will affect all other controllers that depend on the same method. Your code gets ugly quickly. Beginning with the first deviation of functionality, your code will get uglier and uglier. And this ugliness is kludgy, at best. You have to do silly things like if(checkForSomethingThatOnlyExistsOnChildAController()) and else if(checkForSomethingThatOnlyExistsOnChildBController()). That kind of stuff is complete rubbish. If you have ever done it, smack yourself in the face, right NOW. (smacked myself)

LET'S TRY AGAIN

There are better ways. If you have some functionality that you want to share with two different controllers, the way to share it is NOT by adding the method to the parent scope, as shown above. The way to share code between two controllers is by putting that code into a service. Each controller will have their own event handler, and they will each call the service to get the shared code that is housed there.

Let me rewrite the above code to show you what I mean.

So, what we end up with is each child controller has their own click handler. It isn't inherited from their parent anymore. #yay Additionally, we have pulled the reusable code out into a service, making it easier to share/reuse. #yay Further, our click handlers aren't coupled anymore. They are free to do their own specific things without clobbering one another. #yay

CONCLUSION

When we are tackling a problem and building a new app, or a new section of an existing app, we don't always know what the end-product will look like. Thus it is impossible to always forsee what you will need to do and make perfect design decisions with our code. However, by following some design principles, and using a solid style guide, we will make our life easier. As well as the lives of those who will maintain the code after we write it. Writing code this way will improve your codes readability, make it easier to maintain, and improve the reusability of your code.

This is my take on sharing methods between controllers. My take on sharing variables between controllers is slightly less strict. I will post about it another day. The TLDR is don't do it, unless it absolutely make sense. And when you do it, talk to the variable directly. Refer to it as $scope.$parent.foo instead of $scope.foo. Your code will be easier-to-read/more-predictable if you refer to things by their fully qualified name. However, this topic also deserves it's own post.

T. Wendi McCourtie

Communications Assistant at Education Ecosystem

9 年

Aaron Frost thanks for sharing your knowledge it is this kind of information that needs to be shared more widely than some of the things that are popular on the Internet on this topic. Do you stream yourself at work? I'd love to expand my knowledge. Are you on .livecoding.tv?

回复

I'm going on several years as well... do you have any merit badges left? I never got one :'(

回复
Shyam Seshadri

Building cool stuff | Technology | Product | Google | Amazon | ISB

10 年

Another simple thing that helps prevent this is the controllerAs syntax, which prevents unintentional (or intentional!) inheriting of scope methods based on the prototype chain. The combination of that along with this kind of methodology, is sweet sweet success in my opinion :D

Vincent BOURDEIX

Founder at Web2Bee

10 年

This is the kind of refactoring any developper should take the time to do, as soon as some code is going to get duplicated, because it's simple and quickly done. In general, I spend more time refactoring existing code, as the project evolve, than writing new code. Keeping a code DRY on a daily basis is easy, whereas having to do it after weeks or month of evolutions is a nightmare. Thanks for sharing your thoughts.

Erik Isaksen

Front End Engineer at Accenture Federal

10 年

Such a simple & easy pattern to follow but it's so important for large teams and rapidly changing code. Services are easily the most well understood way to share code and I think the first example you have is how it starts in a new or small project. Once the app grows and one or two items need sharing it never gets refactored Thanks for sharing your sharing style Aaron.

要查看或添加评论,请登录

Aaron Frost的更多文章

  • Domo's Champion Process

    Domo's Champion Process

    Life at Domo Many people, and more specifically, many engineers, peer into the fishbowl that is Domo, and wonder what…

    19 条评论
  • Community = Building Bridges

    Community = Building Bridges

    My first approach to learning code was going to school at the local community college. Truth be told, I am not exactly…

    3 条评论
  • Where did ng-conf come from?

    Where did ng-conf come from?

    Quite a few people have asked me how I became one of the ng-conf organizers. I usually tell them that it was luck.

    8 条评论
  • AngularJS Rocks: Kicking A Dead Horse

    AngularJS Rocks: Kicking A Dead Horse

    Yesterday was a great day. After months of planning and preparing, yesterday a group of us put on one of the biggest…

    2 条评论
  • Jailbreaking Angular Apps: a real story about an experience I had recently

    Jailbreaking Angular Apps: a real story about an experience I had recently

    AngularJS is my favorite JS framework. I have never shied away from saying it.

    2 条评论

社区洞察

其他会员也浏览了