5

whatheco.de

 3 years ago
source link: https://whatheco.de/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Static Checker for Immutability in Kotlin

An immutable object is an object whose state cannot be modified after it is created. Immutable objects have several desirable properties, of which the two most important ones relevant to this post are:

  • They are inherently thread-safe: being read-only, they can be accessed safely from separate threads without having to worry about unexpected state or overwriting changes.
  • They can act as value objects: two value objects created equal should remain equal, which is guaranteed when they are unable to change state.

Therefore, it is common to implement objects as immutable, and software frameworks may require/expect polymorphic objects passed to their APIs to be immutable. Unfortunately, correctly implementing an object as immutable relies on the developer’s expertise in most mainstream OOP languages (it cannot be enforced by the programming language).

Data classes in Kotlin certainly simplify creating value objects: an equals, hashCode, and copy function are automatically generated. However, data classes are not immutable by default! Kotlin still allows defining var members on data classes, and adding members of mutable types.

True guarantees for immutability would have to be baked in to the programming language/compiler, or verified using a static checker. While proposals to support immutability in Kotlin exist, a fully functional static checker for Kotlin is already available—detekt.

Detekt contains a rule out of the box to verify whether all members in data classes are specified as val, but does not verify whether those members are immutable types. Furthermore, not all immutable objects should necessarily be implemented as data classes, and there might be cases in which mutability in data classes is desirable.

Having a need to enforce developers that extend base types in a framework I am working on as immutable and/or as data classes, I implemented a detekt plugin which enables verifying whether concrete classes are implemented as specified according to annotations applied to base types (e.g., @Immutable and @ImplementAsDataClass).

For example, the following implementation will warn NotImmutable is not implemented as immutable when running the static checker since Mutable.foobar is specified as var:

class Mutable( var foobar: Int )
class NotImmutable( val mutable: Mutable ) : Base
@Immutable
interface Base

The plugin is definitely not complete yet, in that it does not verify all cases which may be mutable, but it already catches a majority of errors and as an open-source contribution on GitHub I hope other might take an interest and contribute to the project.

Posted on August 30, 2020August 30, 2020Categories Kotlin, OOP, Software DesignLeave a comment on Static Checker for Immutability in Kotlin

List of Strongly-Typed Objects Acting Like Enum in Kotlin

Suppose you have a list of object instances (Kotlin’s concept for singleton classes) that are logically related to one another and you therefore want to group them together, but also want to provide direct (non-index- or iterator-based) access to them, similar to how you access an enum.

How would you go about doing that in Kotlin?

As an example, take the following DataType interface and implementing object Geolocation:

interface DataType { val typeName: String }
object GeolocationType : DataType
{
override val typeName: String = "geolocation"
fun create( longitude: Double, latitude: Double ) =
Pair( longitude, latitude )
}

Imagine many more DataType‘s: WeightType, StepcountType, etc. Now you want to provide a list of SupportedTypes containing all the types your codebase supports, but you also want to provide direct access to that list, so that the create() method (and other potential type-specific members) for Geolocation can be called.

While enums in Kotlin are fairly powerful—they largely behave like normal classes and can implement interfaces—they do not support generic type parameters and (as far as I could figure out) enum values cannot be instantiated based on existing instances. You could let the enum implement the interface of the instances you want to represent and override all methods redirecting them to the wrapped instance, but:

  • This introduces an intermediate instance, which might not be desirable for equality checking.
  • Does not provide access to type-specific members, such as create() in the example given.
  • Leads to heavy code bloat which is no fun to maintain.
enum class SupportedTypes : DataType
{
GEOLOCATION
{
override val typeName = GeolocationType.typeName
// This method can't be accessed!
fun create( longitude: Double, latitude: Double ) =
GeolocationType.create( longitude, latitude )
}
}

Instead, I opted to create the following base class …

open class EnumObjectList<T>
private constructor( private val list: MutableList<T> ) :
List<T> by list
{
constructor() : this( mutableListOf() )
protected fun <TAdd : T> add( item: TAdd ): TAdd =
item.also { list.add( it ) }
}

.. and use it as follows:

object SupportedTypes : EnumObjectList<DataType>()
{
val GEOLOCATION = add( GeolocationType )
}

This now allows to iterate all supported types, just like enums or a list, but also to get the full type information (including generics) when accessing the member directly:

val supportedTypeNames = SupportedTypes.map { it.typeName }
val data = SupportedTypes.GEOLOCATION.create( 42.0, 42.0 )

For a real-world use case, which this simplified example was based on, check out PhoneSensorMeasure.SamplingSchemes in the project for which I introduced this base class.

Posted on May 5, 2020May 5, 2020Categories Kotlin, Software Design1 Comment on List of Strongly-Typed Objects Acting Like Enum in Kotlin

Socratrees: private beta launched!

Over a year ago I announced Socratrees, a platform to support online argumentative discussion.

Complex interrelations between different statements which make up an argument are often hard to follow, or hard to contribute to, when forced into a linear format. This is an unfortunate characteristic of essentially all modern media used to present arguments and host discussions. Socratrees offers an alternative by outlining arguments into intuitive hierarchies of supporting and opposing statements.

example-tree.png

Our mission statement reads as follows:

  • Transparency first: our primary goal is not to find out who is right or wrong, but to improve transparency of thought.
  • Finding common ground: encourage consensus building, to build unity.
  • Inclusiveness: represent all opinions, also minorities and repressed groups.
  • Facilitate conducive discussions.
  • Inspire critical thinking.
socratrees-logo

Since the start of this month, the site is now in private beta during which we will evaluate how well our current design supports these goals and how it can be approved upon. This contributes to research on argument technologies. Join private beta and help us make discussions great again!

Posted on August 6, 2018August 10, 2018Categories HCI, SocratreesLeave a comment on Socratrees: private beta launched!

Is Microsoft finally embracing ubiquitous and activity-centric computing with Microsoft 365?

During the vision keynote at Microsoft Build 2018, Satya Nadella introduced the Microsoft 365 platform, a new technology which aims to improve the integration between different Microsoft products and devices (and even other vendors). As great as that is, the underlying motivation is much more interesting and reads like the introduction to a typical paper on activity-centric computing—a line of research originating in the 80s (referred to in my earlier writing as ‘activity-based computing’) which argues for an alternative to the current file-, window-, and application-dominated user interface paradigm.

During a single day you’re using multiple devices, you’re at multiple locations, working with multiple people, and interacting using multiple senses. That is the world we already live in. We need an operating system, we need a platform, that abstracts the hardware at that level, that creates an app model at that level. Single devices will remain important, but this ‘meta orchestration’ is what we need to do. We need to ‘up level’ even our concept of what an operating system is. And that is what Microsoft 365 does. – Satya Nadella, Microsoft Build 2018

microsoft-365

This ‘meta orchestration’ is what research prototypes in activity-centric computing typically support by introducing ‘computational activities’ which can be managed by the user or inferred by the system, can be suspended and resumed, can roam across devices, and can be shared with others.

Activity-centric computing addresses deep-rooted information management problems in traditional application-centric computing by providing a unifying computational model for human goal-oriented ‘activity’, cutting across system boundaries. – Upcoming review on activity-centric computing.

Certainly, Microsoft is aware about activity-centric computing and has even contributed to it in the past (e.g., Scalable Fabric and Project Colletta). Even more, Satya starts the keynote by quoting Weiser who first introduced the term ubiquitous computing, a related and overlapping field of research.

The most profound technologies are those that disappear. They weave themselves into the fabric of everyday life until they are indistinguishable from it. – Mark Weiser, The Computer for the 21st Century

But, what is really exciting about this announcement is that this is the first time a major software company seems to embrace (and publicly announce) this as the future of computing. In the past, a research group at Apple Computer (including Donald Norman) has toyed with the idea, IBM has a suite of collaboration tools supporting activities, and some features (such as virtual desktops) have been slowly incorporated into most operating systems. But for activity-centric computing to truly succeed it needs to be integrated into the very fabric of computing. In research, most prototypes have largely been inhibited by having to build on top of the very infrastructure they set out to change. As I conclude in my PhD thesis on Task and Interruption Management in Activity-Centric Computing:

Norman and Verganti compare incremental innovation with radical innovation through the use of a hill-climbing analogy: “Incremental innovation attempts to reach the highest point on the current hill. Radical innovation seeks the highest hill”:

incremental-innovation

… [activity-centric computing] envisions a radically new computing paradigm incompatible with the current antiquated desktop metaphor for office work. Building activity-centric computing systems is a continuous uphill battle against an industry which is only trying to achieve local maxima. In contrast, activity-centric computing pursues radical innovation, aiming for one unifying global maximum.

With the introduction of Microsoft 365, Microsoft is taking its first steps towards a new infrastructure which could potentially host this new computing paradigm and its entailing principles.

The world’s applications going forward need a ubiquitous computing fabric from the cloud to the edge. They need a new app model that is distributed, event-driven, and serverless. – Satya Nadella, Microsoft Build 2018

This is reflected in some of the other announcements, such as live code sharing between Visual Studio and Visual Code (which in research we call ‘activity sharing’), application-less event handlers hosted using Azure functions and adaptive cards which can host content within other applications (decoupling of functionality and applications), but perhaps most clearly by how ‘computational activities’ will be represented in Windows 10 going forward.

Timeline and sets in Windows 10

In the technology keynote on day 2 of the Build conference, Joe Belfiore discussed how the recently introduced ‘timeline’ feature in Windows 10 interplays with Microsoft Graph, a ‘cloud-backed data store’ to store organizational and personal data.

With timeline, the basic idea is that the things that you do on your PC, or other devices, are available in a single click from the taskbar. You can scroll back through time, see everything you were working on, and just click to resume. Now, the key idea here though is that timeline is based on the Microsoft Graph and therefore it enables cross-device experiences [including iPhone browsing history]. – Joe Belfiore, Microsoft Build 2018

microsoft-timeline.png

This history of the user’s interactions across devices are not in themselves ‘computational activities’. Computational activities require the ability for the user to aggregate disparate resources (managed by separate applications), such as web pages, Office documents, images, etc. This, Microsoft has decided to implement as what they call ‘sets’. In 2012 I discussed why traditional tabbed windows (managed by a single application) are inherently broken, and suggested how an implementation similar to ‘sets’ might lead to more scalable window management. With sets, all work related to a single ‘activity’ can be grouped under a single window using multiple tabs (regardless of the application used). More importantly, this ‘activity’ window can be closed without losing work and retrieved at a later moment in time when ready to resume work (which in research we call ‘activity suspend and resume’). Furthermore, this can even be done on a different device than where the work was first initiated (which in research we call ‘activity roaming’).

In my own research, I implemented similar features on top of Windows 7 in a system called ‘Laevo’, but in addition also looked at how activity planning and the handling of to-do items (traditionally supported by electronic calendars) can be integrated with such ‘computational activities’ or ‘sets’; why duplicate the effort of managing items in a calendar when they are already represented as activities?

Most of the time spent implementing such novel new systems is on ‘hacking’ the operating system and applications you intend to support to become ‘activity-aware’, and building a distributed ‘activity model’ which different devices can use to show and resume activities. With Microsoft Graph, Microsoft is building the necessary distributed infrastructure to start building such ‘activity models’ and is encouraging application developers to integrate with it; an essential step towards moving activity-centric computing from ‘the lab’ into production.

It thus seems Microsoft is finally implementing activity-centric computing as it was first envisioned in 1986 by Yoshiro Miyata and Donald A. Norman, targeting radical innovation as opposed to incremental innovation. There is still a long way to go towards incorporating other aspects of the original conceptualization of personal computing (as demoed by Alan Kay in the video below), but this is definitely a step in the right direction!

Alan Kay giving a demo of what commercial personal computers (unfortunately) did not turn out to be: https://t.co/hKybCLJ8ME

— Steven Jeuris (@StevenJeuris) April 24, 2018

Posted on May 11, 2018August 29, 2019Categories ABC, HCILeave a comment on Is Microsoft finally embracing ubiquitous and activity-centric computing with Microsoft 365?

Fluent Design System in Windows 10: Aesthetics over Usability?

At the Build 2017 conference, Microsoft revealed upcoming changes to the way applications will be (and can be) designed, introducing their Fluent Design System in the Windows 10 Fall Creators Update. This update focuses on the role which light, depth, motion, material, and scale can play in the design of user interfaces (UIs): really nice and impressive stuff which can certainly be used to improve user experiences. However, given that it has been a recurring theme in UI design to prioritize aesthetics over usability, I want to take a critical look at one of the newly introduced features—reveal highlight.

Reveal uses light to make interactive elements stand out. Light illuminates the interactive element the user can interact with, revealing hidden borders. The light also gently illuminates other interactive elements that are nearby.

… The Reveal behavior does this by revealing the clickable content’s container when the pointer is nearby.

For example, see the difference between the calculator application in Windows 10 and the same calculator using ‘reveal’.

reveal

Certainly an improvement, but at this point I feel it is worthwhile to take a couple more steps back to compare this with what the calculator looked like in Windows 7.

win7-calc

Less pretty, to be sure, but notice in particular how there is no need to hover over the memory buttons to perceive that they can be clicked and where to do so. To me, the UI modifications introduced as part of Windows 8 and 10 are two steps back and ‘reveal’ is one step forward, mitigating some of the earlier mistakes: the power of perceived affordances took a backseat to ‘flat design’, effectively stripping many UI elements of their clarity in how they can be used: where to click, can they be clicked, and what type of element it is. The question I would like to ask is: Should buttons ever look like ordinary labels in the first place?

While it is awesome to have additional development tools available to create more pleasing ‘on hover’ effects, conceptually this is nothing new. From a design perspective, it would still not make sense to require a user to hover over important UI elements to only then be able to interpret what they are. Therefore, at this point I would merely like to highlight that ‘reveal’ with the purpose of revealing functionality should likely be used sparingly, only for non-essential user interface elements. Whether or not the memory buttons in the calculator are ‘important’ (and potential alternate ways of visualizing them) is a different discussion to be had.

As researchers in user interface design know, perceived affordances improve usability. Conversely, I blogged about how the lack of affordances in the window manager of Windows 10 complicates resizing and moving windows around. Ironically, this was demonstrated perfectly by Ashish during his presentation on how to use the Fluent Design System features in XAML, as he spent 32 seconds on resizing a window to its desired size while narrating “Sorry. If this machine cooperates.” and Tim helpfully instructing him that he is “anchoring [the window] too high …”.

The (literal) bottom line of this post: great new stuff in Windows (and XAML), but I hope this post serves as a warning to think of usability first when using the new Fluent Design System features, aesthetics only second.

Posted on October 11, 2017Categories HCI, WPFLeave a comment on Fluent Design System in Windows 10: Aesthetics over Usability?

Make Discussions Great Again

There is one upside to the recent election of president Donald Trump (yes, the title of this post is a pun) and the earlier withdrawal from the European Union by the UK: it has become a whole lot easier for me to pitch an idea which I’ve been advocating (with some opposition) for nearly a decade now. It is my hope that the project I’m announcing in this post will help fight fake news—possibly the main driving force behind these events.

Given the growing body of knowledge accumulated by mankind, most professions require an extreme degree of specialization. Nowadays, you can be the most knowledgeable person on one topic while simultaneously being the most ignorant when it comes to another. Yet, society seems to expect us to have an opinion on everything impacting our daily life, from climate change to immigration issues, regardless of whether or not we have a comprehensive understanding of the topic at hand. This is where media comes in, which is supposed to keep us up to date and well-informed.

However, there is a problem with modern media. Although today we can access more information, faster than ever before, we are still left to our own devices when it comes to judging how relevant or valid this constant stream of data is. Finding information is easy (and even hard to ignore), but evaluating it is more difficult than ever. Consequently, most of us rely on whatever sources we deem authoritative and form our opinions based on that. The current prevalence of misinformation and fake news indicates this poses a risk, but as I will argue here, is merely symptomatic of a larger underlying problem.

The different media we use today to share knowledge and host discussions unnecessarily segregate opposing views. For example, this blog post makes the case for an alternative medium for discourse, but the only way to contest parts of the containing argumentation (although overall you might agree) is by writing a reply in the comments section (separated from the main article). Only through a fair amount of clarification (e.g., by referring to certain sentences within the article) will it be made clear how your comments relate to the overall blog post and might we be able to carry forward a fruitful discussion. As you have likely experienced, similar discussions can easily turn into stressful conflicts (both online and in real life discussions). But why should this be so?

Debaters on comprehensive scientific problems are … like lawyers who have to take a side. Each of them intends to strengthen his own arguments and to weaken the arguments of the aggressor—but no judge is in the chair. … Finally we find ourselves all together in the same ship and are co-operating even when we think we are fighting one another.

— Otto Neurath (1940), “Universal jargon and terminology.”

Discussions are inherently collaborative. As opposed to lectures, during which information is handed to you on a platter, discussions encourage you to share your own world views. Naturally, this gives rise to disagreement; if we were all like-minded, conversations would be rather dull (in fact, there would be no discussion at all). However, disagreement should not be seen as conflict but rather as an opportunity to learn; a chance to explore and understand perspectives different from yours. Unfortunately, it is all too common to fall into the trap of turning a discussion into a lecture; to start preaching your own world views without seeking to understand those of others. But if your goal is truly to convince someone, it is all the more important to seek out common ground first. The ideal argument is tailored to the person you are talking to, not merely an elaborate summary of what you know. In short, a conducive discussion should be as much about listening as it is about talking.

As such, having a one-on-one discussion is difficult enough as is, but trying to do the same online (a medium everyone has access to) is near impossible. Unless the medium is designed with large-scale discussion in mind! A linear format is incapable of expressing the underlying complex structure of argumentation with multiple opposing views. It is up to the reader to mentally connect the different statements which make up a discussion, to find out how they contribute to a larger topic, and to understand which conclusions can be drawn from them.

For the past few years I have had a vision on how to improve discussions and argumentation on the internet (based on my experience with the extremely successful network of Q&A sites: Stack Exchange). Countless brainstorming sessions and reading on the side later have eventually culminated into the design of a social network website, Socratrees, currently under active development.

Introducing Socratrees: The Socratic Tree of Knowledge

Complex interrelations between different statements which make up an argument are often hard to follow, or hard to contribute to, when forced into a linear format. This is an unfortunate characteristic of essentially all modern media used to present arguments and host discussions. Socratrees offers an alternative by outlining arguments into intuitive hierarchies of supporting and opposing statements. This design is loosely based on argumentation theory. However, we do not expect you to be familiar with theory in order to start using Socratrees.

Over the next couple of months I will start announcing specifics and open up parts of the project to the public. When interested, you can already sign up for private beta which gives you an exclusive opportunity to help shape this project from the very beginning! Until then, we welcome any questions, ideas, or feedback on our dedicated subreddit.

Posted on March 10, 2017March 11, 2017Categories HCI, Socratrees1 Comment on Make Discussions Great Again

How to Get (Actual) Dell Support

Karen Quintos, senior vice president and Chief Marketing Officer at Dell, is quoted to have said:

“Listening and responding to customers is so basic and fundamental. The emergence of social media elevates how companies can act on the feedback they get from customers,”

Any Dell representative claiming Dell provides good customer support has not spent any time within the trenches of Dell’s technical support themselves. In this article I will reflect on my three-month long (and continuing) struggle with what Dell refers to as “the best-in-class services and support experience that you have come to expect.” By doing so I hope to provide a guide for any future Dell customers on how to receive the support you have a right to as part of your purchase, while discussing likely reasons for the atrocious support Dell is more commonly known for. The article is structured as follows: first I will provide an overview of key problems identified with Dell technical support, second I list concrete suggestions on how to get better customer support (the part you might want to jump to in case you are just here to get advice), and third I discuss Dell as a case study on how company management can ruin product quality and customer support.

Dell’s seven deadly sins

First, let’s resolve some of that pent up anger you might have through comic relief. After my experiences with Dell I could not help but notice the similarity between the Dell logo and the multi-national conglomerate in the television series Mr. Robot—Evil Corp.

dell_evil

Or how aptly the Veridian Dynamics commercials in Better Off Ted seem to portray Dell’s business strategy.

People lie. Companies protect their interests. It’s different.

Likewise, Veridian Dynamics stance on ethics resembles Dell.

Right and wrong. It means something. We just don’t know what.

Comedy aside, scouring the net for customer dissatisfaction with Dell reveals just how close to the truth this satire gets. As explained in a follow-up article in 2005 to a viral post by Jeff Jarvis, “Dell lies. Dell sucks.” (having a measurable impact on Dell’s reputation), Jeff explains:

I learned some time ago that you can search Google for any brand, followed by the word “sucks”, to find out just how much ill will is attached.

It is now 2016. I decided to do some investigative journalism to find out how common the problems I encountered with my first ever Dell purchase are. Inspired by Jarvis, the two graphs below depict google hits (corrected for yearly revenue) for each of the major laptop brands. Dell ‘only’ takes second place when querying whether a company sucks, but takes the lead in being the most hated.

dell

Investigating where this hatred comes from requires a more thorough analysis of Dell’s customer support, which I have ample of experience with after three months of continued hardware and software issues using my XPS 15 9550. For a 2142-dollar laptop (€1944) one expects (and pays for) a swift resolution when the device becomes inoperable, as opposed to three months which pass before receiving a functioning laptop (¼th of the warranty). The reality is thus different entirely, and borders on the absurd. The following summary is based on personal anecdotes, but many similar horror-stories are scattered online.

  1. Dell support is slow, really SLOW: the three months it took Dell to get me a full replacement is testimony of this, but even the most basic steps towards this goal take weeks. After Dell agreed to a full replacement, it took 17 days before the new order was placed. This includes seven workdays just to send me the specifications of the new laptop; essentially a copy/paste (which coincidentally they got wrong the first time around).
  2. Dell support does not know, or own, its own products: I spent several hours on the phone to explain that the flashing battery light indicator on the front of the laptop indicated my battery was no longer working, as per their own documentation. Dell support does not have working laptops by hand; they fully rely on debugging your machine remotely.
  3. Dell firmware incapacitates its high-end hardware: the BIOS, drivers, and other firmware (e.g., PremierColor, offering true-to-life colors for their flagship monitors) is some of the most bug-ridden, untested, undocumented, software I have ever encountered. Support simply recommended me to uninstall PremierColor, as well as to revert to an older BIOS version. A BIOS update released to resolve a particular issue with the monitor instead exacerbated it. To date (three updates and several months later) this erroneous fix remains unaddressed, and the common resolution of rolling back to an older BIOS version remains unacknowledged by support.
  4. Dell is unaware, or acts ignorant, about issues reported by users: many users seek support on the Dell community, which unfortunately is almost devoid of Dell employees. Nonetheless, there is more valuable information to be found here (including resolutions such as reverting to the older BIOS version) than by contacting Dell support.
  5. Dell is wasteful: in total UPS delivery has shown up at my doorstep six times, while Dell was fully aware I was not at home or not ready to deliver a package on these specific dates.
  6. Dell pursues the minimum support required: although Dell boasts about its premium support with “[o]nsite service after remote diagnosis within 1-2 business days”, the reality is Dell requires you to spend an entire day on the phone to establish you have a broken battery, several days to ship you a new battery (for which you need to be at home for delivery), expects you to have the necessary torque screwdrivers to replace the battery yourself, and requires you to spend another day at home to await pickup of the old broken battery.
  7. Dell upper management does not take responsibility: Dell tries its very best to keep you entertained with first-line technical support; unfortunate lackeys who are mainly paid to divert your attention away from Dell’s upper management. Dissatisfaction with delays in technical support is redirected to customer care, which in turn redirects you back to technical support. Social media support is a facade put up to give the impression that @DellCares, but in reality is just another middleman pointing back to technical support.

Knowing your rights

If the treatment you are receiving by Dell feels unjust to you, firstly know you are not alone. Dell has a history of lawsuits filed against it by consumers, including a lawsuit against deceptive business practices and failure to provide on-site timely repairs. Dell also “knowingly downplayed hardware defects for millions of computers”, for which it settled. Therefore it is worthwhile reviewing what Dell owes you as part of your purchase.

Review Dell’s terms & conditions (this might differ depending on your point of sale, but the following gives an indication of things to be aware about):

  • Under warranty, Dell has to refund or repair the product, but will not provide any further compensation (e.g., consequential damages or unavailability of the product).
  • Warranty won’t be extended when the product is replaced or repaired.
  • Dell will send parts or provide an engineer service only if it has been established that the problem cannot be solved by recommended troubleshooting procedures (except when you have special needs). (From Dell’s European Collect and Return Service)
  • No warranty is provided for Dell software. Dell only commits to delivering the software regardless of whether it works or not (e.g., PremierColor).

At first sight this paints a grim picture where Dell can provide ‘support’ indefinitely until the warranty runs out, regardless of the state the product is in. I am skeptical of this; it seems highly unlikely Dell could sell you a cardboard box claiming it to be a laptop, ‘fixing’ it for just as long as the warranty lasts. Therefore I am currently pursuing a complaint requesting compensation based on the Consumer Terms of Sale:

(12 A) Either party may terminate this Agreement (i) if the other party commits a material breach which is not cured within 30 days of written notice or (ii) if the other party ceases, or threatens to cease, to carry on business or becomes insolvent.

I claim Dell has failed to deliver me a functioning laptop within 30 days, and gave them notice of this breach. In my specific case, I have not had a ‘laptop’ in the true sense of the word for over three months, since I had no functioning battery requiring the device to remain plugged in to an external power source at all times.

Whether or not you want to pursue your inquiry with Dell to this extent, I can provide you with a couple of concrete tips based on my experience with technical support and my reading of the terms of sale:

  • Take pictures and videos of erroneous behavior, and write down error codes: for straightforward hardware issues with laptops, run Dell’s Preboot System Assessment and note down error codes prior to contacting Dell.
  • Avoid phone support: not only is phone support painstakingly slow (spelling service tags, error codes, and starting all over when redirected), if you ever want to pursue your issues with Dell, you need a written notice of the problems you encountered.
  • If a refund or replacement is taking too long (or is denied), don’t wait too long before filing a complaint through an external party defending your rights: citizens of Canada and the United States can do this for free through Better Business Bureau (BBB). European citizens might have luck finding a similar service through Online Dispute Resolution. Dell seems proud of their BBB statistics, which includes resolutions within a month, but fails to consider that the majority of customers do not know about BBB. Furthermore, Dell seemingly sees no harm in wasting weeks of customers’ time, requiring them to talk to technical support during work hours.
  • Consider the advantage of a full refund over a complete product replacement, in particular when nearing the end of your warranty. Using a full refund the same product can be purchased, effectively renewing your warranty.

How company management can ruin product quality and customer support

In the same vein as Douglas Adams’ quote on technology, the following could be stated about Dell support:

We are stuck with support when what we really need is a product that works.

Dell support is primarily about appearances, not results. To exemplify, the report on how to listen and engage in the digital marketing age commissioned by Dell in 2011, is focused primarily on influencing customer’s perception (think pointless endeavors like @DellCares), not around resolving actual issues reported by customers:

“I believe the greatest benefit has been that our customers who use social media and interact with our efforts see us as a more progressive company because we are using multiple channels for communicating.” — Marketer at enterprise banking company

dellSource: businessinsider.com

Corporate management has put in place a support system which might look good on paper, but fails miserably from the consumer’s perspective. Dell’s hierarchical company structure, comprising several departments each focusing on their respective tasks, each adhering to strict workflows and predefined communication channels, has resulted in a company which can hardly communicate internally, let alone, communicate effectively with customers in a timely manner. As derogative as this sounds, this is based (again) on personal anecdotes collected over the past three months. Although I did attempt to request more detailed information from Dell, they unfortunately did not reply:

  • Communicating technical issues reported by customers resembles a game of Chinese whispers, where front-line support distorts and filters information prior to redirecting it to the engineering department. No direct communication with qualified engineers seems possible, regardless of the amount of technical details the end-user provides.
  • Known issues are not communicated internally (or at least not effectively). For example, widespread public feedback on erroneous firmware releases goes unanswered. Instead, hardware replacements are sent out for issues which have long since been identified to be software-related.
  • Technical support and customer support are two separate departments which do not communicate internally. It is up to the customer to reach out to both, restating the problems they encountered. That said, I have yet to find out what purpose customer support serves, more than redirecting you back to technical support.
  • Internal communication within Dell slows down to a crawl since everybody needs to report to somebody higher up. In the end, nobody takes responsibility and the only way for consumers to get things done (in a timely manner) seems to be by filing a complaint through an external organization.

In short, the best way to get Dell support ironically seems to be to spend as little time as possible talking to Dell support. Instead, once Dell has failed to deliver you a functioning system within 30 days (or sooner), immediately proceed with a complaint through an external organization requesting a full refund or replacement system. Hopefully, through this writing, Dell becomes aware of the shortcomings in their support system, and can start working towards improving customer support so that less drastic measures are required in the future.

Posted on October 12, 2016February 26, 2018Categories About me5 Comments on How to Get (Actual) Dell Support

Why can’t we file Windows bug reports?

A bit of a rant today, for which I apologize in advance.

So far, I have always been quite pleased with Microsoft Connect. As a bug reporting platform for Microsoft, I am under the impression that most issues are given professional consideration, even though they might go unanswered in the long run. The Microsoft Community on the other hand—the only place to submit bug reports concerning the Windows operating system—is a joke. One can not help but feeling treated like an average chum when an underpaid overseas employee ‘answers’ your question by posting a suggestion along the lines of:

giphy

In other words, the Microsoft Community is a help desk, tailoring to problems which can be solved by pointing to documentation, or posting a friendly reminder to update your computer, rather than a bug reporting platform. Perhaps justifiably, I got angry when trying to report on a recent issue with my new XPS 15:

No, the above ‘recommendation’ is not helpful. In fact, although I am certain your intentions are well, it even comes across as offensive. Please let me clarify why, and why you (or rather, Microsoft) might want to reconsider how bug reports for the Windows operating system currently work.

As part of my workday (as a software engineer), I took time off to report on a bug which could help out further development on a product I use every day as part of my work (the Windows operating system). I know pinpointing bugs can be hard, and detailed bug reports are hard to come by. Therefore, I figured sharing my findings could help out anyone working on this product by either making them aware there is a problem, or by pinpointing where the problem in particular might lie. Consider it free labor on my behalf, because I care about the product which makes up my everyday work environment. I do the same whenever I encounter problems with Visual Studio, and every other product I rely on. To this end, I have had great experiences with Microsoft Connect; as a counterexample to the ‘Microsoft Community’ here, I feel the Visual Studio team takes feedback from the community seriously, provides timely feedback, and iteratively improves on the overall product based on community interaction.

Unfortunately, such a ‘community’ seems to be non-existent for Microsoft Windows. As if possessed with magical foresight, I was warned this “community is crap” and I should expect nothing but “crappy unhelpful ‘suggestions’ which after about a week or so are enforced as the accepted answer by moderators”. Please let this sink in for a moment: this is the impression that professionals that try to contribute to this community (and Windows) are left with after posting. Sure, they won’t report on any more bugs; do you believe this means they are solved? More likely, the product or particular feature reported on is abandoned altogether.

This is where you, Sayan, come in. An unfortunate employee of Microsoft, hired to post anything remotely related from the documentation, seemingly assuming any question on this site must be posted by a granny that just received her first tablet computer for her 75th birthday. Unfortunately this also means you are now the one being bombarded with this wall of text, for which I apologize. Feel free to redirect this to whoever ‘higher-up’ believes they are providing good ‘product support’ for Windows.

It is a bit hypocritical to pester people with pop-ups requesting automated bug reports each time a crash occurs, or requesting people to enable application reporting ‘to improve your experience’, but seemingly disregard any detailed feedback people provide voluntarily. Why is there no professional, public, bug reporting site for Windows?

For now I have disabled this “setting[ ] which adds to its beauty”, since I can obviously not expect my newly purchased >2000 dollar laptop to handle it. If you believe this means my question is answered, by all means mark it as such. Alternatively, if this bug report inspires your curiosity and you require more information in order to pinpoint the exact problem, I am more than willing to cooperate. I hope I provided you with sufficient information to run a repro on your end. I already ran two. ‘Helpful’ would be taking this bug report seriously, and you (Microsoft) doing the same.

Why does Microsoft (apparently deliberately) block off bug reports by professionals? They could easily set up Microsoft Connect to welcome Windows bug reports. Even without the developers looking into those issues directly, I feel by merely opening such a site up to the community better support than what currently is provided can be achieved. Cutting off such ‘volunteer’ testers is a big missed opportunity by Microsoft.

Posted on August 2, 2016October 12, 2017Categories Crazy Ideas2 Comments on Why can’t we file Windows bug reports?

Multiplayer Point ‘n Click Adventure Games: Long Overdue

“What are adventure games?”, you might ask. When confronted with this question I usually reply they are interactive movies, where you need to solve puzzles in order for the plot to progress. As you interact with objects and characters within the game, the backstory is revealed. The first few minutes of Resonance provide a good first impression of what a point ‘n click adventure game has to offer: captivating cutscenes, followed by seemingly trivial interactions with the game environment, which regardless reveal a rich underlying story.

resonanceExample of a point ‘n click game (Resonance), where the player needs to interact with objects in the game environment in order to progress the plot.

Adventure games have gone somewhat out of fashion over the years, making way for more fast-paced action-packed video games, like first-person shooters. However, a few—mainly independent—developers have kept the genre alive, and true gems (like Resonance) are still released sporadically. They generally adhere to the core game mechanics (as well as witty dialogues) introduced by the classics, and often still prefer old school pixel artwork over modern graphics.

One overlooked feature of adventure games is they are inherently suitable to be played by multiple players;not true multiplayer, but for the lack of a better word, lets call them potential ‘audience games’. At countless occasions I have invited friends over to kick back in the couch, open a beer, and gaze at a projection or screen as somebody point ‘n clicks his way through the game’s narrative. Similar to watching a movie, but different in that shouting throughout (to point out what to click next) is not only appreciated, but in fact encouraged. 1394641-200px_rubberchickenThere is something suspiciously entertaining about listening to people’s concoctions on what item to combine with the “rubber chicken with a pulley in the middle” in order to finally put it to good use; usually followed by a short silence and a subsequent “Why on earth would you want to do that?”. I dubbed such evenings (and late nights) ‘Adventure Game Nights’, and wanted to report on what works and what does not. In addition, I see opportunities for making adventure games true multiplayer experiences.

After years of hosting such events for uninitiated and seasoned players alike (I once even played a game over Skype), some things became apparent:

  • It is best to pick games with a strong narrative, rather than a shallow story line. In other words, games like Resonance, The Inner World, Still Life, and The Blackwell Legacy appeal to a wider audience than true classics like Monkey Island. Games on the far end of this spectrum, interactive dramas like The Walking Dead, are the perfect gateway drug for people to get hooked on the genre, but unfortunately lack the complexity which make adventure games stand out.
  • Spoken dialogues are essential! It is near impossible to stay focused as a group when everyone needs to read on-screen text at their own leisure and pace.
  • If you cherish your night rest, start early, and pick a game which doesn’t last too long (aim for a maximum of seven hours). Short episodic adventure games offer a solution, although they generally aren’t as captivating (the Blackwell series being the exception). Ideally, in case you have a core group of point ‘n click addicts, you can decide on a longer game and play it over several evenings.
  • Pixel hunting (scrutinous scanning of the screen to find anything clickable) is exacerbated when playing in group; you’ll hear people shouting “Can you click on the red thingy in the bottom corner?”, at times followed by “We already clicked that!”. A quick primer on how to tell whether something is clickable or not in advance is recommended.

The takeaway message for game designers and developers is there might be a broader audience for point ‘n click adventure games than they traditionally anticipate. Rather than solely tailoring adventure games to single player experiences, there is an opportunity to design adventure games with group experiences in mind. Besides changing the overall format so it can be consumed in one sitting (similar to movies), it would be worthwhile experimenting with features which account for multiple players wanting to interact with the game environment simultaneously. To this end designers could leverage the fact that players each carry a powerful computer in their pockets (smartphones) allowing for rich interactions. Some obvious candidates: maintain a history of interactions and dialogues, ‘vote to skip’, suggested puzzle resolutions including a point system, …

The possibilities are endless … A multiplayer point ‘n click game is long overdue!

Posted on December 27, 2015December 27, 2015Categories About me, Crazy Ideas2 Comments on Multiplayer Point ‘n Click Adventure Games: Long Overdue

Non-generic Wrapper instead of Base Class or Interface

A common solution to treating a generic type as non-generic is to implement an interface or make the generic type extend from a non-generic base class. Among other reasons, this allows you to instantiate a collection of generic types. There are varying implementations of this pattern, but they all seem to share this common strategy. In this article I present an alternate approach favoring composition over inheritance which I argue is more appropriate in circumstances where the intent is to break type safety.

To clarify, I will follow Steven Lowe’s argumentation on misuse of inheritanceSemantically, the statement “SomeType<T> is SomeType” is not always true; SomeType<T> is not a proper subtype of SomeType when the base type exposes type-specific bits (as Jon Skeet puts it). In this case the extending type imposes more restrictions than the base type. When there is a need to expose type-specific bits (implying type casts are involved), using inheritance does not follow the Liskov substitution principle (LSP). Regardless, such subtypes seem common. Just consider Microsoft’s List<T> implementing a non-generic IList which to quote Eric Lippert, “is a bit odd, since List for any type other than object does not fulfill the full contract of IList”.

From this it becomes clear there are real-world scenarios where a generic type needs to be accessed in a non-generic way (e.g. during reflection as I argued previously). Type safety is temporarily broken, leaving it is up to the caller to guarantee only the correct types are used. How then to improve on the following common implementation? Note that since the non-generic interface is implemented explicitly, the caller consciously needs to cast to ISomeType, somewhat alleviating the problem of possible misuse.

public interface ISomeType
{
object Value { get; set; }
}
public class SomeType<T> : ISomeType
{
public T Value { get; set; }
// Explicit implementation (cast to ISomeType needed to be used).
object ISomeType.Value
{
get { return this.Value; }
set { this.Value = (T)value; }
}
}

We need a non-generic interface but are given a generic interface, so why not apply the adapter pattern?

An adapter helps two incompatible interfaces to work together. […] Interfaces may be incompatible but the inner functionality should suit the need.

Since the class we are trying to create an adapter for is generic, our adapter implementation needs to be generic too. However, we can expose the non-generic interface which will be used by the client. Just like a usual adapter, the non-generic wrapper contains the adaptee and refers all of the IAdaptor calls to it, casting to T where necessary.

public interface IAdaptor
{
object Value { get; set; }
}
class NonGenericWrapper<T> : IAdaptor
{
private readonly Adaptee<T> _adaptee;
public NonGenericWrapper(Adaptee<T> adaptee)
{
_adaptee = adaptee;
}
public object Value
{
get { return _adaptee.Value; }
set { _adaptee.Value = (T) value; }
}
}

Furthermore, to facilitate the creation of this non-generic wrapper (and in addition hiding its implementation) the wrapper can optionally be initialized from within the adaptee and added as a member. This approach seems similar to how user interface controls in .NET expose the window handle they operate on as a member variable, allowing for unsafe operations when the control class does not offer the required functionality.

public class Adaptee<T>
{
public T Value { get; set; }
public IAdaptor NonGeneric { get; private set; }
public Adaptee()
{
NonGeneric = new NonGenericWrapper<T>(this);
}
}
Pattern which can be used to expose a non-generic interface from within a generic class.Pattern which can be used to expose a non-generic interface from within a generic class.

This approach still requires boiler-plate code to be written and maintained (NonGenericWrapper<T>), but no longer breaks the Liskov substitution principle. Ideally creating non-generic wrappers can be automated, of which I created an early prototypical solution before (not functional in all scenarios). Until then, this solution provides a more robust implementation for complex scenarios using generics, like collections of generic types with varying type parameters on which the same operations need to be performed. This might be the topic of a future post.

Posted on December 15, 2015March 31, 2019Categories .NET, Generics, Software DesignLeave a comment on Non-generic Wrapper instead of Base Class or Interface

Missing Affordances in Windows 10

Before heading out to the shooting range and placing Windows 10 on the target stand, let it be said that Windows 10 is a great improvement over Windows 8 and definitely a step in the right direction. However, this post is not concerned with overall impressions, neither with minor bugs which I’m certain will be ironed out over time. Rather, it sets out to highlight (call it nitpicking if you want) several annoying aspects of the redesigned window manager which I don’t expect to see changed any time soon. At first these seem like minute manageable details. However, when it comes to usability seemingly small issues can become a major annoyance when running into them on a regular basis, especially when they occur during moments of high workload where the window manager is already put under a great amount of stress.

Affordances

There is no need to go into detail about the notion of affordances (and its many interpretations),except for presenting one of the earlier definitions (The Psychology of Everyday ThingsNorman 1988, p.9):

“…the term affordance refers to the perceived and actual properties of the thing, primarily those fundamental properties that determine just how the thing could possibly be used. […] Affordances provide strong clues to the operations of things. Plates are for pushing. Knobs are for turning. Slots are for inserting things into. Balls are for throwing or bouncing. When affordances are taken advantage of, the user knows what to do just by looking: no picture, label, or instruction needed.”

Within user interface (UI) design, this means UI components should thus ‘afford’ clicking, dragging, moving, or any other operation that is supported by presenting the user with clear visual clues.

Window Manager in Windows 10

As Windows evolved, the styling of application windows was designed to be more and more in line with current minimalistic trends in interface design. Styling preferences aside, unfortunately this also introduces changes in the visible affordances to work with windows. In the following figure, notice in particular how the distinction between the title bar, the menu bar, and the window border are removed in subsequent versions of Windows.

Different styling of application windows in (from top to bottom) Windows 7, Windows 8, and Windows 10.

You might wonder, which affordances does this affect? Take a look at the old documentation on how to manipulate windows. In particular, I notice two major changes which bother me.

Resizing windows: 

In Windows 7, there was a visible border above which the mouse pointer changed to a resize icon. There was thus an easy visible target to point to when resizing windows.Resizing windows in Windows 10.

In Windows 10, all borders (except the top border) are invisible. To resize a window you need to hover over the empty area surrounding the window in order for the resize option to appear. Even more challenging is resizing the top right corner. Try figuring out where the resize option appears, as opposed to where the close button lights up! This is complicated immensely since the top border is visible (but overlayed by the close button starting from Windows 8), and the side border is invisible. Hovering over this area is quirky and unpredictable to say the least.

Moving windows:

The title bar can be used to move the application window using the mouse (click and drag). However, in Windows 10 there is no longer a visible separation between the title bar and the menu bar. [UPDATE: Microsoft has since released an update reintroducing colored title bars.] Note that the menu bar cannot be used to drag the window. The pointing task to move a window is thus complicated since there are no visual clues to determine whether a window can be dragged from a given position (not even on hover). However, since it seems the menu bar has been removed for modern Windows applications, this is mainly a problem for classic desktop applications (and will be until they are phased out).

Discussion

In line with the concept of affordances, Microsoft’s user experience checklist for desktop applications states the following:

Never require users to click an object to determine if it is clickable. Users must be able to determine clickability by visual inspection alone.

  • Primary UI (such as commit buttons) must have a static click affordance. Users shouldn’t have to hover to discover primary UI.
  • Secondary UI (such as secondary commands or progressive disclosure controls) can display their click affordance on hover.

For your convenience, the definitions (taken from Microsoft’s glossary) of some of the more obscure concepts listed above:

commit button—A command button used to commit to a task, proceed to the next step in a multi-step task, or cancel a task. […]
primary command—A central action that fulfills the primary purpose of a window. For example, Print is a primary command for a Print dialog box. […]
secondary command—A peripheral action that, while helpful, isn’t essential to the purpose of the window. For example, Find Printer or Install Printer are secondary commands for a Print dialog box. […]
progressive disclosure—A technique of allowing users to display less commonly used information (typically, data, options, or commands) as needed. For example, if more options are sometimes needed, users can expose them in context by clicking a chevron button.

Using this terminology it can thus be argued Microsoft now considers window operations to be ‘secondary commands’, as opposed to ‘primary commands’. Personally I don’t find what in essence are invisible UI components good design, regardless of whether their functionality becomes visible on hover. More importantly, the lack of any visual distinction (even on hover) between the title bar and the menu bar contradicts Microsoft’s own design guidelines. It seems like usability took a backseat to styling, just for the sake of having a ‘flat’ look.

Posted on October 15, 2015September 21, 2018Categories HCI1 Comment on Missing Affordances in Windows 10

Core Values Theory: Hacking Emotions

Underwood: “And you don’t make decisions on emotions?” Tusk: “Decisions based on emotions aren’t decisions at all. They’re instincts, … which can be of value. The rational and the irrational complement each other. Individually they’re far less powerful.”

This exchange between the manipulative protagonist Frank Underwood and billionaire Raymond Tusk in House of Cards highlights a key argument I’ve been raising during discussions on relationships for years—decisions based on emotions aren’t decisions at all. It sets the scene for a rational account on relationships I’ve come to refer to as ‘core values theory’ during many heated conversations late into the night. My own understanding of the concept, based on nothing else but the experience of life, seems to have solidified sufficiently in order to recount it here. Although you are reading a software design blog, don’t expect anything IT related beyond the title “Hacking Emotions” from here on out.

What do you want?

what do you want

Seems like a simple question doesn’t it? “What do you want in life?” The truth though is that the majority of people you ask this question either greet you with a blank stare, or simply state they “just want to be happy”. Try it out for yourself! Next time, rather than discussing the newest episode of Game of Thrones, catch a friend off guard by asking this very question. You might be surprised to discover a general consensus that we are all just pawns in the grand scheme of things; passive bystanders whose roles are limited to either jumping on the passing train, or waiting for the next one. “Carpe Diem” offers a rich perspective on life, make the most out of each moment, but does it exclude glancing at the train schedule so you know where you are headed?

The problem with the blank stare, or solely relying on emotions to decide on a course of action, is you assume a passive role in life. You let your environment decide for you and simply express approval or disapproval. You do not grow as a person—you do not learn what it is that makes you happy or unhappy, what your goal is in life. Ultimately, it is counterproductive; simply pursuing the experience of happiness does not guarantee it in the long run, as you do not gain an understanding of how to maintain it. A case in point being our current materialistic society; quick-fix possessions do not lead to true happiness, on the contrary, it is self-destructive.

In his book “The 7 habits of highly effective people”, Stephen R. Covey’s advocates becoming aware of one’s own internal ‘maps’: where you stand, and where you want to be headed.

Each of us has many, many maps in our head, which can be divided into two main categories: maps of the way things are, or realities, and maps of the way things should be, or values. We interpret everything we experience through these mental maps. We seldom question their accuracy; we’re usually even unaware that we have them. – Stephen R. Covey

Far from being a book I would recommend, it still contains valuable ideas, including the suggestion of being proactive as opposed to reactive in lifeBeing proactive does not simply mean taking matter into your own hands, but also implies identifying that which concerns you, in order to work towards enlarging your influence on that which truly matters to you. It implies a positive stance in life, asking yourself “What can I do?”, rather than “Why does this happen to me?”, the result of which is a rewarding sense of empowerment.

circle-of-influence
Source: http://www.centreforconfidence.co.uk/

Part of what makes us human is we do not have control over our emotions. It is outside of our circle of influence, but most definitely within our circle of concern. How then, to take a proactive stance when emotions are involved?

So, what DO you want?

Relationships, being one of the most fundamental building blocks in life, give rise to the strongest of emotions: love, hate, loneliness, jealousy, … and happiness. While I imagine that most people readily agree with the earlier quote from House of Cards, I have yet to meet anyone that truly applies it in all aspects of life, including relationships. On the contrary, mainstream culture seems to disregard any sense of rationality when it comes to love. Love is impenetrable to human thought, and should be left to destiny. Media does a good job of reinforcing this simplistic view, even in nontraditional “Once upon a time …” movies: “It just happened. […] I just woke up one day and I knew.” – 500 Days of Summer

Unless you aren’t looking for ‘happy ever after’, the problem is relationships (and marriages) also “just happen” to end because “the love is gone”. This common view on relationships is a reactive one.

One of my most controversial viewpoints in life is that relationships should not be dictated by feelings. I look at emotions as a manifestation of an underlying cause which you do have some level of control over. I am not declaring war on feelings here. Feelings (or lack thereof) are useful signposts put up by your body. However, it is your mind’s job to follow the right ones and decide where to go. A proactive approach by no means guarantees a ‘happy ever after’, but more importantly increases your awareness of what you are looking for and allows you to learn from past experiences (what to repeat, and what not to repeat). I do not believe in relationships built solely on top of feelings, and consider them a fruitless endeavor; emotional roller-coasters that make you feel alive, but in the end you still need to exit the theme park.

There is a need to identify who you are, what you want in life, i.e. to identify your identity—your core. As often expressed: “Find yourself before you find love.”

Core Values

In a nutshell, core values theory advocates identifying objective values you expect your partner to have in a relationship, based on your expectations in life. They are testable, meaning, as you get to know someone, you can objectively judge whether or not they fit these criteria. They are ‘core‘ values in the sense that they make up your identity; changing them would imply changing your nature, your personality. Emotions do not come into play. Within Stephen R. Covey’s diagram it could be depicted as an unbendable center you are unwilling to change.

core_values_theory

Ironically, a common response to this is “But how can you be so picky? If one thing on the list doesn’t work out, you give up? You do not open up yourself to new experiences”. The truth though is most people already have a similar list, but just aren’t aware about it. By externalizing and objectifying it for some reason it becomes a faux pas. Their list however is usually longer, transient, more restrictive than the core values I am talking about here, and includes subjective values like “it needs to feel right”, or “it needs to be love at first sight”. The ‘list’ is nothing more than a mental exercise, identifying key aspects in your life on which to make more rational decisions when clouded by emotion, or even in the absence of emotion. If anything, it is more in line with the idiom, “There are plenty of fish in the sea”, recognizing you are not after ‘the one’, but after anyone you can fully respect, and love.

There is some reasoning behind this madness. Firstly, you should not think less of your spouse; a relationship is built on mutual respect. In the case of conflicting core values I argue this is unsustainable. It easily turns into recurrent arguments throughout the relationship, where you want to out-argue the other, causing resentment and loss of respect. Secondly, you should not expect to change or ‘fix’ your partner in a relationship; do not expect the core values of your partner to change, it is outside of your circle of influence. Your energy should be focused elsewhere, where you can actually make a change, and where you can still discover yourself.

This ‘theory’ has some controversial implications. There is nothing wrong with dating someone you have no feelings for, yet are sexually attracted to. Consider it an opportunity to discover your core values. From my own experience I can tell you either feelings will follow, or you learn something new about yourself to take with you into subsequent relationships. But more importantly, a breakup should be indicative of discovering a mismatch in core values, which makes it less of a loss, and more of a learning experience.

Conclusion

This perspective on relationships comes at a price. Most people want to be swept off their feet, where emotions take center stage. I’m a rational person, and prefer placing rationality at the center. Either way, the stage is big enough, and there is room for both. It might seem hard to believe in a long-term relationship with such conflicting perspectives, but luckily, a rational center is not a core value to me. I know I can learn a lot from an emotional counterpart, and I like to think this works both ways.

Posted on May 27, 2015October 11, 2018Categories About me2 Comments on Core Values Theory: Hacking Emotions

Generic TypeConverter for XAML

TypeConverter‘s in WPF are part of the underlying mechanism which allow you to assign values to attributes of complex types within XAML using plain strings. For example, whenever you specify Point‘s.

<LinearGradientBrush StartPoint="0,0" EndPoint="1,1" />

Typically, you specify a TypeConverter for a certain type by applying the TypeConverterAttribute to it.

[TypeConverterAttribute( typeof( PointConverter ) )]
public struct Point : IFormattable

Since attribute arguments cannot use type parameters, this prevents you from specifying a generic TypeConverter for a generic class. I came across this issue while implementing a type converter to support specifying instances of my generic Interval class from XAML. The following is not possible.

// attribute argument cannot use type parameters
[TypeConverter( typeof( IntervalTypeConverter<T, TSize> ) )]
public class Interval<T, TSize>

However, you can write a non-generic TypeConverter which is capable of converting strings to several different target types. When using XAML you can obtain a IDestinationTypeProvider service through the context which is passed to the ConvertFrom method. From here you can retrieve the fully specified target type, including generic type parameters. Through reflection you can then call a Parse method on the specific type to take care of initializing an instance of the desired type. An example for Interval can be found in my library.

public override object ConvertFrom(
    ITypeDescriptorContext context,
    CultureInfo culture,
    object value )
{
    var typeProvider =
      (IDestinationTypeProvider)context.GetService( typeof( IDestinationTypeProvider ) );
    Type targetType = typeProvider.GetDestinationType();

    // ... convert to desired target type using a parsing method

    return base.ConvertFrom( context, culture, value );
}

However, it is important to note that this type provider will only work for XAML, since the IDestinationTypeProvider service is only provided by XAML’s ServiceProviderContext. It is thus not desirable to add this TypeProvider to types which work independent from XAML, like my Interval class. In addition this would require referencing the System.Xaml assembly.

How then to make XAML use this type provider without applying the attribute to the type definition? One option is applying the TypeConverter attribute on a per-property basis.

The per-property type converter technique is particularly useful if you choose to use a property type from Microsoft .NET Framework or from some other library where you cannot control the class definition and cannot apply a TypeConverterAttribute there.

However, this implies a lot of redundancy, having to apply the attribute to every property of that specific type. Using TypeDescriptor.AddAttributes() you can assign a TypeConverter at runtime.

Any subsequent TypeDescriptor.GetConverter() call will then return the converter for the specified type. Unfortunately this does not work for XAML, since XAML does not seem to take component modifications at runtime into account. Therefore, in order for this to work, we need to implement this runtime behavior ourselves. Recall that XAML does load TypeConverter‘s specified in TypeConverterAttribute‘s. We can thus use a special type converter which redirects its implementation to a converter loaded through TypeDescriptor to hook into XAML’s type conversion runtime. I implemented a RedirectTypeConverter which can be used as a base class for this exact purpose. Each of its methods first ensures the converter is initialized using TypeDescriptor, and then redirects the call to this converter. When TypeDescriptor.GetConverter( _type ) returns the redirecting type converter itself, this means no converter was specified using TypeDescriptor, hence no conversion is supported for this type.

protected RedirectTypeConverter( Type type )
{
	_type = type;
}

public override object ConvertFrom(
	ITypeDescriptorContext context,
	CultureInfo culture,
	object value )
{
	InitializeConverter();
	return _converter.ConvertFrom( context, culture, value );
}

public void InitializeConverter()
{
	if ( _converter != null )
	{
		return;
	}

	_converter = TypeDescriptor.GetConverter( _type );
	if ( _converter.GetType() == GetType() )
	{
		string message = string.Format(
		  "Conversion failed. Converter for {0} is missing in TypeDescriptor.", _type );
		throw new InvalidOperationException( message );
	}
}
class RedirectIntervalTypeConverter : RedirectTypeConverter
{
	public RedirectIntervalTypeConverter()
		: base( typeof( Interval<,> ) )
	{
	}
}

Applying this converter using TypeConverterAttribute to generic types thus allows redirecting type conversion to a converter which supports multiple target types in environments which provide information about the target type (like XAML using IDestinationTypeProvider). You only need to add the converter once, and it will be supported for all of your dependency properties using them.

TypeDescriptor.AddAttributes(
  typeof( Interval<,> ),
  new TypeConverterAttribute( typeof( IntervalTypeConverter ) ) );

Posted on February 14, 2015May 12, 2018Categories .NET, Generics, Software Design, WPF, XAML2 Comments on Generic TypeConverter for XAML

Interval: Generic Ranges in C#

There is no doubt about it; out of all the programming languages I ever experimented with, C# has offered me the most streamlined positive development experience so far. It is a modern, ever-evolving language, which now that C# and the whole .NET framework is turning to open source, is guaranteed an even greater future. However, some core constructs commonly available in other languages, like intervals which I introduce an implementation of in this post, are missing. E.g., Ruby has had Ranges for quite some time.

A Range represents an interval—a set of values with a beginning and an end.

Straightforward, but due to the lack of support for generic calculations in C#, a hassle to implement. However, as introduced by Marc Gravell, with some runtime compilation trickery involving expression trees, far from out of reach. I’ve had an Interval class within my core library for quite some time, but just now refactored it to also support more complex intervals, e.g. an interval between two DateTime instances, which thus represents a TimeSpan.

Without further ado, an example of what using this looks like in practice.

// Mockup of a GUI element and mouse position.
var timeBar = new { X = 100, Width = 200 };
int mouseX = 180;

// Find out which date on the time bar the mouse is positioned on,
// assuming it represents whole of 2014.
var timeRepresentation = new Interval<int>( timeBar.X, timeBar.X + timeBar.Width );
DateTime start = new DateTime( 2014, 1, 1 );
DateTime end = new DateTime( 2014, 12, 31 );
var thisYear = new Interval<DateTime, TimeSpan>( start, end );
DateTime hoverOver = timeRepresentation.Map( mouseX, thisYear );

// If the user clicks, zoom in to this position.
double zoomLevel = 0.5;
double zoomInAt = thisYear.GetPercentageFor( hoverOver );
Interval<DateTime, TimeSpan> zoomed = thisYear.Scale( zoomLevel, zoomInAt );

// Iterate over the interval, e.g. draw labels.
zoomed.EveryStepOf( TimeSpan.FromDays( 1 ), d => DrawLabel( d ) );

As you might notice, the timeRepresentation interval has just one generic parameter (Interval<int>), whereas thisYear has two (Interval<DateTime, TimeSpan>). The less generic (one type parameter) class is a simple wrapper around the more generic base type which has two type parameters; the first denotes the type used to represent any position within the range, whereas the second type is used to represent differences between these positions. When these types are the same, the simplified wrapper can be used. Likewise, a TimeInterval wrapper can easily be created if you find Interval to be too verbose.

Worth noting here to understand how it works under the covers is the constructor which sets two public static fields used during operations when conversions to double are needed. Arguably, this could be improved by having a factory creating the intervals and using constructor injection instead.

public TimeInterval( DateTime start, bool isStartIncluded, DateTime end, bool isEndIncluded )
	: base( start, isStartIncluded, end, isEndIncluded )
{
	ConvertDoubleToSize = d => new TimeSpan( (long)Math.Round( d ) );
	ConvertSizeToDouble = s => s.Ticks;
}

Once you start incorporating the notion of an interval in your programming arsenal you will be amazed by the opportunities which present themselves where to use them! Some actual examples within my core library:

To get an impression of the full range of currently supported operations, check out the unit tests.

Posted on November 22, 2014July 11, 2018Categories .NET, Expression Trees, Generics, Software Design1 Comment on Interval: Generic Ranges in C#

From Personal Information Management to Humane Interaction

While discussing file management in the paper on Laevo I presented today at the UIST conference, I conclude …

[…], in essence files are a remnant of the original desktop metaphor. Users are forced to mentally connect window representations to the files they represent. When restoring window configurations users are [unnecessarily] confronted with finding all the related files.

I reflect on this later in the discussion:

[…], raising interesting questions for further research on how window management can be redesigned to outgrow its original purpose. Further research on Laevo is therefore to increasingly move away from files, as their main intent of persisting information could be replaced by persisting window configurations […]

This is in line with an old post of mine on window management, where I concluded:

Taking this to the extreme: assume closing a window would be the same as deleting a file. Would you actually ever have to know about the underlying file system again? Window management and file management could become one and the same thing.

Originally I titled the current post, “From File Management to Time Management”, since one of the conceptual challenges I like to confront myself with is to design for never having to reopen a file again. Rather, I want to support revisiting the full context (including the window representation of the file) which the original file was part of. As a desktop interface, Laevo uses a temporal representation allowing you to revisit any prior, or planned activity in time.

However, after a yet again inspiring talk by Bret Victor on “The Humane Representation of Thought: a trail map for the 21st century” as the closing keynote of the UIST 2014 conference, I realized that just as file management is a remnant of the original desktop metaphor, so is window management. Windows are a side effect of the digital rectangles we’ve grown so accustomed to within our lives. Window representations are mere visual abstractions of richer concepts and ideas which could be expressed in entirely different ways using all of our senses, rather than being restricted to visual and symbolic notations. The reason why we stick to them is because they allow for dynamic (connected) behavior, which is where the tangible all-around-us world falls short. Following the same argument that we should be phasing out file management, so should we attempt to eliminate the need for window management. The more intermediate abstractions we can remove to interact with the concepts and ideas we actually want to address, the better.

Nonetheless, my underlying thesis remains. The temporal (and associated contextual) dimension is a very tangible, humane concept, we should continue to design for.

Posted on October 9, 2014December 23, 2014Categories HCI, Laevo1 Comment on From Personal Information Management to Humane Interaction

Laevo presentation @ UIST 2014 conference

Posted on August 13, 2014September 29, 2014Categories ABC, HCI, LaevoLeave a comment on Laevo presentation @ UIST 2014 conference

Getting started with the Java SignalR SDK

Microsoft has just released a Java SignalR SDK which allows Java and Android clients to access ASP.NET SignalR back ends. The library is open source, and currently it is up to you to build the .jar packages yourself. For your convenience I’ve uploaded my built .jar files. Given that this library as of yet is still fairly undocumented, and I spent quite some time on getting it up and running, I figured I’d provide a short introduction tutorial here. I found the C# SignalR client documentation to be the most useful while figuring out the API as the classes and methods overall seem to correspond. The tests in the GitHub repository are another useful resource. I’ll mainly be focusing on the specific differences in the Java library, and refer you to the original documentation for more elaborate information.

We will create a simple Hub supporting bidirectional communication. A quick and easy way to get a C# back end up and running for the purpose of this tutorial is to self-host a SignalR server in a simple console or WPF application. The following C# code shows a simple hub with one method which can be called by the Java client, SendMessage.

public class MessageHub : Hub
{
	public static event Action<string, string> MessageReceived = delegate { };

	public void SendMessage( string name, string message )
	{
		MessageReceived( name, message );
	}
}

I added a static event handler which can be consumed by the console or WPF front end to display the received message. SendMessage is called from a different thread, so in case you want to update the UI, don’t forget to use a dispatcher!

MessageHub.MessageReceived  += ( name, message ) => _dispatcher.Invoke(
    () => { MessageBox.Content = String.Format( "{0} said {1}", name, message ); } );

Onwards to the client side code! To set up a Java project which can use the SignalR client API, add the ‘signalr-client-sdk.jar’ and ‘gson-2.2.2.jar’ to the project build path. For Android projects the references need to be added differently. Drag the two jars, and the additional ‘signalr-client-sdk-android.jar’ to the libs folder in Eclipse. By doing so they will automatically be added as Android libraries.

As mentioned before, the SignalR Java client follows the same structure as the C# client API, thus setting up a connection is quite similar. However, for Android applications an additional platform component needs to be loaded as shown below; also don’t forget to add internet permission to your manifest file, or you will receive a SocketException when trying to connect.

Platform.loadPlatformComponent( new AndroidPlatformComponent() );
// Change to the IP address and matching port of your SignalR server.
String host = "http://192.168.0.xxx:8080";
HubConnection connection = new HubConnection( host );
HubProxy hub = connection.createHubProxy( "MessageHub" );

This simply configures the connection. Establishing the actual connection is somewhat different than the C# documentation due to limitations of Java. To mimic language support for async in C#, the SignalRFuture class is introduced. Asynchronous operations return an instance of this class, without actually performing any real work yet. What follows is example code of how to start the connection synchronously by calling get() on the SignalRFuture. Don’t forget to cleanly stop() the connection when shutting down the application.

SignalRFuture<Void> awaitConnection = connection.start();
try {
	awaitConnection.get();
} catch (InterruptedException e) {
	// Handle ...
} catch (ExecutionException e) {
	// Handle ...
}

In case your server is up and running, you should now be ready to start listening to and submitting messages. Again, listening to events in C# is more straightforward since it supports lambdas as the C# client API documentation demonstrates.

stockTickerHubProxy.On<Stock>( "UpdateStockPrice", stock => Console.WriteLine(
    "Stock update for {0} new price {1}", stock.Symbol, stock.Price) );

Doing something similar in Java requires elaborate inline anonymous classes, or the creation of a handler class per event you want to listen to. Suppose the server would send a message “context.Clients.All.UpdateStatus( “Online” );”, handling this the ‘C# way’ would like as follows:

hub.on( "UpdateStatus",
    new SubscriptionHandler<String>() {
        @Override
        public void run( String status ) {
           // Since we are updating the UI,
           // we need to use a handler of the UI thread.
           final String fStatus = status;
           handler.post( new Runnable() {
               @Override
               public void run() {
                   statusField.setText( fStatus );
               }
           } );
        }
    }
, String.class );

Therefore, Microsoft has seemingly added a method not available in the C# API to the Java client. Calling hub.subscribe( listener ) where listener is an object implementing corresponding methods for every available incoming event is a much more straightforward way to listen to messages. Under the covers this uses reflection to hook everything up correctly. These methods need to be public!

hub.subscribe( this );
...
public void UpdateStatus( String status )
{
	final String fStatus = status;
	handler.post(new Runnable(){
		@Override
		public void run() {
			statusField.setText( fStatus );
		}});
}

More complex types work as well, as long as it is supported by JSON. I don’t know the specifics, but this will be dependent on the SignalR server and the gson library used by the SignalR Java client. The following code prepares the client to call a new method on the server which you can add to the MessageHub: “public void SendCustomType( CustomType object ) { … }“.

// A simple C# class which can be sent over SignalR.
public class CustomType
{
	public string Name;
	public int Id;
}
// The same type as defined in Java.
public class CustomType
{
	public String Name;
	public int Id;
}

Finally, calling the earlier SendMessage() and the newly added SendCustomType() can be done as follows. As you can see, remote method invocation again returns a SignalRFuture, and a subsequent get() is needed.

try {
    hub.invoke( "SendMessage", "Client", "Hello world!" ).get();
    hub.invoke( "SendCustomType",
        new CustomType() {{ Name = "Universe"; Id = 42; }} ).get();
} catch (InterruptedException e) {
	// Handle ...
} catch (ExecutionException e) {
	// Handle ...
}

Similarly, you can simply pass custom objects from the server to the client by adding the custom type as a method parameter: “public void SomeMethod( CustomType bleh ) { … }

Posted on March 20, 2014May 12, 2018Categories Distributed Computing, Java, SignalR31 Comments on Getting started with the Java SignalR SDK

Generic Attributes in C#

As awesome as C# is, once you want to do some more advanced stuff with attributes, you quickly run into several limitations. There is even a Microsoft Connect entry on this issue.

  • Attributes can’t be generic, since a generic type cannot derive from ‘Attribute’.
  • An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.

Using TypeDescriptor and a whole bunch of custom code these limitations can be overcome. In this post I will describe an easier straightforward way by which to create something similar to generic attributes, ignoring the second issue for now. In future posts I will discuss how and where these attributes can be used for something I previously called attribute metabehavior.

The idea is quite straightforward; although attributes can’t be generic, nothing prevents you from adding generic instances to them. These instances can later be extracted at run time using reflection. The trick of course is initializing the generic instance. Once you know the Activator class can create instances by knowing their Type definition, the solution becomes self-evident. By simply passing the generic type as an argument to the attribute, instance creation can be delegated to Activator. Optional constructor arguments can also be passed as attribute arguments.

public class BehaviorAttribute : Attribute
{
	/// <summary>
	///   The dynamically created instance of the type passed to the constructor.
	/// </summary>
	public object DynamicInstance { get; private set; }

	/// <summary>
	///   Create a new attribute and initialize a certain type.
	/// </summary>
	/// <param name = "dynamicType">The type to initialize.</param>
	/// <param name = "constructorArguments">
	///   The arguments to pass to the constructor of the type.
	/// </param>
	public BehaviorAttribute(
		Type dynamicType,
		params object[] constructorArguments )
	{
		DynamicInstance =
			Activator.CreateInstance( dynamicType, constructorArguments );
	}
}

This attribute can then be be applied as follows:

class Answer<T>
{
	public T Value;

	public Answer( T value )
	{
		Value = value;
	}
}

[BehaviorAttribute( typeof( Answer<int> ), 42 )]
class TheWorld {}

Using ordinary reflection, the instance can be extracted.

Type type = typeof( TheWorld );
var behavior = (BehaviorAttribute)type
    .GetCustomAttributes( typeof( BehaviorAttribute ), false ).First());
var genericInstance = (Answer<int>)behavior.DynamicInstance;
int answer = genericInstance.Value;

What follows is up to you, how will you use this? I’ll describe a few advanced use cases in subsequent posts.

Posted on October 19, 2013May 8, 2018Categories .NET, Generics9 Comments on Generic Attributes in C#

Start of Laevo user studies

timeline_smaller

As part of my PhD I created Laevo, an alternate way by which work can be organized under Windows 7/8, and now it needs to be evaluated by several participants during a 2 week study. Laevo augments your current windows environment with a couple of extra options to organize your daily activities. The goal is you attempt to use these features during a full 2 week period, while continuing doing the activities you ordinarily do. How much you want to use the system is entirely up to you, but ideally you have it running during the full 2 weeks. You can either exit Leavo at the end of each day, or use Window’s sleep and hibernate functionality.

You would help me out greatly by installing Laevo, and trying it out. You can start the 2 week period of using it either on Monday the 5th, 12th or 19th of August. At the end of each day please give some feedback on your experiences with the system that day by shortly answering a set of questions. This shouldn’t take longer than 5 minutes/day. You can compile the feedback in one document and send it to me at the end of the 2 weeks (sjeu AT itu.dk).

  1. Why was or wasn’t Laevo useful for you today? At a minimum state one positive and one negative points, but open feedback is encouraged.
  2. What activities have you done today that weren’t represented in Laevo at some point?
  3. What was/were your main activities today? In case they were represented in Laevo, where did they originate from (self-initiated, to-do item, email to-do, other)?
  4. Have you scheduled any activities today? Did you also plan them on the time line? Why (not)?
  5. Did you use Leavo’s to-do list today? Why (not)? How?
  6. Did you use Laevo’s Activity Context library today to store or retrieve files?
  7. Were there occasions where you considered creating an activity or to-do item but eventually decided not to? If so, why?
  8. Please have a look at your time line. Does the overview of today reflect the actual activities you did today? Why (not)?

You can contact me for any information on sjeu AT itu.dk, but I will be out of office until the 11th of August.

When the application crashes there should be a “log.txt” file available in “C:\Users\<username>\Documents\Laevo”. Please email this to me. In case you continue encountering problems which severely hinder you from your work, please report them so I can try sending you a new version of Laevo to resolve the issues.

Please forward this to any participants which might be interested. Thank you for helping me out!

Posted on August 4, 2013August 26, 2013Categories ABC, HCI, LaevoLeave a comment on Start of Laevo user studies

Call for Laevo user study participants

Custom

With great pleasure I can finally announce the first public installer of Laevo, a project I started out working on as part of my master’s thesis, and am now continuing working on as part of my PhD. In short, it allows you to organize your work in new ways which Windows traditionally doesn’t offer you. In case you spend most time of the day working on your PC you might be interested in trying it out. The project has come a long way and is finally ready for the greater public, hence I am looking forward to your input on what you think about the system. You would help me out greatly by installing Laevo, trying it out for one to two weeks, and giving feedback on it afterwards. Please send me an email (sjeu at itu.dk) or simply contact me in case you are interested in participating.

You can download the latest version (v0.1.3) here. This is a more recent version than the one I linked to on twitter earlier this week. In case you already installed the previous version, simply uninstall the old version and install the new one. Your data and settings will be saved. To get you started I strongly advise you to quickly read through the manual so you know about the functionality offered.

Posted on July 17, 2013August 3, 2013Categories ABC, HCI, Laevo4 Comments on Call for Laevo user study participants


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK