#m!a: b0rk
Explore tagged Tumblr posts
Text
a reminder t0 myself all the magic an0ns i’m under.
1 note
·
View note
Text
Week 289
Happy Thursday! I've seen this week the SwiftWebUI project by @ziezeit and @ar_institute, and I think it's great. Of course, as the GitHub repo says, "this is a toy project, do not use in production". However, this just confirms my hunch from when SwiftUI was announced, that this could be so much bigger than just for iOS/macOS/watchOS/tvOS. I'm very curious and excited to see how this project evolves.
Articles
Creating a custom Combine Publisher to extend UIKit, by @twannl
Getting started with Swift package manager in Xcode, by @kairadiagne
iOS Memory Management in Under 6 Minutes, by @hassanedesouky
Join the dark side and implement Dark Mode in iOS, by @andrei_hogea
Managing Data Flow in SwiftUI, by @mecid
SwiftUI: Loading Data on Demand, by @objcio
Thoughts on SwiftUI, by @radiantav
UIStackView, by @kaishin
Tools/Controls
DiffableDataSources - 💾 A library for backporting UITableView/UICollectionViewDiffableDataSource, by @ra1028fe5
BiometricKeychain - Easily store data in the keychain with biometric authentication, by @dobreandl
Captain AHAP - Create, edit and share custom haptics files (AHAP), by @theandreamazz
Combinative - UI Event Handling, by @noppefoxwolf
Business/Career
Why a good boss likes it when people complain, by @catehstn
Get your work recognized: write a brag document, by @b0rk
UI/UX
Designing for iOS 13, by @ebaehr
Videos
WWDC 2019 Top 10 Videos, by @rcritz
Credits
cagricolak, dobreandl, theandreamazz, mecid, ra1028, moelnaggar14, rbarbosa, valianka
1 note
·
View note
Text
Bite Size Bash by b0rk is awesome!
@b0rk is at it again with another fanastic zine. This one's about a topic that's unusually near and dear to me so I absolutely couldn't resist snapping it up.
Bite Size Bash is everything you should expect from a Julia Evans zine: comprehensive, insightful, and fun. While I have a few quibbles with the content (I'm sorry but set -e is the devil's own work, and please don't read a file or anything else line by line with a for loop) but these little quibbles are far outweighed by the mountain of other good and cogent content in the zine.
I especially love her descriptions of what bash is particularly good at: Gluing processes together, concurrency management, and execution tracing, for a small sample.
If you've been ignoring my advice about diving into Greg's Bash Guide (or even if you haven't been) I would whole-heartedly recommend grabbing yourself a copy of Bite Size Bash and getting familiar with one of the most pragmatic tools available to anyone developing software (or operating in any other way) a *nix system.
0 notes
Text
Choosing Emаil Mаrkеting Software
Choosing Emаil Mаrkеting Software
Choosing the right email marketing ѕоftwаrе is nоt thе еаѕiеѕt process. I аm nоt gоing to ѕit hеrе аnd tell уоu еxасtlу which оnе to сhооѕе bесаuѕе thеrе are mаnу thаt have fеаturеѕ thаt blоаt them by mу ѕtаndаrdѕ, but уоu may find thеm uѕеful. Sо, I аm simply going tо givе you one оf thе fеаturеѕ that I think аnу еmаil mаrkеting ѕоftwаrе ѕhоuld hаvе as a standard feature.
…
View On WordPress
0 notes
Text
Week 246
Happy Thursday! 30 minutes after we sent out last week's edition, Apple confirmed the 12th of September as the date of their next event. And then there were even more rumours, more leaks and even higher expectations. I'm looking forward to the event. But don't be taken away by all the new flashy things they will launch. It's usually one week after the September event when the new iOS version will be released. So make sure you're testing your app on iOS 12 😄
We got more submissions than we included in our newsletter. If you want, you can check out the rest on our GitHub
Articles
How drawing works in an Xcode playground, by @iosbrain
Early returning functions in Swift, by @johnsundell
Private properties in protocols, by @aligatr
Why you’re not supposed to call description, by @olebegemann
Creating Swift Package Manager tools from your existing codebase, by @paulio87
do try Antitypical's Result to catch Async Errors in Swift, by @ndrewmcknight
Tools/Controls
DSJSONSchemaValidation - JSON Schema draft 4, draft 6 and draft 7 parsing and validation library, by @podkovyr
Mew - The framework that support making MicroViewController, by @mercari_app
SwiftSyntax - SwiftPM package for SwiftSyntax library, by Apple
DataSourceKit - Declarative, testable data source of UICollectionView and UITableView, by @_ishkawa
Business/Career
How to teach yourself hard things, by @b0rk
A Farewell to StreamToMe, by @cocoawithlove
How To Leverage Apple Pre-order For Your iOS App Launch, by @sylvainww
UI/UX
How to Simplify the Process of Credit Card Data Input on Mobile, by @101babich
When Motion Creates Emotion, by @101babich
Credits
podkovyrin, rbarbosa, markohlebar
4 notes
·
View notes
Text
Node module deep-dive: fs
Time for another Node module deep-dive!
I got some great feedback from folks that it would be interesting to dive into the C++ portions of the Node codebase in these annotated code reads. I agree. To be honest, I've avoided it up to this point mostly because of insecurities about my own knowledge of C++ and understanding about system-level software. But you know what, I am setting all that aside and diving into the C++ portions of the Node codebase because I am a brave and fearless developer.
I say this to clarify that don't take anything I say as absolute fact and if you have insights into portions of the code I misunderstood, let me know on Twitter.
Anyway, let's get down to the fun stuff.
I've been thinking a lot about the fs module. The fs module is a part of the standard library in Node that allows the developer to interact with the filesystem. You can do things like read files, write files, and check the status of files. This is very handy if you are doing something like building a desktop application using JavaScript or interacting with files in a backend server.
One of the fs functions that I use the most is the exists function, which checks to see if a file exists. This function has actually be deprecated recently in favor of fs.stat or fs.access. So with this, I figured it would be interesting to dive in and see how fs.access works in Node. Just so we are all on the same page, here is how you might use fs.access in an application.
> const fs = require('fs'); undefined > fs.access('/etc/passwd', (error) => error ? console.log('This file does not exist.') : console.log('This file exists.')); undefined > This file exists.
Neat-o! So we can pass a filename and a callback that takes an error. If the error exists then we cannot access the file but if it does not exist then we can. So let's head over to the fs module in the codebase to see what's up. The code for the fs.access function looks like this.
fs.access = function(path, mode, callback) { if (typeof mode === 'function') { callback = mode; mode = fs.F_OK; } else if (typeof callback !== 'function') { throw new errors.TypeError('ERR_INVALID_CALLBACK'); } if (handleError((path = getPathFromURL(path)), callback)) return; if (typeof path !== 'string' && !(path instanceof Buffer)) { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', ['string', 'Buffer', 'URL']); } if (!nullCheck(path, callback)) return; mode = mode | 0; var req = new FSReqWrap(); req.oncomplete = makeCallback(callback); binding.access(pathModule.toNamespacedPath(path), mode, req); };
So like I mentioned before, it takes a path and a callback. It also takes a mode parameter which you can read more about here. Most of the first few lines in the function are your standard validation and safety checks. I'll avoid going into them here because I think they are pretty self-explanatory. I know it's kind of annoying when people do the hand-wavey thing about code so if you have specific questions about these lines I'm overlooking, just ask me.
The code gets a little bit more interesting once we get to the last few lines in the function.
var req = new FSReqWrap(); req.oncomplete = makeCallback(callback); binding.access(pathModule.toNamespacedPath(path), mode, req);
I've never seen this FSReqWrap object before. I assume it's some low-level API within the Node ecosystem for dealing with asynchronous requests. I tried to figure out where this Object is defined. The require statement for it looks like this.
const { FSReqWrap } = binding;
So it looks like it is extracting the FSReqWrap object from binding. But what is binding?
const binding = process.binding('fs');
Hm. So it seems to be the result of invoking process.binding with the 'fs' parameter. I've seen these process.binding calls sprinkled across the codebase but have largely avoided digging into what they are. Not today! A quick Google resulted in this StackOverflow question, which confirmed my suspicion that process.binding was how C++-level code was exposed to the JavaScript portion of the codebase. So I dug around the Node codebase to try and find where the C/C++ code for fs resided. I discovered that there were actually two different C-level source files for fs, one associated with Unix and another associated with Windows.
So I tried to see if there was anything resembling a definition for the access function in the fs C source for Unix. The word access is referenced four times in the code.
Twice here.
#define X(type, action) \ case UV_FS_ ## type: \ r = action; \ break; switch (req->fs_type) { X(ACCESS, access(req->path, req->flags));
And twice here.
int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { INIT(ACCESS); PATH; req->flags = flags; POST; }
Now you know what I meant about the whole "The C part of this code base makes me nervous" bit earlier.
I felt like the uv_fs_access was a lot easier to look into. I have no idea what is going on with that X function macro business and I don't think I'm in a zen-like state of mind to figure it out.
OK! So the uv_fs_access function seems to be passing the ACCESS constant to the INIT function macro which looks a little bit like this.
#define INIT(subtype) \ do { \ if (req == NULL) \ return -EINVAL; \ req->type = UV_FS; \ if (cb != NULL) \ uv__req_init(loop, req, UV_FS); \ req->fs_type = UV_FS_ ## subtype; \ req->result = 0; \ req->ptr = NULL; \ req->loop = loop; \ req->path = NULL; \ req->new_path = NULL; \ req->cb = cb; \ } \ while (0)
So the INIT function macro seems to be initializing the fields in some req structure. From looking at the type declarations on the function parameters of functions that took req in as an argument, I figured that req was a pointer to a uv_fs_t Object. I found some documentation that rather tersely stated that uv_fs_t was a file system request type. I guess that's all I need to know about it!
Side note: Why is this code written in a do {} while (0) instead of just a sequence of function calls. Does anyone know why this might be? Late addition: I did some Googling and found a StackOverflow post that answered this question.
OK. So once this filesystem request object has been initialized, the access function invokes the PATH macro which does the following.
#define PATH \ do { \ assert(path != NULL); \ if (cb == NULL) { \ req->path = path; \ } else { \ req->path = uv__strdup(path); \ if (req->path == NULL) { \ uv__req_unregister(loop, req); \ return -ENOMEM; \ } \ } \ } \ while (0)
Hm. So this seems to be checking to see if the path that the file system request is associated with is a valid path. If the path is invalid, it seems to unregister the loop associated with the request. I don't understand a lot of the details of this code, but my hunch is that it does validation on the filesystem request being made.
The next invocation that uv_fs_access calls is to the POST macro which has the following code associated with it.
#define POST \ do { \ if (cb != NULL) { \ uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \ return 0; \ } \ else { \ uv__fs_work(&req->work_req); \ return req->result; \ } \ } \ while (0)
So it looks like the POST macros actually invokes the action loop associated with the filesystem request and then executes the appropriate callbacks.
At this point, I was a little bit lost. I happened to be attending StarCon with fellow code-reading enthusiast Julia Evans. We sat together and grokked through some of the code in the uv__fs_work function which looks something like this.
static void uv__fs_work(struct uv__work* w) { int retry_on_eintr; uv_fs_t* req; ssize_t r; req = container_of(w, uv_fs_t, work_req); retry_on_eintr = !(req->fs_type == UV_FS_CLOSE); do { errno = 0; #define X(type, action) \ case UV_FS_ ## type: \ r = action; \ break; switch (req->fs_type) { X(ACCESS, access(req->path, req->flags)); X(CHMOD, chmod(req->path, req->mode)); X(CHOWN, chown(req->path, req->uid, req->gid)); X(CLOSE, close(req->file)); X(COPYFILE, uv__fs_copyfile(req)); X(FCHMOD, fchmod(req->file, req->mode)); X(FCHOWN, fchown(req->file, req->uid, req->gid)); X(FDATASYNC, uv__fs_fdatasync(req)); X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); X(FSYNC, uv__fs_fsync(req)); X(FTRUNCATE, ftruncate(req->file, req->off)); X(FUTIME, uv__fs_futime(req)); X(LSTAT, uv__fs_lstat(req->path, &req->statbuf)); X(LINK, link(req->path, req->new_path)); X(MKDIR, mkdir(req->path, req->mode)); X(MKDTEMP, uv__fs_mkdtemp(req)); X(OPEN, uv__fs_open(req)); X(READ, uv__fs_buf_iter(req, uv__fs_read)); X(SCANDIR, uv__fs_scandir(req)); X(READLINK, uv__fs_readlink(req)); X(REALPATH, uv__fs_realpath(req)); X(RENAME, rename(req->path, req->new_path)); X(RMDIR, rmdir(req->path)); X(SENDFILE, uv__fs_sendfile(req)); X(STAT, uv__fs_stat(req->path, &req->statbuf)); X(SYMLINK, symlink(req->path, req->new_path)); X(UNLINK, unlink(req->path)); X(UTIME, uv__fs_utime(req)); X(WRITE, uv__fs_buf_iter(req, uv__fs_write)); default: abort(); } #undef X } while (r == -1 && errno == EINTR && retry_on_eintr); if (r == -1) req->result = -errno; else req->result = r; if (r == 0 && (req->fs_type == UV_FS_STAT || req->fs_type == UV_FS_FSTAT || req->fs_type == UV_FS_LSTAT)) { req->ptr = &req->statbuf; } }
OK! I know this looks a little bit scary. Trust me, it scared me when I first looked at it too. One of the things that Julia and I realized was that this bit of the code.
#define X(type, action) \ case UV_FS_ ## type: \ r = action; \ break; switch (req->fs_type) { X(ACCESS, access(req->path, req->flags)); X(CHMOD, chmod(req->path, req->mode)); X(CHOWN, chown(req->path, req->uid, req->gid)); X(CLOSE, close(req->file)); X(COPYFILE, uv__fs_copyfile(req)); X(FCHMOD, fchmod(req->file, req->mode)); X(FCHOWN, fchown(req->file, req->uid, req->gid)); X(FDATASYNC, uv__fs_fdatasync(req)); X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); X(FSYNC, uv__fs_fsync(req)); X(FTRUNCATE, ftruncate(req->file, req->off)); X(FUTIME, uv__fs_futime(req)); X(LSTAT, uv__fs_lstat(req->path, &req->statbuf)); X(LINK, link(req->path, req->new_path)); X(MKDIR, mkdir(req->path, req->mode)); X(MKDTEMP, uv__fs_mkdtemp(req)); X(OPEN, uv__fs_open(req)); X(READ, uv__fs_buf_iter(req, uv__fs_read)); X(SCANDIR, uv__fs_scandir(req)); X(READLINK, uv__fs_readlink(req)); X(REALPATH, uv__fs_realpath(req)); X(RENAME, rename(req->path, req->new_path)); X(RMDIR, rmdir(req->path)); X(SENDFILE, uv__fs_sendfile(req)); X(STAT, uv__fs_stat(req->path, &req->statbuf)); X(SYMLINK, symlink(req->path, req->new_path)); X(UNLINK, unlink(req->path)); X(UTIME, uv__fs_utime(req)); X(WRITE, uv__fs_buf_iter(req, uv__fs_write)); default: abort(); } #undef X
is actually a giant switch-statement. The enigmatic looking X macro is actually syntactic sugar for the syntax for the case statement that looks like this.
case UV_FS_ ## type: \ r = action; \ break;
So, for example, this macro-function call, X(ACCESS, access(req->path, req->flags)), actually corresponds with the following expanded case statement.
case UV_FS_ACCESS: r = access(req->path, req->flags) break;
So our case statement essentially ends up calling the access function and setting its response to r. What is access? Julia helped me realized that access was a part of the system's library defined in unistd.h. So this is where Node actually interacts with system-specific APIs.
Once it has stored a result in r, the function executes the following bit of code.
if (r == -1) req->result = -errno; else req->result = r; if (r == 0 && (req->fs_type == UV_FS_STAT || req->fs_type == UV_FS_FSTAT || req->fs_type == UV_FS_LSTAT)) { req->ptr = &req->statbuf; }
So what this is basically doing is checking to see if the result that was received from invoking the system-specific APIS was valid and stores it back into that filesystem request object that I mentioned earlier. Interesting!
And that's that for this code read. I had a blast reading through the C portions of the codebase and Julia's help was especially handy. If you have any questions or want to provide clarifications on things I might have misinterpreted, let me know. Until next time!
7 notes
·
View notes
Text
Friday-ish links
Chicago Clojure - 2017-06-21 - Stuart Halloway on Repl Driven Development on Vimeo
One of the better descriptions of what
Colin Jones on Twitter: "Git hooks are basically the same concept as JS form validations. You still need backend validations (CI) if you want your end result to be valid." / Twitter
This is how I feel about all development technologies (from the language on up the stack). If you're in my way I'm going to figure out how to break through you or go around you. My cycle time is too precious. Write-time vs. Polish-time vs. Run-time is a thing.
Interactive Van Gogh Painting
Wooooooooooooooooooooooooooooooooooooooow!
↑ is literally how I sounded playing with this.
via Interactive Van Gogh Painting : InternetIsBeautiful
Minecraft by Illumina in 41:35 - Summer Games Done Quick 2020 Online - YouTube
Super Smash Bros. 64 by Bubzia in 8:29 - Summer Games Done Quick 2020 Online - YouTube
The Social Dilemma | Netflix
My buddy James mentioned this to me the other day.
Brian Marick on Twitter: "Idle Sunday morning thought. Matthew 6:5-6 is pretty explicit. The ostentatiously religious must get that thrown at them often. I assume there are canned responses about how that doesn't apply to, say, Mike Pence. What are they? https://t.co/uD5AcUo2Kt" / Twitter
Code Complete: A Practical Handbook of Software Construction, Second Edition: McConnell, Steve: 0790145196705: Amazon.com: Books
I think Code Complete is the book I would hand every software developer at the start of their career.
What's yours?
Where indeed did I pick up the strange 'boxen' noun?
Tim Visher on Twitter: "@nickcanz @ceeoreo_ You can really throw people for a loop when you go with 'boxen' for multiple computers. I don't even know where I picked that one up. Some awful mutation of https://t.co/DuwZYaQ87v and box, I guess." / Twitter
EmacsWiki: Emacsen
🔎Julia Evans🔍 on Twitter: "shellcheck ♥ permalink: https://t.co/aRQuOTorZm https://t.co/eMOJQf3YyX" / Twitter
Shellcheeeeeeeeck!!! \( ゚◡゚)/
Avoiding Microservice Megadisasters - Jimmy Bogard - YouTube
Probably a re-hash of old territory if you've ever seen a talk about how to do micro-services well but if you haven't this is not a bad place to start.
Martin Scorsese - The Art of Silence - YouTube
Crypt of the NecroDancer: AMPLIFIED by SpootyBiscuit in 14:53 - Summer Games Done Quick 2020 Online - YouTube
This is absurd.
Hillel dressed as Data & Reality author Bill Kent on Twitter: "Unpopular opinion: gifs and memes in conference talks are an antipattern. No, I'm not saying humor is an antipattern. Humor is great, put more of it in talks. Gifs and memes specifically are an antipattern." / Twitter
Unpopular opinion, indeed.
🔎Julia Evans🔍 on Twitter: "${…}: how to do string operations in bash permalink: https://t.co/6lJmoE8I2B https://t.co/b40jt20HoI" / Twitter
Just, you know, follow Julia.
0 notes
Text
Cоntеnt Mаrkеting for Business
Cоntеnt Mаrkеting for Business
Image by Gerd Altmann from Pixabay
Yоu рrоbаblу undеrѕtаnd that соntеnt mаrkеting is a nесеѕѕаrу еlеmеnt tо уоur рrоfеѕѕiоnаl ѕuссеѕѕ. As tесhnоlоgу еvоlvеѕ and mоrе tools аrе being оffеrеd to уоu оn a rеgulаr basis, оthеr аѕресtѕ оf marketing еvоlvе with the new tесhnоlоgiеѕ. Hоwеvеr, content mаrkеting рrеttу muсh rеmаinѕ as it always wаѕ.
Content Marketing: Thе сhаngеѕ thаt hаvе оссurrеd
Techno…
View On WordPress
0 notes