Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

OT: Stupid User Interfaces

by afoken (Canon)
on May 30, 2017 at 23:29 UTC ( #1191652=perlmeditation: print w/replies, xml ) Need Help??

Just a little rant ...

I came home quite late, after a long day. Some excavator or a poor guy with a spade has cut a major power line. The power network company has fixed that, at least provisionally, so power was already back when I came home. What could be wrong?

The microwave oven happily told me it was 7:15 am. Oh well. Press the clock button. Oops, that was the timer, better press the other button with a very similar clock symbol. "12h" on the display. No, I'm in Europe, I want 24 h. Turn the wheel button. Wrong. Now I'm adjusting hours in the 12 h system. Press the clock button a few more times, jumping past minutes, back to "12h", then to "24h", then again minutes. Oops. Well, give the clock button a few more cycles. "24h". Yes! Now, rotate the wheel button. "1:", "2:", "3:", ..., "11:". Ok, turn it in reverse: "10:", "9:", ... "23:". OK. Push the wheel button. "BEEEP! Stupid user!". Oops. Push the clock button again. I wonder how many push cycles are left. Adjust the minutes. ":00", ":01", ... ":23". Push the wheel - no "BEEEP!" - ok, I'm tired. Press the clock button once more. Done.

Home office ISDN system phone: It displays its name and its firmware version. WTF? Maybe power did not come back cleanly? Unplug the combined ISDN and power jack, and fiddle it back in. Nope, does not help. Load the configuration program, adjust a minor setting, write back the configuration, to clean up NVRAM / EEPROM. Also does not help. Maybe the PBX lost its clock? Sure it did. It has no RTC, or at least no battery backup. But thanks to ISDN, it will adjust its clock when I call some external number and establish a connection with someone else. So I called a free hotline, and waited for their answering system. Yepp, it talks to me. Hung up. The PBX should now have adjusted its clock. But wait: The stupid phone still shows name and version, not date and time. Well, let's flash the firmware. It's just a few more mouse clicks. "Firmware is already at 2.3e. Do you still want to update the firmware?" Sure. About a minute later, the phone goes through a little disco mode, slowly flashing almost all LEDs, then comes back with name and version, and is still stuck there. Grrrrrrr! Where is my password for the support forum? It must be something simple. RTFM before posting nonsense. Yeah, right: That stupid phone refuses to switch to date and time until it has fetched the current date and time from the PBX. And the PBX does not have current date and time, despide having made a successful external call. Did some internal calls from and to the office phone. No help. So, dig through the three manuals of the PBX, and yes, there is a way to adjust the PBX's clock manually. Just dial a magic 20+ digit code, put in date and time at the right positions, and it will adjust its clock. So, let's start. Error at the fifth digit or so, PBX beeps "STUPID USER" and refuses any more configuration until I hang up. But hey, I've a smart office phone, I'll enter the magic code before picking up the handset, as I can correct errors there. Well, nice idea, but the phone dials dumb, whereas the PBX expects some delays in the code. Again, it beeps "STUPID USER" and expects me to hang up. And lo and behold, somehow the phone has managed to get date and time from the uncooperative PBX and shows date and time instead of name and version, as if nothing has happened. Why doesn't that *$%%! phone simply display "Date and time not set in PBX"? And why doesn't that PBX contain a sub-1$ RTC chip and a similarily cheap CR2032?

Answering machine. No. Not today. It has a display. It blinks "St" = Stellen (adjust time). It has << (rewind) and >> (forward) buttons, and it has + and - buttons. And a set button. + and - do not work for adjusting time, you have to use << and >>. OK, but that stupid machine insists on speaking every single number. "Adjusting time. [Silence] 1 hour. [Silence] 2 hours. [Silence] 3 hours." It's 23:45 or so. Holding down the buttons changes the increment from 1 to 5 after some ages. After some more ages, about at sunrise, I would be finished. No, it will have to wait.

Other mains-powered clocks have adjusted fine, thanks to DCF77. The clocks in my sat receivers have automatically adjusted to the time broadcasted via satellite. No problem.

Computers, including firewall? All fine. A nice reboot mail from the server, all subsystems happy, VMs have stopped. Push a few start buttons, and they all come back. No problems. Perhaps I should automate the VM startup, too. But then again, the uptime of the server is usually in the range of 100 to 300 days, interrupted only by hardware upgrades or men with spades. I don't really have to automate, but I could. Maybe someday. RTCs on PC systems have a battery backup. I think the firewall does not, but like all my systems, it adjusts via NTP thanks to pool.ntp.org.


It seems that today is the official bad user interface day:

At work, a client wants another prompt for the user interface of the product we've developed. Currently, to switch from simple mode to advanced mode, you have to press the "settings" button, then either enter a code or at least confirm that you are qualified for advanced mode, and then you have to press yet another button to stay in advanced mode. Now, when you press the "settings" button, you first shall have to confirm that you really wanted to press the "settings" button. Aaaaaah!

OK, to be fair, at the same time, the last button press to stay in advance mode should no longer be required. But still: How often should a user confirm a completely harmless switch from simple to advanced mode? Should the product prompt for social security number of the user and his manager and five fingerprints from each of the two before switching modes?

And I won't write any more about Qt, QML and the state of its documentation, more than just PITA. Or perhaps just a few sentences more. When do people learn that documentation is the most important part of software? Code examples are good, they can avoid a lot of prose. But examples are stupid if they show only the documented detail, stripped from all required surroundings. How do I use a complex object that requires a lot of setup? Like this:

simpleObject { id: "foo" magicStuff: complexObject { id: "bar" ... //<-- literally! All setup omitted from the exa +mple. } }

And not a line more. All setup omitted, you are expected to guess what you may need to set up, and how. You have to dig through the inheritance, and hope for some clues in an unrelated part of the documentation. Or you have to search for the source code. Trace the source code. Find out what happens in the complex object, and what it expects to have been set up. "If it was easy to use our code, you wouldn't get paid so much!"

Documentation is the user interface to 3rd party code, and in case of Qt/QML, it sucks. Yes, there is worse documentation. But I spend half a day digging through heaps of this crap and did not get one step further.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Replies are listed 'Best First'.
Re: OT: Stupid User Interfaces
by davies (Prior) on May 31, 2017 at 10:08 UTC

    I've been ranting about documentation for years. It's my unshakeable belief that no-one documents their own work well. In the first place, the skills are different. How many programmers have been on any sort of creative writing class? A tiny minority, and for good reason. In the second, even if the programmer is a good writer in other circumstances, s/h/it's too close to the code. Things that are absolutely obvious to the programmer are obscure to the new user. Even assuming those two hurdles away, in the case of commercial software, there is usually a rush to get it out of the door, meaning that documentation gets skimped. This is even more true now that documentation is written for the internet rather than being produced in glossy manuals.

    One of the drawbacks of "free as in beer" software is that customer complaints count for less than they do in businesses. This is not to say that the writers of free software don't care about documentation. But they do have other priorities, such as earning a living, and are entitled to do the tasks that interest them (like adding features) first, even assuming that they are able to.

    Never having used Qt or QML, I decided to look at one of them - Qt - to see what it does and whether you were being unreasonable. If anything, you were being generous. I have read the entire documentation for Qt.pm and still have not the slightest clue what it does. Those who find this surprising are invited to read http://search.cpan.org/~awin/Qt-0.03/Qt.pm and point out what I have missed.

    Regards,

    John Davies

      Those who find this surprising are invited to read http://search.cpan.org/~awin/Qt-0.03/Qt.pm and point out what I have missed.

      I take your point. What you might have missed is that you have linked to a 20-year-old version of the dist. In fairness to the authors/maintainers, the 6-year-old version at http://search.cpan.org/~cburel/Qt-0.96.0/qtcore/lib/QtCore4.pm is a bit more prosaic.

        I hadn't missed that it was very old. But I googled for Perl Qt and that was what came up. It looked right and has nothing to indicate that it isn't the latest version. I checked specifically on the CPAN page for the usual "Latest version" link and there was none. I'm not surprised that there is a later version. Nor am I surprised that the docs I pointed to have not been amended to indicate that they are deprecated and giving a link to something better, but I am disappointed.

        By the same token, while the docs you link to are more verbose and therefore I haven't read them as thoroughly, I don't see anything in them, either, hinting at what Qt actually does. Again, I'm disappointed but not surprised. A problem I have seen in lots of documentation is that it sends the user on a massive yak shaving exercise making it extremely hard and time consuming to find the precise document that tells me what I want to know. If I were thinking of trying to contribute to the Perl community by improving documentation, Qt could not be a candidate module as I still can't see where to start or what it is supposed to do.

        I did mention that I tend to rant about documentation, didn't I? I think I'd better stop here. :-)

        Regards,

        John Davies

        Let me show some more details. For that project, I use Qt 5.3 (C++) and QML on an embedded Linux system. The current problem was:

        There is a TableView that is fed with data by a ListModel. (To be continued ...)

        And here, things already get ugly:

        1. There seems to be no way to get documentation for a selected (i.e. my) Qt/QML version. There is a 4.x set of documentation, currently (and probably finally) at 4.8; and there is a 5.x set, currently at 5.8 or 5.9. No 5.3. Let's hope the 5.x set documents every change since 5.3. (Yes, maybe the complete documentation should come with the Linux distribution. No, it does not. The distribution sucks even more.)
        2. Then, I want a table. It should be fed by a model. Why is that model called ListModel and not TableModel? Well, it is an implementation detail. The table looks like a table, but it is really a modified ListView, where each list element is a table row.

        A new requirement: The table shall contain sections.

        Qt can do that. Nice. Less work for me, or so I thought. Here is the entire documentation of the section feature for TableViews:

        section group

        section.property : string

        section.criteria : enumeration

        section.delegate : Component

        section.labelPositioning : enumeration


        These properties determine the section labels.

        See also ListView.section.

        Isn't that great? A piece of art! To be fair, ListView.section is a link. Guess what waits behind that link:

        section group

        section.property : string

        section.criteria : enumeration

        section.delegate : Component

        section.labelPositioning : enumeration


        These properties determine the expression to be evaluated and appearance of the section labels.

        Now, where have I seen that before?

        OK, now I'm unfair. The text actually continues:

        section.property holds the name of the property that is the basis of each section.

        After that, it's talking about ListView not automatically sorting data, stacking order (which has the magical property of being 2), and performance issues. So, I need to set section.property in my TableView (that is actually a mutated ListView, or to say it nice, that inherits from ListView) to some magical name of some property. Umm, yes, the part left of the colon is obvious.

        There is a code example. And even a picture of how a sectioned ListView should look like. Let's look at the code:

        // The delegate for each section header Component { id: sectionHeading Rectangle { width: container.width height: childrenRect.height color: "lightsteelblue" Text { text: section font.bold: true font.pixelSize: 20 } } } ListView { id: view anchors.top: parent.top anchors.bottom: buttonBar.top width: parent.width model: animalsModel delegate: Text { text: name; font.pixelSize: 18 } section.property: "size" section.criteria: ViewSection.FullString section.delegate: sectionHeading }

        I'm not making this up. This is the EXACT copy of the example code.

        So, section.property is set to "size" in this example. Why? What does that mean? I know that the delegate stuff is responsible for painting onto the screen, and apart from delegates, the only other interesting thing left is the model. It's something with the ID animalsModel. So there must be something named size in that model. Let's look at that model.

        Oops, it's not in the example code. Never heard of SSCCE? Obviously not. Well, the ListView document fills a few pages, so maybe that model was previously used to explain other stuff? You wish. There is exactly one animalsModel, right in that non-working example. And that does not mean there is only one hit in that document. There is exactly one hit in the entire documentation! (Or at least Google is not able to find anything but copies of that single document and completely unrelated pages talking about experiments with animals.)

        So, what's in a model like ListModel? RTFM, where "F" is not "fine". A ListModel is documented to have two properties. One is named count, the other is named dynamicRoles. No property named size. But let's read on:

        The ListModel is a simple container of ListElement definitions, each containing data roles. The contents can be defined dynamically, or explicitly in QML.

        No size property. No property at all.

        There is also an example:

        The following example shows a ListModel containing three elements, with the roles "name" and "cost".

        import QtQuick 2.0 ListModel { id: fruitModel ListElement { name: "Apple" cost: 2.45 } ListElement { name: "Orange" cost: 3.25 } ListElement { name: "Banana" cost: 1.95 } }

        Yeah, sure. Why use animals when you can use fruits to explain that? From there on, the examples get more and more complicated, but no animals and no size property. And nothing that attempts to place fruits into groups. But the example is roughly similar to how my model looked at that time.

        Again, to be fair, there is a good hint in that document that I did not see. In this sentence from the third paragraph in the "detailed description":

        Elements can be manipulated via the model using the setProperty() method, which allows the roles of the specified element to be set and changed.

        What section.property in ListView / TableView expects is the name of a "role" in a ListElement (here's the doc), which is a user-choosen name of a property in all ListElements in a ListModel. Quoting ListElement:

        List elements are defined like other QML elements except that they contain a collection of role definitions instead of properties. Using the same syntax as property definitions, roles both define how the data is accessed and include the data itself.

        The names used for roles must begin with a lower-case letter and should be common to all elements in a given model. Values must be simple constants; either strings (quoted and optionally within a call to QT_TR_NOOP), boolean values (true, false), numbers, or enumeration values (such as AlignText.AlignHCenter).

        So, redefining names of things in every document, and reusing names used for other things is a quite clever way to force clients to hire a consultant. No, we didn't hire one. I know consultants from three former jobs. I don't want consultants in my office. Not that kind of consultants.


        I choose the hard way, searching Google for working examples, and finally found one (no animals, no fruits). It's pretty simple. Choose a name. "group" may be a good one. Add that name to each and every ListElement in the model. Choose any value you like for group, and assign the same value for all ListElements that should be in the same group / section.

        Now, section.criteria. Qt/QML must somehow compare each ListElement's group name, and insert a section into the list / table whenever it changes. Take a deep breath before reading on:

        section.criteria holds the criteria for forming each section based on section.property. This value can be one of:

        • ViewSection.FullString (default) - sections are created based on the section.property value.
        • ViewSection.FirstCharacter - sections are created based on the first character of the section.property value (for example, 'A', 'B', 'C' sections, etc. for an address book)

        A case insensitive comparison is used when determining section boundaries.

        And that's all. Either compare the entire value using some vagely specified compare function, or compare the first character using the same vagely specified compare function. There is no other way.

        I don't want to think about how that compare function compares the "normal" I/i and the turkish variants with a dot on I and no dot on i. And I also don't want to know how the code behind ListView extracts a "character" from a Unicode string. Perhaps I should think at least about the former thing, because the group names in my application are translated to various languages. For now, I won't. I've spend way too much time with that documentation, and if it breaks for some exotic language, I'll fix it later. No one will get hurt if that table does not look as pretty as it should.


        This problem may look trivial, because I've still simplified some things. Translations, generating model data from Office documents at compile time (using Perl, what else?!), look and feel of that table, optimizing for a small screen with tiny pixels, and so on. And of course, this is a propritary system, and the client will certainly be not amused if parts of the source code or significant implementation details pop up at every corner of the internet.

        Now guess how much fun I had trying to find out how to draw graphs from data in a model that automatically update when the data in the model changes. In the end, I got rid of the model for drawing and instead passed a Javascript AoH around. It may not be as nice as a model, but it gets the job done in less time.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: OT: Stupid User Interfaces
by jmlynesjr (Chaplain) on May 30, 2017 at 23:42 UTC

    Years ago, in the States at least, a company sold a kit to repair the flashing clock digits on VCRs...a piece of black tape to cover the display.

    James

    There's never enough time to do it right, but always enough time to do it over...

Re: OT: Stupid User Interfaces
by talexb (Canon) on May 31, 2017 at 18:45 UTC

    Interesting .. my current contract involves writing ETL scripts (or, as we call them in the trade, 'data-munging' scripts) that take a variety of input flat files, split them up into fields, re-organize the data in the fields, and write the result out to a variety of flat files, until some mainframe folks figure we have a match. That's the Perl development part.

    My scripts don't go on to live on any production system, however. My actual deliverable is the documentation, in Excel spreadsheets, showing the input records, the output records, and the transformations for each of the fields. And it's an interesting switch to go from writing logic in Perl, to describing these transformations in pseudo-code. It really is a different skill set.

    My guess is that your battles with products are the result of siloed development. As opposed to my situation, where I'm coding and then documentating, I imagine that engineering builds a User Interface but never use actually it, not do they have Marketing test it. Maybe it's because there isn't time, there are no resources, or any other reason that you can think of. Then the manual writing team fiddle with the prototype unit and write something up, but they don't actually use the unit either. Everyone probably blindly imagines that setting the clock is something that gets done once, upon installation, when the packing materials and manual are clearly to hand -- and if it takes 10 minutes, who cares or remembers that pain.

    I think the problem here is that everything insists on knowing what the current time is, rather than having things networked together so that part of an appliance power-up sequence would be 'Go get the current time/date from the local ntp server', solving issues with power outages and Daylight Savings. Unfortunately, that scenario doesn't fit with the lowest common denominator (yet), so we have several different appliances, all with their own unique way of setting time.

    At least some of the devices are grown-up and can handle this sort of situation. :)

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

Re: OT: Stupid User Interfaces
by afoken (Canon) on Jul 29, 2020 at 06:16 UTC
    Maybe the PBX lost its clock? Sure it did. It has no RTC, or at least no battery backup.

    Just a little update from my future self:

    I rescued the fully-featured variant of my ISDN PBX from the garbage bin. This one has all the bells and whistles, supports ten instead of just six analog phones, supports a module to add a second external ISDN line and a second internal ISDN bus, supports a second door line module. But it is basically the same hardware as my PBX. My PBX just has a few components and connectors not mounted. I opened the rescued PBX and had a look around, and found "the usual suspects". And in a corner of the PCB, I found pads for a CR2032 battery holder and an eight pin RTC chip next to it.

    So the hardware seems to support a hardware RTC including a battery backup. But at some time late in development, the manufacturer decided not to mount the RTC components and instead rely solely on the software and ISDN network features. That's more than just annoying!

    On the other hand, the RTC battery would have been placed in an "unreachable" area of the case, locked behind sealed screws. So after about five to ten years, the battery would be drained and the PBX would either refuse to work or fall back to the current behaviour. To fix that, the manufacturer would have to re-layout the PCB to move the battery to the connectors area, or add another removeable cover to the case to allow access to the battery holder.

    Removing the RTC and battery from the design allowed the PBX to work continously for more than twenty years. So after all, getting rid of the RTC and battery was probably a good idea.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

      20 years? I want eternity

        You know that Voight-Kampff test of yours? Did you ever take that test yourself?

        🦛

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://1191652]
Approved by marinersk
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (7)
As of 2020-08-05 11:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Which rocket would you take to Mars?










    Results (35 votes). Check out past polls.

    Notices?