Thread: Help with some website design...

  1. #91
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by laserlight View Post
    Do you find that these sites have vendor lock-in with respect to the core aspect of code hosting? The way I see it, the vendor lock-in happens at the level of the bells and whistles like bug tracker or wiki. The version control repository itself, assuming that you use distributed version control, is not locked-in, other than the lock-in that happens at the level of the version control tool.
    Hmm... I did mean those ancillary features in my comment too. But you will be incorrect by assuming you are not incurring into GitHub vendor lock-in also at the level of the git repository. There are TWO problems with GitHub on this regard (the first less problematic than the second):

    1) GitHub Flow

    GitHub imposes its own git workflow. This is fine, because GitHub Flow is really not a bad workflow. The problem is that if your project requires a different methodology, you'll have to face GitHub specialized UI which is tailored to their workflow. For instance, you cannot really emulate git-flow in GitHub; GitHub master is meant to be always deployable, however you branch/merge features and pull requests directly from/into master. Some gymnastics may allow you to work with git-flow under GitHub if you keep a separate repository that only merges the development branch into GitHub. But this is really just using GitHub to host code, not to actually work with it. Alternatively, you can just go ahead and create git-flow branches and instruct your users. But the UI defaults will be working against you all the time and you need to always remember to switch branches or point to a different target branch than the omnipresent master default. You are solving the problem by with increased complexity and a very real chance for mistakes.

    GitHub Flow was designed out of the necessity to simplify the workflow of simple projects, which usually face constant and rapid deployment. And it works! I mean, it has too. A whole lot of people use it successfully. But I always like to take a step back on things that are popular choices and said to be "simpler and easier". I happen to not trust very much those two words on software development. I immediately become suspicious and try to see for myself.

    And the thing is: Many projects on GitHub are not simple and do not have rapid deployment schedules. The lack of a development branch where a feature merge can go through a second screening layer (especially useful when you have many people working on different features) is begging for master branches with a higher rate of bugs. And I'm pretty sure (I haven't done a study on this) that the more complex projects on GitHub have higher revert rates and they bug trackers have a larger number of bugs, that aren't just a normal result of the project complexity, but are actually originated by the decision to employ GitHub Flow.

    Workflow is a central aspect to version control. Git itself allows all manner of workflows. But GitHub imposes its own vendor lock-in on the user. And come the day you wish or need to migrate to another service (or host your own), you may not have the specialized GitHub Flow as an offer, which will complicate adoption and force you into complex project management decisions.

    (2) Pull Requests

    GitHub has its own implementation of pull requests, different from Git. And it is actually a bad implementation. It is odd that the very central feature of GitHub Flow is so weak. This is an old problem to some users and even Linus had something to say about it. Personally I find it ludicrous that you can't even tag a pull request. But in a nutshell, GitHub doesn't offer a patch culture to the collaborative development process. It completed discarded it between choosing to implement its own pull request module and forcing users into its own web interface for presentation and discussion of the pull request.

    Come the day you need to change your source code hosting provider, you will almost certainly lose your entire pull request history due to GitHub vendor lock-in. The only thing remaining will be the pull request entry in your repository and the merge sometime later. I won't buy the argument that Git itself does not perform recording keeping of pull request discussions. It does not need to; Git is not an email program. But pull requests discussion is an essential function of pull-requesting/patching and it needs to be saved for future reference. Email and mailing lists have been the traditional safest method to do just that. For a reason.

    Lack of text formatting features on the pull request message (one of the things that annoyed Linus) are another example of an implementation that will only work under GitHub. Migrate and you can bet all your pull requests messages will be a complete mess.

    -----------------------------------------------------------------------------------

    Now for something completely different

    As I said before, I did mean to also include such ancillary features like the bug tracker, schedules, or wiki present in almost all popular SCMs. These are usually better understood in the context of vendor lock-in. It's like we give these features the vendor lock-in pass. As if they are not an important part of the development process, or they are hard features not to lock the user in. Needless to say I find that is a big mistake.

    Bug trackers in particular are one of the saddest stories in software development. While we have successfully created all sorts of standards, unspoken rules, or tools with mass appeal, on about everything related to software development, bug trackers still suffer from a complete lack of powerful generic tools that a large part of the industry adopts as an unspoken standard, muck like Git, Mercurial and SVN have become de facto version control standards. And because of this it is reasonable to expect everyone and their mother want to implement their own bug tracker on their own source code hosting business.

    (It is actually telling of us software developers, that we start to fail to care and come up with powerful solutions right on the frontier of our interaction with the real customers of our work. It does not speak highly of us. And despite having dealt with final customers -- along with the difficulties that entails. Oh, do I have stories! -- almost all my professional career, I can say I'm not one to come with the usual 'customers are dumb' jokes. And never liked to hear them. In almost 30 years of doing this I never forgot who I really work for and who really pays the bill. I wish more developers remembered too. And I wish more developers thought a little of what is that waiter thinking when we can't even make our minds about something as simple as the menu offerings.)

    The problem however is that vendor lock-in can happen in here too, not because these features have been specially designed, but because the vendor does not offer access to the source code and database contents, removing from the user any chance to change or adapt the code, or use the raw data as a basis for the migration process. Such is the case of GitHub.
    Last edited by Mario F.; 05-03-2015 at 09:11 AM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  2. #92
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Okay, don't laugh at how slow I've been learning this.

    Tell me what you guys think of this new page :
    Code:
    <!DOCTYPE html>
    <html>
        <head>
            <title>Test Page</title>
            <style></style>
            <script>
    var tabInterface = new(function()
    {
        var self = this;
        var form = null;
        var input = null;
        var voteData = null;
        var prevColor = null;
        var currColor = "#468499";
        
        self.mouseover = function(evt)
        {
            var ev = evt || window.event;
    
    
            prevColor = (prevColor != currColor ? ev.currentTarget.style.backgroundColor : prevColor);
            ev.currentTarget.style.backgroundColor = currColor;
        };
    
    
        self.mouseout = function(evt)
        {
            var ev = evt || window.event;
    
    
            ev.currentTarget.style.backgroundColor = prevColor;
        };
    
    
        self.highlightFocused = function(evt)
        {
            var ev = evt || window.event;
    
    
            prevColor = (prevColor != currColor ? ev.target.parentNode.parentNode.style.backgroundColor : prevColor);
            ev.target.parentNode.parentNode.style.backgroundColor = currColor;
        };
    
    
        self.clearFocused = function(evt)
        {
            var ev = evt || window.event;
    
    
            ev.target.parentNode.parentNode.style.backgroundColor = prevColor;
        }
    
    
        self.highlightRow = function(idx)
        {
            var row = voteData[idx].row;
            row.style.backgroundColor = "#cce5ff";
        };
    
    
        self.clearRow = function(idx)
        {
            var row = voteData[idx].row;
    
    
            if (idx % 2 == 0)
                row.style.backgroundColor = "#ffffff";
            else
                row.style.backgroundColor = "#DFD7DF";
        };
    
    
        self.clearAllRows = function()
        {
            for (var i = 0; i < voteData.length; ++i)
            {
                self.clearRow(i);
    
    
                voteData[i].slctElem.tabIndex = 0;
            }
    
    
            input.tabIndex = 0;
        };
    
    
        self.find = function(evt)
        {
            var ev = evt || window.event;
            ev.preventDefault();
    
    
            input = document.getElementById("search-input");
            var phrase = String(input.value).toLowerCase();
    
    
            if (phrase.length == 0)
            {
                self.clearAllRows();
                return;
            }
    
    
            var tabIdx = 1;
    
    
            var first = -1;
    
    
            for (var i = 0; i < voteData.length; ++i)
            {
                var select = voteData[i].slctElem;
    
    
                if (voteData[i].name.indexOf(phrase) >= 0)
                {
                    if (first == -1)
                        first = i;
    
    
                    self.highlightRow(i);
                    
                    select.tabIndex = tabIdx;
                    ++tabIdx;
                }
                else
                {
                    self.clearRow(i);
    
    
                    select.tabIndex = -1;
                }
            }
    
    
            input.tabIndex = tabIdx;
            ++tabIdx;
    
    
            voteData[first].slctElem.focus();
    
    
    
    
        };
    
    
        // small function to build the lookup table
        self.buildLookup = function()
        {
            voteData = [];
    
    
            var names = document.getElementsByClassName("name");
    
    
            for (var i = 0; i < names.length; ++i)
            {
                voteData[i] = {
                                name : String(names[i].textContent).toLowerCase(),
                                row : names[i].parentNode,
                                slctElem : names[i].parentNode.querySelector("select")
                              };
            }
    
    
            //console.log(voteData);
        };
    
    
        // mock constructor
        self.init = function()
        {
            self.buildLookup();
    
    
            form = document.getElementById("search-form");
            form.addEventListener("submit", self.find);
    
    
            for (var i = 0; i < voteData.length; ++i)
            {
                var select = voteData[i].slctElem;
    
    
                select.addEventListener("focus", self.highlightFocused);
                select.addEventListener("blur", self.clearFocused);
    
    
                var row = voteData[i].row;
    
    
                row.addEventListener("mouseover", self.mouseover);
                row.addEventListener("mouseout", self.mouseout);
            }
        };
    });
    
    
    document.addEventListener("DOMContentLoaded", tabInterface.init);
            </script>
        </head>
        <body>
            <table id="vote-table">
                <tr style="background-color : #ffffff">
                    <td class="name">MutantJohn</td>
                    <td>
                        <select>
                            <option>C</option>
                            <option>C++</option>
                            <option>Java</option>
                            <option>Python</option>
                            <option>Fortran</option>
                        </select>
                    </td>
                </tr>
                <tr style="background-color : #DFD7DF">
                    <td class="name">Nominal Animal</td>
                    <td>
                        <select>
                            <option>C</option>
                            <option>C++</option>
                            <option>Java</option>
                            <option>Python</option>
                            <option>Fortran</option>
                        </select>
                    </td>
                </tr>
                <tr style="background-color : #ffffff">
                    <td class="name">phantomotap</td>
                    <td>
                        <select>
                            <option>C</option>
                            <option>C++</option>
                            <option>Java</option>
                            <option>Python</option>
                            <option>Fortran</option>
                        </select>
                    </td>
                </tr>
                <tr style="background-color : #DFD7DF">
                    <td class="name">Salem</td>
                    <td>
                        <select>
                            <option>C</option>
                            <option>C++</option>
                            <option>Java</option>
                            <option>Python</option>
                            <option>Fortran</option>
                        </select>
                    </td>
                </tr>
                <tr style="background-color : #ffffff">
                    <td class="name">Alpo</td>
                    <td>
                        <select>
                            <option>C</option>
                            <option>C++</option>
                            <option>Java</option>
                            <option>Python</option>
                            <option>Fortran</option>
                        </select>
                    </td>
                </tr>
                <tr style="background-color : #DFD7DF">
                    <td class="name">laserlight</td>
                    <td>
                        <select>
                            <option>C</option>
                            <option>C++</option>
                            <option>Java</option>
                            <option>Python</option>
                            <option>Fortran</option>
                        </select>
                    </td>
                </tr>
                <tr style="background-color : #ffffff">
                    <td class="name">cyberfish</td>
                    <td>
                        <select>
                            <option>C</option>
                            <option>C++</option>
                            <option>Java</option>
                            <option>Python</option>
                            <option>Fortran</option>
                        </select>
                    </td>
                </tr>            <tr style="background-color : #DFD7DF">
                    <td class="name">Elysia</td>
                    <td>
                        <select>
                            <option>C</option>
                            <option>C++</option>
                            <option>Java</option>
                            <option>Python</option>
                            <option>Fortran</option>
                        </select>
                    </td>
                </tr>
            </table>
            <div id="search-div">
                <form id="search-form" method="POST" action="#">
                    <input id="search-input" type="text" value=""></input>
                </form>
            </div>
        </body>
    </html>
    Btw, if you want your name to be included or want a language to be included, please let me know. I'd love to add it!

    I think making some elements of the table un-tabbable was a smart design choice for rapid entry of names.

  3. #93
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    var tabInterface = new(function()
    O_o

    I figure now is as good a time as any.

    I don't know where the approach started, but I can tell you that Nominal Animal is just using the extra syntax for stylistic reasons. You are creating the closure in any event, and you are using the captured variables in any event. You don't need `new' syntax or the `this' reference. You can just return the context of the closure. You absolutely should wrap your functions and data into a namespace object, you don't need `this' and the closure.

    You can obviously continue to have both if you like the look of the thing; I'm just saying you can accomplish the namespace without multiple layering.

    Soma

    Code:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script type="text/javascript">
    (function (window) {
        var dictionary, init, stuff;
        dictionary = {
            doSomething: function () {
                document.body.innerHTML = '<p>' + stuff.join(', ') + '!</p>';
            },
        };
        init = function () {
            dictionary.doSomething();
        };
        stuff = [
            'Hello', 'World'
        ];
        /* You really need to do more checks, but the post is just an example. */
        if (window) {
            window.whatever = init;
        }
    }(window));
    document.addEventListener("DOMContentLoaded", whatever);
        </script>
        <title>Title</title>
    </head>
    <body>
    </body>
    </html>
    Code:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script type="text/javascript">
    var whatever = (function () {
        var hello, init;
        hello = function () {
            document.body.innerHTML = '<p>Hello, World!</p>';
        };
        init = function () {
            hello();
        };
        return init;
    }());
    document.addEventListener("DOMContentLoaded", whatever);
        </script>
        <title>Title</title>
    </head>
    <body>
    </body>
    </html>
    Code:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script type="text/javascript">
    /* I'm writing this as if you were using a library as with the `$(function(){...})' mechanic. */
    document.addEventListener("DOMContentLoaded", function () {
        document.body.innerHTML = '<p>Hello, World!</p>';
    });
        </script>
        <title>Title</title>
    </head>
    <body>
    </body>
    </html>
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  4. #94
    Registered User Alpo's Avatar
    Join Date
    Apr 2014
    Posts
    877
    Quote Originally Posted by phantomotap;
    Code:
    (function (window) {
        var dictionary, init, stuff;
        dictionary = {
            doSomething: function () {
                document.body.innerHTML = '<p>' + stuff.join(', ') + '!</p>';
            },
        };
        init = function () {
            dictionary.doSomething();
        };
        stuff = [
            'Hello', 'World'
        ];
        /* You really need to do more checks, but the post is just an example. */
        if (window) {
            window.whatever = init;
        }
    }(window));
    That's how I like to do it as well. Is it recommended to import the global object though? I've been just importing my namespace object and whatever modules I'm using.


    Quote Originally Posted by MutantJohn;
    Okay, don't laugh at how slow I've been learning this.

    Tell me what you guys think of this new page :

    Code:
        // Lots of code :D
    For functionality, I would say it looks like you've hit or nearly hit the mark. I'll need some more time to read and debug, but some things to be mindful of in your code (just from reading it a few times):

    Variables in JavaScript (var) don't have block scope, so when you declare them inside if's for's or other constructs just keep in mind they are still visible outside of that scope. There is a newer 'let' keyword that declares a variable at block scope only, but it's new so compatibility issues might make it not worth it.

    The == operator allows for type coercion, which in JavaScript is pretty extreme, and lots of it don't make sense.
    Code:
    if ("" == 0) {
        alert("wtf?");
    }
    Edit: I meant to recommend the === and !== operators here . They don't allow for the nutty type coercions.

    If you are going to be working with a lot of HTMLCollections, NodeLists, or whatever there is an idiom that makes these objects behave more like arrays, giving you access to the Array methods (which can be a lot easier than loops). I rewrote the "buildLookup" method to show what I mean:

    Code:
        self.buildLookup = function() {
            // A function to turn a single ".name" element to an object with your data:
            var eleToData = function (ele) {
                return {
                    name: ele.textContent.toLowerCase(),
                    row: ele.parentNode,
                    slctElem: ele.parentNode.querySelector("select")
                };
            };
            // Now we can use "splice" to turn the HTMLCollection into a real Array.
            // This works by binding the ".name" collection to the 'this' argument of the Array splice method, which
            // is returning elements {0, length} in a new Array.
            // Then the map function is applied to create an array of your objects in one line.
            voteData = Array.prototype.splice.call(document.getElementsByClassName("name"), 0).map(eleToData);
        };
    You might also want to protect event.target in the same way you do the original event:
    Code:
    var target = event.target || event.srcElement; // old IE-ism
    Last edited by Alpo; 05-11-2015 at 12:27 AM. Reason: mishtyped
    WndProc = (2[b] || !(2[b])) ? SufferNobly : TakeArms;

  5. #95
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Code:
    (function (window) {
        var dictionary, init, stuff;
        dictionary = {
            doSomething: function () {
                document.body.innerHTML = '<p>' + stuff.join(', ') + '!</p>';
            },
        };
        init = function () {
            dictionary.doSomething();
        };
        stuff = [
            'Hello', 'World'
        ];
        /* You really need to do more checks, but the post is just an example. */
        if (window) {
            window.whatever = init;
        }
    }(window));
    document.addEventListener("DOMContentLoaded", whatever);
    What on God's green Earth does this mean? Namely, why
    Code:
    (function(window){ .. }(window));
    ? What does that mean? I don't think I've ever seen this kind of syntax.

    And thanks for the head's up about the type-checking as well (I was wondering about that lol), Alpo. And about declaring variables inside the for-loop scope as well. JavaScript is not very intuitive from a C perspective. Well, the language and what it does are but the syntax is so the opposite of how I think lol.

    Edit : Lol I found this : http://toddmotto.com/what-function-w...-really-means/

    I'm reading it now. Now it's all starting to make more sense. Yeah, JavaScript is weird but I'm glad the OOP part is intuitive. Well, that and finally getting a grasp of DOM has helped a lot.
    Last edited by MutantJohn; 05-11-2015 at 10:47 PM.

  6. #96
    Registered User Alpo's Avatar
    Join Date
    Apr 2014
    Posts
    877
    Quote Originally Posted by MutantJohn
    What on God's green Earth does this mean?
    It is called a closure. The gist of it is that functions in JavaScript retain the scope they are created in, and also have a reference to the next outer scope:

    Code:
    function () {
    
        var a = 10, b = 20;
    
        function () {
    
            var b = 15;
    
            // When I use the variable 'a' at this point, there is no 'a' in this scope.
            // The symbol is then looked up by checking the reference to the outer scope.
            // 'a' is found in the scope directly before this one, so we get the value 10.
    
            // 'b' is found in this scope, so it has the value 15
        }
    }
    This might seem useless at this point, but imagine we wanted some resource that we wanted an object or function to be able to use, but we want the resource to be private to that object:

    Code:
    var checkPassword = (function () {
    
        // We define a variable that can only be referenced by 
        // the function that I'm going to return:
    
        var pw = "The grey crow moos at midnight. ";
    
        return function (str) {
            return (str === pw);
        };
    }());
    Now when someone calls checkPassword() passing in a string, there will be this 'pw' variable that is not defined in the current scope. So the next outer scope is checked, pw is found, and the comparison can be made. This is JavaScript's main way of expressing privacy (afaik).

    It doesn't need to be a function that is returned however, you can also return an object that will have privileged access to the outer scope. Also, instead of declaring the variable as I did, you could also pass it to the closure function in the following way, for the same effect:

    Code:
    var checkPassword = (function (pw) {
        return function (str) {
            return (str === pw);
        };
    }("The grey crow moos at midnight. "));
    If we had a namespace variable (or module, ect) that we wanted to bind to a particular symbol we can also accomplish it with closures:

    Code:
    (function (myApp, $) {
        
        // myApp being an object where I defined various things
        // jQuery is bound to the $ symbol inside this closure
        // (so long as it's not redefined)
    
    }(myApp, jQuery));
    The method I like to use to make the code more modular is to use closures to build up an interface object. The interface object is then returned from the closure, and the user can access it's resources only through whatever methods are defined on that object. (Although there are usually sneaky ways to access private things anyway, but I'm not clever enough to figure those out most of the time ).
    WndProc = (2[b] || !(2[b])) ? SufferNobly : TakeArms;

  7. #97
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Yeesh. Closures are confusing. O_o

  8. #98
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Okay, now this is the only part confusing me about phantom's first example,
    Code:
        /* You really need to do more checks, but the post is just an example. */
        if (window) {
            window.whatever = init;
        }
    Where does "whatever" come from? Can I just declare it like this?

  9. #99
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Where does "whatever" come from? Can I just declare it like this?
    O_o

    What?

    o_O

    You don't know how objects and properties work?

    You've already been using the exact same mechanism over and over in your examples.

    Code:
        self.mouseover = function(evt)
        {
            var ev = evt || window.event;
     
     
            prevColor = (prevColor != currColor ? ev.currentTarget.style.backgroundColor : prevColor);
            ev.currentTarget.style.backgroundColor = currColor;
        };
    Do you know where `mouseover' comes from?

    *shrug*

    You really need to get the basics down before you start trying to build up with different browsers interfaces.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  10. #100
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Quote Originally Posted by phantomotap View Post
    O_o

    What?

    o_O

    You don't know how objects and properties work?

    You've already been using the exact same mechanism over and over in your examples.

    Code:
        self.mouseover = function(evt)
        {
            var ev = evt || window.event;
     
     
            prevColor = (prevColor != currColor ? ev.currentTarget.style.backgroundColor : prevColor);
            ev.currentTarget.style.backgroundColor = currColor;
        };
    Do you know where `mouseover' comes from?

    *shrug*

    You really need to get the basics down before you start trying to build up with different browsers interfaces.

    Soma
    I think I'm just surprised that we can just add a property to an object. I get that there's a window object but I didn't know we could just yolo add something onto it lol.

  11. #101
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I think I'm just surprised that we can just add a property to an object. I get that there's a window object but I didn't know we could just yolo add something onto it lol.
    O_o

    I'm not going to jump heavily into details or discuss various implementations, but you should know that you have already been adding properties to an object.

    The Javascript language is built on a flavor of the prototype-based polymorphisms concept.

    The `new' you've been using, as continued from examples posted by Nominal Animal, is creating a new object from the `Object' prototype before passing a reference to the newly created object to the hidden `this' argument.

    The literal syntax you've used is syntactical sugar for creating a new object from the `Object' prototype followed by inserting properties.

    Code:
    var voteData = new Object();
    myCar.name = String(names[i].textContent).toLowerCase();
    Code:
    voteData = {name : String(names[i].textContent).toLowerCase(),};
    The array syntax you've been using is similar syntactical sugar, but the interpreter is hiding even more from your view. Yes. The array syntax you've used `voteData[i] = /* ... */;' is adding properties to an object created from the `Array' prototype which chains from the `Object' prototype. The interpreter is just hiding all the magic.

    The functions in Javascript are also a descendant of the `Object' prototype. The `Function' prototype, like `Array', has some hidden juice which the interpreter uses.

    The major interface of most Javascript libraries is a `Function' object with a lot of properties added.

    The shims some of us have discussed add functionality and properties to existing prototypes which are themselves descendant of the `Object' prototype.

    The point is that the foundation of the Javascript language is "we can just add a property to an object". Basically, everything in Javascript has foundations in the `Object' prototype; you are only adding properties and functionality to a given instance or a descendant prototype.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  12. #102
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Thank you, phantom!

    I think I'm just too used to C++. Man... I really miss strong-typing and having to hard-define objects. *sigh*

    I guess that's what makes JavaScript so functional though, the ability to just add anything to anything. Hmm... Still... Is there a strongly-typed version of JavaScript out there? I've seen a Java to JavaScript converter but I don't think that's what I want. Or should I be asking, is there a browser that implements a strongly-typed scripting language for client-side control over the browser?

  13. #103
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by MutantJohn View Post
    I think I'm just too used to C++. Man... I really miss strong-typing and having to hard-define objects. *sigh*
    Heh.. you're now feeling first-hand the effects of a limited viewpoint. (I'm laughing *with* you, because I feel that too sometimes, even after two decades of paid work using about a dozen different programming languages.)

    You will find that getting over that feeling, instead of retreating to familiar programming language territory, will make you a better programmer. It is because it will open your mind to solutions that appear in different languages (paradigms, really), and simply see a wider range of possibilities. I'm sure some here disagree, and I'm not sure I'm expressing this using the correct concepts.. my point is, overcome the feeling, try to learn the new way of thinking, and you'll find that the code you write in any programming language is likely to become better.

  14. #104
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    I think JavaScript's syntax is confusing and the user needs to do a lot of reading on their own to understand. I don't think it's a very naturally expressive language. For me, I need a full view of everything to ever have a chance of understanding it. My understanding became much stronger once I learned about DOM. DOM is the actual thing we want.

    JavaScript is entirely optional. I feel like the language would benefit from a stronger typing system or at least an optional one. Take this one part of C or C++ and apply it. I don't mind doing typecasts manually if I must. I think it'd make the code more understandable on a lower/implementation level or for people who have no idea what the hell they're doing, like me.

    Granted, C++ looked like gibberish to me at first. It really did. C++ is incredibly ugly. I've started looking at some of the STL code and the thrust library which is also C++-based. They're so God awful ugly. I guess all the abstractions they made make a lot of sense to the development team but for someone from the outside... Eh.

    I think there definitely is a such thing as too much abstraction and I find myself jumping all over the software's source files because I can't remember what the wrapper around the wrapper around that one wrapper wrapped around that one part of data I actually care about looked like.

    C is like this perfect paragon of what every language wishes it looked like. C is just so naked... I love it!

    That being said, this topic has been very productive for me. I'm thinking about looking into promises more if they can allow for living, breathing web pages.

  15. #105
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by MutantJohn View Post
    I think JavaScript's syntax is confusing and the user needs to do a lot of reading on their own to understand. I don't think it's a very naturally expressive language. For me, I need a full view of everything to ever have a chance of understanding it. My understanding became much stronger once I learned about DOM. DOM is the actual thing we want.
    DOM is simply a document representation. It's not a language. You can't do anything with it. You need some language to manipulate it. You cannot really compare it to JavaScript. Take it this way, your comment above reads like, "I don't like hammers. What we really need is just nails."

    Quote Originally Posted by MutantJohn View Post
    JavaScript is entirely optional. I feel like the language would benefit from a stronger typing system or at least an optional one. Take this one part of C or C++ and apply it. I don't mind doing typecasts manually if I must. I think it'd make the code more understandable on a lower/implementation level or for people who have no idea what the hell they're doing, like me.
    You are starting down on an important road. You are learning more than one programming language. This is a profound decision that will shape you as a developer. It is important that right from the start you do the good walk, instead of going down those side roads that will only sidetrack you.

    And one of those side roads a whole lot of people take is to want to criticize a language based on what they know from another language. Don't do that. Don't argue for strong typing in JavaScript because you are used to it in C. This is not how languages get developed and evolve. There's got to be a good reason to make such a dramatic decision. And despite two decades having come and gone, no one could ever successfully argue for why JavaScript should be strongly typed.

    Learn the different paradigms. More important than getting languages to work the way you want, is to work with languages the way they were designed for. It will enrich you, your knowledge, and make you better prepared to tackle all sorts of programming challenges, including learning other types of languages with other types of paradigms. In particular you must keep the following in mind concerning the type system of a language: If a language allows users to define their own types (UDTs), the language type system is largely irrelevant to a programmer outside any performance considerations. It will be just a fact that your UDTs can enforce strong typing semantics in a weakly typed language, or weak typing semantics on a strongly typed language. You choose what you want. And because you did what is right and adapted to both type systems during your learning of programming languages, you'll know exactly when you need a strongly type UDT or a weak typed UDT, instead of trying to force the same paradigm on all cases.

    In the particular case of JavaScript you need to adapt to the fact it has nearly no primitive types and almost everything you see is derived from the Object class. this is an important paradigm, whether you like it or not. It is present in many important languages that you may one day have to face.

    More than most people in these forums, you will hear me argue for programming languages that offer choices to programmers. It is a contradiction in terms to make a language more powerful or more expressive by omitting features. A programming language that has both weak and strong typing is a godsend programming language. But I'm under no illusion that not only this is a difficult thing to implement (unless you use compiler switches, which would just defeat the purpose) but also that trying to add a new type checking mechanism to an already existing programming language is like trying to build the second floor on top of the roof. It just won't work. The language foundations don't support the new weight and the roof has to go. Might as well do a new programming language. Such language doesn't exist yet.


    Quote Originally Posted by MutantJohn View Post
    Granted, C++ looked like gibberish to me at first. It really did. C++ is incredibly ugly. I've started looking at some of the STL code and the thrust library which is also C++-based. They're so God awful ugly. I guess all the abstractions they made make a lot of sense to the development team but for someone from the outside... Eh.
    I don't know what ugly means. C and C++ are perhaps the most elegantly written languages I have ever seen. Almost everything in them seems to have be implemented by an artist committed to every little detail. Both languages marry terseness with expressiveness in a way that one would thought was impossible. Some people like to argue for languages like Python as being expressive. It reads like English, they say. That's fine, whatever. But I personally prefer languages that read like computer programs.
    Last edited by Mario F.; 05-15-2015 at 04:19 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 12-11-2012, 12:25 AM
  2. Website Design....again
    By Sentral in forum A Brief History of Cprogramming.com
    Replies: 14
    Last Post: 10-29-2006, 05:47 AM
  3. Website design!
    By Sentral in forum A Brief History of Cprogramming.com
    Replies: 28
    Last Post: 10-07-2006, 12:38 AM
  4. website
    By the Wookie in forum Windows Programming
    Replies: 1
    Last Post: 11-07-2002, 02:25 PM