I am trying to understand the best practices for structuring an ember.js application. This slide from tomdale:
https://speakerdeck.com/u/tomdale/p/emberjs-more-than-meets-the-eye?slide=55
has a concise description of how to apportion the application logic. However in trying to follow these guidelines I have finding some problems:
The router is growing too large. According to the presentation the router "responds to events from views", but this results in a lot of code when there are dozens of views.
There are a huge number of controllers. In a Rails application the CRUD actions typically reside in the same controller, however for ember apps it seems that there should be a one controller to list records, one to view a record, one to create a record, etc.
It doesn't feel very DRY because I am ending up with so many files between the controllers, views and handlebars templates that each only have a couple of lines of code.
I am trying to decide if the problem is that I am applying the guidelines incorrectly, or whether these guidelines only work for trivial applications.
Does anyone have any advice - especially on how to manage the growth of the router?
I think that saying Ember encourages too many controllers is like saying Javascript encourages too many functions. Yeah, you can go crazy with proliferation of either. Or you can do the opposite, and have it work exactly as you need. In general, always remember that your app should be exactly as complex as it needs to be, and no more so. You don't need to use a certain architecture or pattern just because some famous coder guy used it, nor even because it seems to be 'the Ember way'. Even 'Universal Good Things' like Separation of Concerns, MVC, etc. are principles & models which you should try to understand fully then use to the extent that they serve your needs. I think that the ability to selectively break rules and patterns for the right reasons is far more telling a sign of a great hacker than slavish devotion to the dogma of the programming gods. This is a craft, not a religion. (But YMMV. Perhaps there's a special circle of hell reserved for coders like me. I'm betting against it.)
Specific to Ember, I tend to use Controllers around my data models and/or around a particular user workflow, rather than around each view. Then use Routing/State Managers as the glue between your views, and I generally use Event Managers on views to handle browser events within each view, including sending instructions to the router. So, if I have an app that revolves around, say, Customers and Products, I'll have a controller for each, just as I tend to do in Rails. This will result in each controller holding more functions and computed properties than some people like to have in one place. It also means that I can't necessarily reuse my views in another context, because they're hard-wired to the controller. And yes, this is poor Separation of Concerns. But that's not an absolute good if it causes complexity that has no payoff.
Also on the subject of Controllers, I think folks particularly tend to proliferate controllers unnecessarily for subsets of your main data model. Say you've got a products controller, and you want to store the products that a given user is collecting in a comparison tool. Most people seem to create a new controller for this, but it's perfectly legit to push these into an additional array or other Enumerable inside of your Products controller or Customers controller, or on your Customer model. This keeps objects that rely on the same functions and properties within a closer scope. The content object in each controller is, AFAIK, just another Enumerable. It has a few special implicit references to the Controller, but isn't magic. There's no functional reason I've found not to use additional ones too. They work just as well with bindings, with #each, etc.
Similarly, some people just LOOOVE to break their app down into a million files, nest them 15 deep in the file structure, etc. More power to you, if that helps you to visualize the underlying logic, and make it clear to the rest of your team. For me, it just slows me down on projects with only a 1-3 person engineering team. Folks also tend to reproduce the file-based style of other MVC systems they're familiar with (like Rails), where files are the necessary explicit structure for separating views and other logic objects. This becomes an article of faith and a deeply ingrained habit. But in Javascript MVC, I have found that it often serves no such purpose and is strictly redundant to the implicit design. I tend to use a single, carefully organized file for my entire Ember app (separating it from any other non-library JS), with lots of indentation and nesting where that helps me to visualize the hierarchy. Whatever you do, file-wise, it's all the same at runtime, provided that you deliver it all to the right place at the right time. With Ember and JS, file structure is for the needs of your team, and nothing else. Calibrate accordingly.
(IMPORTANT CAVEAT: if you do use a million files, you'd better be using a pre-compiler to manifest them all together for delivery to the user, or you're going to take a huge latency hit on delivering all those files separately.)
(ANOTHER IMPORTANT CAVEAT: with a large team or a rapid daily release schedule like GitHub's, file-based separation of your logic can make version-control easier than doing lots of merges into the same file, where your merge tool may get confused. Again, this is an issue of managing and monitoring your human processes, and doing merges carefully, rather than a technical requirement imposed by your JS framework.)
(LAST IMPORTANT CAVEAT: Then again, sometimes the difference between a technical requirement and a human/procedural requirement is fuzzy. If you break your developer's brain, you also tend to have a broken app. So, do what works for the people and processes you have to deal with in getting it built.)
As I said before, YMMV. I'm not a coder God, as you can tell from my reputation score, so you may feel free to disregard me. But I stand behind the idea that you should use only as much complexity, only as much file-structure, and only as many higher-level abstractions (like routing, which may actually be overkill for limited-purpose single-page apps) as serves your needs; and no more.
I think we are developing a quite large ember app (about 45 views at the moment). It implies almost the same count of controllers and templates).
Indeed our router is quite large, but we manage it quite easily by splitting it into many files. Basically, each file represent one screen of the app and is responsible for maintaining a functional set. Here is an extract of the router:
Router = Ember.Router.extend({
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
unlogged: Ember.Route.extend({
route: 'welcome',
connectOutlets: function (router) {
var applicationController = router.get('applicationController');
applicationController.connectOutlet('welcome');
}
}),
logged: Ember.Route.extend({
route: 'app',
projects: Ember.Route.extend({
route: 'projects',
collection: ProjectsRoute,
member: ProjectRoute,
showProjects: function (router) {
router.transitionTo('projects.collection');
}
})
})
})
Then it the same in the ProjectRoute. Each time there seems to have to many feature in one route, we split it.
You can even reopen a route to extend it, and to plug other functionnality in it.
ProjectState.reopen({
scenarios: ScenariosRoute,
showScenarios: function (router) {
router.transitionTo('scenarios.collection');
}
});
It implies more files, but with a good organization, it's no hard to maintain, as it's very rare you work on all features at the same time. Usually, I have nore more 4 opened files simultaneously (view, controller, template, route)
I don't know if it's a best practice, but it works pretty fine for us
Related
I'm building/managing a django project, with multiple apps inside of it. One stores survey data, and another stores classifiers, that are used to add features to the survey data. For example, Is this survey answer sad? 0/1. This feature will get stored along with the survey data.
We're trying to decide how and where in the app to actually perform this featurization, and I'm being recommended a number of approaches that don't make ANY sense to me, but I'm also not very familiar with django, or more-than-hobby-scale web development, so I wanted to get another opinion.
The data app obviously needs access to the classifiers app, to be able to run the classifiers on the data, and then reinsert the featurized data, but how to get access to the classifiers has become contentious. The obvious approach, to me, is to just import them directly, a la
# from inside the Survey App
from ClassifierModels import Classifier
cls = Classifier.where(name='Sad').first() # or whatever, I'm used to flask
data = Survey.where(question='How do you feel?').first()
labels = cls(data.responses)
# etc.
However, one of my engineers is saying that this is bad practice, because apps should not import one another's models. And that instead, these two should only communicate via internal APIs, i.e. posting all the data to
http://our_website.com/classifiers/sad
and getting it back that way.
So, what feels to me like the most pressing question: Why in god's name would anybody do it this way? It seems to me like strictly more code (building and handling requests), strictly less intuitive code, that's more to build, harder to work with, and bafflingly indirect, like mailing a letter to your own house rather than talking to the person who lives there, with you.
But perhaps in easier to answer chunks,
1) Is there REALLY anything the matter with the first, direct, import-other-apps-models approach? (The only answers I've found say 'No!,' but again, this is being pushed by my dev, who does have more industrial experience, so I want to be certain.)
2) What is the actual benefit of doing it via internal API's? (I've asked of course, but only get what feel like theoretical answers, that don't address the concrete concerns, of more and more complicated code for no obvious benefit.)
3) How much do the size of our app, and team, factor into which decision is best? We have about 1.75 developers, and only, even if we're VERY ambitious, FOUR users. (This app is being used internally, to support a consulting business.) So to me, any questions of Best Practices etc. have to factor in that we have tiny teams on both sides, and need something stable, functional, and lean, not something that handles big loads, or is externally secure, or fast, or easily worked on by big teams, etc.
4) What IS the best approach, if NEITHER of these is right?
It's simply not true that apps should not import other apps' models. For a trivial refutation, think about the apps in django.contrib which contain models such as User and ContentType, which are meant to be imported and used by other apps.
That's not to say there aren't good use cases for an internal API. I'm in the planning process of building one myself. But they're really only appropriate if you intend to split the apps up some day into separate services. An internal API on its own doesn't make much sense if you're not in a service-based architecture.
I cant see any reason why you should not import an app model from another one. Django itself uses several applications and theirs models internally (like auth and admin). Reading the applications section of documentation we can see that the framework has all the tools to manage multiple applications and their models inside a project.
However it seems quite obvious to me that it would make your code really messy and low-performance to send requests to your applications API.
Without context it's hard to understand why your engineer considers this a bad practice. He was maybe referring to database isolation (thus, see "Working multiple databases" in documentation) or proper code isolation for testing.
It is right to think about decoupling your apps. But I do not think that internal REST API is a good way.
Neither direct import of models, calling queries and updates in another app is a good approach. Every time you use model from another app, you should be careful. I suggest you to try to separate communication between apps to the simple service layer. Than you Survey app do not have to know models structure of Classifier app::
# from inside the Survey App
from ClassifierModels.services import get_classifier_cls
cls = get_classifier_cls('Sad')
data = Survey.where(question='How do you feel?').first()
labels = cls(data.responses)
# etc.
For more information, you should read this thread Separation of business logic and data access in django
In more general, you should create smaller testable components. Nowadays I am interested in "functional core and imperative shell" paradigm. Try Gary Bernhardt lectures https://gist.github.com/kbilsted/abdc017858cad68c3e7926b03646554e
I'm making an essay about AngularJS vs EmberJS. In here I compare these two with different questions and at the end a decision is made for which one is better for developing web applications based on the answers of these questions.
One question that I have struggled with for EmberJS is about maintainability. I haven't been able to find one article that gives information about this, unlike AngularJS.
I would like to know how does EmberJS helps you maintain your EmberJS web application. What concepts or whatever, does it provide to help you achieve a high level of maintainability for your web applications build with EmberJS.
Thank you for any help regarding answering this question.
How does Ember help you maintain your application?
Some of this is subjective/debatable, but in the spirit of essays, here are some points for Ember in terms of maintainability:
Because Ember is so highly opinionated, it makes it really easy for other Ember developers to understand your project quickly and pick up where you left off. While the framework has a pretty infamous learning curve, once you're comfortable with Ember, most applications share a lot of similarities. Ember has a prescribed 'way' for doing most things -- from file structure to REST api interaction. If you've worked on one Ember project, moving in to do maintenance on another should feel very familiar. It's a big, standardized toolbox.
The Ember Inspector browser plugin gives you a lot of transparency into what's going on beneath the hood of your application. It's very helpful to debug and maintain Ember apps. I haven't really seen anything yet that's quite the same for other frameworks. (https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi?hl=en)
Ember's handlebars templates don't allow you to put complex logic in your template. Any "if" check in a template must refer to a boolean value. This means less places to look to track down what you need to work on, and more testing of raw functions because your view isn't handling more than basic logic. It also encourages more readable templates.
Ember comes with built-in tooling for unit tests, integration tests, and end-to-end tests. This encourages devs to build tests for their applications or contribute to the existing tests of a project. Tests are good for maintainability.
Good luck!
This is more of an exploration question.
We have been using breeze.js in our projects for a while and have been quite satisfied with it; it ties nicely into concepts we already know and use (change tracking, metadata, backend agnostic...)
Now we are evaluating the possibility to move our front-end from backbone/marionette/knockout stack to ember.js (which seems to be more of a complete framework than a "pick-only-what-you-need" approach in backbone). We are exploring to possibility to keep using breeze.js as our data management layer on the client-front.
But how can the integration of models returned from the server (server stack: node.js + mongoDB) be done with models defined by ember.js?
A typical ember model definition could be:
var Person = Ember.Object.extend({
Property1: 'foo',
Property2: 'bar'
});
where you can see the extension "Ember.Object.extend"
Breeze.js upon receiving data from server attach a AspectEntity to them (and if Knockout is defined, wrap properties in observables ). How could returned objects somehow be "transformed" into ember.js objects?
Maybe the way we approach this problem and the way we think about this integration is totally wrong or that we should entirely reject this "ember-breeze" combo. From google search we have not found cases where breeze is used with ember.js or some guidance. That is why we come to the stackoverflow community: is it possible? what are the possible pitfalls to look ahead?
There does not seem to be much in the way of existing solutions. The Breeze.js User Voice has some 2-year-old issues that never got much traction; support from that library does not seem to be imminent.
I would recommend exploring Ember-Data as your data management layer. It supports many (if not all) of the concepts you mentioned, and it's the default recommended data library for Ember applications.
That said, as far as trying to make Breeze.js work, you could probably take the objects returned from Breeze and turn them into Ember.Objects using Ember.Object.create, but you'd have to build a layer between Breeze and Ember that essentially serializes between Breeze objects and Ember objects in both directions.
I have been working with Ember Data and i'm trying to understand some concepts. I have a quite heavy data intensive app, my back-end has endpoints that return a lot of records.
So, basically i have Route's that have something like this.store.findAll('places') which can return thousands of places having each one several text intensive fields like services or description.
This is only one of the resources, there are a few more that handle that amount of data as well.
My main concern is that the app hits some kind of limit or becomes unresponsive. So my question is that: How does Ember Data manage large amount of records ? Is there any best practice to handle those kind of scenarios ?
How does Ember Data manage large amount of records?
The same way as it handles a small amount of records. It's not going to do anything special for performance if you try to load/fetch a large number of records. You need to handle that yourself.
Is there any best practice to handle those kind of scenarios?
Unfortunately, no. Pagination of some sort is really the only way to accomplish this. But as you can see in this thread, there's quite a bit of discussion about the "best" way to do it. There are adapters and plugins made to handle this scenario, as well as server-side boilerplate designed to make it easy. But there really is no canonical way of doing pagination with Ember Data.
In my opinion, the best way to handle large amounts of data is to design a query endpoint and implement it on your server, handling everything yourself. This will be the most tailored to your application and the easiest to understand. If it sounds complicated, that's because it is. Data set segmentation/pagination is not a simple problem to solve, you will definitely run into issues along the way. That's why there's no agreed-upon best practice yet.
Update: Javier Cadiz mentioned the JSON API in the comments so I thought I would mention it. The JSON API does seem to be the new defacto standard for Ember Data, and it does specifiy a pagination method. However, the JSON API is fairly new and isn't widely adopted yet. I believe it wasn't until very recently that Ember Data switched to the JSON API adapter as its default. Using this pagination would mostly likely require you to conform to the entire API, not just the pagination aspect. (Although you can always steal certain ideas from it.) Because of that, I'm not sure if I'd call it a best practice just yet.
Bottom line: the JSON API way of pagination may be the way of the future, but it's not currently very popular. (Although that's just my opinion based on what I see/read. There's no saying how many people are using it privately.)
This question is subjective by nature, but I am curious about a specific thing, so hopefully there is a decent answer.
I tend to be a little old fashioned and like to create all my pages static and get the design just the way I like it (or at least very close) before I start breaking it down into handlebars and components and templates. This is mostly because the Ember "Getting Started" Guide taught me that process.
Is this the common practice, generally?
I am the front-end Designer and Developer for my company, and basically I have two separate workflows, one for Design, and one for Development/Testing.
Is there a way to merge the two and get a single streamlined workflow (perhaps a JS task that can split up static pages into templates by using some special markup??)
Design tends to be a little easier when you are working with static pages.
Development (especially when using EAK or Ember-CLI) expects everything to be modular and dynamic.
Is there any clear answer to this question?
I posted a similar question on Ember Forums, but have not gotten many view, so I figured I would try here.
Short answer when you're building an app with Ember you want to build around the URL structure, due to the way the URL and Router interact. Here's an awesome talk by Tom Dale about the URL. This makes it a very outside in approach, since each layer deeper in the url is content that's generally embedded 1 level deeper in the page.
http://vimeo.com/68390483