You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

Coding Guidelines

Ambari Web Frontend Development Environment

  • Application Assembler: Brunch

We use Brunch as the client-side application assembler: http://brunch.io/
Brunch can generate an application skeleton that is well structured with common client-side libraries (Backbone.js/Ember.js, jQuery, JavaScript/CoffeeScript, Stylus/LESS, etc). Build and deploy automatically in the background as you modify the source files. This lets you break up the application into a number of JS files for code organization and reuse without worrying about runtime load performance. For QA/production deployment, we can turn on JavaScript/CSS minification for fast application loading. Run automated tests.Run a Node.js-based web server with a single command so that you can easily run the application from the application root directory without any special configuration.

Install Node.js from http://nodejs.org/.
We have created a Brunch-based application and checked it into Github. To check out the project from the Github repository, run:

git clone  git://git.apache.org/ambari.git
cd ambari-web
sudo npm install -g brunch
npm install

To run the web server (and to enable continuous build/deploy), run:

brunch watch --server

Or use the shorthand: brunch w --s

  • IDE: PhpStorm

All front-end developers should use PhpStorm by JetBrains. JetBrains has granted all contributors of Apache Ambari a free license for PhpStorm and IntelliJ (if you also need to do Java development - IntelliJ is a superset of PhpStorm, but PhpStorm is lighter so it is recommended if you are not modifying Java code).

  • IDE Plugins

Go to Preferences->Plugins->Browse repositories and install “Node.js” and “Handlebars” plugins.
Coding Conventions

Before checking in any HTML/JavaScript/CSS files, they must be formatted with the IDE to maintain consistency.
Also, the IDE will give warnings in the editor about implicit globals, etc. Fix these warnings before checking in code.
IDE Code Formatting Customization

We will use all default settings for Code Style in the IDE, except for the following:

Go to Preferences
Code Style->General
Line separator (for new files): Unix
Make sure “Use tab character” is NOT checked
Tab size: 2
Indent: 2
Continuation indent: 2
Code Style->JavaScript:
Tabs and Indents

Make sure “use tab character” is NOT checked
Set Tab size, Indent, and Continuation indent to “2”.
Spaces->Other
Turn on “After name-value property separator ‘:’

In general, the following conventions should be followed for all JavaScript code: http://javascript.crockford.com/code.html

Exceptions to the rule from the above:
We use 2 spaces instead of 4.
Variable Declarations:
“It is preferred that each variable be given its own line and comment. They should be listed in alphabetical order.”
Comment only where it makes sense. No need to do alphabetical sorting. “JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.” This does not need to be followed.

  • Unit Testing

Unit tests are written using Mocha.
Run unit tests via
brunch test

Coding Guidelines for Ambari Backend

  • Following points are borrowed from hadoop wiki:
    • All public classes and methods should have informative Javadoc comments.
    • Do not use @author tags.
    • Code must be formatted according to Sun's conventions, with one exception:
    • Indent two spaces per level, not four.
    • Contributions must pass existing unit tests.
    • The code changes must be accompanied by unit tests. In cases where unit tests are not possible or don’t make sense an explanation should be provided on the jira.
    • New unit tests should be provided to demonstrate bugs and fixes. JUnit (junit4) is our test framework:
    • You must implement a class that uses @Test annotations for all test methods.
    • Define methods within your class whose names begin with test, and call JUnit's many assert methods to verify conditions. Please add meaningful messages to the assert statement to facilitate diagnostics.
    • By default, do not let tests write any temporary files to /tmp. Instead, the tests should write to the location specified by the test.build.data system property.
    • Logging levels should conform to Log4j levels
    • Use slf4j instead of commons logging as the logging facade.
    • Logger name should be the class name as far as possible.

Unit tests http://wiki.apache.org/hadoop/HowToDevelopUnitTests
The tests should be named *Test.java

Unit testing with databases
We should use JavaDB as the in-memory database for unit-test. The database layer/ORM should be configurable to use in memory database. Two things are important for the db in testing.
Ability to bootstrap the db with any initial data dynamically.
Ability to modify the db state out of band to simulate certain test cases.
One way to achieve the above could be to implement a database access layer only for testing purposes, but it might cause inconsistency in ORM objects, which needs to be figured out.

Stub Heartbeat handler
For testing purpose it may be a good idea to implement a stub heartbeat handler that only simulates interaction with the agents but doesn’t interact with any real agent:
It will expose an action queue similar to the real heartbeat handler, but will not send anything anywhere, will just periodically remove the action from the queue.
It will expose an interface to inject artificial responses for each of the actions, which can be used in tests to simulate agent responses.
It will also expose an interface to inject node state to simulate failure of nodes or lost heartbeats.
Guice framework can be used to inject stub heartbeat handler in testing.

EasyMock
EasyMock is our mocking framework of choice. It has been successfully used in hadoop.
A few important points:
An example of a scenario where Easymock is apt: Suppose we are testing deployment of a service but want to bypass a service dependency or want to inject an artificial component dependency, the dependency tracker object can be mocked to simulate the desired dependency scenario.
Ambari server is by and large a state driven system. EasyMock can be used to bypass the state changes and test components narrowly. However, it is probably better to rather use in-memory database to simulate state changes and use EasyMock only when certain behavior cannot be easily simulated. For example consider testing API implementation to get status of a transaction. It can be tested by mocking the action manager object, alternatively, it can be tested by setting the state in the in-memory database. In this case, the later is a more comprehensive test.
Avoid static methods and objects, Easymock cannot mock these. Use configuration or dependency injection to initialize static objects if they are likely to be mocked.
EasyMock cannot mock final classes, so those should be avoided for classes likely to be mocked.

Take a look at: http://www.easymock.org/EasyMock3_1_Documentation.html for docs.

Guice
Guice is a dependency injection framework and can be used to dynamically inject pluggable components.
Please refer
http://code.google.com/p/google-guice/wikJamiroquaii/Motivation
IMO we can use Guice in following scenarios:

Pluggable manifest generator: It may be desirable to have different implementation of manifest generator for non-puppet setup or for testing.
Injecting in-memory database (if possible) instead of a real persistent database for testing. It needs to be investigated how Guice fits with the ORM tools.
Injecting a stub implementation of heartbeat handler.
It may be a good idea to bind API implementations for management or monitoring via Guice. This will allow testing of APIs and the server independent of the implementation via mock implementations. For example, the management api implementation in coordinator can be mocked so that API definitions and URIs can be independently tested.
Injecting mock objects for dependency tracker, or stage planner for testing.

  • No labels