Last month, @ukelilybee spoke at the DublinJS conference about the use of Ember.js at Intercom

The title was: "A People's History of Ember"

The PeoplE V. EMBER

or why choosing Ember for your front-end framework in 2019 should be considered a crime against coding.

This presentation is entitled:

Stipulations

  • Ember is a front-end framework. 
  • Unlike React or Vue, (or "just the view" frameworks) Ember is a full-MVC framework.
  • It has a command line tool which makes scaffolding a new project a matter of typing "ember new" 
  • It adheres to a philosophy of "convention over configuration," (like Ruby on Rails)
  • It has a short release cycle (six weeks) and a long depreciation period (18 months.) 
  • One of Ember's key selling points is it's tight integration with it's router which makes mapping pieces of code to urls simple. 

Opening Arguments (Prosecution)

While it is possible to write good ember code
Ember makes it incredibly easy to write bad code.

Charge: Ember makes it easy to write bad code.

  • Most solutions to problems in Ember involve setting or retrieving values on "this", but this presents us with a number of problems:
     
    • It can be difficult (especially in Javascript) to determine what the context of "this" is. (Or conversely, where a context is being accessed from, via "this.")
       
    • It's impossible, without console logging a particular this, to figure out what methods and properties are available to "this" in Ember.
       
    • It is practically impossible to find out what properties and methods are part of a singleton (Ember.Service), and what are essentially parent class instances (Ember.Mixin) because both are referenced identically and look identical to debugging tools/console.log(). 

Charge: Ember makes it easy to write bad code.

Exhibit A for the Prosecution

export default Controller.extend(Noti, Modal, InputErrorParser,{
  ajax: inject('ajax'),
  userService: inject('user'),
  i18n: inject(),
  /* ... many lines of code abridged ... */
  obsShowUserForm: observer('userService.controllerUserId', function(){
    if(!isBlank(this.userService.controllerUserId)){
      this.set('selection', 'userForm')
      this.set('selectedUserId', this.userService.controllerUserId)
    }
  }).on('init'),
  obsUserModel: observer('selectedUserId', function(){
    if(!isBlank(this.selectedUserId) && this.selection === 'userForm'){
      this.store.findRecord('user', this.selectedUserId).then((fullUser) => {
        this.set('userKycRejected', fullUser.kycRejected)
        this.set('userKyc', fullUser.kyc)
        this.set('selection', 'userForm')
        this.set('userModel', new Changeset(fullUser, lookupValidator(UserValidation),UserValidation))
      })
    }
  }),
  obsCompanyEmailTerm: observer('companyTerm', 'emailTerm', function () {
    this.set('page', 0);
    this.refreshList(500);
  }),
  obsSelection: observer('selection', 'countryTerm', function () {
    if(this.selection !== 'userForm'){
      this.set('page', 0);
      this.refreshList(0);
    }
  }),
  usersEmpty: computed('selection', '{customers,pending,rejected}List', function () {
    if(this.selection === 'userForm'){
      return false
    }else{
      const list = this.get(`${this.selection}List`);
      return isEmpty(list) || isEmpty(list.user)
    }
  }),

Opening Arguments (Prosecution)

in the attempt to make Ember easy to write,
Ember has made itself extremely difficult to read, reason about, debug, or add features to.

Ember is difficult to read and debug.

Exhibit B for the Prosecution

import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
import { inject } from '@ember/service';
import { Promise } from 'rsvp';
import Route from '@ember/routing/route';
import $ from 'jquery'

export default Route.extend(ApplicationRouteMixin,{
  session: inject('session'),
  loginedUser: inject('landlord'),
  wp: inject('welcome-pack'),
  beforeModel: function(transition){
    $(document).on('click', function(event){
      if(!$(event.target).hasClass('drop-down')){
          $('.drop-down').removeClass('show');
        }else{
          $('.drop-down').not($(this)).removeClass('show');
          $(event.target).addClass('show');
        }
    })
    this._super(transition);
  },
  model(){
    return new Promise((reslove, reject) => {
      this.store.findAll('welcome-pack').then((welcomePack) => {
        this.wp.setWp(welcomePack.objectAt(0))
        document.title = this.get('wp.wp.tenantName')
        reslove()
      }, (err) => {
        reject(err)
      })
    });
  }
});
export default DS.Model.extend({
  companyLogo: DS.attr('string'), //<- had to add this line. 
  tenantName: DS.attr('string'),
  actualCompanyLogo: //<- and this line
    computed('companyLogo', function(){  
    return isBlank(this.companyLogo) 
      ? "/assets/images/logo-placeholder.png" 
      : this.companyLogo;
  })
})

Opening Arguments (Prosecution)

The "Convention over configuration" philosophy of Ember means that it is extremely difficult to learn compared to other frameworks, and once learned, is no faster to develop for than other frameworks.

CHARGE: Difficult to learn because of C-over-C

Testimony

"Before it's easy in Ember, you have to learn Ember." 

Opening Arguments (Prosecution)

The "Convention over configuration" philosophy of Ember means that a programmer who learns Ember will not find any of his skills transfer to other frameworks or general programming.

Charge: Ember skills don't transfer

Expert Witness: https://2017.stateofjs.com/2017/front-end/results

Charge: Ember skills don't transfer

Expert Witness: Google Trends

Opening Arguments (Prosecution)

Good code is "loosely coupled and highly cohesive."

By design, ember is tightly coupled and incohesive.

Opening Arguments (Prosecution)

The short release cycle combined with the long depreciation cycle means that multiple (and obsolete) ways of accomplishing the same goal are present in most long-term ember codebases, making it difficult to reason about and debug.

Opening Arguments (Prosecution)

Ember is an MVC framework that
does not do the model, View, or controller well.

The People Vs. Ember

By brianboyko

The People Vs. Ember

  • 496