- Joined
- Mar 28, 2023
Correct me if I'm wrong, but isn't it typically the client's responsibility to manage caching?Server.
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
Correct me if I'm wrong, but isn't it typically the client's responsibility to manage caching?Server.
There are few APIs in software development as convoluted as UI APIs. There are so many intricacies, so many user expectations, so many corner cases to handle that few other subsystems compare.Nothing is a bigger ego boner killer for me than having to create a UI to demonstrate code. I should only be allowed to make UIs for the blind.
Correct me if I'm wrong, but isn't it typically the client's responsibility to manage caching?
I assume the images here would be novel to the client.Correct me if I'm wrong, but isn't it typically the client's responsibility to manage caching?
A big problem is that UIs are more async by nature and hardly anyone knows how to do proper async. Some UI libraries will create layers of abstraction hell to "help" with this and others won't.There are few APIs in software development as convoluted as UI APIs. There are so many intricacies, so many user expectations, so many corner cases to handle that few other subsystems compare.
I'm dealing with a C event loop right now, trying to juggle signals and poll FDs. This is, itself, such an onerous task that there are three big libraries used to help folks with it. But it's peanuts compared to UI dev. ( https://www.sitepoint.com/the-self-pipe-trick-explained/ -- explains the self-pipe trick for handling signals; this is considered standard operating practice in Unixish development.)
One of my first projects as a learning teenager, over half a lifetime ago (Edit: two thirds of a lifetime ago for the earliest bits; I grow painfully old...), was trying to make some basic UI elements in Delphi and Visual Basic. It led me to hate UI work. When I finally got around to learning the Linux command line, things clicked, and I've been derisive of UI since... and then I grew until I started working on console UIs. Now graphical UIs are less of a headache to me, because I see the how and why better.
But UIs are a bundle of sheer insanity that require YEARS of specialization to be anywhere near comfortable with developing.
Personally, my favorite way to write UIs when I have to is using a functional approach. I have the components provide functions to run at certain points in the loop. It actually feels pretty nice to use, at least for me.A big problem is that UIs are more async by nature and hardly anyone knows how to do proper async
I saw something in little overview blurb in the docs for Go's atomic package a while back that stuck with me:Personally, my favorite way to write UIs when I have to is using a functional approach. I have the components provide functions to run at certain points in the loop. It actually feels pretty nice to use, at least for me.
Share memory by communicating; don't communicate by sharing memory.
Promise
objects you have that sort of pipe-like flow similar to with .then()
and the results flow in when they're ready, but this extends further to async functions that function like indefinitely running workers that pass data to each other. Workers can be spawned, feed output, then close their output channel(s) to signal they're done, and you get that cascading effect where closing a source will close the rest of the receivers down the line. Combine this with Go's extremely lightweight goroutines and impressive scheduler, and you have something immensely powerful and ridiculously responsive since you can throw any slow or blocking procedures to a separate thread and feed the result from it to your normal data flow.func newChatLog(feed <-chan *Message) (<-chan *Message, error) {
cfgDir, err := os.UserConfigDir()
if err != nil {
return nil, err
}
baseDir := filepath.Join(cfgDir, "sockchat/logs")
logDir, err := newLogDir(baseDir)
if err != nil {
return nil, err
}
lf, err := openLog(filepath.Join(logDir, fmt.Sprintf("%s.log", time.Now().Format(dateFmt))))
if err != nil {
return nil, err
}
lw := bufio.NewWriter(lf)
out := make(chan *Message, 2048)
go func() {
defer func() {
lw.Flush()
lf.Close()
close(out)
}()
for msg := range feed {
fl := ""
if msg.IsEdited() {
fl += "*"
}
fmt.Fprintf(lw, logFmt, time.Unix(msg.MessageDate, 0).Format("2006-01-02 15:04:05 MST"),
msg.Author.Username, msg.Author.ID, fl, msg.MessageRaw)
out <- msg
}
}()
return out, nil
}
out
channel pretty quickly and the func launched with go
(goroutine) will continue to run in the background. The defer
routine in that goroutine will trigger asynchronously when feed
closes and the for
loop exits. I manage message object allocation using freelists to cut down on garbage collection, so I need to be careful what accesses those message pointers before releasing/freeing them back to the freelist. Doing the log stuff with the message then passing the pointer along is a foolproof way to do so Thedefer
routine in that goroutine will trigger asynchronously whenfeed
closes and thefor
loop exits.
defer
is one of the coolest features I've seen in a language in a while, I've wanted something similar in many of my own projects.It's amazing for cleanup stuff like closing file descriptors or freeing memory. You say up top near the declaration whatever cleanup you want to do and you don't have to worry about it anymore. Anyone who has done error handling in C with early returns will know this issue well. In C, I usedefer
is one of the coolest features I've seen in a language in a while, I've wanted something similar in many of my own projects.
goto
with labels to sections near the bottom of the function that you can chain together as you allocate more shit in the function.defer
is a godsend for unlocking mutexes as well.Most languages have it as try-finally, but this is typically paired with exceptions, which Go doesn't have.Isn't defer literally just class destructors/RAII in c++ without having to make a class boilerplate
It's useful for that, but at its core, it allows you to queue up tasks to run upon the scope wrapping upIsn't defer literally just class destructors/RAII in c++ without having to make a class boilerplate
It's the same core idea, butIsn't defer literally just class destructors/RAII in c++ without having to make a class boilerplate
defer
is more flexible since you can defer any function, including anonymous ones. You can see my chat client example above defers an anonymous function that's used to flush the log writer buffer and close the log file. All defer
s run async as goroutines when the caller returns, so I do this here in a wrapper func to ensure ordering, but you can use this for all sorts of stuff where chronology is less of a concern. Think of it like scheduling an async routine to run later on upon return and just how powerful that could be.// The kernel socket code is no doubt enjoying watching us squirm.
Same.Well, fortunately what I'm doing now is just a very minimal demo. It's just that any time I touch HTML/CSS I end up shitting out some geocities tier garbage that I know looks bad but I cannot figure out how to fix
I mean, caching is ultimately just a technique. With web stuff, we're a lot more familiar with the client-side cache, because of all the http headers relating to the subject. But if performance requirements justify it, you can toss in a cache anywhere in the stack it makes sense.Correct me if I'm wrong, but isn't it typically the client's responsibility to manage caching?
Don't make it too holy or "Photoluminescent African Americans" will come after you.I'm working on a new language, it's like C but with classes
It needs a name that emphasizes it's an incremental improvement on C. How about C+=1?I'm working on a new language, it's like C but with classes. But even better, you can use your old c code and libraries! Surely this hasn't been done before.
A KF making a programming language is going to be C- let's be real because it's super leen man.It needs a name that emphasizes it's an incremental improvement on C. How about C+=1?
Better call it "D." Oh wait, there already is a D language that is this level of retarded.A KF making a programming language is going to be C- let's be real because it's super leen man.
Yeah, and also you can go to the next level and move stuff around from a spinny disk to a SSD to memory depending on how frequently the content is accessed.I mean, caching is ultimately just a technique. With web stuff, we're a lot more familiar with the client-side cache, because of all the http headers relating to the subject. But if performance requirements justify it, you can toss in a cache anywhere in the stack it makes sense.