Rocksolid Light

Welcome to RetroBBS

mail  files  register  newsreader  groups  login

Message-ID:  

Xerox never comes up with anything original.


devel / comp.lang.javascript / Code review: personnel scheduling app

SubjectAuthor
* Code review: personnel scheduling appluserdroog
+* Re: Code review: personnel scheduling appJulio Di Egidio
|`* Re: Code review: personnel scheduling appluserdroog
| `- Re: Code review: personnel scheduling appJulio Di Egidio
`* Re: Code review: personnel scheduling appMichael Haufe (TNO)
 `* Re: Code review: personnel scheduling appluserdroog
  +- Re: Code review: personnel scheduling appMichael Haufe (TNO)
  `* Re: Code review: personnel scheduling appMichael Haufe (TNO)
   `- Re: Code review: personnel scheduling appluserdroog

1
Code review: personnel scheduling app

<963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18273&group=comp.lang.javascript#18273

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:ac8:6883:0:b0:419:a33e:e6fa with SMTP id m3-20020ac86883000000b00419a33ee6famr190146qtq.5.1696814137000;
Sun, 08 Oct 2023 18:15:37 -0700 (PDT)
X-Received: by 2002:a05:6808:bc8:b0:3a8:43ed:ce9c with SMTP id
o8-20020a0568080bc800b003a843edce9cmr5498608oik.1.1696814136682; Sun, 08 Oct
2023 18:15:36 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Sun, 8 Oct 2023 18:15:36 -0700 (PDT)
Injection-Info: google-groups.googlegroups.com; posting-host=24.107.183.247; posting-account=G1KGwgkAAAAyw4z0LxHH0fja6wAbo7Cz
NNTP-Posting-Host: 24.107.183.247
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
Subject: Code review: personnel scheduling app
From: luser.droog@gmail.com (luserdroog)
Injection-Date: Mon, 09 Oct 2023 01:15:36 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 5122
 by: luserdroog - Mon, 9 Oct 2023 01:15 UTC

This a single-page web app for viewing and manipulating the
daily schedule of people for a business like a restaurant or a
multi-restaurant theme park. It evolved from a very stupid simple
bash script but ultimately I thought it would be easier to spend
weeks and months to rewrite it in html/javascript rather than
trying to teach my coworkers how to use termux and emacs on
a phone. They're not computer people, just regular people.

So after 3 re-writes, it seems to be mostly in a workable form
but with bugs and stupids a-plenty I'm sure.

The UI is organized as an area with expandable controls, kinda
like menus, and the whole control area can be collapsed down to
the date to make a more printable page. In the "file" controls there
is a text box where you can paste text of the daily schedule copied
from paycor.com (previous versions worked with data from
whentowork.com) -- but note that the parser uses a hard-coded
key based on our company name which is present in the text so
the program will not be usable as-is for this function without
modification for the specific paycor client.

Once it's loaded with data, the app should provide intuitive editing,
sorting, filtering and writing little text notes attached to persons or
locations. There is also an experimental section allowing
customization of extra fields in the personnel data beyond the
required 5 fields which are: location, position, name, start time,
end time.

You can use this link to see the program in action upon a fictious
set of people and locations:

https://luser-dr00g.github.io/cm-pc.html?q=data+for+Friday+July+1%2C+2023%0Acustom+fields%3A+%5B%7B%22here%22%3A%22clickbox%22%7D%2C%7B%22notes%22%3A%22text%22%7D%5D%0Astation+notes%3A+%7B%7D%0ADesk+Concierge%0A%09M.+Myster%0910%3Aam-5%3A30pm%09%09%0AFood+Service+Corkscrew+Bar%0A%09Screwball+Sam+McKenzie%0910am-6pm%09%09%0AFood+Service+Even+Sillier+Place+Job%0A%09Firstname+Lastname%099%3A30am-4pm%09%09%0AFood+Service+Pie+in+the+Sky+FOH%0A%09Daisy+Dukes%099%3A30am-4pm%09%09%0A%09Kandoo+Candide%093pm-6pm%09%09%0AFood+Service+Pie+in+the+Sky+BOH%0A%09Piper+Prawne%099%3A30am-4pm%09%09%0A%09Someother+Name%093pm-6pm%09%09%0AOperations+Floor+walker%0A%09Pied+Piermont%0911am-4pm%09%09%0ARetail+Gift+Shop%0A%09Matron+Marms%099am-6pm%09%09%0AServices+Groundskeeping%0A%09That+old+dude%095pm-5%3A15pm%09%09

The code is viewable from github.
The html/css/javascript is in one file:
https://github.com/luser-dr00g/luser-dr00g.github.io/blob/ebe90e12ce13df2ffd96385552f744dc9430d7c7/cm-pc.html
and the separate components:
https://github.com/luser-dr00g/luser-dr00g.github.io/blob/ebe90e12ce13df2ffd96385552f744dc9430d7c7/click.js
https://github.com/luser-dr00g/luser-dr00g.github.io/blob/ebe90e12ce13df2ffd96385552f744dc9430d7c7/more.js
https://github.com/luser-dr00g/luser-dr00g.github.io/blob/ebe90e12ce13df2ffd96385552f744dc9430d7c7/tabs.js

zip (whole project, more than these files):
https://github.com/luser-dr00g/luser-dr00g.github.io/archive/ebe90e12ce13df2ffd96385552f744dc9430d7c7.zip

The code is organized (loosely) around the MVVC design.
A few global variables hold the "Model" data. The output()
function renders this data into HTML structures populated
with event handlers. Any event handler which wants to alter the
model has to call one of the Model's interface functions
which first creates an Undo/Redo record for the change
and then does a Redo (albeit for the first time this time).

So, it's my attempt to do an MVC design but with all Procedural
Programming. There's barely any OO except for using a class
to make a web component like you have to do. I have a sense
that maybe I've been avoiding OO too much and judicious
sprinkling of it might help.

Any critique or other comments welcome, even from Julio.
Earlier versions of the web components have been
discussed in previous threads started by me.

--
Additional sentence that is very curt and declarative.

Re: Code review: personnel scheduling app

<9ec432b3-bbf4-4e17-9b89-6745042d5c46n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18274&group=comp.lang.javascript#18274

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:a05:6214:1929:b0:658:71f8:7b35 with SMTP id es9-20020a056214192900b0065871f87b35mr184359qvb.7.1696820031423;
Sun, 08 Oct 2023 19:53:51 -0700 (PDT)
X-Received: by 2002:a05:6808:1916:b0:3ae:2024:837d with SMTP id
bf22-20020a056808191600b003ae2024837dmr7960556oib.8.1696820031218; Sun, 08
Oct 2023 19:53:51 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Sun, 8 Oct 2023 19:53:50 -0700 (PDT)
In-Reply-To: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=93.44.211.31; posting-account=F3H0JAgAAADcYVukktnHx7hFG5stjWse
NNTP-Posting-Host: 93.44.211.31
References: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <9ec432b3-bbf4-4e17-9b89-6745042d5c46n@googlegroups.com>
Subject: Re: Code review: personnel scheduling app
From: julio@diegidio.name (Julio Di Egidio)
Injection-Date: Mon, 09 Oct 2023 02:53:51 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 2348
 by: Julio Di Egidio - Mon, 9 Oct 2023 02:53 UTC

On Monday, 9 October 2023 at 03:15:41 UTC+2, luserdroog wrote:
<snip>
> <https://github.com/luser-dr00g/luser-dr00g.github.io>
>
> The code is organized (loosely) around the MVVC design.
> A few global variables hold the "Model" data. The output()
> function renders this data into HTML structures populated
> with event handlers. Any event handler which wants to alter the
> model has to call one of the Model's interface functions
> which first creates an Undo/Redo record for the change
> and then does a Redo (albeit for the first time this time).

Which suggests you are rather lumping model an controller.
But the code is too unstructured to look at (unless you pay
me for a couple of days of re-engineering): 2K+ lines of
lumped HTML+CSS+JS is simply not good enough. I'd
advise you to start by separating things... and while you
are at it, review all naming and code structure.

> So, it's my attempt to do an MVC design

It isn't: indeed nobody can understand MVC who has not
actually tried to build a project with explicit model, view
and controller components.

> Any critique or other comments welcome, even from Julio.

You must be kidding.

HTH,

Julio

Re: Code review: personnel scheduling app

<eaeb8578-aca2-41bb-b1cc-cb3f77182543n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18275&group=comp.lang.javascript#18275

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:ad4:4ba7:0:b0:64f:9386:a3a6 with SMTP id i7-20020ad44ba7000000b0064f9386a3a6mr267298qvw.7.1696942801270;
Tue, 10 Oct 2023 06:00:01 -0700 (PDT)
X-Received: by 2002:a05:6808:218a:b0:3ab:84f0:b4a5 with SMTP id
be10-20020a056808218a00b003ab84f0b4a5mr9430476oib.3.1696942801019; Tue, 10
Oct 2023 06:00:01 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Tue, 10 Oct 2023 06:00:00 -0700 (PDT)
In-Reply-To: <9ec432b3-bbf4-4e17-9b89-6745042d5c46n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=24.107.183.247; posting-account=G1KGwgkAAAAyw4z0LxHH0fja6wAbo7Cz
NNTP-Posting-Host: 24.107.183.247
References: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com> <9ec432b3-bbf4-4e17-9b89-6745042d5c46n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <eaeb8578-aca2-41bb-b1cc-cb3f77182543n@googlegroups.com>
Subject: Re: Code review: personnel scheduling app
From: luser.droog@gmail.com (luserdroog)
Injection-Date: Tue, 10 Oct 2023 13:00:01 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
 by: luserdroog - Tue, 10 Oct 2023 13:00 UTC

On Sunday, October 8, 2023 at 9:53:58 PM UTC-5, Julio Di Egidio wrote:
> On Monday, 9 October 2023 at 03:15:41 UTC+2, luserdroog wrote:
> <snip>
> > <https://github.com/luser-dr00g/luser-dr00g.github.io>
> >
> > The code is organized (loosely) around the MVVC design.
> > A few global variables hold the "Model" data. The output()
> > function renders this data into HTML structures populated
> > with event handlers. Any event handler which wants to alter the
> > model has to call one of the Model's interface functions
> > which first creates an Undo/Redo record for the change
> > and then does a Redo (albeit for the first time this time).
> Which suggests you are rather lumping model an controller.
> But the code is too unstructured to look at (unless you pay
> me for a couple of days of re-engineering): 2K+ lines of
> lumped HTML+CSS+JS is simply not good enough. I'd
> advise you to start by separating things... and while you
> are at it, review all naming and code structure.
> > So, it's my attempt to do an MVC design
> It isn't: indeed nobody can understand MVC who has not
> actually tried to build a project with explicit model, view
> and controller components.

Sigh. I suppose you're right. It kind of has these components
"spiritually" but not explicitly. All of my design work is done
on paper. So there are several sketches with the Model, View
and Controller parts as separate boxes with arrows connecting
them. But then I just wrote functions for all the arrows and
the larger structure vanished. Plus, several of my functions are
really, really long with deep nesting (taking full advantage of
my 2 space indents) and still have to do crazy hand formatting
to squeeze everything in.

ach. oop.

Re: Code review: personnel scheduling app

<54fd401e-59ac-44a3-86e6-d3eab0424858n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18276&group=comp.lang.javascript#18276

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:a05:620a:cf4:b0:76c:c5bf:6af5 with SMTP id c20-20020a05620a0cf400b0076cc5bf6af5mr241107qkj.14.1696946137790;
Tue, 10 Oct 2023 06:55:37 -0700 (PDT)
X-Received: by 2002:a05:6808:138c:b0:3a8:48fc:aaa5 with SMTP id
c12-20020a056808138c00b003a848fcaaa5mr9680507oiw.5.1696946137625; Tue, 10 Oct
2023 06:55:37 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.goja.nl.eu.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Tue, 10 Oct 2023 06:55:37 -0700 (PDT)
In-Reply-To: <eaeb8578-aca2-41bb-b1cc-cb3f77182543n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=93.44.211.31; posting-account=F3H0JAgAAADcYVukktnHx7hFG5stjWse
NNTP-Posting-Host: 93.44.211.31
References: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
<9ec432b3-bbf4-4e17-9b89-6745042d5c46n@googlegroups.com> <eaeb8578-aca2-41bb-b1cc-cb3f77182543n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <54fd401e-59ac-44a3-86e6-d3eab0424858n@googlegroups.com>
Subject: Re: Code review: personnel scheduling app
From: julio@diegidio.name (Julio Di Egidio)
Injection-Date: Tue, 10 Oct 2023 13:55:37 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
 by: Julio Di Egidio - Tue, 10 Oct 2023 13:55 UTC

On Tuesday, 10 October 2023 at 15:00:07 UTC+2, luserdroog wrote:
> On Sunday, October 8, 2023 at 9:53:58 PM UTC-5, Julio Di Egidio wrote:

> Sigh. I suppose you're right. It kind of has these components
> "spiritually" but not explicitly.

No, it doesn't, and I have said how: and that you can't see it,
not even parse my reply, until you try and do it. And it won't
take just one attempt, rather years...

Your code is somewhat cleaner than what I remember from
few years ago, though far from perfect, but for the rest, now
as then, you seem committed to remain the same crank.

EOD.

Julio

Re: Code review: personnel scheduling app

<32090dcf-befa-48d0-b98a-0618b236d934n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18277&group=comp.lang.javascript#18277

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:a05:620a:29d5:b0:777:56f8:7bfd with SMTP id s21-20020a05620a29d500b0077756f87bfdmr55037qkp.12.1697307449193;
Sat, 14 Oct 2023 11:17:29 -0700 (PDT)
X-Received: by 2002:a05:6808:200c:b0:3a1:f2a4:3d7 with SMTP id
q12-20020a056808200c00b003a1f2a403d7mr15684797oiw.1.1697307448889; Sat, 14
Oct 2023 11:17:28 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.goja.nl.eu.org!3.eu.feeder.erje.net!feeder.erje.net!feeder1.feed.usenet.farm!feed.usenet.farm!peer01.ams4!peer.am4.highwinds-media.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Sat, 14 Oct 2023 11:17:28 -0700 (PDT)
In-Reply-To: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=2603:6000:8900:6915:344f:9d91:553d:4c7d;
posting-account=hYRygAoAAABkmvJVmPilz9Q1TOjgPQAq
NNTP-Posting-Host: 2603:6000:8900:6915:344f:9d91:553d:4c7d
References: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <32090dcf-befa-48d0-b98a-0618b236d934n@googlegroups.com>
Subject: Re: Code review: personnel scheduling app
From: tno@thenewobjective.com (Michael Haufe (TNO))
Injection-Date: Sat, 14 Oct 2023 18:17:29 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 6494
 by: Michael Haufe (TNO) - Sat, 14 Oct 2023 18:17 UTC

On Sunday, October 8, 2023 at 8:15:41 PM UTC-5, luserdroog wrote:
>
> [...]
>
> The code is viewable from github.
> The html/css/javascript is in one file:
> https://github.com/luser-dr00g/luser-dr00g.github.io/blob/ebe90e12ce13df2ffd96385552f744dc9430d7c7/cm-pc.html
> and the separate components:
> https://github.com/luser-dr00g/luser-dr00g.github.io/blob/ebe90e12ce13df2ffd96385552f744dc9430d7c7/click.js
> https://github.com/luser-dr00g/luser-dr00g.github.io/blob/ebe90e12ce13df2ffd96385552f744dc9430d7c7/more.js
> https://github.com/luser-dr00g/luser-dr00g.github.io/blob/ebe90e12ce13df2ffd96385552f744dc9430d7c7/tabs.js
>
> zip (whole project, more than these files):
> https://github.com/luser-dr00g/luser-dr00g.github.io/archive/ebe90e12ce13df2ffd96385552f744dc9430d7c7.zip
>
>
> The code is organized (loosely) around the MVVC design.
> A few global variables hold the "Model" data. The output()
> function renders this data into HTML structures populated
> with event handlers. Any event handler which wants to alter the
> model has to call one of the Model's interface functions
> which first creates an Undo/Redo record for the change
> and then does a Redo (albeit for the first time this time).
>
> So, it's my attempt to do an MVC design but with all Procedural
> Programming. There's barely any OO except for using a class
> to make a web component like you have to do. I have a sense
> that maybe I've been avoiding OO too much and judicious
> sprinkling of it might help.
>
> Any critique or other comments welcome, even from Julio.
> Earlier versions of the web components have been
> discussed in previous threads started by me.

To quote Kent Beck: "Make it work, make it right, make it fast"

You've finished step 1, so iteration and improvement should be straightforward.

Avoiding OO/modules can work but makes things progressively harder as the codebase size increases as everything is in the same namespace (informally speaking). Some functions are more related to each other than others so defining an explicit grouping and naming them gives you power over them and an organizing principle. An object/class/module accomplish this.

I'd suggest improving the separation of concerns as the intent of the code is non-obvious unless you run the application.

1. separate out your domain.

What are the abstract, platonic concepts of the application divorced from the interface and how you're storing them?
From what I can see you have: "Station" as the the lone top level entity and a number of supporting entities:

// TypeScript
class Station {
location: Location
position: Position
name: string
timeSpan: TimeSpan
presence: boolean
notes: string
}

enum Location { ... }

enum Position { ... }

2. Separate out your data access

The responsibility of loading/saving data should be separated from other concerns. Define and use the Repository pattern for each primary entity:

abstract class Repository<T> {
getById(id: string): Promise<T>
getAll(): Promise<T[]>
update(item: T): Promise<void>
save(item: T): Promise<void>
delete(id: string): Promise<void>
}

class LocationRepository extends Repository<Location> {
/* manipulate localstorage and such. You can also perform the mappings to/from JSON here */
}

3. Explicitly define your use cases.

The application you're writing should be ignorant of how data is stored and what the UI looks like. By defining explicit use cases you can obtain
"Screaming Architecture". In other words by simply looking at the project we know exactly what it's doing by only glancing at the code and not running it.

A Use Case is either a Command or a Query and can be build via the Command Pattern:

abstract class UseCase<T,U> {
abstract exec(t: T): U
} abstract class Command<T> extends UseCase<T, void> {}
abstract class Query<U> extends UseCase<void, U> {}

This enforces the CQS principle <https://en.wikipedia.org/wiki/Command%E2%80%93query_separation>

An example usage:

class ShowStationsUseCase extends Query<Station[]> {
constructor(
private repo: Repository<Station>
) { super() }

exec(): Station[] {
const stations = this.repo.getAll()
// sort or whatever data massaging you want
return stations
}
}

4. The presentation layer utilizes use cases instead of mixing business logic and such as it is now:

class MyStationListingComponent {
repository = new StationRepository()
useCase = new ShowStationsUseCase(this.repository)
...
constructor() {
super()
// in constructor, or maybe in a callback method:
const stations = this.useCase.exec()
this.present(stations)
}
}

This is a very impressionistic set of suggestions and is a variant of what is referred to as "Clean Architecture" which unifies the "Hexagonal" and "Onion" architectures:

<https://www.plainionist.net/Implementing-Clean-Architecture/>

Re: Code review: personnel scheduling app

<125fd145-4617-479a-a40b-7ce1aa3c74f4n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18278&group=comp.lang.javascript#18278

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:a05:620a:828f:b0:778:905f:277d with SMTP id ox15-20020a05620a828f00b00778905f277dmr75510qkn.6.1697640464798;
Wed, 18 Oct 2023 07:47:44 -0700 (PDT)
X-Received: by 2002:a05:6870:3286:b0:1e9:a128:7f1b with SMTP id
q6-20020a056870328600b001e9a1287f1bmr2609468oac.6.1697640464507; Wed, 18 Oct
2023 07:47:44 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Wed, 18 Oct 2023 07:47:44 -0700 (PDT)
In-Reply-To: <32090dcf-befa-48d0-b98a-0618b236d934n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=24.107.183.247; posting-account=G1KGwgkAAAAyw4z0LxHH0fja6wAbo7Cz
NNTP-Posting-Host: 24.107.183.247
References: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com> <32090dcf-befa-48d0-b98a-0618b236d934n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <125fd145-4617-479a-a40b-7ce1aa3c74f4n@googlegroups.com>
Subject: Re: Code review: personnel scheduling app
From: luser.droog@gmail.com (luserdroog)
Injection-Date: Wed, 18 Oct 2023 14:47:44 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 3478
 by: luserdroog - Wed, 18 Oct 2023 14:47 UTC

On Saturday, October 14, 2023 at 1:17:33 PM UTC-5, Michael Haufe (TNO) wrote:
> On Sunday, October 8, 2023 at 8:15:41 PM UTC-5, luserdroog wrote:
[snip]
>
> This is a very impressionistic set of suggestions and is a variant of what is referred to as "Clean Architecture" which unifies the "Hexagonal" and "Onion" architectures:
>
> <https://www.plainionist.net/Implementing-Clean-Architecture/>

Thanks a bunch. I think this is exactly what I needed. I feel like we're
all on the same page, although to me it's still a palimpsest.

As a start, and because my bias is typically from the low-level view,
I've tried to carve off a tiny component just to deal with saving and
loading user preferences tied to a control like a checkbox.

For the larger task, I'm finding it very difficult to imagine the thing
from a top-down Object Oriented view ignoring concerns about
the representation. But I expect this will become easier after more
reading about these patterns (searching like "repository vanilla js",
"usecase presentation vanilla js", etc). Again, thank you. I feel like
I've caught the scent.

html:
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html" charset="UTF-8">
<html>
<body>
<input id="box" type="checkbox">
</body>
<script src="app.js"></script>
</html>

app.js:

const prefs = persistent( localStorage, "prefs", {} );
init();

function init(){
bindCheckboxToPrefs( "#box", "checked" );
}

function bindCheckboxToPrefs( selector, propName ){
let input = document.querySelector( selector );
if( prefs.hasOwnProperty( propName ) )
input.checked = prefs[ propName ];
input.addEventListener( "click",
(event) => prefs[ propName ] = event.target.checked );
}

function persistent( storage, key, initial ){
let data = storage.getItem( key ) ?
JSON.parse( storage.getItem( key ) ) :
initial;
let proxy = new Proxy( data, {
set( target, prop, receiver ){
const ret = Reflect.set( ...arguments );
storage.setItem( key, JSON.stringify( data ) );
return ret;
}
} );
return proxy;
}

Re: Code review: personnel scheduling app

<492a2bf7-180d-47ff-903c-f580855c1125n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18279&group=comp.lang.javascript#18279

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:a37:f503:0:b0:76d:a57f:6f5a with SMTP id l3-20020a37f503000000b0076da57f6f5amr121660qkk.3.1697649747250;
Wed, 18 Oct 2023 10:22:27 -0700 (PDT)
X-Received: by 2002:a05:6808:183:b0:3a8:41a7:eafc with SMTP id
w3-20020a056808018300b003a841a7eafcmr2008183oic.7.1697649747032; Wed, 18 Oct
2023 10:22:27 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Wed, 18 Oct 2023 10:22:26 -0700 (PDT)
In-Reply-To: <125fd145-4617-479a-a40b-7ce1aa3c74f4n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=2603:6000:8900:6915:ac1f:d04:5fa:41da;
posting-account=hYRygAoAAABkmvJVmPilz9Q1TOjgPQAq
NNTP-Posting-Host: 2603:6000:8900:6915:ac1f:d04:5fa:41da
References: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
<32090dcf-befa-48d0-b98a-0618b236d934n@googlegroups.com> <125fd145-4617-479a-a40b-7ce1aa3c74f4n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <492a2bf7-180d-47ff-903c-f580855c1125n@googlegroups.com>
Subject: Re: Code review: personnel scheduling app
From: tno@thenewobjective.com (Michael Haufe (TNO))
Injection-Date: Wed, 18 Oct 2023 17:22:27 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 3783
 by: Michael Haufe (TNO) - Wed, 18 Oct 2023 17:22 UTC

On Wednesday, October 18, 2023 at 9:47:49 AM UTC-5, luserdroog wrote:

> As a start, and because my bias is typically from the low-level view,
> I've tried to carve off a tiny component just to deal with saving and
> loading user preferences tied to a control like a checkbox.
>
> For the larger task, I'm finding it very difficult to imagine the thing
> from a top-down Object Oriented view ignoring concerns about
> the representation. But I expect this will become easier after more
> reading about these patterns (searching like "repository vanilla js",
> "usecase presentation vanilla js", etc). Again, thank you. I feel like
> I've caught the scent.

"Everything should be built top-down, except the first time." - Alan Perlis

The reason top-down (Use Case driven) is preferred generally is so you stay on target and constrain yourself to the goal.
This can avoid creeping featurism. Also it enables you to create an MVP you can then iterate upon.

The comment on "except the first time" I interpret as referring to the need for a well-defined domain (Domain-Driven Design wasn't a thing when Perlis wrote that). Example, I can define some use-cases for a graphics drawing program (create layer, flood, etc), but how far will I get if I don't have a concept of platonic shapes to work with? Each use-case might end up doing it their own way instead of utilizing a common language (Domain of Discourse).

I have a couple **draft** blog posts you might find helpful as an analogy:

https://github.com/thenewobjective/thenewobjective.github.io/blob/ec8bc7aee3151d8ff300b87e4a0920f542ec94e8/_drafts/tile-graphics/2023-07-15-1-from-domain-to-display.md

https://github.com/thenewobjective/thenewobjective.github.io/blob/ec8bc7aee3151d8ff300b87e4a0920f542ec94e8/_drafts/tile-graphics/2023-07-15-1-from-domain-to-display.md

What I'm building there isn't important, more-so the shape of the the approach. Each feature is implemented as a vertical slice through the onion:

https://github.com/thenewobjective/thenewobjective.github.io/blob/ec8bc7aee3151d8ff300b87e4a0920f542ec94e8/media-library/software-systems-engineering/clean-architecture.png

There are other ways to approach this (a hierarchy of "onions" in a PAC/HMVC style), but that's another rabbit hole we'd have to tackle in another thread.

Re: Code review: personnel scheduling app

<22921a66-7986-44dd-bfc0-899c9d90460cn@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18280&group=comp.lang.javascript#18280

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:ae9:e648:0:b0:778:8db2:6725 with SMTP id x8-20020ae9e648000000b007788db26725mr89902qkl.1.1697650320786;
Wed, 18 Oct 2023 10:32:00 -0700 (PDT)
X-Received: by 2002:a05:6808:213:b0:3b2:ec65:399e with SMTP id
l19-20020a056808021300b003b2ec65399emr513661oie.3.1697650320536; Wed, 18 Oct
2023 10:32:00 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Wed, 18 Oct 2023 10:32:00 -0700 (PDT)
In-Reply-To: <125fd145-4617-479a-a40b-7ce1aa3c74f4n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=2603:6000:8900:6915:ac1f:d04:5fa:41da;
posting-account=hYRygAoAAABkmvJVmPilz9Q1TOjgPQAq
NNTP-Posting-Host: 2603:6000:8900:6915:ac1f:d04:5fa:41da
References: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
<32090dcf-befa-48d0-b98a-0618b236d934n@googlegroups.com> <125fd145-4617-479a-a40b-7ce1aa3c74f4n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <22921a66-7986-44dd-bfc0-899c9d90460cn@googlegroups.com>
Subject: Re: Code review: personnel scheduling app
From: tno@thenewobjective.com (Michael Haufe (TNO))
Injection-Date: Wed, 18 Oct 2023 17:32:00 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
 by: Michael Haufe (TNO) - Wed, 18 Oct 2023 17:32 UTC

On Wednesday, October 18, 2023 at 9:47:49 AM UTC-5, luserdroog wrote:

> As a start, and because my bias is typically from the low-level view,
> I've tried to carve off a tiny component just to deal with saving and
> loading user preferences tied to a control like a checkbox.

Try to think in terms of "what" you're doing instead of "how". What you've presented are implementation details of storage and presentation, but what's the reason for them?

// usecases

LoadFilters
ApplyFilters
ChangeTheme
LoadTheme
etc.

Re: Code review: personnel scheduling app

<87f7da2b-7c41-4f46-b738-79ac0188039fn@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=18281&group=comp.lang.javascript#18281

  copy link   Newsgroups: comp.lang.javascript
X-Received: by 2002:ac8:540b:0:b0:417:b53c:5d4c with SMTP id b11-20020ac8540b000000b00417b53c5d4cmr57308qtq.1.1697823540844;
Fri, 20 Oct 2023 10:39:00 -0700 (PDT)
X-Received: by 2002:a05:6808:200c:b0:3b2:e53e:cf2d with SMTP id
q12-20020a056808200c00b003b2e53ecf2dmr801246oiw.1.1697823540524; Fri, 20 Oct
2023 10:39:00 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer01.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.javascript
Date: Fri, 20 Oct 2023 10:39:00 -0700 (PDT)
In-Reply-To: <22921a66-7986-44dd-bfc0-899c9d90460cn@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=24.107.183.247; posting-account=G1KGwgkAAAAyw4z0LxHH0fja6wAbo7Cz
NNTP-Posting-Host: 24.107.183.247
References: <963227be-2594-4ae3-8d4c-4b65b3d3e142n@googlegroups.com>
<32090dcf-befa-48d0-b98a-0618b236d934n@googlegroups.com> <125fd145-4617-479a-a40b-7ce1aa3c74f4n@googlegroups.com>
<22921a66-7986-44dd-bfc0-899c9d90460cn@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <87f7da2b-7c41-4f46-b738-79ac0188039fn@googlegroups.com>
Subject: Re: Code review: personnel scheduling app
From: luser.droog@gmail.com (luserdroog)
Injection-Date: Fri, 20 Oct 2023 17:39:00 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 3933
 by: luserdroog - Fri, 20 Oct 2023 17:39 UTC

On Wednesday, October 18, 2023 at 12:32:05 PM UTC-5, Michael Haufe (TNO) wrote:
> On Wednesday, October 18, 2023 at 9:47:49 AM UTC-5, luserdroog wrote:
> > As a start, and because my bias is typically from the low-level view,
> > I've tried to carve off a tiny component just to deal with saving and
> > loading user preferences tied to a control like a checkbox.
> Try to think in terms of "what" you're doing instead of "how". What you've presented are implementation details of storage and presentation, but what's the reason for them?
>
> // usecases
>
> LoadFilters
> ApplyFilters
> ChangeTheme
> LoadTheme
> etc.

Ok. I'm starting to grasp something. This is similar, but not exactly the same,
as the many lists in my notebook of "little features" which then translated
into snippets of code inserted into the various paths (bloating up various
"hub" functions into long fiddly "storybook" code). So instead, all of these
fabulous little tweaks and fancies need to be reified, things in their own right,
with a name and a ... shudder ... *class*, perhaps.

And yes, the Preferences gizmo just sidesteps the whole exercise. Because
of course I was going to use it as a grab bag for unrelated things like the
filter settings, sorting settings, style settings. Rather each of these: viz.
filter, sorting, styles can, and I suppose ought to, be Repositories. And the
storage options for it can be more varied than just shipping JSON over to
localStorage. Maybe I can make a ComposedRepository to actually wrap
these things in a single PreferencesRepository but at a higher level of
composition. But, all of these gives me what I want: nice abstractions.
Goodly sized/scoped boxes to encapsulate the behavior I want from these
conjured entities.

I think I'm getting it. So I'm listing out lots of little useCases in english sentences.
Then I can refine the list, rewrite it a few times, and appropriate groupings
should become apparent as the steps progress. Good thing pens are cheap...

And the tempting part is ... with a little more organization, then my fancy
gizmos can be even more fancy. Instead of regular expressions matched
against predefined fields, I could make a filter builder something like the
Scratch language. You create an expression "<field> <operator> <pattern|value>"
and compose them together with "and" and "or" and "not", give it a name,
manage the list of saved ones.... sigh. baby steps.

1
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor