I’m working on the handwritten kanji character recognition. At least that part doesn’t need reworking, I thought. Maybe it doesn’t, though I plan to improve on it a bit. What gives me headaches (apart from the fast changing weather) is that I don’t really understand a lot of the code now.
As I’m working on the new version, I try to describe what each part of the code does, so I’m adding comments everywhere. In the original code there was almost none. I could easily understand what the program does, so why add any? Good code explains itself? I have seen that line a lot before. Unfortunately it’s only true about code which solves a very simple, easy to understand problem with a simple algorithm. NOT for handwritten kanji character recognition.
I can’t make much out of the old code without considerable effort doing so. Because of this, even copying the old code takes a lot of time. Not that I’m just copying it either. I’m not sure whether all of my old decisions made sense or not, but regardless of that I would probably make different ones now. It’d be good if someone reading that code (even if it’s me years from now) could figure out why those decisions were made.
I think I’ve learned my lesson, but that doesn’t mean every single line will get commented either. Some parts really do explain themselves. Others might not be obvious to everyone, but as I was solving the same problems the same way years back, they will be easy to read in the future too. I have seen code before which had more comments than code, and it was hard to read because of that. If the algorithm is complicated, explaining it in a few long paragraphs at the start of the code is better than writing a description about each line.
Just to clarify, I’m writing this because it helps me concentrate while I code. I doubt anyone will change their habits because of this blog.
Whenever I touch Qt designer to design a new window I feel like I have to rant about it. So here is my rant: layouts in Qt are bad bad bad bad bad!
I think I’ll need to find other ways to vent my frustration.
UPDATE: I didn’t want to make just another blog post about this stupidity, that’s why I’m expanding this post instead. I’ll spend this day trying to make a window with things placed at specific locations. And it’ll take the whole day. Again. When it comes to Qt’s window layouts and widgets the usual (and only working) solution is to “write it yourself.” If it weren’t the only real option for making cross platform apps, I’d be too frustrated to use it any longer.
UPDATE2: It turns out what I could easily achieve in c++builder (or directly in winapi – done both) is impossible in Qt. I spent the whole day looking for a solution and it can’t be done. Now I’ll have to figure out a way how not to make the kanji handwriting recognizer window butt ugly.
Disclaimer: This is a programming topic. Not that scary though.
As the title says, it is possible to not write well optimized code, but replace it with threads. (VERY simply put, a thread is a program within a program. It runs at the same time another part of the program* runs.)
Is it bad practice or good? I think it depends. For example in previous versions of zkanji I had to store a lot of temporary data during the long-term study, to make it fast to get the next item after answering another. This is a way of optimization, you make extra care that everything works fast. This also added a lot of complexity to the code, and complex code is harder to fix if something works badly. Because of that optimization I was too scared to change the code to allow adding new items to study, after you finished studying previous items for the day.
So how do we replace optimization with threads? If you can make more code to run at the same time, the program will appear to be doing its task faster. (I’m not an expert at this but maybe if you are on a laptop this will also drain its batteries a bit faster.) In our case in zkanji, while you are thinking about the answer to an item, the program can do “stuff”. For example, it can find the next item to show after the current one. Finding the next item is fast while there are not many items to study, so there would be no need to add a thread just for that, but after years and years adding new items, it can have a visible lag after the answer was given and before the new item is shown.
This is probably a very simple example, but as the lag wouldn’t be more than a second on slower computers, I don’t think it’s worth my time optimizing it. And also, you’ll be able to add new items to study any time. I will consider adding new threads for small things like this if they make my life easier and the program simpler, but threads come with their own complexities and difficulties, so avoid them if possible.
*Technically speaking, the “another part of the program” is another thread. Every program has at least one thread, even if it’s only the single main thread.
I have heard this before and read it at many places online, that generally if you can recall something 2-3 months after the last time you were exposed to it, that something is probably already in your long-term memory. Although the article on Wikipedia about long-term memory seems to give a lot of confusing contradictory definitions. Whatever, in zkanji I’ll mark a word as “learned” if you could answer it correctly after a period of 60 days. Haven’t decided about what to do with kanji yet. Probably something similar but when you could answer the written form of a word correctly that contains it. Learned kanji won’t be “unlearned” if the vocabulary goes back to the not-learned list though (after 1-2 wrong answers).
I tried to collect a few specifics about the design changes I have in mind. This is not a complete list and it’s more like a listing of stuff rather than a well thought out blog post.
- Dictionary searches or the general features that can be accessed will stay, though might change a bit.
- I plan to remove study statistics of study groups (not the long-term study).
- I want to add some kind of “learned” status for words and kanji. For that I have to connect the stats of the long-term study and study groups, and the old stats are in the way.
- I want to remove the “kanji card” button, and the custom definitions that you could set there. I think nobody used that feature and there was no point to it.
- You’ll still be able to set custom definitions for words in the long-term study to make them easier to learn. The same definitions will be used in the simpler study groups.
- There will be as many long-term study decks as you like.
- If you finished studying for a day with long-term study, you’ll still be able to add more words and continue studying.
- No more checkboxes for groups, as those didn’t do anything.
- Everything will have its separate window to avoid the cluttered interface zkanji currently has, and I plan to make every dialog non-blocking.This is how zkanji started out originally but the windowing library in c++builder wasn’t really good for many main windows so I scrapped that idea. I hope it’ll work this time.
- As almost everything is re-written from scratch, all the windows will be different and the context-menu might look very different too. It’s kinda hard to make a good looking interface in Qt, so the first version probably won’t look too good.
The list probably goes on. For example I wanted an example sentences browser but it won’t be in the initial version.
I have no idea what to show in the kanji information window and how. It’s a cosmetic feature in my opinion. I sometimes (though rarely) use the “part of” and “parts” panel on it, and ignore the rest. When I was a beginner in Japanese I thought those numbers and the kanji’s meaning are so important for my study, but now I think otherwise. Learning vocabulary (with the correct kanji) is so much more useful than kanji readings and such. I still plan to make such a window (mostly for the stroke order diagram), but the format how the data is presented will probably be very different.
If you find anything wrong with the plans, please comment about it.
With every single feature I rewrite I always think about what should be changed to make it better. There are many decisions to be made, but changing stuff is not easy. I’m sure a lot of people will be angered if something is removed, and many others if things get changed. I could of course keep everything as it is. In a way this is the most appealing choice. It’s not surprising many developers and companies choose this path, but this is also why a lot of programs don’t get better.
Unfortunately there’s nobody I could ask about the changes I intend to make. If I only asked a single person they wouldn’t be able to help as they can’t possibly know the needs of all users either. So in the end changes will be made, features will be removed or completely reworked. People will get angry. This is not what I’m aiming for, but asking everyone on this blog what they want is difficult, as people rarely come to developer blogs. (I never intentionally visit such either.)
When a feature is completely changed, the data stored in user data files is usually changed (or removed) as well. Because of this in most cases there is no going back. I believe everything I change is for the better, but only time can prove that. Still, it will be difficult to change things back if a decision turns out to be wrong.
Basically what I’m trying to say is that if you want something to be in some way you can still get it while I’m working on the new zkanji. But it’ll be late to complain after the release.
Rewriting zkanji to be cross platform requires certain changes. One of these changes is how the folder, where the program will save its user data, is decided.
Currently zkanji looks into its own data folder where it was installed, and if that’s writable (i.e. because it’s not the “Program Files” folder), it shamelessly starts dumping all its saved data there from that on. Otherwise it looks up the App Data folder’s path and uses that one. (Or at least a sub path in it.) This had the happy consequence that if you installed zkanji on an external hdd and moved it to another computer, it was automatically working like a portable installation.
I think this works fine, and I wouldn’t change it, but I don’t know the preferences of other people and operating systems. So rather than letting the program decide, the new version will ask the user where to save its data. This might be another extra click you might find inconvenient, but at least it should be safer and will only happen once.
The new algorithm will first check whether the data folder on the install path is writable at all. Because if it’s not, there’s no real question what to do. (So the App Data will be used as there is no other location it could safely write to.) If it is writable though, the program will also check for the existence of previously written user data in there. (You could of course fake the user data, making empty files with expected names. Zkanji won’t really check whether they are valid.)
Next it’ll look into the (OS dependent) application data folder, and whether user data exists there already or not. If user data is only found in one location, that location will be used and no questions asked. On the other hand if both are found (and can be written to) zkanji will assume a portable installation. I first thought that it should save the choice in its configuration (or .ini) file, but if there are two folders with user data, both will have a config file, so it would be pointless to check.
Of course you might want to override the automatic choice. In case you have a fresh install of zkanji on a portable drive, and the host computer also has a zkanji installed, the program on the portable drive will assume that it is not portable. It has found user data in the App Data location and nothing on the local install path, so there’s no real way to determine the truth.
In that case, if you want to make the install portable, there will be an option for that in the settings. Once you selected it, user data will be saved to the installed data folder, and no more misunderstandings will arise (hopefully). The other way around, that is, if you want to make the portable install to be non portable, the only way is to move the local data to the App Data location. If I’m not lazy when I get to that part, the program will do it for you. Overwriting existing data will need a confirmation of course.
Hopefully this change won’t be noticeable at all. Already existing user data won’t be deleted or moved around, just used as it is.