Skip to content

Decision Log

Flynn Duniho edited this page May 29, 2024 · 3 revisions

001 Tool Selection 6ab5fd94

SUMMARY: Selected brunch as build tool, using React as our component framework.

In our original devplan, I allocated 4 days to port the old tools from PLAE to NetCreate. Our "day" estimate equals six actual working hours; as I reviewed various State of Javascript 2017 articles it occurred to me that 24 hours would be adequate time to make a few careful tool changes to gain improvements in compile speed and accessibility to generalist programmers. So far I've billed about 4 hours out of the 24 hours, though there are a lot of unbilled research hours that I consider part of professional practice, so I think this will pay off.

The major change is the switch from Gulp to Brunch as our general "build tool", which takes source html and js files and compiles them into a webapp that can be served to a web browser. Gulp was an improvement over Mimosa in its flexibility and "configuration is code" ease-of-understanding. However, the Gulp plugin ecosystem is full of weeds and unmaintained releases. Brunch, by comparison, minimizes the amount of configuration and has a few strong (if not well-described) principles that are much easier to grok. It's also a single tool with a long history (6 years of supporting modular javascript). While it also has plugins, the amount of configuration is considerably less though the plugin authors vary in their implementation of configuration. However, the overall goal of Brunch is to have smart, minimal-configuration defaults that just work along with auto-configuration through clever sniffing of the package.json. Gulp, by comparison, has many plugins but each one has esoteric configuration that requires changes to multiple files. Brunch is also theoretically much faster at compiling than Gulp, which was getting slow.

I briefly toyed with replacing React with HyperApp, which is much smaller and shares the "less is more" philosophy. React has semantics that feel overblown and cumbersome, particularly its state management and property passing conventions. Adding Redux also irritates me with its half-assed, poorly named approach to hooking it in. HyperApp, on review, looked much cleaner and appropriate for a small project like ours, and we were going to use our own state manager anyway from PLAE. HyperApp also understands JSX. However, I stayed with React because I was able to get it to work first, and I know Joshua has been looking into React so it would be nice to keep. React is HUGE too, so we can find more documentation and assistance with it.

After a few hours of massaging things into place, we now have a skeleton build system in place with Brunch that will compile from our source directories, launch a server, and handle livereload in the browser as source files change. I also have stub javascript modules and React components, which use Brunch's module approach (replaces requirejs, which by many accounts is going the way of the dodo). With this base in place and working predictably, I can start adding additional libraries and build-out the skeleton webapp itself.

002 Adding Client Libraries cc7ef5934

SUMMARY: Added Bootstrap 4.0.0 and dependencies Popper, jQuery to NetCreate as CDN libraries because this seemed more efficient.

With the module system in place, I wanted to add the Bootstrap 4.0.0 CSS Framework. How hard could this be? Most of the Brunch skeletons that do an npm install bootstrap which also requires installing jquery and something called popper. There is not an inconsiderable amount of brunch-config changing to make these libraries declare globals that are compatible with the module system. This requires reading up about the idiosyncracies of Brunch plugin system. It was exactly the same with RequireJS config; it seems that Brunch hasn't escaped this. Very irritating.

On disadvantage of using the jquery and bootstrap npm packages is that they are HUGE and have many dependencies when you do an npm install. I wasn't in the mood to deal with it, so I made static copies of bootstrap, popper, jquery javascript AND css by going to the Bootstrap 4 example page (make sure you don't go to the alpha version, since the syntax has changed on release). Then I stuffed them into the vendor folder. Brunch is smart enough to combine the js and css into the joinTo props of brunch-config, which point to nc-lib.js and nc-lib.css files respectively. These are included by index.html.

003 Module Reorganization 090eebc3

SUMMARY: Reverse decision to use static vendor libraries for bootstrap and jquery; now using NPM integration feature of brunch to include in the library bundle. This seems like a better way to do it.

004 Add React, ReactRouter 3f895159

SUMMARY: The init.jsx file is in the same directory as init-appshell.jsx, which draws the main UI. It's now easier to add the menu link AND route information by editing just init-appshell.jsx. Rewrite import statements (which are used by webpack into CommonJS-style const mod = require('modulename') calls.

005 Determine View and Model Conventions 53b275c3

SUMMARY: Can create plain HTML webapps now that still have access to its own instance of the modular system code; these are located in app/assets/htmldemos. Full-blown React apps are located in the view directory. Edit init-appshell.jsx to add routing paths and menu links.

005 Determine View and Model Conventions 4e373119

SUMMARY: Add Ben's D3 forcedemo HTML through our system in only five minutes. It lives in app/assets/htmldemos/d3forcedemo

There are two stages to the NetCreate prototype development. In the first stage, we are making simple single-page HTML demos to play with the concepts behind interface design and visualization approaches. These are like code playpens, loading libraries from CDNs and incorporating scripts and styles in-line in a single HTML document. In the second stage, we take the good parts from these demos and integrate them into a system that provides networked and persistent data storage inside a React-based framework.

To make an HTML playpen app, you save it into assets/htmldemos. To make a system module, you save it into app/view. Then, modify app/init-appshell.jsx to add clickable links to the code.

006 Event Conventions

SUMMARY: We are using the "Level 2 DOM Events" style that looks like target.addEventListener('click', function (event) { ... });

In the past, our system design tended to follow the example of Javascript code on the Internet, which used a blend of various techniques dating from ancient inline-html (<button onclick="myClickHandler()"/>) to the more recent assigned to a handler property (button.onclick = function (event) { ... }). It's better to use the addEventListener form, which is pretty newish, because it allows multiple subscribers to the same target AND you can remove them too. We've also used different conventions for expressing the idea of notification as "notifiers", "subscribers", "callbacks", "transactions", "remote procedure calls", and so forth. Moving forward we'll try to make these all part of a big event system so there is less to remember.

See EventTarget interface and Event interface for details.

007 Conversion to 2-space TABS as SPACES 6397f0a4

SUMMARY: We're using spaces as tabs, with a tab size of 2. It's possible to configure SublimeText to make this not-terrible in editing.

The big advantage of 2-space tabs is that nested HTML and JSX is more compact. The advantage of spaces is that the text can be pasted easily into a web page without the tabs expanding the the giant default of 8 spaces. The disadvantage of spaces is that pressing TAB inserts two spaces, which requires TWO BACKSPACE PRESSES. There's an increase in file size too, but file sizes have not been a big deal for 10 years.

There are SublimeText settings that fix the "two backspace presses" issue. Here are the settings I am using in the syntax-specific settings for .js and .jsx files:

"translate_tabs_to_spaces": true,
"use_tab_stops": true,
"tab_size": 2,
"detect_indentation": true,
"draw_white_space": "all",
"trim_trailing_white_space_on_save": true,

Also, we're using editorconfig to help enforce the tabsize/tabstyle standard as defined in the .editorconfig file

008 Unified EventEmitter and MessageEmitter

SUMMARY: Expanding on 006, adding conventions for APIs that use Events (local scope) and Messages (network scope) with best practices for implementing asynchronous code. We also account for "event-driven" situations (e.g. user interface updates and data binding) and "event-like" scenarios (e.g. application lifecycle, tracking mode switches)

Our previous system design didn't use a consistent approach to handling callbacks, event handling, and change notification. We tended to use whatever was convenient at the time of writing the code. This has lead to confusion in knowing what approach to use at what time within the context of a webapp. We don't have best practices for writing asynchronous event-driven code other than what is implicitly established by code style and key modules like UNISYS and SYSLOOP.

009 Review Autocomplete Demo

The AutoCompleteDemo has been refactored to use the Unified EventEmitter/MessageEmitter in a redesigned UNisis

Clone this wiki locally