Getting your hands dirty and feet wet with Open Web Component Recommendations...sort of.
This a cross-post of a Feb 26, 2019 article from Medium that takes advantage of my recent decision to use Grammarly in my writing (so, small edits have been made here and there), thanks for looking again if you saw it there đđ˝ââď¸ and if this is your first time reading, welcome!
Welcome to âNot Another To-Do Appâ, an overly lengthy review of making one of the smallest applications every developer ends up writing at some point or another. If youâre here to read up on a specific technique to writing apps or have made your way from a previous installation, then likely you are in the right place and should read on! If not, itâs possible you want to start from the beginning so you too can know all of our charactersâ backstories...
If youâve made it this far, why quit now?
Reusable and Scaleable Data Management
You know whatâs kind of popular right now? Functional programming. You know whatâs a great way to deliver features build to take advantage of functional programming concepts? ES Modules. You know whatâs a great way to manage logic trees without relying on switch
or if/else
statements? The strategies pattern. What do you get when you mix them all together? Reusable and Scaleable Data Management. Or, at least I certainly hope so (yes, thatâs another good one to take down to the comments)...hereâs how I did it.
Reuse
On the reusable end of the spectrum, letâs start with the functional interface by which we interact with the lifecycle of our list of to-dos (creating it, adding to-dos to it, and completing to-dos on it). Access to this can be gained via import { newToDos, addToDo, completeToDo } from './to-do-manager';
. Here we get functional controls to initialize a new set of to-dos (i.e. return []), add a to-do (i.e. return [...todos, newTodo]
), and remove a todo (i.e. return [...todos.filter(todo => todo.id !== completedId)]
. Across each of these, we establish and maintain the identity of our individual to-dos while generating a new identity for the resulting list of to-dos, which will trigger the render pipeline in our LitElement
based application. Further, their being exports allows them to be used and reused across our application and tests while being prepared for being made an external dependency if at some point this data became useful across multiple applications. If you want to use them in your To-Do application, fork me on GitHub!
Scale
On the scaleable side of the spectrum, weâll be looking at the rest of the code in [src/to-do-manger.js](https://github.com/Westbrook/to-do-app/blob/master/src/to-do-manager.js)
which covers the ability to deliver work level customized suggestions for the user via the workLevelMessage(todos)
export. While this data is also structured for use across the application and possible externalization as well, whatâs really nice about it is how it is structured to scale.
function workLevelMeter(todos) {
const workLevelCounts = Object.keys(workLevelByTodoCount);
const count = workLevelCounts
.find(todoCount => todos.length <= todoCount);
return typeof count !== 'undefined'
? workLevelByTodoCount[count]
: workLevelCounts.length;
}
export function workLevelMessage(todos) {
return workLevelMessages[workLevelMeter(todos)];
}
Notice how rather than attempting to structure an extended if/then
tree or switch
statement to outline which the message to return from [workLevelMessage](https://github.com/Westbrook/to-do-app/blob/master/src/to-do-manager.js#L52)
the [workLevelMeter](https://github.com/Westbrook/to-do-app/blob/master/src/to-do-manager.js#L44)
method relies on a series of object and array methods (thanks to our previous commit linting experience) to resolve the appropriate message. This means that regardless of whether to the current five levels of workloads and their associated messages, to a single one, or to fifty levels, this same logic will apply. We donât need to go about adjusting what could easily become an awkward logic tree when you choose to make additions to the messages delivered or alterations to the levels at which their delivered, we just add the associated information to the data structure:
export const workLevelMessages = {
0: 'Looks like you don\'t have anything to do right now. Take a break!',
1: 'Looks like you\'re almost done. Keep it up!',
2: 'Still a little more work to do. Don\'t loose focus!',
3: 'It\'s a tough job, but somebody\'s got to do it.',
4: 'This may look like a lot, but I know you can do it!',
5: 'Maybe it\'s time to take a vacation? I won\'t judge.',
/* New message */ 6: 'There\'s a new message in town!',
};
export const workLevelByTodoCount = {
0: 0,
3: 1,
6: 2,
9: 3,
14: 4,
/* New work level */ 50: 5,
};
The above additions will immediately be available to uses with 50 or more to-dos, no logic alterations needed. And, even better, with the additional export of [workLevelMessages](workLevelMessages)
and [workLevelByTodoCount](https://github.com/Westbrook/to-do-app/blob/master/src/to-do-manager.js#L36)
those additions are also immediately added to the testing process.
And, in the end...
If you are sure Iâm wrong, want to celebrate how right I am, or teach me ways I can be even crazier/insightful/progressive/right/et al. about anything youâve read this far, I hope you know the refrain...the comments you take, and equal to the comments you make. Or at least I heard (something like) that somewhere.
As is noted above, the code shared throughout our conversation to date has not always been what ended up as final in my application. In case youâve not gotten a chance to see what did, feel free to read the whole codebase on GitHub.
Open-wc Starter App
Quickstart
To get started:
git clone https://github.com/open-wc/open-wc-starter-app.git
cd open-wc-starter-app
npm install
npm start
Scripts
-
start
runs your app with auto reload for development, it only works on browsers which support modules for faster builds -
start:es5
runs your app for development, it only works on browsers that don't support modules (IE11) -
build
builds your app for production and outputs it in the /dist folder -
start:build
runs your built app using a plain web server, to prove it works without magic đ -
build:stats
creates an analysis report of your app bundle to be consumed by Webpack Visualizer and Analyser -
test
runs your test suite -
lint
runs the linter for your project
You can also see the current final application on Netlify. Itâs tied to the GitHub repo above, so by current...I really mean it. Itâs putting all of the ideas weâve discussed in action live on the internet, and I hope the conversations weâve shared about the development of it have proved useful to you in some way.
To bring us back to where we started, hereâs a little refresher on the concepts that I wanted to find their way into my little To-Do app:
- component-based code architecture
- custom property based style API
- event-based state management
- style sharing
- unit testing
- web component-based UI
Over the course of some tightly related and others wildly tangential approaches, I hope you agree that I did a decent job of making a pass at each and every one of them. Some of these techniques are enabled by the team behind Open Web Components and their brand new Starter App. Some of them are rooted deeply in the tools recommended therein. And, others are flights of fancy that Iâve cooked up or heard over the course of years working with applications on the web.
If I havenât said it yet, or in some cases if you hadnât heard it yet, Iâm not planting a stake in the ground to say that any of them are bar none the best in their class, and even less so am I trying to say that any of them would apply to projects of any size or holotype. What I do hope is that maybe like yet another set of interesting voices I follow in the field the subjects covered so far spark, not joy, but an interesting conversation between you and your other self, you and your team, you and me, or possibly even any small part of the larger javascript community. The more we get together to talk about our techniques and fret out the edge cases and the exactitudes that make them up, the happier weâll be. (Oh, look, maybe I did mean for it to spark joy...) So, take the discussion to the comments below, the @ messages on Twitter, your favorite Slack, or this one were working with the web platform, web components, LitElement, and Open Web Components are all trending (at least most of the time), and Iâll see you there!
Fin.
The Short Game
As voted on by a plurality of people with opinions on such topics that are both forced to see my tweets in their Twitter feed and had a free minute this last week, a 9000+ word article is a no, no.
So, it is with the deepest reverence to you my dear reader that Iâve broken the upcoming conversations into a measly ten sections. Congratulations, youâre nearing the end of the first! If youâve enjoyed yourself so far, or are one of those people that give a new sitcom a couple of episodes to hit its stride, hereâs a list of the others for you to put on your Netflix queue:
- Not Another To-Do App
- Getting Started
- Test Early, Test Often
- Measure Twice, Lint Once (I, for one, welcome our robot overlords. Maybe theyâll do the writing every time I have an idea to deliver a crazy long series of articles like this...)
- Make it a Component
- Make it a Reusable Part
- Does Your Component Really Need to Know That?
- Separate Things Early, Often, and Only as Needed
- Some Abstractions Arenât (Just) For Your App
- Reusable and Scaleable Data Management/And, in the end... (you are here)
- See the app in action
Special thanks to the team at Open Web Components for the great set of tools and recommendations that theyâve been putting together to support the ever-growing community of engineers and companies bringing high-quality web components into the industry. Visit them on GitHub and create an issue, submit a PR, or fork a repo to get in on the action!
Top comments (0)