Skip to content

Instantly share code, notes, and snippets.

@tonysamperi
Last active August 31, 2021 17:09
Show Gist options
  • Save tonysamperi/c69352a3b5b358e96d04ad75d5ad8c13 to your computer and use it in GitHub Desktop.
Save tonysamperi/c69352a3b5b358e96d04ad75d5ad8c13 to your computer and use it in GitHub Desktop.
UBI frontend onboarding

Environment

Premise

All of the following paths will be relative to the FE_COMPONENT folder, which is in the root of each branch. You'll need to work only in the FE_COMPONENT folder, so you should download that directly, since SVN allows you to.

So when talking about "root" we will refer to FE_COMPONENT

Branch preview

What's in the branch

The branch contains the sources of 2 projects:

  • IW Bank home banking: every folder excluding iwb-migration
  • IW Bank migration: only iwb-migration

More details will follow

Getting started

Setup NodeJS

Get the binaries of node here:

http://artl101p.hbl.local/nexus/content/repositories/raw-private/nodejs/v10.15.3/

Ensure your .npmrc config (in your %userprofile% folder) has the following lines

registry=http://artl101p.hbl.local/nexus/content/repositories/npm-public/
strict-ssl=false
sass_binary_site=http://artl101p.hbl.local/nexus/content/repositories/raw-private/node-sass/​

IDE

We choose as default IDE Microsoft Visual Studio Code. It's a good practice to keep the IDE up-to-date. We'll add a few external plugins, to have a consistent code formatting and quality:

  1. dbaeumer.vscode-eslint
  2. esbenp.prettier-vscode

A ".vscode" folder will be in the root folder, providing the IDE settings.json and (optionally) the keybindings.json config files.

A .eslintrc.json file will be in the root folder, providing the config for eslint plugin, so don't forget to run npm i before starting devs.

Note: this will enforce a consistent code-style, so for example only double-quotes will be allowed. Please do not edit the eslintrc to avoid issues.

Project structure - BANKING

This refers to the AngularJS projects (see What's in the branch)

  • /pages

    • It should basically contain all the files which arent start_pages: one folder for each feature of the home banking. Currently each folder has 3 or 4 folders inside, depending on if sass was used for that page:
      • js
      • css
      • templates
      • scss (optionally)
  • /js/states

    • Here there's all the configuration for the app routing. Each route can be defined in core.js and optionally (preferably) the template config of that route can be defined in nav.js

IWB Migration

Intesa landing page

You can find the new landing page for migration under pages/intesa. The page basically generates an iframe, loading the iwb-migration dist. The handleSocketMessage handles events from the Angular app, to trigger actions (such as navigation or session refresh) into the AngularJS app.

Be sure to check that the getIframeUrl fn matches the output of the Angular build, the expected is:

const getIframeUrl = function () {  
    if (!window.sysEnv || window.sysEnv === "SVI") {  
       return "http://localhost/iwb-migration/dist/ubi-app-local";  
  }  
  
    // eslint-disable-next-line compat/compat  
  return [location.origin, "cs/qui/iwb-migration/dist/ubi-app", ""].join("/");  
};

Homepage dialogs

In the UBI migration, we created several dialogs, with different templates, according to the migration profile of the logged user. Refer to the UBI branch under js/app/route-callbacks/USER_CHECKS and js/app/route-callbacks/route-callbacks.service. The service contains the instructions to handle the USER_CHECKS callbacks, which are triggered by the route change, when entering the lpHome (see js/states/core.js).

Additional menu item (Intesa / Fideuram)

In the sources a new menu item "Intesa" has been added in js/app/servicesMock/Utility/GetMenu.json, and the related route has been configured in the core.js. Locally everything is supposed to work fine. To enable the additional item remotely you need to update the JSON files usually referring to some UBI/IW employee. To handle conditional menu items you need to add logics in js/app/appUtils.js, in the method getMenu

getMenu

Disable mocks remotely

In order to give the client a preview of the app, currently environment.prod has the mocksEnabled property set to true. IMPORTANT: remember to set it to false to enable real calls after deploy.

Do's

1) File naming

To have consistency and immediate perception of what a file does, we should use the following convention: feature-content-name.content-type.ext

We don't have a prefix ID for the Home Banking project, but we could start using one now. Something like nbd (Nuova Banca Digitale, even if it's not that new after all 😂). The prefix is useful to recognize immediately project components from external ones.

So for example while creating a directive for a dialog which shows the login for the pages in "Multibanca", I would go:

  • multibanca-access-dialog.directive.js
  • multibanca-access-dialog.directive.scss
  • multibanca-access-dialog.directive.html

or, if we choose to add the prefix:

  • nbd-multibanca-access-dialog.directive.js
  • nbd-multibanca-access-dialog.directive.scss
  • nbd-multibanca-access-dialog.directive.html

The js contents will have to show consistency with the file naming, so it's likely that the directive inside would be called MultibancaAccessDialog or NbdMultibancaAccessDialog.

2) Code quality 1

When a feature is complex or for example it contains a <wizard> it's a good thing to have compartmentalized business logics. So each step may have a dedicated controller and html file: a good controller must do few good things rather than many messy things.

3) Use of controller aliases

The controller boiler you can find in the /pages/boiler folder

In order to handle multiple controllers in a single feature, controller aliases allow a better control over data in nested controllers. Every new controller must be used with an alias.

E.g. a controller named fooController should have in the html:

<something ng-controller="fooController as foo">...</something>

A boiler will be in the /pages/boiler folder with the js file and the related html and css, as you can see in the picture above.

4) Code quality 2

  • Methods should never exceed 30-35 line of code. If you're writing longer methods, they probably do different tasks, but this is bad for code comprehension and maintenance.

  • If your code contains too many "if-else" then you should probably think of another way of writing it (e.g. map methods into a object or class).

5) Code quality 3

Private, Protected, Public, Readonly

There's no such thing as modificators when using plain javascript which complains with the AngularJS project scope.

BUT

Since controllers will benefit of the inheritance chain, we can consider everything under the $scope instance as public while everything else is private. So the $scope should contain only what will be actually used in the view.

By following this approach, code will be more maintainable and easy to read and most importantly it will be more efficent!!!

6) Variable naming

The general rule is to use camelCase, but it's a good practice using PascalCase for providers.

Variables name must have a meaning, suitable with the content.

7) Use of functions

Functions should be created inside controllers only when they're not meant to be static. Static functions can be imported through RequireJs, since they might perform operations which may be shared across several controllers.

To be more clear: let's avoid duplicated code as possible!!!

8) Styles

All of CSS rules should be lowercase-hyphenated (AKA kebab-case) Adding a prefix is also very very good:

  • To recognize custom rules from ones provided by libraries (such as Bootstrap)
  • To avoid conflicts among rules with may have too generic names

A good rule name would be: .ubi-margin-2x { margin: 16px; }

9) Code quality 4

Please let's not do this

This is exactly how NOT TO WRITE A GOOD CONTROLLER

In the picture above we can see 4 don'ts in 1: creation of undefined props (totally useless), tons of assigns, useless variables and an unnecessary logic operation on CANALE (CANALE exists, because it's in the constant NbdConstant. If anybody ever damages that constant there would be problems anywhere in the project, so I think we would notice).

Due to CI (yui-compressor) compile problems, we cant use most of the ES6 features, like the use of let. We can use const, though. So when a variable is not reassigned, remember to use const instead of var. One good thing we can use, is lodash, which would let us write the above as:

_.extend(ContoPagaRate.simulaPrenotazionePianoRequest(), {
   canale: NbdConstant.canale,
   rapporto: $scope.rapportoModel.rapporto,
   importoPiano: $scope...blah...blah.importo
});

This will avoid time loss and data loss (in the example approximately 100 bytes. Imagine how much loss is there in an entire controller and in all controllers which are loaded during navigation). But more importantly it will make the code more easy to read and maintain.

Dont's

1) Use of the $rootScope/window for data sharing

This is the most evil thing you can do with AngularJS. If you really need a layer to pass data anywhere, you create a factory for that purpose.

2) Use of functions inside bindings or inside $watch

This is the second most evil thing you can do with AngularJS.

When you put a function inside an attribute, that function will be called several times in each digest. In 100% of the cases it's useless, because you can control dynamically your value through your controller. Compared to this bad practice a $watch is more or less 10 times better, since it's called less times.

Another bad practice is watching functions. In 99.999% of the cases, it's useless. This practice should be your very last resource.

3) Use of jQuery ($) or even VanillaJS to manipulate DOM

This can't be done. For real. AngularJS is in the dark about your actions if you do so. The right way of manipulating the DOM in AngularJS is through directives.

4) Use of $timeout

If something is not updating properly is your fold 100% of the times. So try to figure out why. There might be cases where a bad plugin integration (some bad directive) is actually not working and in that case you're allowed to use $scope.$evalAsync, so you don't ever need $timeout.

5) Vintage tags

We are in 2021 and web is evolving faster and faster. So we try to avoid old stuff such as:

  • <b> (<strong>)
  • <i> (<em>)
  • <u> (CSS text-decoration: underline)
  • <input type="button" value="foo"> (<button>foo</button>)

6) CSS classes with no matching rule

If you suspect that a css class on some element is useless, try removing it! It's ultra simple from the inspector: you just have to uncheck a checkbox. This will save a lot of useless data and will keep easier to read and edit your HTML!

7) Useless vars / functions / files

Useless function, since it gets called only once

The creation of vars which are pointless is way too frequent.

A few examples:

  1. vars before return
  2. functions called once (see picture)
  3. functions which call functions
  4. entire "pages" folders cloned (V2) and 1 files used actually
  5. Creation of object with undefined/null properties

8) Useless imports and injections

If you added some files in the "define" or "require" call in a js file, it will probably cause an http call to get a file. If you added some params to your controller function, it will certainly cause calculations and memory use. For nothing.

9) Inline styling

The extreme evil for maintenance is inline style. Stylesheets exist specifically to group rules. And it's very important to use them in a good way, especially where components doesn't get encapsulated! So it's a very good practice to define an attribute (or a classname) for the main container (usually the div which has padding-container-wrap in the classlist) and write all rules accordingly (using sass you will simply wrap everything with that attr).

10) Use of !important

This is a real pain in the ass, especially when changing a general rule, which may affect other elements. When a rule doesn't work, you must ask yourself why. Then go and read the "style" paragraph in the "Do's" chapter.

11) Double negations

Really. I've seen stuff like if(!angular.isDefined) or !angular.isUndefined.

Can we please not do this? Pretty please?

12) ng-init

The ng-init directive has a precise purpose which is not running functions you declare in your controller. If you have no clue of what the ng-init directive really does, then you shouldn't use it. In most of the cases a local function like const init = function(){ ... }; called from the bottom of your controller is more than enough.

13) $broadcast and $emit

This is worse than the ng-init, because these events can travel across multiple scopes.

The absolute worst is something like $scope.$root.$broadcast('someEvent').

In 99.999% of cases this is totally useless and causes an extraordinary effort for the application. Also this practice may easily lead to undesired behaviours. So use this if you really know what you're doing.

But just know that there's RxJS in the project, so you may want to explore that! 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment