Holisitic Development: Anatomy of FrankenApp V3
Notes
- This is for conceptual reading.
- It’s important to have as much discussion as possible. Nothing here is set in stone. Bring suggestions, friendly debates, new ideas, concerns–whatever you got.
- Additionally, there’s a reservations section in each step. If you have concerns, but don’t have time for a full meeting, write one there or leave a comment.
Beating This Metaphor to Death
This entire document follows the process of building the app as if it were a living, breathing organism. Apologies in advance for the run-on metaphor.
In some ways the analogy is useless, as building biological lifeforms is not in our wheelhouse (as far as I know). However, I think it will be helpful to separate different parts of the app out into holistic systems. More importantly, we can see how they’d all come together.
It’s also important to note that each of the systems are crucial, and if one is built poorly, the app fails on some level. Every app has this problem, and its usually poor design on one of these systems that will cause it to get sick–and in some cases–die a miserable death.
V3 is our monster baby, and we want it to live forever.
The Systems
Cardiovascular System:
This system is responsible for the speed, rhythm, transport, and flow of data. While this is a very important system, JS, React and the bundler handles most of this by default.(render cycle -> heartbeat, function and logic branches -> veins and arteries, thread of execution -> internal clock).
All we need to do is understand how this stuff works.
Nervous System:
Responsible for the acquisition, storage, and reshaping of data. We could think of the fetching as sensory organs like the eyes and ears, the context as the brain’s hippocampus (storage), high level utilities as various parts of the brain, and low-level utils as the nerves.
Context and hooks allow the app to send signals from one part to the other. Logic written in functions tells the entire organism what to do with that data, and where.
Moreover, deciding on a coding paradigm and style gives the app its character (from a DX point of view).
Skeletal System:
Routing and page structure. Closely linked with the nervous system (spine/routers).
This is a simple system for us to implement, but it needs to be done really well. Once the structure of the app is set in place, it becomes really hard to change.
Immune System
This is the app’s self-regulatory system. It prevents mutations and spread of bad patterns before they spread throughout the body. Testing, types, and linting are large factors here. But also processes outside the app like code review and QA.
This metaphor is especially useful here, because protective measures have a chance to go ‘auto-immune’ and make things worse. Balance is key.
Digestive System
Coordinated ways for the app to grow. The boost dev workflow. What we often refer to as the ‘boost rails’. Community developers can feed the app, and because this system is in place, the app will get stronger instead of sick.
Muscular System
These are the UI components. From the primitives to macro elements. These items do the heavy lifting and are responsible for firing events. These also define the look and feel of the app. For brevity, we could also include the Epidermal system (skin) in this part of the metaphor. These items respond to the nervous system in predictable patterns.
Reproductive System
This system’s purpose is to foster development of applications outside of itself. This could come in the form of refactoring components and utilities to be used across other apps (ex. SDKs and component libraries) Having code built specifically for reuse allows the community to quickly build special use bolt-ons and micro-frontends.
Endocrine System
Error handling. 404. Event emitters. RPC is down. Sub graph is down. No Wallet.
Things that signal changes that the entire app needs to listen for, and change states across the board.
Recipe
Step 1: Sequence DNA
DNA creates alignment throughout the app. It’s the blueprint of the app.
- DNA is the design documents of various types. These attempt to make informed decisions on architecture before that architecture is built.
- Some examples:
- Map of backend architecture (centralized && decentralized)
- Map of all core contract interactions and args
- Data models (legos)
- Component design document. (UX/UI)
- Page design document (UX/UI)
- Stack document (Decisions on which software we use)
- This Document. Designing which parts of the app perform which function, and choosing when to roll those out.
- Designs for each (bodily) system in the app
- Various hacking endeavours to test assumptions
This step addresses the app as a whole and largely focuses on how each system within the body should be designed.
Reservations:
Wouldn’t this work ONLY if everything goes to plan?
Nothing will go to plan. It’s likely that most things will slip off the path. The point of having a work-plan is to be more resilient and coordinated when things do change, we can mark it down somewhere central, and alert everyone working on the app that this change happened.
In order to coordinate in parallel, there needs to be a common understanding. Creating a base-line plan, allows us to know how changes will affect each system in advance. In doing so, we’ll become more adaptive.
We never really know until the code runs
Agreed. Which is why it’s important to hack together some prototypes and tests.
Step 2: Grow Cells
Cells are the building blocks of the app. One of the great advantages we have working on V3 is that we learned a lot already through our other science experiment – V2.
We learned that there are core primitives for pretty much every system in the app. In this stage we build the primitives first, before moving on to the factories and structure.
Muscular system:
Event and UI components that do work
- Basic UI components (Button.jsx)
- Compound or wrapped components (TributeInput.jsx)
- Mini-layouts and multvariant components (ProposalCard.jsx)
- Parts will be handled through libraries
Nervous System:
Components that transfer data from one form to another
- Some Utility Libraries.
- For systems where we are sure we need external fns. For example, we have duplicate utilities for changing token values. None of them work really well. Would be great to have one set of functions that always work
- Queries
- generalized single utilities (ex. pipe, omit, objFlter. Could come from util library)
- Other atomic parts that would be used for managing the app.
Immune System
- Unit tests
- Type declarations
- Build general type guards
- Dev environment (prettier, eslint)
Reservations:
Shouldn’t a component know the data structure of an app before building?
In most cases, no. Components only need to know the minimum data to display UI. This helps keep our components as stateless and dumb as possible.
Step 3: Shape the app.
For this step, we turn away from the micro and focus on the macro. We need to build out the app’s general shape.
The vitals (builders and factories) are awaiting data from the nervous system, and the nervous system needs to know in which direction it needs to route its data.
Skeletal System
- Finalize tree and decide on tree structure
- This structure should be built to handle whatever state management pattern we choose. A skeleton to support Redux or MobX would be very different than regular contexts.
- Build out the spinal column of the app, the routers. These are going to decide how the data will flow into the view.
Nervous System
- Build out queries
- Wait for resolvers
- If we’re using contexts for state management, decide where to localize storage of data.
- If not using contexts, and are using a global state management library like Redux, localization matters less as rendering is cleaner.
- Have state respond cleanly to route changes. For example, switching from one DAO view to another should unmount the DAO view, then mount the next DAO view to prevent the view from ‘sticking’.
Endocrine System
- Have the nervous system respond cleanly to major events in the app (wallet/no-wallet, network change, userchange).
- Make sure the emission of those events don’t cause runaway loops.
Immune System
- Test that events (hormones) emitted trigger logic in the nervous system
- Test that after every event, the state being display is correct
- Do the same for route changes.
Step 4: Vitals
While it would be tempting to build everything down the component tree from here, we need to keep in mind the scaling demands the app will be placed under. For scaling, we need to build the factories of the body–organs.
This app should be able to generate an infinite amount of forms, contract interactions, boosts, minion configs and more. For that we need organs to autonmously produce components on the fly, instead of having us code them over and over.
Nervous System
- Build query resolvers to match demands from factories and builders
- Determine proposal types quickly and efficiently
- Build polling system
- Build bytecode compiling system
- Build application state queries (search notation)
- Build a TX matrix
- Build specialized type guards
Muscular System
- Build formBuilder
- Build contentBuilder
- Ensure builders compose UI elements seamlessly
- UI elements can work standalone or outside builders
- Custom hooks for stuff we do all the time
Digestive System
- Finalize shapes of legos (TX, Forms, Fields)
- Compose legos into boosts
- Organize minion utilities
- Third-party boosts and boost UI (form builder) can load their own packages and SDKs.
Immune System
- Using legos, write tests to ensure that the factories respond perfectly to data.
- Define types for legos
- Unit tests for txHelpers
- Build type guards throughout the app thus far.
- Testing that the factories are getting the data they need.
Step 5: Tying it all together
We start with generic layout components to make sure that the framing is consistent across the app. Then we apply those layout components to the pages.
This is also where we begin to use the DAO config from the API to orchestrate UI and organize data.
Muscular System
- Build layout generics
- Build out new nav features
- Compose micro components into macros
- Use Builders where we can.
- Compose macros with DAO config data from API
- Build out interchangeable pop-out elements that respond to DAOconfig
Nervous System
- Build CRUD ops for playlists
- Build CRUD ops for boosts
- Handle state changes for CRUD ops
Endocrine System
- Build UI for error handling system
- Have nervous system respond to changes in DAOdata
- Macros respond to mobile
Immune System
- Tests to ensure that the pieces fit together
- Tests to ensure errors from API are handled
- Test that nav and other macro UI are responding correctly to events
Step 6 - The Face of DAOhaus
With all the systems in place and everything ticking along nicely, the last thing to do is build out all the one-off features that give the app its identity.
Lots of these features would be on the hub-level. Explore, Summon, Hub, Socialtools. And on the DAO level, we may rebuild the pop-outs (elements that can be swapped with boosts)
Because these features are so core to DAOhaus’s identity, there’s a large advantage to building them last. The builders at this point would be experienced with the new systems. Often what gets built last shines.
Since these services are the ‘first impression’, it’s a great advantage to not have to think about systems design or ‘just getting things to work’. Instead the focus is on detail.
Here’s also where we could do style one-offs. Maybe there’s some helpful illustrations, or an in-app walk-through of the services for new users.
Muscular System
- Nothing is really added to the system per se, we’d just need to be mindful that we’re using it.
Immune System
- Another crucial stage for testing.
- Though there are a lot of unit tests layered in, we’d want to go through the app and try to break things.
- Devs will know where the weak spots are.
Next steps:
At this stage, the app is complete. This is where we might shift our focus from core UI/UX to DX. If people are finding this mental model useful, then I can write out the next steps.
Step 7: Feeding and Growing the App
- community dev
- meeting and testing scaling demands
- handling new integrations
- supporting community devs
Step 8: Spawning New Apps
- refactoring useful general code to help others build app in the ecosystem
- How to handle shift to V4
Step 9: Saving for retirement
- Self sustainability
- App Decentralization (hosting, git platform, slaying centralized dependencies)
- Plans for community ownership and operation (outside of WarCamp)
Step 10: Longevity
- Continuous upgrades and patches for health.
- How this will tie in with child APIs
- How this will tie in with community
- Full transfer of ownership to a vibrant community (immortality)