MVVM: When MVC isn’t Enough

19. December, 2012

MVC is a great concept to create user interfaces in a sane way but it has its drawbacks. Let’s imagine a simple case: A login service.

What do we need? User name and password.

So the model looks like this:


String login;
byte[] password;

Is that enough to create the view? Yes.

But where do we put the code to encode and check the password? Is that part of the model, the view or the controller?

It’s not really part of the model because the data model doesn’t care how we encode passwords. For the model, a password is just an byte array. That’s even enough to check passwords – to compare two byte arrays, you don’t need to know how they were created.

Is it part of the view? The view should just display a “*” per byte, it doesn’t do anything with passwords.

Which means the encoding method goes into the controller. This isn’t necessarily the right place – we’ve just run out of options.

Users can log into our service, now. But how do they register?

For registering, you should allow the user to repeat the password to avoid  typos. The view is simple enough but where do we store the repeated password?

Do we really want to extend our data model for this case?

Also, we need a second password check which works with plain passwords. But the model only stores encrypted passwords. We could convert both passwords into one unencrypted string and store both into the data model for the typo check and encrypt them before saving the data in a database. And we could make the check work for both encrypted and unencrypted passwords and if we make a mistake, unprotected password end up in the database …

So this is where MVC fails: Editors often need additional code and data to edit the plain data model. I could put all this into the view but that would violate the separation of concerns: A view displays a model, it doesn’t contain one. Ideally, views and controllers should have no state at all.

This is what MVVM solves: Instead of using the “real” plain data model, each UI component has a “view model” which replaces the data model. This model contains all the information that the view needs and all special “business logic” where the business is “editing the data.”

The view model knows how to talk to the data model and we have again separated concerns. When the controller is started, it converts the data model into a view model. And when the controller saves the data, it tells the view model to update the data model.

This approach solves a whole host of problems:

  • You can easily split complex data from the model into several, independent UI elements.
  • You have a place where you can put business logic shared by view and controller
  • Needs of the view and the controller don’t leak into your data model
  • The data model doesn’t change while the editor is active.

The last point is important: With the MVC model, it’s hard to share the same model between threads and users because the controller could change parts of the model at any time. It’s often impossible to do these changes in an atomic way, so other controllers might see an invalid state.

With MVVM, you can create locks that protect the model as long as the view model updates the data model. The locks will only be necessary in these update methods and nowhere else. That means you will have a few distinct places where you will need locks and suddenly, the impossible becomes feasible.


Designing a Garbage Bin

17. December, 2012

Many of us have noticed that designing software is surprisingly hard but many don’t know why that is. The simple answer: Design is the art to balance contradicting goals.

Not convinced?

Let’s design a public garbage bin together.

What do we want?

  1. Big enough so it never spills
  2. Easy to clean
  3. Nice to look at
  4. Robust enough to withstand riots
  5. Soft enough to cushion the impact of car
  6. Long lifetime
  7. Cheap

It’s easy to see that “cheap” contradicts almost anything else. “Nice to look at” means an (expensive) artist has to build the form. Big garbage bins ain’t cheap. Easy to clean and robust mean high quality materials for hinges and locks. Easy to clean and long lifetime involve expensive surface materials and finishing.

It should be easy to lift for the cleaning crew but not for rioters. When a car hits it, the bin should give way. So these contradict each other as well.

Still not convinced? Look at my elevator example.


Java Toolbox

9. November, 2012

 posted an article with some tools that you should know about when developing Java code: “A Software Craftsman’s Toolbox: Lightweight Java libraries that make life easier.

Along the same lines, Jeeeyul came up with an idea to make

System.out.println( "Hello World." );

produce this output:

(MyHelloWorld.java:10) : Hello World.

Just takes 34 lines of code: “Make System.out.println() Rocks!


Comfortable Access to Config Options in Python

12. October, 2012

I always felt that Python’s ConfigParser API could be better. I like to access my config options like this:

    self.config.option

To solve this, I wrote ConfigProvider which can copy options from ConfigParser into a Python instance:

class ConfigProvider:
    __doc__ = 'Interface which can copy values from ConfigParser into a config object'
    
    def __init__(self, cfg):
        self.cfg = cfg
    
    def update(self, section, cfg):
        __doc__ = 'Updates values in cfg with values from ConfigParser'
        
        for name, value in inspect.getmembers(cfg):
            if name[0:2] == '__' or inspect.ismethod(value):
                continue
            
            #print name
            if self.cfg.has_option(section, name):
                setattr(cfg, name, self.cfg.get(section, name))

The magic happens in update() which examines the config object that you pass in and which copies the values from the external ConfigParser into it.

The gist “Comfortable config access with Python” contains the whole code and a demo.


TNBT: Documentation Sucks

11. October, 2012

Documentation is the unloved step-mother of software development: Nobody likes it.

On the writing side, documentation is either considered a waste of time:

  • I could write code in that time
  • It won’t be valid anymore after the code changes tomorrow, anyway
  • There is no way to make sure you can trust documentation
  • Stringing sentences is hard work, especially when you want to make them easy to read, understand and interesting to follow.
  • It’s hard to connect code samples with documentation
  • If I describe too many details, readers will be bored. If I omit too many, they will be confused. There is no way to know which level of detail is good.

On the reading side, it’s a waste of time:

  • I need to solve a problem, I don’t have time to search in a huge dump of text
  • If the author doesn’t trust the documentation, how can I?
  • It will contain too many details that I already know and omit too many facts that I need to understand what is going on.

The core of the issue is that documentation and code are two different things. Documentation is, by nature, abstract. It’s at least one step removed from the solution.

Does it have to be that way?

I hope, with new technologies like Xtext or JetBrains’ Meta Programming System, we will eventually be able to turn documentation into code.

So instead of writing hundreds of lines of code to open a window, give it a size, make sure it remembers its size and position, etc., we could write:

Allow the user to edit a Customer object which has properties from foaf:Person and one or more addresses.

Users can search for Customer objects by any of the name fields.

Note that the links are part of the documentation and the code; the underlying code generator should follow them and examine the code/documentation on the other side.

Related Articles:


Better Maven Deploy

9. October, 2012

mvn deploy has two major issues:

  1. If the project has several modules and the build fails in the middle, you will end up with a repository that is a mix of old and new modules.
  2. The POM must have the correct values in the distributionManagement element.

The former can break builds for your colleagues, the latter means you have to edit the POM file. Not a big deal – unless the POM file comes from an external source, say, an OSS project. If you edit it, you need to maintain the changes. But it gets ugly when your changes are committed to the external project.

The following script solves both problems. In a nutshell, it copies the POM, removes any existing distributionManagement elements, adds the ones you want and then builds using the new, temporary POM. If the build succeeds, the temporary POM is deleted.

The build itself is split into two steps. The first step does a local build, the second build skips tests and only uploads the results. It does run the compilers again but since the code was already built a few seconds ago, this shouldn’t be an issue.

Shell script.


Enums With More Than One Name

8. October, 2012

In Java, you sometimes encounter places where you need an enum with more than one name (or key). Here is the pattern that I use:

import java.util.HashMap;
import java.util.Map;

enum X {
    // "A" is the name of the enum, "a" is the second name/key.
    A("a"), B("b");

    private final static Map<String,X> MAP = new HashMap<String,X>();
    static {
        for( X elem: X.values() ) {
            if( null != MAP.put( elem.getValue(), elem ) ) {
                throw new IllegalArgumentException( "Duplicate value " + elem.getValue() );
            }
        }
    }

    private final String value;

    private X(String value) { this.value = value; }
    public String getValue() { return value; }

    // You may want to throw an error here if the map doesn't contain the key
    public static X byValue( String value ) { return MAP.get( value ); } 
}

Things to note:

  1. There are additional parameters in () after the enum name.
  2. You need a custom constructor which accepts the additional parameters. Like other Java classes, you can have as many constructors as you need.
  3. I’m filling the static map from a static block inside of the enum declaration. Looks odd but works. Java will first create all instances and then invoke the static code in my custom enum.
  4. You can look up enum values by using the static method byValue(). The name is not very good (it’s easy to get confused with enum‘s valueOf()). When the field is called code, I use byCode(). So in real life, it will be less confusing.

Xtend for Java Developers

2. October, 2012

There are a couple of common pitfalls when a Java developer starts using Xtend.

Java Xtend Description
String.class typeof(String) Get the class instance of a type
Long.MAX_VALUE Long::MAX_VALUE Accessing static fields
Foo.Bar Foo$Bar Accessing inner classes

Example: org.slf4j logging

private Logger log = LoggerFactory.getLogger(Foo.class)    // Java

        Logger log = LoggerFactory::getLogger(typeof(Foo)) // Xtend

Also, the .. or upTo operator has a severe bug. The code for i: 0..list.size won’t work as expected. First of all, it will iterate once too many.

The obvious fix for i: 0..(list.size-1) doesn’t work when the list is empty because it will iterate twice (0, -1) and it won’t iterate at all if the list has a single element.

Use .. only with constant operands (i.e. 1..5 is OK, list.size..0 isn’t). If you need to iterate over a range [start … end), use this gist instead.


New Font by Adobe: Source Code Pro

27. September, 2012

Some of us know that software not only has to work, it also should be beautiful.

One important aspect here is the font. How does this look:

1Il|iO0oB8

If you can’t tell for sure which character is which, you probably don’t use a good font.

Paul D. Hunt, a font designer working for Adobe, finally spent some time to make life for his fellow developer easier:

As a font developer, I spend a good chunk of each day coding in a text editor and reading output messages from a terminal window, so I can appreciate the importance of a good monospaced font. (source)

If you’re interested in font design, his blog post contains some of the ideas and decisions he made when designing the font. Btw, the text above looks like this in Source Code Pro:

Some potentially confusable characters

You can download the font on Sourceforge or look at the source at GitHub.


Targeted Spamming via Facebook

26. September, 2012

 

In the past few weeks, I started getting mails from friends which just contain a link:

hey, Aaron

    http://some-dubious-link/a/b/c/

9/25/2012 12:34:56 PM

Turns out that someone is analyzing my Facebook account and sends me mails using names from my friends list.

If you get such a mail, don’t click on the link. It probably points to a page which infects your computer with a virus.

Right now, these mails are pretty easy to identify as fake because the email address is wrong. But you should know that the sender address in emails is just a text; neither the sending nor the receiving computer will check what is in there. A spammer can write anything into that field. If the scheme starts to fail too often, I expect to see “better” email addresses.

This means as a receiver, you should never click on links in emails. As a sender, you should never share links by email.