Are you looking to update a rakish application, which you have been chipping away at from a long while and not ready to do so in light of its dynamic customer base and the financial worth it brings to the table, at that point this insight will illuminate you to make the ideal strides expected to relocate a precise application and why it is the need of great importance.
As of today, the source of information is far beyond expectation, however are we presented to the correct sort of data that we are searching for? Specific occasions not, such is the situation when teams are moving the precise applications and giving it the ideal engineering.
So here are the problems are that looked by large number of ng-applications and how can we defeat them:
- Brittle Architecture
- Mediocre Performance
- Spaghetti data flow
- Lack of implementation of SOLID principles
Let us look at each of those setbacks.
In spite of the fact that the architecture of your application is great however not sufficient, which means it is not utilizing the full-fledged features of Angular.
The one significant issue teams are confronting is to ready to adapt up to the constant change requests.
Most of the time this situation arises, when we are making changes in the functionalities of a piece of the framework, which will out of the blue can cause reactions in other, which in the outcome delays the timeline, as you need to test the entire framework sometimes for the surety.
If you are dealing with such circumstances more often, then you need to work upon your system engineering.
As teams are not exposed to the concepts of dynamic components (explained in the later part) the applications are not exceptionally wealthy in terms of performance.
For instance, there is a common scenario of the component having n number of children, so what happens is user interacts with one or two children and not with everyone every time, so the problem is that the DOM gets heavier each time a child is added and thus increasing the loading time.
Spaghetti data flow
As the application grows, interactions between the Lego blocks of application also increase, which often results in unexpected data flow in our system.
These scenarios are very difficult to debug as the developer is not fully aware of which communication with services or Input & Output, changed the state. Unfortunately, such stuff is always difficult to control in programming.
Lack of implementation of SOLID principles
SOLID stands for
- S — Single responsibility principle
- O — Open closed principle
- L — Liskov substitution principle
- I — Interface segregation principle
- D — Dependency Inversion principle
In object-oriented computer programming, SOLID is an acronym for five design principles intended to make software designs more understandable, flexible, and maintainable.
It is not related to the GRASP software design principles. The principles are a subset of many principles promoted by American software engineer and instructor Robert C. Martin.
Though they apply to any object-oriented design, the SOLID principles can also form a core philosophy for methodologies such as agile development or adaptive software development.
For detail implementation of SOLID principles, you can refer to this very informative article.
To overcome these setbacks several design patterns needs to be implemented.
In simple terms, Lazy Loading is loading the feature modules of the application on run-time, or we can say on-demand.
The most important concepts of application performance are Response Time, and Resources Consumption.
Response Time: This is the time it takes the web application to load and the UI interface to be responsive to users. Lazy loading optimizes response time by code splitting and loading the desired bundle.
Resources Consumption: Humans are impatient creatures if a website takes more than 3 seconds to load, 70% of us will give up. Web apps should not take this long to load. So, to reduce the amount of resources loading, lazy loading loads the code bundle necessary at a time.
Lazy loading speeds up our application load time by splitting it into multiple bundles and loading them on demand.
Advantages of lazy loading:
- High performance in bootstrap time on initial load.
- Modules are grouped according to their functionality.
- Smaller code bundles to download on initial load.
- Activate/download a code module by navigating to a route.
Dividing the application into Core, Shared & Feature Modules
One of the goals Angular Projects should be is to make Modules & UI Components more reusable. To achieve this, we need to make sure the code is well-isolated and have a simple and clear dependency model.
When building small ng-apps, we more often tend to come up with project structure like this:
The code is structured by technical perspective dividing it into Components, Directives, Services, Models etc.
When creating an enterprise solution, it is always recommended structuring code in terms of feature modules, which is also suggested by Angular Style Guide which might look like this:
The code becomes also more flexible to changes as features are isolated from other feature modules and UI components can also be reused.
That is not it the above feature folder structure will enable us more isolation, portability, and lazy loading.
Smart & Dumb Components
First, let us define what Smart and Dumb components are.
- A Dumb Component is a component that works like a pure function.
(A pure function is a function that for given function arguments, will always produce the same return value.)
A Dumb Component is just like that. It is a component that for received data (inputs), will always look and behave the same, possibly also producing other data (events, via outputs).
- A Smart Component is a component is more like an impure function.
(An impure function is a function that touches “the outer world”: either by getting data from external services or by producing side effects.)
A Smart Component is just like that. It is not only dependent on its inputs but also on some kind of external data (“the outer world”), which is not passed directly via @Input(). It might also produce some side effects that are not emitted through the @Output() interface.
- For example, a component that gets current user data from a singleton service instantiated elsewhere; from an external API; or Local Storage. A component that changes the state of an external service; issues an API call; or changes the stored data in Local Storage.
The Dumb component is sometimes called “Pure”, “Presentational” as well. The Smart component is sometimes called “Impure”, “Connected”, “Container”.
Keep in mind: Smart vs Dumb is not Stateful vs Stateless!
People often mistake those terms, but for me, they are unrelated to each other. See as follows:
- A Dumb Component has no external dependencies and causes no side effects (but still might or might not have a local state).
- A Smart Component has external dependencies or causes side effects (but still might or might not have a local state).
MVP Pattern (Model-View-Presenter)
This one is a Game-Changer.
Model-View-Presenter (often abbreviated MVP) is an architectural software design pattern for implementing the user interface (UI) of an application. We use it to minimise complex logic in classes, function, and modules (software artifacts) that are hard to test. In particular, we avoid complexity in UI-specific software artifacts such as Angular components.
To apply the Model-View-Presenter pattern to an Angular application, our components will belong in one of these three categories:
- Presentational components (Dumb Components)
- Container Components (Smart Components)
Most of us are now familiar with Smart (Container) & Dumb (Presentation) Components, Presenters is a new term.
Presenters will contain complex presentation and business logic. The presenters will not have any UI and more often no or fewer dependencies which makes them easier to test.
The pattern beautifully explained by Lars Gyrup Brink Nielsen in his truly informative article.
Dynamic means, that the location of the components in the application is not defined at build time. That means, that it is not used in any angular template.
Instead, the component is instantiated and placed in the application at run-time.
As the application goes through agile methodology sprints it gathers component mass during its development life cycle.
One of the major problems it creates is making our DOM heavier, meaning containing several HTML stuffs at a given point of time.
The DOM of dynamically loaded components loads when we want them to, which in turn greatly improves our performance and loading time as well, and our DOM remains clean.
We have loaded dynamic components with the help of two different methods which are
- Using ComponentFactoryResolver
- Using Angular Cdk Portals & Overlay
One thing I can surely say after implementing all patterns is that if you are looking to deliver an enterprise solution or an angular app with awesome architecture, these patterns are a certain shot thing.