29 124E 1F 235 47 469 2F 184D 28 FEC
|
Falvotech.
Conquering the world is easy — what do you do with it afterwards?
|
|
In a recent e-mail to our group at work, I saw a link to Ender, the No-Library Library. I'm sorry, but I can't concentrate on work until I get a few things off my chest, for this page demonstrates so nicely how not to make websites for programming tools.
Ender's website suffers from a number of, frankly, positively epic failures. When I am given a link to a website describing some programming tool, I expect to at least find some information about what uses the tool has. Unfortunately, I find none of this; the website seems to take the hipster approach to documentation, where if you don't know what it's useful for, you're not the intended audience in the first place.
I have a pretty big beef with the project's alleged description. Can anyone explain to me what No-Library Library
means? This makes no sense to me. I suppose, in the strictest interpretation of English, one could surmise from the title of the website that use of the Ender module in your site would grant your site the awesome power of an English article. Of course, any sane reader, regardless of sense of humor, will find this preposterous. We find later in the site that one can somehow extend this package. Further, it comes with a standard cadre, or Jeesh
, of stuff you can more or less depend on. To my understanding, this sure seems awfully similar to a library to me, and maybe even touching on some aspects of frameworks. I find a library of libraries
far more correct a description.
The website tells me nothing about Ender as such. Nothing at all. Despite the multifarious code examples, I haven't a clue what Ender actually is, what problems it solves, and why they think Ender makes a better tool than some other alternative. I should note that I've seen similar code examples for such tools as Node.js and jQuery, so to my untrained eye, I simply cannot divine the information I need to know about Ender just by looking at the code. Ender's page proves so nebulous to me that I can't even speculate on what a potential competing product might be.
Ender's website really needs to answer the following questions, in my estimation, to truly communicate with its reader:
Ender is an open, powerful, next level JavaScript library composed of application agnostic submodules wrapped in a slick intuitive interface,means nothing to me. I already know it's open; the source appears under the MIT license. I already know it's Javascript because of the provided code examples. I already know the interface
is slickand, at least for the cherry-picked examples given,
intuitiveagain thanks to the code examples. So, please, tell me something I don't know.
Because in the browser - small, loosely coupled modules are the future, and large, tightly-bound monolithic libraries are the past,tells me absolutely nothing. Everyone and their grandmother's pet pooch would agree with this observation. I'm interested in more tangible cost/benefit analyses, not fluff that would appeal to a philosophy major.
Please don't get me wrong. Ender probably solves a nice batch of problems for a wide variety of web-app developers. I just think that the hipster school of documentation doesn't serve it justice, and might even subtract from its potential up-take in the industry. People complain about the poor state of documentation all the time in the software engineering community. The problem isn't a programmer's lack of desire to document; rather, programmers tend towards documenting the wrong things entirely.
I've never written a free-form text editor before, let alone something as sophisticated as an IDE. This means that I'll be taking a journey of discovery along with the reader. Without even a single like project under my belt to guide me in its design, I will rely on stepwise refinement to try and discover a crude idea of what's needed to make such a project. You can think of this as a kind of spike solution, but on paper.
It's much faster to change a paper design than it is to change code, even if it is only exploratory in nature.
People expressed interest in how I come up with reusable, easy-to-maintain software in unaugmented Forth, a language not widely known for these attributes. Readers may find details concerning the Declarative, Imperative, then Inquisitive programming conventions and related material online, yet interest in practical, real-world applications of the concepts discussed remains. Instead of tearing down the video game I wrote to prove and exemplify the benefits of my coding style, I propose instead the creation of a completely new project: a general purpose, programmer-optimized text editor based loosely on my experiences from using both Oberon System and Wily. I expect the completion of the editor project will require a significant number of coding techniques I've developed so far, thus serving as an adequate foundation on which to explain my techniques.
Dear Ruby,
Hello, you probably remember me from last week, where you and I cooperated in the migration of Ning's content store tests from Perl. That was a lot of fun, and I'm pleased with the substantially smaller and easier to maintain finished code. However, you might also remember me from the coding exercise undertaken today, where I tried to interface some Selenium tests with our back-end infrastructure for a more detailed system integration test concerning new user sign-ups and sign-ins.
Now, Ruby, I like you. A lot. You're funny, witty, concise, and unlike Perl, you usually do the right thing. You've saved me countless lines of code, and thus, countless hours of hacking and debugging. But today, you have transgressed. Remember that module I wrote called ApplicationCoreBinding? You know, the one where you repeatedly insisted that you could not find the symbol find_cores? I've been meaning to talk to you about that; you see, your behavior with respect to find_cores proved most disappointing to me.
First, I think we both can agree on the meaning of the module keyword and what it implies, particularly in reference to defining both a namespace and a mix-in, like so:
# put this in file lib/foo.rb
module Foo
def find_cores(type)
# code to locate one or more cores of type 'type' here.
end
end
In addition, I think we both agree on what the meaning of the require keyword and all that it entails:
# put this in file test/core/test.rb $:.unshift(File.join(File.dirname(__FILE__), "..", "..")) require 'lib/foo'
Unfortunately, despite having written far greater than 10,000 lines of Ruby since working at Ning, you would think we could both agree on what the include directive means. I don't know about you, but I take my definition from the thousands of on-line documentation sources available, including on-line books, tutorials, blog posts, FAQs, dedicated question/answer sites like Stack Overflow, and more. My interpretation of what include means conforms to the commonly held view that you take the code embodied in a module and (semantically, if not in actuality) plop it, lock, stock, and barrel, inside the class where it's found, like this:
#append this to test/core/test.rb
class Bar # < Baz, it doesn't really matter
include Foo
def aMethod(someType)
cores = find_cores(someType)
# ... deal with cores here.
end
end
By your own online documentation, then, you indicate that I should have the ability to invoke find_cores without any further qualification because the include word reiifies, among other things found in the Foo module, the definition of find_cores in the lexical scope of Bar. Quite literally, the above code and the following code should behave exactly the same:
class Bar # < Baz, it doesn't really matter
def find_cores(type)
# code to locate one or more cores of type 'type' here.
end
def aMethod(someType)
cores = find_cores(someType)
# ... deal with cores here.
end
end
However, today, for some reason, and as far as I can tell only for my ApplicationCoreBinding module, you decided to not function according to expectations. Instead, you disrespectfully, tenaciously, and vociferously complained that find_cores remains undefined. I might have suspected incompetence on my own behalf, were it not for the fact that even my IDE, arguably equipped with only approximate
2 support for Ruby refactoring, nonetheless demonstrated full capability of locating the find_cores definition with all but Bar's text editor window closed, and selecting Find Declaration
in the pop-up menu.
To exercise my understanding further, I've tried nesting and unnesting the definition of both the definition and the module containing it, the include directive, and even tried different approaches to require, such that it continues to load in the same library. I tried changing the name of the file required, to ensure that you read the desired source file at compile-time. I also changed the module name included into the class, to see if things would break at compile-time. Much to my amazement and disappointment, it didn't. Apparently, inclusion of modules occurs at run-time in your world, despite the impression I received from countless websites on the matter. Four and a half hours of debugging effort later, I remain utterly defeated by this most perplexing and vexing problem.
So, I really need to know: which is it going to be, Ruby? You cannot exhibit favorable inclusion semantics in one class, and hostile semantics in another. You really do need to decide, will you or will you not cooperate with me in my endeavor for QA automation? A uniform yay or nay will provide me with the information I need to move on with the project. But, seemingly non-deterministic behavior such as today's exhibition just reeks of conspiracy with Perl. Have you been seeing Perl again? Has Perl been pushing drugs to you again?
Interpreter belligerency contributed heavily to why I broke up from Perl so long ago. Truly, I do not wish this to happen between us, as well. Ruby, I love you, but you need to trust in me, that when I desire a mix-in in my class, I genuinely intend for that mix-in's presence. If you cannot respect that, then I fear our relationship will come to an untimely, inamicable end. If it's Perl you want, then go, for I desire nothing to do with Perl or her friends. But, if it's me you want, then you need to tell me why you refuse to define find_cores. Okay?
With warm regards and grave concern, Samuel A. Falvo II |
1 And, an open letter to the Ruby language developers. Really, guys, WTF?!
2 Netbeans 6.9.1
While preparing some software to help illustrate a topic I'd like to cover during a Forth Day presentation, I found myself needing a decent random number generator. While numerous random number generators for Forth exists, few simultaneously meet the criteria of being easy to integrate and easy to maintain. Available implementations either assume environmental dependencies not offered by my Forth environment, or make use of either local variables or PICK. I decided to write my own implementation, based on Wikipedia's description of the algorithm. The result, while still not what I'd call easy to read
1, certainly seems easier to maintain. The code uses neither local variables nor PICK or ROLL words, and the stack never gets deeper than a handful of elements.
I reproduce the source code for study below.
\ Implementation of Mersenne Twister as taken from
\ http://en.wikipedia.org/wiki/Mersenne_twister
\
\ I am aware of Wil Baden's sources, but I had difficulty
\ getting it to compile under SwiftForth out of the box.
\
\ This module exposes the following API:
\
\ seeded ( uSeed -- )
\ Seeds the random number generator with the provided 32-bit,
\ unsigned value.
\
\ probability ( -- u )
\ Returns a random value that falls in the range [0,
\ $FFFFFFFF].
\
\ All other definitions are safe to shadow/redefine elsewhere.
\
\ Copyright (c) 2010, Samuel A. Falvo II
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or
\ without modification, are permitted provided that the following
\ conditions are met:
\
\ * Redistributions of source code must retain the above copyright
\ notice, this list of conditions and the following disclaimer.
\
\ * Redistributions in binary form must reproduce the above
\ copyright notice, this list of conditions and the following
\ disclaimer in the documentation and/or other materials
\ provided with the distribution.
\
\ * Neither the name of Samuel A. Falvo II, Falvo Technical
\ Solutions, nor the names of its contributors may be used to
\ endorse or promote products derived from this software
\ without specific prior written permission.
\
\ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
\ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
\ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
\ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
\ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
\ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
\ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
\ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
\ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
\ THE POSSIBILITY OF SUCH DAMAGE.
CREATE states
624 CELLS ALLOT
VARIABLE index
: reset ( nIndex -- )
states OVER 1- CELLS + DUP @ 30 RSHIFT SWAP @ XOR 1812433253 *
OVER + $FFFFFFFF AND SWAP states SWAP CELLS + ! ;
: randomized ( -- )
1 BEGIN DUP 624 < WHILE DUP reset 1+ REPEAT DROP ;
: seeded ( uSeed -- )
states ! 0 index ! randomized ;
: y ( nIndex -- y )
DUP 1+ 624 MOD CELLS states + @ $7FFFFFFF AND
SWAP CELLS states + @ 31 LSHIFT + ;
: altered ( nIndex -- )
DUP y DUP 1 AND 2567483615 * >r 2/ OVER 397 + 624 MOD CELLS
states + @ XOR r> XOR SWAP CELLS states + ! ;
: scrambled ( -- )
0 BEGIN DUP 624 < WHILE DUP altered 1+ REPEAT DROP ;
: probability ( -- u )
index @ 0= IF scrambled THEN index @ CELLS states + @
DUP 11 RSHIFT XOR DUP 7 LSHIFT 2636928640 AND XOR DUP 15 LSHIFT
4022730752 AND XOR DUP 18 RSHIFT XOR index @ 1+ 624 MOD index ! ;
1 I attribute much of the difficulty to the algorithm's inherent data management complexity.