Chitika

November 14, 2012

JavaScript modularity with RequireJS (from spaghetti code to ravioli code)

Today I would like to describe how you can make your JavaScript code much much much better.

We know a lot about how to make our c# code much better. And we always use it.
We split out our c# code to classes, put the classes to modules, put the modules to layers, etc.

But we never do the same for our JavaScript code. And this is a big mistake.

And that's why we have a lot of Spaghetti Code inside our apps.

The main problems with function spaghetti code are:

  • It's really hard to figure out where the one block of code begins and where the other ends
  • Who's responsible for what?
  • How are we deal with global scope pollution (e.g. use the same variables in different pieces of code)
  • Low code re-use
  • Not easy to maintain, test and debug.

I'm not going to describe in details what the functional spaghetti code is, because you can find a lot of references in the Internet.
I would like to show here how to avoid it and make your code better using RequireJS.

Function spaghetti code

Let's start with a simple example of spaghetti code. (I can't say that it is really good example of horrible spaghetti code, but it is simple, so it's easy to understand and see all the changes)

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Phase 1</title>
</head>
<body>
    <div>
        <h1>Modular Demo 1</h1>
    </div>
    <div id="messagebox"></div>

    <script src="../Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>

    <script type="text/javascript">

        var baseUrl = '/api/messenger/';

        function ShowMessage(id) {
            $.ajax({
                url: baseUrl + id,
                type: 'GET',
                dataType: 'json',
                success: function(data) {
                    $("#messagebox").html(data);
                }
            });
        }

        var id = 55;
        ShowMessage(id);
        
    </script>
</body>
</html>

As you can see it's really simple example. The code sends ajax request to get a message from server and then puts this message to div container.
This code is correct and works well. And at the same time not perfect but is an example of spaghetti code.

All of your code logic (sending the request, putting a message to a div container) located in the same function.

I would like to repeat again, that it is not perfect example, but we need really simple one to better undersand how we can improve it.

JavaScript modules

First of all I would like to describe how you can use the module pattern to create a module in JavaScript.

Let's start with an example first.

        var messenger = (function ($) {
            var text = 'I am a module',
                showMessage = function() {
                    $("#messagebox").html(text);
                };

            return {
                showMessage: showMessage
            };
        })($);

That's it. You have a module - messenger.
This module has internal part:

            text = 'I am a module',

And exposes externally function:

            return {
                showMessage: showMessage
            };

So, for the other code only showMessage will be visible.
And it is really simple to use it:

            messenger.showMessage();

Also in this example our module depends on jQuery. You can see it here:

        var messenger = (function ($) {
            . . .
        })($);

As you can see it's really simple to create a module in JavaScript.

Let's see how we can re-factor our code.

Ravioli code

When you eating the ravioli you are totally sure where is the one ravioli and where is another one.
Also, to take SRP (single responsibility principle) into account we have to separate our code into modules which have only single responsibilities.

This is the result:

        var config = (function() {
            var baseUrl = '/api/messenger/';

            return {
                baseUrl: baseUrl
            };
        })();

        var dataservice = (function($, config) {
            var callApi = function (url, type, callback) {
                    $.ajax({
                        url: url,
                        type: type,
                        dataType: 'json',
                        success: function (data) {
                            callback(data);
                        }
                    });
                },
                getMessage = function (id, callback) {
                    url = config.baseUrl + id;
                    callApi(url, 'GET', callback);
                };

            return {
                getMessage: getMessage
            };
        })($, config);

        var messenger = (function ($, dataservice) {
            var showMessage = function(id) {
                dataservice.getMessage(id, function(message) {
                    $("#messagebox").html(message);
                });
            };

            return {
                showMessage: showMessage
            };
        })($, dataservice);

        (function (messenger) {
            var id = 55;
            messenger.showMessage(id);
        })(messenger);

As a result we have 4 modules. Let's describe them:

  • config module - for storing our global variables
  • dataservice module - for doing communication with the server (sending ajax requests and getting the response back)
  • messenger module - for showing a message (placing a message into containers)
  • main module - as starting point of our app

And it's really easy now to change our modules if needed, for example if we will decide to change our communication mechanism with the server, or to change our messenger to show a message into jQuery dialog.

Split out your modules

The next step is splitting your modules out into JavaScript files.
Because it is not really good solution to place your JavaScript code into HTML.

At the end you will have four JavaScript files.

config.js

        var config = (function() {
            var baseUrl = '/api/messenger/';

            return {
                baseUrl: baseUrl
            };
        })();

dataservice.js

        var dataservice = (function($, config) {
            var callApi = function (url, type, callback) {
                    $.ajax({
                        url: url,
                        type: type,
                        dataType: 'json',
                        success: function (data) {
                            callback(data);
                        }
                    });
                },
                getMessage = function (id, callback) {
                    url = config.baseUrl + id;
                    callApi(url, 'GET', callback);
                };

            return {
                getMessage: getMessage
            };
        })($, config);   

messenger.js

        var messenger = (function ($, dataservice) {
            var showMessage = function(id) {
                dataservice.getMessage(id, function(message) {
                    $("#messagebox").html(message);
                });
            };

            return {
                showMessage: showMessage
            };
        })($, dataservice);

main.js

        (function (messenger) {
            var id = 55;
            messenger.showMessage(id);
        })(messenger);

Also, we have to change our HTML to load all of these JavaScript files.

index.html

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Phase 1</title>
</head>
<body>
    <div>
        <h1>Modular Demo 1</h1>
    </div>
    <div id="messagebox"></div>

    <script src="../Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>

    <script src="config.js" type="text/javascript"></script>
    <script src="dataservice.js" type="text/javascript"></script>
    <script src="messenger.js" type="text/javascript"></script>
    <script src="main.js" type="text/javascript"></script>
   
</body>
</html>

Finally, our code looks much better now.

Loading modules in proper order

Everything almost perfect in our code, except of loading scripts in the proper order.
Honestly, we do this task, but we do it manually.
Everything changes if you decide to order your modules in HTML files in alphabetical order.

    <script src="config.js" type="text/javascript"></script>
    <script src="dataservice.js" type="text/javascript"></script>
    <script src="main.js" type="text/javascript"></script>
    <script src="messenger.js" type="text/javascript"></script>

I've just put the module main.js above messenger.js. And unfortunately it has really changed behavior of our app.
Instead of showing a message it shows an exception now.

Line: 1
Error: 'messenger' is undefined

It has been happened because we changed the order, and module main.js has been loaded before messenger.js. As a result module main.js tries to call messenger.showMessage(), but the messenger is undefined, because it has not been loaded yet.

Of course, in this simple example we can easily control the order of the four scripts, but in a real application we can manage 30, or 50 or even more modules.

And it becomes a serious problem.

In this case RequireJS can really helps.

RequireJS

The following command in the Package Manager console will install RequireJS package into your ASP.NET application:

PM > Install-Package RequireJS

RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node. Using a modular script loader like RequireJS will improve the speed and quality of your code.

In other words RequireJS really helps:

  • To define our modules
  • To resolve module dependencies
  • To load scripts in the proper order (and asynchronously)

So, RequireJS really helps to define a structure to the modules in a JavaScript applications.

RequireJS modules

First I would like to show how you can create modules using RequireJS.
I will use the same example as I used to show how to create a JavaScript module.

    define('messenger',
        ['jquery'],
        function ($) {
            var text = 'I am a module',
                showMessage = function() {
                    $("#messagebox").html(text);
                };

            return {
                showMessage: showMessage
            };
        }
    );

It looks as easy as a JavaScript module. But I would like to describe some differences.
The RequireJS module starts with:

    define('messenger',

Where 'messenger' is the module ID. You can use this ID if you want to reference this module in other modules.

The next line describes dependencies of this module:

       ['jquery'],

In this example our module depends on jQuery only.

And then you have to specify module body as a function.

As you can see it's really simple to create a module using RequireJS.

Using RequireJS

Let's change all of our modules.

config.js

define('config',
    [],
    function () {
        var baseUrl = '/api/messenger/';

        return {
            baseUrl: baseUrl
        };
    }
);

dataservice.js

define('dataservice',
    ['jquery', 'config'],
    function ($, config) {
        var
            callApi = function (url, type, callback) {
                $.ajax({
                    url: url,
                    type: type,
                    dataType: 'json',
                    success: function (data) {
                        callback(data);
                    }
                });
            },
            
            getMessage = function (id, callback) {
                url = config.baseUrl + id;
                callApi(url, 'GET', callback);
            };

        return {
            getMessage: getMessage
        };
    }
);

messenger.js

define('messenger',
    ['jquery', 'dataservice'],
    function ($, dataservice) {
        var showMessage = function (id) {
            dataservice.getMessage(id, function (message) {
                $("#messagebox").html(message);
            });
        };

        return {
            showMessage: showMessage
        };
    }
);

main.js

(function() {
    requirejs.config(
        {
            paths: {
                'jquery': '../Scripts/jquery-1.8.2.min'
            }
        }
    );

    require(
        ['messenger'],
        function(messenger) {
            var id = 55;
            messenger.showMessage(id);
        }
    );
})();

All of the modules look as they were before, except of main module.

In this module I have configured RequireJS to specify where RequiteJS can find the jquery module.

    requirejs.config(
        {
            paths: {
                'jquery': '../Scripts/jquery-1.8.2.min'
            }
        }
    );

And then, I've specified the start up code, which depends on messenger module:

    require(
        ['messenger'],
        function(messenger) {
            var id = 55;
            messenger.showMessage(id);
        }
    );

After all, we have to change our HTML to load our modules.

index.html

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Phase 1</title>
</head>
<body>
    <div>
        <h1>Modular Demo 1</h1>
    </div>
    <div id="messagebox"></div>

    <script data-main="main" src="../Scripts/require.js" type="text/javascript"></script>
   
</body>
</html>

Small remarks about our HTML changes.

We should not load any of our modules or jQuery, because RequireJS will handle it for us.
We have to load RequireJS only, and specify 'data-main' attribute, which tells RequireJS to load main.js script after RequireJS loads. In other words, we specify start up script in 'data-main' attribute.

And after all RequireJS does the 'magic' and loads all of our modules in proper order automatically.

As a result, our code becomes much much better now, as I promised at the beginning of this post.

That's all. And see you next time.

130 comments:

  1. If I could know RequireJs earlier, I would use it in my each web application. Thank you so much for sharing your creative ideas.

    ReplyDelete
    Replies
    1. I do my best, but I don't have a lot of time to post about everything. Thanks for your feedback.

      Delete
    2. Great writing !!thanks :)

      Delete
  2. Thank you so much, this step by step tutorial was a big help for me to setup requirejs!

    ReplyDelete
  3. Very nicely (and lucidly) done! Thanks for taking the time to share.

    ReplyDelete
  4. This was way helpful. Thankyou for taking the time to put this together.

    ReplyDelete
  5. Could you add a section about Require being asynchronous? There are some pitfalls when using jQuery and your modules depend on jQuery that people coming to this blog post should know about (say a view module).

    Thanks for sharing :)

    ReplyDelete
  6. Thanks, that is the best requirejs intro I have ever seen :) One addition, for the performace concerns, probably people want to use a CDN service for jquery, that is how ->http://requirejs.org/docs/jquery.html

    ReplyDelete
  7. Am I the only one who thinks this is madness? Your example takes 13 lines of code -- not beautiful code I agree, but very concise and readable code -- and turns it into 43 lines of harder-to-read code spread over 4 files that the browser has to download separately.

    To extend your ravioli analogy, you've replaced a small bowl of tidy spaghetti with four big bowls of ravioli and then smothered the ravioli with sauce so you can't find them any more :-)

    ...I'm kidding, of course :) A great article, thank you!

    ReplyDelete
    Replies
    1. If you only need to implement a simple scenario like I showed in this simple case, of course, I wouldn't do that. But, if we are talking about small, middle or huge SPA application and we also need to test our code then I will definitely do that.

      Delete
  8. Excellent article. Clear and precise. Just what I wanted.

    ReplyDelete
  9. thank you - this helped me really understand Requirejs with modular pattern.

    ReplyDelete
  10. Thank you, this article is the key to my understanding RequireJS. The ravioli is delicious.

    ReplyDelete
  11. what about alphabetti spaghetti?

    ReplyDelete
  12. For those who are wheat intolerant, is there a wheat free alternative?

    ReplyDelete
  13. From my experience of implementing this, some ravioli get lost in the tomato sauce and it can easily become just as messy

    ReplyDelete
  14. Thank you for this, I am excited by all the pastabilities

    ReplyDelete
  15. I have been trying to understand the usage of require.js. It is a big help. Easy and nice. Thanks

    ReplyDelete
  16. Thank you for this, I am excited by all the pastabilities

    ReplyDelete
  17. Hi, thanks. It was very precise.
    Regards
    Raoul
    Mobile app development company

    ReplyDelete
  18. Very nice post here thanks for it .I always like and such a super contents of these post.Excellent and very cool idea and great content of different kinds of the valuable information's.
    seo company in chennai

    ReplyDelete
  19. wonderful information, I had come to know about your blog from my friend nandu , hyderaba.
    i have read atleast 7 posts of yours by now, and let me tell you, your website gives the
    best and the most interesting information. This is just the kind of information that i had
    been looking for, i'm already your rss reader now and i would regularly watch out for the new posts.

    From

    Oracle Fusion HCM Online Training

    ReplyDelete
  20. This comment has been removed by the author.

    ReplyDelete
  21. This comment has been removed by the author.

    ReplyDelete
  22. Harvard Business Review named data scientist the "sexiest job of the 21st century".This Data Science course will cover the whole data life cycle ranging from Data Acquisition and Data Storage using R-Hadoop concepts, Applying modelling through R programming using Machine learning algorithms and illustrate impeccable Data Visualization by leveraging on 'R' capabilities.With companies across industries striving to bring their research and analysis (R&A) departments up to speed, the demand for qualified data scientists is rising.

    data science training in bangalore

    ReplyDelete


  23. بسم الله الرحمن الرحيم نحن فى شركة الكمال نقوم بجميع خدمات نقل العفش والاساس بافض الطرق تحت اشراف

    فريق كبير مدرب على اعلى مستوى من المستويات مع الفك والتركيب
    شركة نقل اثاث بالطائف
    شركة نقل اثاث بجازان
    شركة نقل اثاث بحائل
    شركة نقل اثاث ونقل عفش بحائل
    والسلامة عليكم ورحمة الله وبركاته



    ReplyDelete
  24. Nice post. It is really interesting. Thanks for sharing the post!
    Digital Marketing Services in India

    ReplyDelete
  25. Thanks for sharing such a knowledgeable code, this is very helpful for me. I will use this, thank you
    Digital Marketing Company

    ReplyDelete
  26. Integrate Msgclub SMS gateway with the help of available ready code in ASP that contains all necessary details
    Bulk SMS API

    ReplyDelete
  27. For Python training in Bangalore, Visit: Python training in Bangalore

    ReplyDelete
  28. The Information which you provided is very much useful for Agile Training Learners. Thank You for Sharing Valuable Information.Salesforce CRM Training in Bangalore

    ReplyDelete
  29. Uniquoe is the Best Digital Marketing Company in India offering Best Digital Marketing Services to
    its clients across all over the globe at a very reasonable price range.
    Best IT Services Provider Company in Delhi
    Digital marketing services in delhi
    web development services in delhi
    seo services in delhi ncr
    best makeup artist in gurgaon

    ReplyDelete
  30. This comment has been removed by the author.

    ReplyDelete
  31. Soft Online provides best training for Oracle Fusion Cloud Financials Online Training with real time experts. We trained with real time projects and provide placement assistance.
    For more details: https://www.softonlinetraining.com/oracle-fusion-cloud-financials/

    ReplyDelete
  32. Whatever we gathered information from the blogs, we should implement that in practically then only we can understand that exact thing clearly on sap bi tutorial , but it’s no need to do it, because you have explained the concepts very well. It was crystal clear, keep sharing..

    ReplyDelete
  33. Thank you so much for sharing the information. It will help me in my future work. Keep sharing this kind of information

    ReplyDelete
  34. This comment has been removed by the author.

    ReplyDelete
  35. Awesome Post!!! I really enjoyed reading this article. It's really a nice experience to read your post. Thanks for sharing.
    Data Science Course
    Data Science Course in Marathahalli
    Data Science Course Training in Bangalore

    ReplyDelete
  36. Whatever we gathered information from the blogs, we should implement that in practically then only we can understand that exact thing clearly, but it’s no need to do it, because you have explained the concepts very well. It was crystal clear, keep sharing..

    sap tutorial

    ReplyDelete
  37. Nice article. For offshore hiring services visit:
    livevictoria

    ReplyDelete
  38. Thank you for sharing nice articles. keep sharing
    AWS Training In Hyderabad

    ReplyDelete
  39. Thanks for the informative article About Data Science.This is one of the best resources I have found in quite some time. Nicely written and great info. I really cannot thank you enough for sharing.

    Java training in chennai | Java training in annanagar | Java training in omr | Java training in porur | Java training in tambaram | Java training in velachery

    ReplyDelete
  40. Hi, Thanks for sharing beautiful stuff, are you guys done a great job...

    AWS Training In Hyderabad

    ReplyDelete
  41. thanks for sharing nice information. its Very use full and informative and keep sharing.
    more : https://www.kellytechno.com/Hyderabad/Course/Machine-Learning-Training-In-Hyderabad

    ReplyDelete
  42. Notwithstanding that this is a cheat, because firstly in general, humans themselves have to learn to think more like the expert machine, rather than the opposite; And even so, it is the continuing, apparently irrelevant, input by humans across the world which will keep this relevant, artificial intelligence training in hyderabad

    ReplyDelete
  43. Lockdown is running in the whole country due to coronavirus, in such an environment we are committed to provide the best solutions for QuickBooks Support Phone Number.
    Contact QuickBooks technical Support Phone Number to get in touch.
    Dial QuickBooks Toll free Number : 1-844-908-0801

    ReplyDelete

  44. The Basics You Have Explained Was Good.Thanks For Sharing The Content With Us.

    Python Training Course Institute in Hyderabad

    ReplyDelete
  45. Attend The Data Science Course From ExcelR. Practical Data Science Course Sessions With Assured Placement Support From Experienced Faculty. ExcelR Offers The Data Science Course.data science courses

    ReplyDelete
  46. I am looking for and I love to post a comment that "The content of your post is awesome" Great work!

    Simple Linear Regression

    Correlation vs Covariance

    bag of words

    time series analysis

    ReplyDelete
  47. I am really happy to say it’s an interesting post to read . I learn new information from your article , you are doing a great job . Keep it up

    Devops Training in Hyderabad

    Hadoop Training in Hyderabad

    Python Training in Hyderabad

    ReplyDelete
  48. it’s really nice and meanful. it’s really cool blog. Linking is very useful thing.you have really helped lots of people who visit blog and provide them usefull information.
    Data Science Training in Hyderabad

    I am really happy to say it’s an interesting post to read . I learn new information from your article , you are doing a great job . Keep it up

    Devops Training in Hyderabad

    Hadoop Training in Hyderabad

    Python Training in Hyderabad

    ReplyDelete
  49. Глина, как основоположный материал, не подлежит выделению вредных веществ. В период горения geotiles geomix montmartre не производит вредных веществ. Серьезная твердость обеспечивает долговечность материала на десятилетия.

    ReplyDelete
  50. ExcelR provides data analytics course. It is a great platform for those who want to learn and become a data analytics Courses. Students are tutored by professionals who have a degree in a particular topic. It is a great opportunity to learn and grow.

    data analytics course
    data analytics courses

    ReplyDelete
  51. Nice & Informative Blog !
    Our team at QuickBooks Customer Service makes sure to achieve maximum customer satisfaction in the current circumstances.

    ReplyDelete
  52. Thank you for sharing this valuable content.
    I love your content it's very unique.
    DigiDaddy World

    ReplyDelete
  53. YouTube is the biggest and best platform for sharing video content online. It’s also an easy way for people to express their creativity,talent, make some extra money, promote individuals or business, and may become a huge “Internet celebrity”.

    ReplyDelete
  54. In this chapter we will talk about SEO Basics, SEO is search engine optimization where we try to rank our website at the top of the search results for a particular set of keywords.

    ReplyDelete

  55. Nice Blog !! i m so happy After Read Your Blog QuickBooks is best Accounting Software is a perfect tool for managing finances. If you need help Regarding this Software just Call at
    quickbooks phone number

    ReplyDelete
  56. Very wonderful informative article. I appreciated looking at your article. Very wonderful reveal. I would like to twit this on my followers. Many thanks! .
    <a href="https://360digitmg.com/india/data-analytics-certification-training-course-in-bangalore>Data Analytics training in Bangalore</a>

    ReplyDelete
  57. I feel really happy to have seen your webpage and look forward to so many more entertaining times reading here. Thanks once more for all the details.
    aws certification cost hyderabad

    ReplyDelete
  58. I have a mission that I’m just now working on, and I have been at the look out for such information data science course in surat

    ReplyDelete
  59. Here at this site really the fastidious material collection so that everybody can enjoy a lot. data science course in surat

    ReplyDelete
  60. This is a smart blog. I mean it. You have so much knowledge about this issue, and so much passion. You also know how to make people rally behind it, obviously from the responses.
    data analytics courses in hyderabad with placements

    ReplyDelete
  61. I really appreciate this wonderful post that you have provided for us. I assure this would be beneficial for most of the people. business analytics course in surat

    ReplyDelete
  62. awesome bolg. if you are looking forquickbook support service. you can contact us at.+1 855-675-3194

    ReplyDelete
  63. good content. if you are lookinf forQuickbooks Support Phone Number you can contact us at.+18776030806

    ReplyDelete
  64. Good contant. we are provide a best service for custumer in Quickbooks support serviceyou can contact us at.+18882724881

    ReplyDelete
  65. Pleasant data, important and incredible structure, as offer great stuff with smart thoughts and ideas, loads of extraordinary data and motivation, the two of which I need, because of offer such an accommodating data here.
    business analytics training in hyderabad

    ReplyDelete
  66. I was curious if you ever thought of changing the layout of your site? Its very well written; I love what youve got to say. But maybe you could a little more in the way of content so people could connect with it better. Youve got an awful lot of text for only having 1 or 2 pictures. Maybe you could space it out better?|data analytics course in jodhpur

    ReplyDelete
  67. Really nice information and informative content. I bookmarked your site for further blogs.
    Data Science Institute in Hyderabad

    ReplyDelete
  68. I feel really happy to have seen your webpage and look forward to so many more entertaining times reading here. Thanks once more for all the details. data analytics course in kanpur

    ReplyDelete
  69. Interesting post!!! Thanks for posting such a useful information. I wish to read your upcoming post to enhance my skill set and keep blogging.
    Nice blog,I understood the topic very clearly,And want to study more like this.

    ibm full form in india |
    ssb ka full form |
    what is the full form of dp |
    full form of brics |
    gnm nursing full form |
    full form of bce |
    full form of php |
    bhim full form |
    nota full form in india |
    apec full form |

    ReplyDelete
  70. Предсказание будущего дает угадать, что вас подстерегает в предстоящее время. Каждый жаждет предугадать собственную судьбу и видит определенные средства гадания более достоверными. Правдивое гадание любит ли любимый это способ понять приближающиеся явления всегда заманивал человека.

    ReplyDelete
  71. Really impressed! Everything is very open and very clear clarification of issues. It contains truly facts. Your website is very valuable. Thanks for sharing.
    cyber security course in malaysia

    ReplyDelete
  72. I’ve read some good stuff here. Definitely worth bookmarking for revisiting. I surprise how much effort you put to create such a great informative website. data scientist course in mysore

    ReplyDelete
  73. If you need help on correctable errors or issues on your desktop, call us at Quickbooks Customer Service Phone Number+1 855-769-6757 to get the best services. We are here 24/7 and are ready to provide answers to all your QuickBooks questions.

    ReplyDelete
  74. Thanks for this post. It proves very informative for me. Great post to read. Visit my website to get best Information About Best UPSC Coaching Institute in Mumbai.
    Best UPSC Coaching Institute in Mumbai
    Top UPSC Coaching Institute in Mumbai

    ReplyDelete
  75. very informative blog Thanks for sharing with us please more visit our Quickbooks customer service at my
    quickbooks support phone number +1 866-448-6293

    ReplyDelete
  76. I m Very happy after read your Informative blog Keep posting Again . If you also any need about Quickbooks Service Regarding information then go through
    QuickBooks Support Phone Number +1 866-669-5068

    ReplyDelete
  77. This comment has been removed by the author.

    ReplyDelete
  78. This Was An Amazing ! I Haven't Seen This Type of Blog Ever ! Thankyou For Sharing.RR Technosoft is the Devops training in hyderabad and it provides Class room & Online Training by real time faculty with course material and Lab Facility.

    ReplyDelete
  79. RR Technosoft is the bestDevops Training Institute in KPHBand it provides Classroom Online Training by real time faculty with course material and Lab Facility.

    ReplyDelete
  80. I like your blog. Keep sharing like these blogs.
    Java Course in Greater Noida

    ReplyDelete
  81. The post was really informative. You've given us a good article. Thank you for sharing. Enrolling in Java training in Solapur can undoubtedly open doors to numerous opportunities and pave the way for a successful career in the ever-expanding world of technology.

    ReplyDelete
  82. Nice thanks for sharing informative

    ReplyDelete