Goodreads recommendations are too good and awful at the same time: they showed me a series that I'm watching already (series based on books), but... the last book in the series. With spoilers.
Wait for a while now, not visiting until I finish it.
Many programming languages recommend the following order of imports: standard library first, then all the third party modules sorted alphabetically, and finally, program's own modules.
Here's an example from Python:
If you look closely, this is the order the countries come out during the Olympic games opening ceremony!
Let's call this import order "olympic sorting".
At first, programs have objects from the problem domain - be it Song, Fruit or House.
Of course, you need abstractions - Object, Model, Class (and perhaps Metaclass) or Message. The customers aren't interested in these, but they are real words at least.
And when that is not enough, enter concepts named after publication authors: Kan extension, Yoneda lemma and Lie group. They don't have corresponding words in the language, so perhaps even the authors don't have hopes of their wide usage.
P.S. Of course, you can just name your types K1 and M1.
Thanks to the library of the company I work in for the ability to request books. "Working Effectively" is more than 10 years old, but the title looked promising.
In essense, all the book advocates is divide (the code into separate pieces), write tests and conquer (make changes). Perhaps about 70% is devoted to the ways of how to achieve that, with examples in Java. So knowledge of Java or at least the OO paradigm is a must before reading (and C and C++ desirable).
Of course, in the time being the programming languages and tools have changed, and it was interesting to compare whether the described techniques are now simpler, obsolete or new ones are needed.
On one hand, Java, being a statically typed language with rather strict decisions, makes one resort to building a complex web of interfaces, overridden methods and objects in the hard cases. To my knowledge, it now has tools that allow circumventing the inheritance, method visibility and other restrictions when testing. But it isn't worthwile in all cases - improving the code structure, even just to run the tests, is beneficial for changes later.
I won't discuss the C++ examples at all, because all they are is cheating on the compiler and linker. A lot of places use macros - I wonder if the author ever got a project where the macros themselves needed testing? However, good to read for the general knowledge.
The place where I envy the author is reliance on the compile stage errors. Thanks to the strict typing, practically the only place where a runtime error is possible is the implicit
int conversion, and this is pointed out several times in different chapters. On the other hand, the author is heavily exploiting
null, suggesting passing if an object of the needed type can't be constructed and hope it works.
There are no higher order functions in the book - perhaps Java didn't have delegates at the time. In C++, of course, one can make callable objects and even custom method tables, but, again, doing it just for testing is an overkill.
An interesting technique I saw that doesn't depend on particular language or paradigm is "scratch refactoring". Having saved the current state in a version control system, you start changing everything you can, however you want, paying no attention to the tests. If the changes touch several areas, that's still fine, continue as you please. And when there is finally a satisfactory result... remove all the changes, revert to the saved version and start again, with tests. The refactoring itself won't advance very far, but the experiment will give you an understanding of the direction to take.
One more note is about the architecture. Very often its understanding is different between team members, especially if the project has an architect detached from the real life. For this not to happen, the author suggests periodically explaining the system or its components' functionality, assuming no prior knowledge, in a limited number of sentences. Thus all the participants get an idealized version of the architecture, and subconsiously strive to support and enhance it instead of making random changes. I wonder whether these idealized descriptions can go into the modules' documentation, or it is worthwile making the team members make them up from scratch every time?
The last thing I want to point out is that the author focuses on writing unit tests. There is a good criterion for them - they are the tests that can run faster than 0.1 seconds. This resolves the contradiction in the "testing in isolation" definition - it's obvious that the
+ operator, when it is used in the tested method, doesn't need a mock, but an external service call, like a database, and similar must be excluded. It is a pity that Django, for example, practically imposes the reverse approach, where there are extensive tools for using ORM when testing and almost none for replacing it.
General recommendation: for working with object-oriented code, worth a read. Techniques specific to a particular language can be leafed through.
I've got an invitation to HackerX. I didn't think it was particularly worthwhile after I've got a repeat notification seeing as I didn't register on the first one, but decided to check it out. By the way, I don't know where did they get my address from - during the registration I was asked for LinkedIn and GitHub so perhaps not from there.
The event itself was crowded. Perhaps 50 people in the room, and that's considering a lot of name tags didn't get picked up. About 15 companies, the only familiar name was Telstra.
But that's not the main thing. During the registration they let me choose my programming languages, asked about GitHub and LinkedIn, but after the introduction they just let everyone take a spot at one of the employers' desks at will (5 minutes to a company). So, as I understand it, there was no matching of companies to developers based on interest - just a career fair.
What's 1 + 2? Let's ask Elm:
---- elm-repl 0.17.1 ----------------------------------------------------------- :help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl> -------------------------------------------------------------------------------- > 1+2 Error: The following HTTP request failed. <http://package.elm-lang.org/all-packages?elm-package-version=0.17.1&since=2016-10-24%2008%3A52%3A34.764973%20UTC> FailedConnectionException2 "package.elm-lang.org" 80 False getAddrInfo: does not exist (Name or service not known)
The most interesting result of any REPL I've ever seen. Will try to convince the workplace to use it.
XMonad can be installed via Stackage. But it's not enough to install, it needs to compile the user configuration -
xmonad.hs. Being installed through
stack install, XMonad tries to call the system GHC, which expectedly can't find the required libraries.
Ideally, XMonad could understand that it's installed through Stack, and called the corresponding compiler. There are precedents - HLint, for example, loads the required libraries for checking the code if it finds
stack.yaml. But meanwhile it can be done manually.
XMonad calls GHC to compile the configuration, so one must first point to it from a wrapper script
This script has to be put in a directory preceding the one used by Stack -
~/.local/bin - in
Now XMonad will call GHC installed through Stack, compile the configuration and launch the result. But all the other programs launched from within it will inherit the same settings, which confuses, among others, Stack itself. To fix this, we need to reinstate the system settings after the launch. Thus, in
The full configuration can be found in my repository:
XMonad 0.13, or any version with e159ec3, supports a custom user build script that should make most of the above unnecessary.
I liked what Kraftwerk did in the start of their career: unique, custom made instruments producing sound that wasn't heard before. Clips and concerts where you couldn't tell real people from robots. But 40 years passed, synthesizers and computers are used by more people than know what those mean, and Kraftwerk, unfortunately, have done nothing new.
Enter Wintergatan: Marble Machine, Starmachine2000 and Sommarfågel. It's not a perfec comparison, but here it is, new sound and self-made instruments. No grandiose ideas yet, but let's see what comes next...
I wanted to replace a Raspberry Pi as a media center with something more powerful, so that the video and the UI doesn't stutter. So I found an Intel Compute Stick clone - MeegoPad T5.
For the impatient: still isn't working properly, but maybe someone else can figure something out.
Surprise number one: it's a 64-bit platform with 32-bit UEFI. To boot from the standard Arch image, put a 32-bit GRUB next to the 64-bit systemd-boot EFI loader already there (or any other loader which can pass parameters to the kernel) and choose it through the UEFI Shell (F7 during startup shows the boot menu).
Wi-Fi module isn't visible during installation, see below - I had an Android phone acting as an access point.
The installation itself is going fine - 64-bit GRUB can install a 32-bit version of itself. But the booting of the installed system stops at:
Loading Linux ... Loading initial ramdisk ...
Here's what helped me:
grub.conf. It's not enough (?) to edit
/etc/default/grub, had to remove it from
The Wi-Fi module is a Realtek RTL8723BS. It is detected and started when rtl8723bs-dkms-git is installed from AUR (also see package comments there). Unfortunately the connection isn't stable and after some time stops working entirely. Applying the recommended patches from the driver page didn't help.
(See update below.)
Despite the awful Wi-Fi transfer speed,
ping results were looking interesting:
PING 22.214.171.124 (126.96.36.199) 56(84) bytes of data. 64 bytes from 188.8.131.52: icmp_seq=1 ttl=50 time=0.00 ms 64 bytes from 184.108.40.206: icmp_seq=2 ttl=50 time=0.00 ms 64 bytes from 220.127.116.11: icmp_seq=3 ttl=50 time=0.00 ms ...
Turns out time on MeegoPad is passing... strangely (lanmei in this example):
$ while sleep 1; do echo "Local: $(date) Lanmei: $(ssh lanmei date)"; done Local: Sun Jan 31 19:37:53 AEDT 2016 Lanmei: Sun Jan 31 19:36:17 AEDT 2016 Local: Sun Jan 31 19:37:54 AEDT 2016 Lanmei: Sun Jan 31 19:36:17 AEDT 2016 Local: Sun Jan 31 19:37:56 AEDT 2016 Lanmei: Sun Jan 31 19:36:17 AEDT 2016 Local: Sun Jan 31 19:37:57 AEDT 2016 Lanmei: Sun Jan 31 19:36:18 AEDT 2016 Local: Sun Jan 31 19:37:59 AEDT 2016 Lanmei: Sun Jan 31 19:36:18 AEDT 2016 Local: Sun Jan 31 19:38:00 AEDT 2016 Lanmei: Sun Jan 31 19:36:18 AEDT 2016 Local: Sun Jan 31 19:38:01 AEDT 2016 Lanmei: Sun Jan 31 19:36:18 AEDT 2016 Local: Sun Jan 31 19:38:03 AEDT 2016 Lanmei: Sun Jan 31 19:36:19 AEDT 2016 Local: Sun Jan 31 19:38:04 AEDT 2016 Lanmei: Sun Jan 31 19:36:19 AEDT 2016 Local: Sun Jan 31 19:38:05 AEDT 2016 Lanmei: Sun Jan 31 19:36:19 AEDT 2016 Local: Sun Jan 31 19:38:07 AEDT 2016 Lanmei: Sun Jan 31 19:36:19 AEDT 2016 Local: Sun Jan 31 19:38:08 AEDT 2016 Lanmei: Sun Jan 31 19:36:20 AEDT 2016 Local: Sun Jan 31 19:38:10 AEDT 2016 Lanmei: Sun Jan 31 19:36:20 AEDT 2016 Local: Sun Jan 31 19:38:11 AEDT 2016 Lanmei: Sun Jan 31 19:36:20 AEDT 2016 Local: Sun Jan 31 19:38:12 AEDT 2016 Lanmei: Sun Jan 31 19:36:21 AEDT 2016 Local: Sun Jan 31 19:38:14 AEDT 2016 Lanmei: Sun Jan 31 19:36:21 AEDT 2016 Local: Sun Jan 31 19:38:15 AEDT 2016 Lanmei: Sun Jan 31 19:36:21 AEDT 2016 Local: Sun Jan 31 19:38:16 AEDT 2016 Lanmei: Sun Jan 31 19:36:21 AEDT 2016 Local: Sun Jan 31 19:38:18 AEDT 2016 Lanmei: Sun Jan 31 19:36:22 AEDT 2016 Local: Sun Jan 31 19:38:19 AEDT 2016 Lanmei: Sun Jan 31 19:36:22 AEDT 2016 Local: Sun Jan 31 19:38:20 AEDT 2016 Lanmei: Sun Jan 31 19:36:22 AEDT 2016 Local: Sun Jan 31 19:38:22 AEDT 2016 Lanmei: Sun Jan 31 19:36:22 AEDT 2016 Local: Sun Jan 31 19:38:23 AEDT 2016 Lanmei: Sun Jan 31 19:36:23 AEDT 2016 Local: Sun Jan 31 19:38:25 AEDT 2016 Lanmei: Sun Jan 31 19:36:23 AEDT 2016 Local: Sun Jan 31 19:38:26 AEDT 2016 Lanmei: Sun Jan 31 19:36:23 AEDT 2016 Local: Sun Jan 31 19:38:27 AEDT 2016 Lanmei: Sun Jan 31 19:36:23 AEDT 2016 Local: Sun Jan 31 19:38:29 AEDT 2016 Lanmei: Sun Jan 31 19:38:29 AEDT 2016 Local: Sun Jan 31 19:38:30 AEDT 2016 Lanmei: Sun Jan 31 19:38:29 AEDT 2016 Local: Sun Jan 31 19:38:31 AEDT 2016 Lanmei: Sun Jan 31 19:38:29 AEDT 2016 Local: Sun Jan 31 19:38:33 AEDT 2016 Lanmei: Sun Jan 31 19:38:29 AEDT 2016 Local: Sun Jan 31 19:38:34 AEDT 2016 Lanmei: Sun Jan 31 19:38:30 AEDT 2016 Local: Sun Jan 31 19:38:35 AEDT 2016 Lanmei: Sun Jan 31 19:38:30 AEDT 2016
The two minute jump near the end is
systemd-timesyncd discovering (how?) that something is wrong and synchronizing via NTP.
The time problem was caused by the kernel patches from RTL8723BS driver. Vanilla kernel keeps the time fine.