Coding conventions
See original GitHub issueBackground
A lot of work was done on UI refactoring (https://github.com/OHDSI/Atlas/issues/633), many initials ides were rethought during the evaluation, a lot of new things were brought into and finally, I feel that we are ready to write down and agree on new coding conventions to make contribution requirements transparent and our codebase - consistent.
Proposal
General patterns
- Folder nesting should follow /split-by-type/split-by-domain/split-by-type/… approach
- All component containers should use ES6 classes. No methods should be defined in
constructor
Project structure
/components
- UI component which is used across two or more different pages sections (folder under /pages) should be placed under
components
folder - Component typically consists of controller, template and styles files; it may also include data models and component-specific utils
- Each component’s controller should extend
Component
class - If a component has methods that are used in a view, it should be decorated by
AutoBind
class (e.g.class FanceSelect extends AutoBind(Component)
to preserve context for those methods - Components should be atomic and follow ‘file per component’ principle. A single file shouldn’t register (export) multiple custom tags
/config
- To store all configuration variables
/extensions
- /bindings - to store Knockout bindings
- /data - to store JSONs and CSVs
- /ko-extenders - to store Knockout extenders
- /plugins - to store RequireJS plugins
/pages
- each tab in nav menu should be represented by folder under /pages
- each nested folder should contain:
index.js
which exports an object with fieldstitle
,buildRoutes
,baseUrl
,icon
routes.js
which exports a function returning routes (either protected by athorizationRoute#AuthorizedRoute
or publicRoute#Route
)const.js
which exports rest url builders, constantscomponents
folder that contains pages components and their nested UI componentsservices
folder if there are more than 2 services- other split-by-type folders to store more than 2 entities of a type used across the section (e.g.
models
,utils
, etc)
- each page should extend Page
- router params should be observed via
onRouterParamsChanged
/resources
- /libs - to store external JS libraries
- /styles - to store application-level styles
- /images - to store application-level images
- /fonts - to store application-level fonts
/services
- To store application-level methods for communication with backend
- May have nested domain-based folders to store appropriate data classes
/utils
- To store utility methods which should be represented by pure functions (no side effects)
To be refactored
/data -> /resources/data /providers -> to be removed by putting stuff into context-specific locations /modules/circe/components -> /components/circe /modules/conceptpicker -> /components/conceptpicker /modules/conceptsetbuilder -> /components/conceptsetbuilder /modules/databindings -> /extensions/bindings /modules/job -> /services/job /modules/plp -> /pages/plp/services /modules/WebAPIPRovider -> /services
Libraries
- It is restricted to use jquery ajax in favor of
/services/http.js
- It is highly recommended to avoid usage of jQuery in favor of Vanilla JS
- It is highly recommended to use Lodash methods instead of introducing new ones
Styling
- All style files should be coded using LESS and levereging benefits of the transpiler
- Styles should be written according to BEM methodology
Dependency management
All external libs should be installed via NPM
Build process
Webpack is a build tool to produce resulting JS and CSS bundles
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (2 by maintainers)
Top GitHub Comments
@chrisknoll thanks for doing all of this digging into dependency management and the build process. In an effort to help myself understand this discussion a bit more, let me attempt to summarize: we currently use AMD module loading (via requireJS) to load up JavaScript dependencies. The upside to this approach is that only the modules that are required to support a page are loaded. The downside is that it can be quite chatty between the client/server when there are a large number of required elements. A build process could be utilized here to create a single unit in JavaScript for those larger “chunks” of the application that are used. I believe this is what you are proposing above when you say:
Let me know if you see any gaps in this summary. Oh and one more item to add to this list:
Code Formatting
Per #655, we’d like to adopt EditorConfig need the ability to have a consistent set of rules for formatting source code. Furthermore, we need a set of standards for our JavaScript code to ensure there are no unused variables, things are declared as
const
, etc. We could consider using EditorConfig with Prettier with ESLint as described in this article:https://survivejs.com/maintenance/code-quality/code-formatting/
and here:
https://stackoverflow.com/questions/48363647/editorconfig-vs-eslint-vs-prettier-is-it-worthwhile-to-use-them-all
I welcome any thoughts on this topic - I have no practical experience with these but they are fairly popular and hope that others might have used them and can provide their feedback.
It seems we need to resolve this as we go into ATLAS 3.0.