thanhnguyen2187 / crypta

An offline-first code snippet manager
https://thanhnguyen2187.github.io/crypta/
MIT License
7 stars 0 forks source link

Re-architect the code #40

Open thanhnguyen2187 opened 8 months ago

thanhnguyen2187 commented 8 months ago

Take a look at SAM pattern and MVVM.

thanhnguyen2187 commented 7 months ago

One related idea on emitting logs from snippets store: https://github.com/thanhnguyen2187/crypta/pull/38#discussion_r1479609599

Let the store comes up with an action/log stream that is capable of recreating the whole store from scratch. Some example actions that the stream emits:

  • {"type": "initialization", "snippets": [...]}
  • {"type": "upsert", "snippet": {id: 1, ...}}
  • {"type": "upsert", "snippet": {id: 1, ...}}
thanhnguyen2187 commented 7 months ago

Some useful code lines:

export type Action =
  | {name: 'initialize', snippets: Snippet[]}
  | {name: 'upsert', snippet: Snippet}
  | {name: 'remove', snippet: Snippet}
  | {name: 'clear', folderId: string}
  | {name: 'clearAll'}

const actionsStream = writable<Action>({name: 'initialize', snippets})
thanhnguyen2187 commented 7 months ago

Folder structure idea:

thanhnguyen2187 commented 7 months ago

Another related comment: https://github.com/thanhnguyen2187/crypta/pull/38#discussion_r1484295119

One idea for later code structure improvement: let the store be managed by a "data manager" directly, and think about putting the migration somewhere else (maybe by the "data manager" itself).

thanhnguyen2187 commented 6 months ago

Food for thought: what if we model the data as a series of immutable events? In theory, it should simplify the code a lot: instead of manually checking and merging the data, we can "merge" (or append, to be precise) the events and be sure that the state is consistent everywhere.


After more digging, it is called: "event sourcing". There is one problem of event sourcing: the memories it requires. A quick testing yields around 0.2KB for each "record". Suppose we have around 1000 snippets (which is... quite a lot), and around 5 records for each snippets (CRUD events), then it becomes 5000 records, which is around... 1MB.

In case we hit an arbitrary limit (1GB, or 5 000 000 records for example), we can try "data compressing", which is:


One related article: https://flpvsk.com/blog/2019-07-20-offline-first-apps-event-sourcing/

thanhnguyen2187 commented 5 months ago

Working on #57, I tried to make it as clean as I can, and came upon XState. The theory behind (state machines and statecharts) led me to reading "Constructing the User Interface with Statecharts" by "Ian Horrocks". The book was really useful on showing a good approach to UI construction design.

thanhnguyen2187 commented 5 months ago

Excerpts from the book:


Chapter 9: Design heuristics and design tests

[...] The overall design strategy is to identify the states of a statechart from the top level downwards. However, it is necessary to understand the behaviour of individual items in order to identify the states and it is impossible to use a purely top-down approach.

Design heuristics

Identify the high-level statechart

The first step in most statechart designs is to identify the high-level states in the design. These states usually correspond to screens (canvases) that a user can navigate between. It is good to have a firm understanding of which user evens will cause the user interface to move between different canvases early in the design process. This allows the user interface to be divided into parts that can be constructed by different developers. By establishing the interfaces between screens early in the design process, problems relating to integrating screens can be avoided.

Hint: Design one screen at a time, but start to understand how to screens interact reasonably early in the process.

[...]

Hint: The high-level states in a statechart correspond to the windows and subwindows in a user interface.

Screen rules

After the high-level states have been identified, the next step is to consider each of the states in more detail. The best starting point is to write down all the items in or associated with a screen. In other words, buttons, menu items, text items, radio buttons, scrolling lists and so on. Also consider keyboard shortcuts [...].

The next stage is to identify whether the behaviour or appearance of an item is constant or whether it varies. [...].

The point of screen rules is to identify the behaviour of items, not so much in terms of what they will do (that is, the actions), but rather when they are available to a user and what the differences in they behaviours are. Screen rules are fragments of a user interface's behaviour that must be combined together in a statechart. They are an important first step in clarifying the behaviour to be modelled and, more importantly, what the common behavioural contexts are.

[...]

The screen rules that need to be identified are summarized below.

Entry and exit rules

What user events cause a screen to be entered or exited? What events cause an application to be closed? Are there different conditions that can affect the behaviour? [...]

Identify any modes

A mode is a state that the software can enter and where the effect of a user event changes depending on the mode. [...]

Identify the screen items that have varying behaviour

Identify all the screen items whose behaviour changes as a user interacts with the screen. There are many ways in which a user interface item can change: for instance, enabled to disabled, visible to invisible, position a to position b, colour x to colour y, and so on. Also, identify items whose attributes may never change, but whose actions may differ under different circumstances. Identify not just the change in behaviour, but what events and conditions cause the change in behaviour.

Identify the screen items that have constant behaviour

There are surprisingly few screen items that always behave in exactly the same way regardless of the context in which they are used. It is worthwhile considering each item in turn an confirming that the behaviour really is constant.

Note that screen rules are a means to an end. They are only temporary design entities and so do not have to be written in the precise tones of a requirements document. The designer of the statechart will be the only person who uses the screen rules. They should not be kept after the statechart has been designed, because all the information stated in them will be translated into the statechart. Atempting to keep a set of screen rules and statechart in step with each other is an unnecessary overhead that few projects will be able to afford. Statecharts should be the definitive specification of a user interface's behaviour.

thanhnguyen2187 commented 5 months ago

High-level requirements and main tasks of the users

The application is geared toward software developers, who want to store and reuse their commonly used code snippets. The main features are:

There are many note-taking applications that support most of those features (Notion, Evernote, Notesnook, massCode), but each doesn't tick every boxes.

Screens