Wenn du woanders als auf dem Server validierst, validierst du nicht Eingaben sondern Ausgaben.
– Fefe
Tag: Software Development
We Really Are Engineers 🎉
Hillel Wayne interviewed people who have worked professionally both as a software and a traditional engineer (from a diverse set of engineering disciplines) to determine if “software engineers” are really engineers … and, yes we are.
He also analyzes myths from and about software engineering and tries to find out if there’s actually something that makes software engineering unique among the other engineering disciplines.
Build Rsync for Android Yourself
To build rsync for Android you’ll need to have the Android NDK installed already.
Then clone the rsync for android source (e.g. from CyanogenMod LineageOS) …
git clone https://github.com/LineageOS/android_external_rsync.git cd android_external_rsync # checkout the most recent branch git checkout cm-14.1
… create the missing
jni/Application.mk
build file (e.g. from this Gist) and adapt it to your case …
… and start the build with
export NDK_PROJECT_PATH=pwd
ndk-build -d rsync
You’ll find your self-build rsync in
obj/local/*/rsync
. ?
Update 2017-10-06:
- Updated sources from CyanogenMod to LineageOS.
- Added links to Gist and Andoid NDK docs
- Updated steps to work with up-to-date setups
If you get something like the following warnings and errors …
[...] ./flist.c:454:16: warning: implicit declaration of function 'major' is invalid in C99 [-Wimplicit-function-declaration] if ((uint32)major(rdev) == rdev_major) ^ ./flist.c:458:41: warning: implicit declaration of function 'minor' is invalid in C99 [-Wimplicit-function-declaration] if (protocol_version < 30 && (uint32)minor(rdev) <= 0xFFu) ^ ./flist.c:467:11: warning: implicit declaration of function 'makedev' is invalid in C99 [-Wimplicit-function-declaration] rdev = MAKEDEV(major(rdev), 0); ^ ./rsync.h:446:36: note: expanded from macro 'MAKEDEV' #define MAKEDEV(devmajor,devminor) makedev(devmajor,devminor) ^ 3 warnings generated. [...] ./flist.c:473: error: undefined reference to 'makedev' ./flist.c:454: error: undefined reference to 'major' ./flist.c:457: error: undefined reference to 'major' ./flist.c:458: error: undefined reference to 'minor' ./flist.c:467: error: undefined reference to 'major' ./flist.c:467: error: undefined reference to 'makedev' ./flist.c:617: error: undefined reference to 'major' ./flist.c:619: error: undefined reference to 'minor' ./flist.c:621: error: undefined reference to 'minor' ./flist.c:788: error: undefined reference to 'makedev' ./flist.c:869: error: undefined reference to 'makedev' ./flist.c:1027: error: undefined reference to 'minor' clang++: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [obj/local/armeabi-v7a/rsync] Error 1
… you probably need to update
config.h
and change
/* #undef MAJOR_IN_SYSMACROS */
to
#define MAJOR_IN_SYSMACROS 1
.
Bottle Plugin Lifecycle
If you use Python‘s Bottle micro-framework there’ll be a time where you’ll want to add custom plugins. To get a better feeling on what code gets executed when, I created a minimal Bottle app with a test plugin that logs what code gets executed. I uesed it to test both global and route-specific plugins.
When Python loads the module you’ll see that the plugins’
__init__()
and
setup()
methods will be called immediately when they are installed on the app or applied to the route. This happens in the order they appear in the code. Then the app is started.
The first time a route is called Bottle executes the plugins’
apply()
methods. This happens in “reversed order” of installation (which makes sense for a nested callback chain). This means first the route-specific plugins get applied then the global ones. Their result is cached, i.e. only the inner/wrapped function is executed from here on out.
Then for every request the
apply()
method’s inner function is executed. This happens in the “original” order again.
Below you can see the code and example logs for two requests. You can also clone the Gist and do your own experiments.
https://twitter.com/riyadpr/status/617681143538786304
Shaven
So basically you write something LISP-ish in JavaScript to get HTML?
Why Programming is Difficult
There are three other things that make programming difficult:
- Fixing things that should not be broken
- No time for learning things
- Bad environment for programming
Let’s look at these things – these are all “time thieves”
Street Fighter II: An Oral History
Street Fighter II: An Oral History tells the story of how Street Fighter II came to be, though interviews and anecdotes of those involved creating it. It’s a lot of fun to read. 😀
Programming is terrible – Lessons learned from a life wasted
There are no words to describe this talk, just watch it!
https://youtu.be/csyL9EC0S0c
Or maybe there are … those of the presenter himself: “A bad programmer talks about bad programming.”
Default Values for Boolean Options in Ruby
Let’s say you read settings from a YAML file and have some sort of settings object. Then you check if certain options are set with custom values or you have to set default/fall-back values on them. If you are dealing with Boolean options you have to be careful … as I had to find out myself.
Initially you would probably do something like the following to set a default value on a Boolean option:
settings[:some_option] ||= true # set default value if nothing set
Do you see the problem? What happens if the option was deliberately set to
false
? You would overwrite it because both cases
nil
(i.e. nothing set) and
false
would evaluate to
false
in the context of the
||=
operator and you would in both cases assign the right hand value (and overriding an explicit user choice in one case) … *ouch*.
So the correct solution is something like the following:
settings[:some_option] = true if settings[:some_option].nil?
Just be careful … 😀
Render Rails assets to string
If you ever needed a way to render a Rails assets to a string, Hongli Lai from Phusion describes how. 🙂
I prepared a Gist wrapping it into a nice helper. 😀
module ApplicationHelper # thanks to http://blog.phusion.nl/2011/08/14/rendering-rails-3-1-assets-to-string/ # you may need to change the owner of the tmp/cache/* directories to the web servers user # e.g. for Debian systems: `chown -R www-data:www-data tmp/cache/*` def render_asset(asset) Conferator::Application.assets.find_asset(asset).body.html_safe end end