Saturday, November 17, 2012

NSLog Format Specifiers

These formatters are used with NSLog, and also Logging.h mentioned in a previous post. Take a look.

%d, %isigned int
%uunsigned int
%ffloat or double
%efloat or double in standard form or scientific notation
%xhex int
%Xhex int
%ooctal int
%ccharacter
%Cunichar
%@object

Examples:

(1)
int num=9;
NSLog(@"The value of the integer is %i", num);

Result: The value of the integer is 9



(2)
NSDate *today= [NSDate date];
NSLog(@"the date is %@",today);

Result:  the date is 2012-11-17 01:15:00 +0000

Monday, November 12, 2012

How to add an existing Xcode project to Source control

If you create a project in Xcode and later you want to add it to source control then you need to run a couple of command line controls. But it's easy.

1. Quit Xcode.

2. Open terminal and navigate to your directory. Using something like:
cd Developer/myprojectname
There is a file in Xcode that we do not want to add to source control. This records the Xcode environment state. Because we're doing this adding manually, we have to tell Git manually to ignore it. If we had told Xcode to add the project to source control when we created the project it would have ignored this file automatically.

3. Type the find command to find the file file.
find .
The file we are looking for is UserInterfaceState.xcuserstate

4. Place the file name into an exclude file.

echo myproject.xcodeproj/project.xcworkspace/xcuserdata/John.xcuserdatad/UserInterfaceState.xcuserstate >.gitignore

This will create the file gitignore

5. Initialise Git
git  init
Did you get an error? (See bottom of post)

6. Add the files
git add .

7. Commit the files to the repository

git commit -m "write a short comment here"



Problem with Git?
Are you getting the command not found?

bash: git: command not found
This can be solved by:

  1. Open Xcode
  2. Open Preferences
  3. Chose the Downloads tab, choose components
  4. Instal the Command line tools.
Bob's your uncle.



Saturday, November 10, 2012

How & why incentives do not work


Firstly, if you have 18 minutes to spare, then rather than read this, go and watch Dan Pink's video at TED.com. It really is food for thought.


In short, Dan says that proof exists to support the statement that incentives - the carrot or the sharp stick - do not work.
They do not work in many types of work. Not all, but most that we are likely to deal with.

But, and here's an interesting thing. Not only do they not work, they actually do harm. They give the opposite of the desired effect.


The candle problem
Dan starts by looking at the the candle problem.

If you give people the following: a candle, a box of pins and some matches, and you then ask them to fix the candle to the wall so that the lit candle's wax doesn't drip onto the table. How could this be done? and do they perform?




(A clue. To solve this you over come functional fixedness)

Do incentives work
If you incentivise this task, i.e. if you give a group incentives such as, 'if you're the fastest you'll get £50, if you're in the top 10% you'll get £20'. Then you get interesting results. (these £ values were not the ones used in the quoted experiement but I have adjusted for inflation :).  I'm sure the experiment holds)

The team that were given the financial incentives actually did a lot worse, and this is not a freak of this experiment or of this challenge. There are many more examples and experiments that back this up.

The solution to the candle problem?
It is at the bottom of the blog page.


Restate the problem and...
If you restate the problem as in this diagram and still give incentives, then the incentives make a significant difference. They have the desired effect and deliver an improvement in performance.

I think it's clear to see why when you realise the pins are no longer in the tray that was being used to collect them together.




So incentives appear to work for mechanistic, well defined tasks, but not for jobs that require creative thought. If the work is clearly defined and has an easy to see goal then the incentives work. It is almost as if the value of the incentive narrows the focus through a fear of losing the sweet carrot or money, or fear of meeting the pointy end of the stick.

This kind of left-brain work seems ideally suited to incentives but more and more our work is right-brain - creative, inventive.

A couple of quotes:
As long as the task involved only mechanical skill, bonuses worked as they would be expected: the higher the pay , the better the performance. 
But once the task called for "even rudimentary cognitive skill," a larger reward "led to poorer performance."

D. Ariely, U. Gneezy, G. Lowenstein, & N. Mazar, Federal Reserve Bank of Boston Working Paper No. 05-11, July 2005; NY Times, 20 Nov. 08



Autonomy - Mastery - Purpose
If we can no longer motivate using incentives or threats then what can motivates?
Dan suggests:
Autonomy - the urge to direct our own lives
Mastery - to get better and better at something
Purpose - the urge to be a art of something bigger than ourselves.


Traditional management
Management is a recent concept and it did not emanate from nature. It's an invention from mankind. It's ideal for compliance but it does not mean that it's always right. Maybe, at times, we need to rethink the management styles based on the three themes above.

I currently work in a very traditional environment and have found myself in a team of dispirited developers that distrust management, distrust each other, and are distrusted by management. I'm stuck in the middle as a Development Manager. My approach has been to apply two themes to improve things. One, traditional management - that is, clearly manage the tasks, the projects and the list of work. Senior management folk like that and the developers do too. The estimates are still off a bit but we can work on that.
The other theme is non-traditional. I encourage Mastery and Autonomy in the way I treat developer tasks and collaboration. I expand their range of influence and never pass on their successes as my own up the traditional management line. I motivate by letting them motivate themselves.
Warning. Senior management don't get this. Not mine anyway and that's probably why my days will be numbered. But I'll keep on trying. It's the only right way.




The answer.




Friday, November 9, 2012

Pages 4.2 not linking to iCloud - This is not your primary account

I have Pages on my iPad and Mac mini, and also my iMac. But I have recently upgraded the OS on my Mac Book Pro to Mountain Lion and Pages and Numbers don't connect to iCloud.

I checked the version of Pages - 4.2. So that should be ok.
I tried to update it from App store and of course it said don't be silly.

I went to iCloud in System Preferences and signed in. All I saw was the oportunity to select Mail, Contacts, Calendars and Notes. What I really wanted was shown below.

The iCloud form told me that I was not logged in with my primary account. But I was.



The task is to delete the iCloud account from the Preferences and log in again.

To do this un-tick the Contacts, Calendars and Notes. Try to untick Mail but it might complain.
If it does complain go to mail and remove the mail account.
Then go to Preferences again and untick the Mail. Now remove the iCloud account by using the "-".

Now add your iCloud account and ensure you tick "Documents & Data".

Now go to Pages etc and when you start it should let you look at your iclid files.

Just the ticket.

Friday, October 26, 2012

Create an ISO image of a DVD on Mac OS X

It seems to be a bit more difficult to create ISO images on the recent Mac Mountain Lion. Though I never did it before, it seems that an option to create an ISO was a part of the Disk Utiltiy application. Now though you can only make a .dmg.

You can try to copy all the files from a DVD to a folder and use Disk Utility to create an ISO but you'll have problems with extended attributes if copying a Mac OS X Install disc.

This works ok.

1. Open Terminal.

2. Now find where the DVD is mounted.


Type :
drutil status
This will tell us where the drive is mounted. It will look something like:

John-Mac-mini:Desktop John$ drutil status Vendor   Product           Rev  HL-DT-ST DVDRW  GA32N      KC12
           Type: DVD-ROM              Name: /dev/disk1       Sessions: 1                  Tracks: 1    Overwritable:   00:00:00         blocks:        0 /   0.00MB /   0.00MiB     Space Free:   00:00:00         blocks:        0 /   0.00MB /   0.00MiB     Space Used:  843:15:63         blocks:  3794688 /   7.77GB /   7.24GiB    Writability:       Book Type: DVD-ROM (v1)

We can check using: mount

John-Mac-mini:Desktop John$ mount/dev/disk0s2 on / (hfs, local, journaled)devfs on /dev (devfs, local, nobrowse)map -hosts on /net (autofs, nosuid, automounted, nobrowse)map auto_home on /home (autofs, automounted, nobrowse)/dev/disk2s3 on /Volumes/My Book Time Machine (hfs, local, nodev, nosuid, journaled)/dev/disk1s3 on /Volumes/Mac OS X Install DVD (hfs, local, nodev, nosuid, read-only, noowners)

I notice that in my example mount gave:
/dev/disk1s3
and drutil gave:
 /dev/disk1

You need to unmount the DVD drive by running: umount
This will need to be run as super user (sudo) and this will require your password.

sudo umount /dev/disk1
Password:


You now need to run the dd command:
sudo dd if=/dev/disk1s3 of="my file name.iso"















Copy DVD contents to a folder on OSX using Terminal

Open, Terminal

Type  
df
This will give us the device names.

You will see something like:

/dev/disk1s3    13158216   12992304    165912    99%   1624036    20739   99%   /Volumes/My DVD stuff

You can highlight and copy the DVD information  using cmd C.

Copy your equivalent to this: 
/Volumes/My DVD stuff

Then navigate to the target folder (using the cd command) such as:

cd /Users/John/Desktop/my target folder/

Now we can do the copying from the DVD to where we are.

cp -rpv "/Volumes/My DVD stuff" ./
If you want it to run quietly, then leave of the v option for verbose. Then if it will only report errors to the screen.

cp -rp


Job done.



Wednesday, October 24, 2012

How to instal Remote disc on an older mac

If like me you have an old Macbook pro and the optical drive has decided to lay down and die, then it's a bit of a problem upgrading the OS if you don't have the App Store.

I wanted to upgrade to Mountain Lion but the version was pre-Snow Leopard (I should have noted the version as I'm writing about it!).

Trouble is, to get from ye-olde version to Mountian Lion I needed to get the App Store, and to do that I need Snow Leopard, which comes on a DVD and will then let me get to the App store. Easy.

I needed to place the Snow Leopard DVD into the drive on my iMac (Mountain Lion), share the DVD drive by selecting Sharing in System Properties.

Then, I needed Remote disc on the old Macbook Pro. Problem is, it's only on newer kit. Well actually it's not. It's actually there, I just needed to configure it.

Open terminal on the Macbook and type:

defaults write com.apple.NetworkBrowser EnableODiskBrowsing -bool true
then

defaults write com.apple.NetworkBrowser ODSSupported -bool true
Then restart the Macbook and in the Finder's sidebar there will be a disc icon. Click on it and off you go.

You can install from there. Fantastic I thought.

I went into System Preferences, Energy Saving, on both computers and set the computers not to go to sleep.

Installing across wifi took 3.5 hours then failed.

I tried again. It failed after the remote drive became unavailable.

I got a router and two cables and networked them together so it would be quicker but now the macbook tells me the HD is damaged.

I ran disk utility on it all it says it's fine so the media is ok.

Pooh.

Remote Disc was working, but I couldn't upgrade the OS with it.

In the end I,
1. Created an ISO of Snow Leopard
2. Formatted a memory stick (journaled)
3. Put the ISO on the stick and installed from there.

It worked - not entirely though. An issue with Spotlight remains that I haven't had time to resolve.
Oh - and my only Macbook is too old for Mountain Lion, or Lion. :)

Monday, September 3, 2012

Javascript functions

(A) The standard way - the Function Definition

This is the std. way a function could be written in Javascript. It's easily recognisable from major programming languages: it has the function keyword, a name, parameters, a function body delimited by curly-braces, and a return.
It is also useful to know, or it might just be interesting, that functions are Objects.

function square(x) {
    return x * x;
};


Invoked by:
square(5);

(B) Standard function declaration assigned to a variable - the Function Expression

This next example assigns the function to a variable. The interesting here is that you can not invoke the function by the function name. You must invoke it by the variable name.


var squareFunction = function square(x) {
    return x * x;
};


Invoked by:
squareFunction(5);


Anonymous function

This next one is the Anonymous function. It is a simplification of the previous.
The function name is omitted. It is usual to use this anonymous version as it is less verbose, however the previous one can be useful when debugging as the function name will appear in the call stack.


var squareFunction = function (x) {
    return x * x;
};

Why the two ways and which one should I use

There are two benefits to using the Function Expression (assigning the function to a var)
1. One is it keeps the function name to the local scope and doesn't pollute the global namespace.
2. The name will show up in debuggers.


The immediately invoked anonymous function

The difference is
1. Wrap the function in brackets
2. Immediately invoke the function afterwards



( function (x) {
    return x * x;
})(numberToSquare);

This is used a lot in jQuery.

Dmitry's

Go and read Dmitry's blog on functions for the whole story. Now here's a bloke who knows his stuff. http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/#question-about-surrounding-parentheses

Saturday, July 28, 2012

Virtual box fails after OSX Mountain Lion upgrade

I just knew it would be trouble.

The lengthy upgrade to OSX 10.8 upset VirtualBox.
This is what greeted me on the restart.


So now what.
I knew I had an old version (4.1.4). And I knew deep down that upgrading wouldn't help.



I needn't have been so pessimistic because all I needed to do, was use the uninstall script.
Unlike other apps where an uninstall can be simply moving the app to the trash, with VirtualBox you run the script in the bottom right hand corner of the instal windows.



You might have a problem with the script with some errors in the terminal wind - caused by open files or some such. The easiest thing to do is restart OSX and don't run an VirtualBox versions. Then run the Uninstall tool. Then go and install VirtualBox.
Helpful?

Simplifying the solution

When solving something, designing a solution or building an interface. We should start by remembering Occam's razor. This is succinctly stated by Einstein as:

"Everything should be made as simple as possible, but not simpler." - Albert Einstein

But this is a bit elegant, sexy and abstract perhaps. Steve Jobs wrote the following that is a bit more concrete and :

“When you first start off trying to solve a problem, the first solutions you come up with are very complex, and most people stop there. But if you keep going, and live with the problem and peel more layers of the onion off, you can often times arrive at some very elegant and simple solutions. Most people just don’t put in the time or energy to get there.” - Steve Jobs


What is really helpful to those in the team that want the little addition to improve the solution.

“Sometimes a design decision is what you don’t put in, as opposed to what you put in.”- John Gruber

I was prompted to write this blog following a chat I had with a colleague and reading Shawn Blanc's posting http://shawnblanc.net/2012/07/mountain-lion-and-the-simplification-of-os-x/

Thursday, July 26, 2012

Question the norm in the dev team

 Apologies but it's a bit pompous of me using Einstein in the same post as my work, but here goes.

"Concepts that have proven useful in ordering things easily achieve such authority over us that we forget their earthly origins and accept them as unalterable givens." - Albert Einstein. 


It seems to me that software development generates a lot of acronyms and methods all providing the definitive in wisdom. As you get longer in the tooth you get cynical and question these saviours. Einstein was on a totally different level of course but the principle is worth thinking about in the development team.


Wednesday, July 4, 2012

First Order Logic

This stuff is great fun.
There are a number of differeing styles of notation and my logic, how I still think, started in electronics and then early Computer Science lessons so I might be a bit wrong in places. It's something I enjoy and I hope to apply it more.

A Predicate

A predicate is a statement that is TRUE or FALSE
An example could be:
A dog is a mammal.
A dog is a fish.
Both of the above are predicates but the second one is false.

We can write those in psudo computer speak as:
IsaMammal(dog)
IsaFish(dog)
Both of the above would return a Boolean.

Symbols we use all the time


→ - Implies

¬ - Not

These two are quantifiers, for obvious reasons 
∃ - There exists. This means that there is one or more, there is at least one value that makes the predicate true.
∀- For all




Inference

This stuff is basic, but interesting if you've not seen it before.
(1) ¬(a and b) = ¬a or ¬b
(2) ¬(a or b) = ¬a and ¬b

(1) Not (a and b), is the same as (not a) or (not b)
(2) Not(a or b) is the same as saying,  (not a) and (not b)

In electronics we used to use "+" for OR, "." for AND and a bar across the letter for NOT.
_   _
a + b  Not a OR Not b  

_____
a + b Not (a or b)

We used to say "break the bar change the sign" to remember the following:
 ___   _ _
 a.b = a+b
 ___   _ _
 a+b = a.b

Not sure if that's of any use but it's true none the less.  DeMorgan's Theorem.

We can use them thus:

If someone says that something is ¬(a and b) 
then to prove them wrong, we have to prove  ¬a or it is ¬b




Two more

(1) This is nearly, or pretty obvious I think: 

If we know that a implies b,
a→b and we know a, then we also know b

(2) This one probably isn't so obvious:
If we know that a implies b,
a→b and we know it is ¬b, then we also know ¬a
Notice that the two rules have a reversal. The first one is Modus Ponens and the second is Modus Tollens. We don't really need to know that but it's posh.

Using modus Ponens:
If we know the creature is a Dog, then we know it is a mammal.
Dog(creature) → Mammal(Creature) 
Using Modus Tollens,
If we know the creature is not a dog, then we know it is not a mammal
¬Mammal(Creature), therefore ¬Dog(Creature)

There are two more, similar

a → b = ¬b → a
¬(a→b) = a and ¬b


Using first order logic to define a Prime number


prime number is a natural number greater than 1 that has no positive divisors other than 1 and itself.

We can write two predicates:
Divisible(a, b) - the integer a is divisible by b.
Greater(a, b) - the integer a is greater than b.

So we can create a predicate for Prime numbers.
Prime(n) returns true if n is a prime, otherwise false if it is not.

Prime(n) = ∀i Greater(i,1) → ¬Divisible(n, i)
Prime(n) = ∀i Greater(i,1) and ¬Divisible(n, i)
The above says, n is a prime number
if for all numbers, i, i is Greater than 1, and n is not divisible by i



Prolog

Just for interest. here's the Prolog code to check if a number is a prime number

Example:  isprime(3).

code:

divisible(X,Y):-
      N is Y*Y, 

      N =< X, 
      X mod Y =:= 0.

divisible(X,Y):- 

      Y < X, 
      Y1 is Y+1, 
      divisible(X,Y1).

isprime(X):- 
     Y is 2, 
     X > 1, 
     \+divisible(X,Y).








Sunday, July 1, 2012

Hick's Law - A Design principle

"The time required to locate and use an option increases as the number of options increases."
Basil Fawlty: Next contestant, Mrs. Sybil Fawlty from Torquay. Specialist subject - the bleeding obvious.

I'm not sure how useful this principle is on its own but I am reminded of it because of a piece of software I have had the great misfortune to come across recently. I don't have to use it but I feel very sorry for the people that do. An absolute horror of a piece of software. 

I am reminded that although it enables users to do stuff, it doesn't make it easy, and it certainly doesn't generate any delight. Those are what we should be looking for now in our applications.

Oh the software: iMIS.
What is it with the "i"? 
Why do they do that?
There is nothing remotely "i" about their system.

For my mind it's Hick's law that makes Pages so much better than MS Word.

Friday, June 15, 2012

Ruby - should I start

Ruby. I've heard people rave about it, I know next to nothing about it, but now I may have a need for it. Can I be bothered to delve in and have a look?
I was reluctant because of time constraints and how to start. I wanted videos as they're quicker than books but there was one article I found that switched me on and gave me the kick I needed. There's probably loads more, and probably better, but this one did it for me:
http://oreilly.com/pub/a/ruby/archive/rails.html?page=1

He instals onto Windows which isn't the best place to be in the world, but it's functional. :)

Thursday, April 19, 2012

London marathon will be last for Fauja Singh

101 years old!

Fauja Singh, who was born in India but moved to Britain in the 1960s, has completed eight marathons since taking up the sport at the age of 89.

http://www.bbc.co.uk/news/uk-17765170


I posted about him last October when he was younger

Friday, April 13, 2012

You are not authorised to run this application. ... illegal value.

"You are not authorised to run this application.
The administrator has set your shell to an illegal value."



Well this isn't good. I closed down all open applications, then tried again but nothing. (I was working in Xcode and iOS simulator plus the usual browsers etc.)
I rebooted, and it worked. Not sure why.
I googled it and the only references I found were for quite a few years ago. Two days ago I updated Xcode and I hope it isn't related to that. I've been waiting for the Xcode crashes but as yet they haven't visited which is a welcome surprise.

Getting started with DDD when surrounded by Legacy systems II, by Eric Evans


I got this email a month or so back. Not sure if I should re-post it or not.
It has two parts,
  1. It advertises the up coming DDD courses in NY, Denver and London. 
  2. Then Eric describes how to get started in a legacy environment - (part II).
The parent website is here: http://domainlanguage.com

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DDD IMMERSION

ENROLL EARLY FOR SUMMER CLASSES

GETTING STARTED WITH DDD WHEN SURROUNDED BY LEGACY SYSTEMS II

STRATEGY 2: AUTONOMOUS BUBBLE

by Eric Evans
  1. Cutting the umbilical
  2. The Synchronizing ACL
  3. Bubble vs. Autonomous Bubble

CUTTING THE UMBILICAL

In a previous newsletter I discussed the "Bubble Context" as a way to get started with DDD when there is not much organizational commitment. The bubble context is completely dependent on the parent context, drawing all its data through an anti-corruption layer (ACL) like an umbilical cord. You can use that strategy when little else might work. However, it has its limits.
Almost all software uses data that comes from other contexts. A lot of interesting domain logic revolves around combining data from different sources and reasoning about it. Even with one source, there may be a significantly new way of thinking about the data that is fundamental to the desired new functionality (a new way of abstracting the domain, i.e. a new domain model). Sometimes this is done in ways that tangle the systems together and prematurely limit design freedom. The bubble context is quite natural way to start with such an undertaking because the team can experiment with models and combinations in isolation from the legacy system, while the Umbilical ACL obtains and translates the data with minimal impact to existing systems.
The Autonomous Bubble is distinguished by the ability to run its software, for a time, cut off from other systems. Information may start to get stale, requests to external service requests start to queue up unfulfilled, but the internal behavior of the software continues to work. Whereas the Bubble Context obtains its data from another context when it is needed, via the umbilical ACL, the Autonomous Bubble typically has some data store of its own. The data store could be in-memory – the storage medium is irrelevant – but the data is in the form native to the context. This is not just a cache of frequently or recently used data. In fact, an umbilical ACL could cache data as a performance enhancement. The point of the local data store is that the overall evolution of the model and design in this context is much more loosely coupled to other contexts. It should be possible to test such a subsystem without mocks of other subsystems.

Main Characteristics of the Autonomous Bubble Strategy

  • Needs organization committed to significant new development with new design approach.
  • Allows new data to be collected and used without involving legacy.
  • Allows decoupled "product" to evolve.
  • May progress from Bubble Context as development is scaled up on a successful pilot project.

SYNCHRONIZING ANTICORRUPTION LAYER

An autonomous context has its own data, sufficient to its core functions, organized according to in its own abstractions. To enable this, the ACL takes on the responsibility of synchronization between data stores in two contexts, which do not depend directly on each other. This ACL activity is asynchronous with any activity in either context, with a service level agreement (SLA) regarding the freshness of the translated data.
Synchronizing ACL
Diagram of Synchronizing ACL
Compare this with the Umbilical ACL of the Bubble Context here

The Nightly Batch Script: Low-tech Synchronizing ACL

Asynchronous synchronization with an SLA sounds more daunting than it is. It can be quite low-tech and examples are all around us. A very familiar implementation of the Synchronizing ACL is the “nightly batch”.
Now a typical nightly batch script does all sorts of things, some of which include important business logic. But, in my observation, one thing most of them do is to update one data store based on another. This could involve importing data from a file. It could involve kicking off a SQL script taking data from one table and transforming it and inserting it into another. It takes many forms, but look at a nightly batch script and you’ll probably find a Synchronizing ACL mixed in there.
    Typical nightly batch script has:
  • SLA: Open of business, next business day
  • Unnecessary coupling: Synchronizing ACL mixed in with once-per-day business logic
  • Unnecessary coupling: Multiple ACLs to multiple contexts lumped together.
If you are trying to establish an autonomous bubble, and you think your translation could be handled as part of a nightly batch script, then make sure you isolate the data copying and translation for your particular context into modules (one per context you are drawing on) which can be kicked off by the script. Don't let it get tangled into the spagetti. You need a decoupled synchronized ACL to pull off an autonomous bubble.

Messaging and Domain Events: A Stylish Synchronizing ACL

A more flexible approach to synchronizing uses messages carrying Domain Events. This can be nicely integrated with other event-driven architectural patterns. This approach can support a range of SLAs, and can update a system while it is being used, while batch scripts typically run while systems are off-line.
People discuss the use of messages and events for integration quite often, but usually they don't talk explicitly enough about what happens when a message crosses a context boundary. Just remember, any information crossing a context boundary must be translated. Messages are not somehow neutral. They are always expressed in some language based on some system of abstractions (a model), and we should not let them enter a context that uses a different language and model.
ACL translating Domain Events
Diagram of Synchronizing ACL translating events from one context
            to another.
Many ways of implementing a Synchronizing ACL are in use and more will come in the future, so I won't try to catalog them. Any mechanism that can update a data store in one context based on data in another, translating along the way, and can do this asynchronously, and without introducing any dependency on it from either context, could be used to implement a Synchronizing ACL. You probably have Synchronizing ACLs in your system now, although they may be tangled with other responsibilities

BUBBLE VS. AUTONOMOUS BUBBLE

The first two strategies I've described each create a "bubble" context, and in this sense they are very similar, and resemble each other when looking inside the bubble. However, the difference in the relationship to the legacy contexts leads to a significant difference in the options for what you can do within the bubbles.
The "Umbilical ACL" from the first strategy gives us as little architectural overhead as possible, but allows no data to be used that can't be mapped from a context continuously attached. Any new information that does not already exist in the legacy system somewhere must be added to the legacy system somewhere, even though it will not be used there! Then it must be mapped into the bubble context, increasing the dependency between the two systems. Clearly this is not the strategy we want once we are introducing significant new information.
In contrast, the "Synchronizing ACL" gives more autonomy to the newly formed context. This autonomous bubble has its own data, some of which is mapped from another context, but it can also have data of its own. So development in the autonomous bubble is not so tightly bound to the older contexts. The model in this context can be more innovative and grow more freely, and a fresh new product can be created.

NEXT TIME: EVOLVING A MODEL IN A BUBBLE

Design freedom is the point of a bubble. The bubble context with an umbilical ACL gives a little freedom, while the Autonomous Bubble can give us a lot if properly managed. However, in the actual unfolding of a development project, there are many ways this can go wrong and bog down before the team has reached its goals. In my next article I'll give some guidelines for process and design that help the team retain and even increase their ability to change the model as the project goes along.

Tuesday, April 10, 2012

Objective C - Dot notation or Message (bracket) notation

Do I prefer the dot notation or the bracket notation. If you spend most of the time in languages like C# then switching to Objective C will definitely generate an opinion or two on the bracket notation. I think it's great sometimes, then I think it's not. What I do like is the way we are forced to think about messages rather than simply calling a method on an object. That is refreshing somehow.

Readability

I'm convinced that the readability of the .notation is somehow easier to read, but then I think it misses some of the action of what is going on. Objective C is about messages and in #2 the message sending seems more obvious.

1. [myObject.doSomething sendAMessage]
2. [[myObject doSomething] sendAMessage]

But is that important when reading someone else's code? Yes I think it is. If I stop looking at the code above as if it were mine, and instead think of it as someone else's, and if I imagine I'm not happy at having to look at this person's code, then #2 does seem easier. Weird.

Attributes and Properties

Well perhaps this is ok for dot notation. For properties it seems to be much better.

1. [display setText:digit]; 
2. display.text = digit;


Structs

You can't send a message to a struct so the dot notation is a simple way of telling the reader that the reference is actually a struct rather than an object. This is a good thing. But, should we really care when we are reading someone else's code. I think not, in general. I think worrying about types is secondary information when understanding code.

Conclusion

I'm probably a fan of Message Notation over Dot notation, but I'm not sure why.
Dot notation for properties, message notation for behaviour is the way to go.




Monday, April 9, 2012

Where is the add-in manager in Mono Develop OR, How to instal MonoMac


MonoMac, a new foundation for building Cocoa applications on OSX using Mono. It's page can be found here.

Well on the website it says to:
        1. Open the Add-in Manager from the Tools->Add-in Manager menu

Well not in my Mono. For me it's in the MonoDevelop menu drop down.


I think MonoMac is installed by default anyway, but if it isn't just go to the Add-in Manager.




Sunday, April 8, 2012

A Recursive Decent Parser in C# using BNF

Introduction

Carrying on from my last two posts I'll quickly take the Backus Naur Form, or the Extended Backus Naur Form and use that to create a simple Recursive Decent Parser.

A word of caution. My use of BNF is a bit loose. If you were to write a EBNF that was going to be machine read, or if you were working on some serious industrial strength domain language then this should be tight and rigorous so that everyone understood the BNF syntax. Mine is a bit loose, but is fine for holding the grammar and being used to write the parser.

My two previous posts have been on:


The project

This is a simple calculator. So simple that it only takes in single characters, 2+1, 9+5 are valid. 12 + 6 isn't. (12 has two digits).


The BNF for the grammar


<expression>  :=  <number>  |
                   "(" <expression> <operator> <expression> ")" 
                   
<operator>  :=  "+" | "-" | "*" | "/" 
<number> := '0' |'1' |'2' |'3' |'4' |'5' |'6' |'7' |'8' |'9' 


Notice that there are three "production rules", expression, operator and number.
This suggests that there will be tree main methods with the same (or similar names).

Notice that I have not used a termination character. No reason why.
Notice that I have used BNF for assignment ":=" rather than "=". Why? I just prefer it.


The code

I tend to avoid comments in code as I firmly believe that the code should comment itself. However, I have taken the BNF rules and placed them as comments above the methods that implement them.
Notice that <expression> has become a method whose name is ExpressionValue()

Take notice of the Exception class. This is a must have really.


using System;

namespace RecursiveDecentParser
{
public class Calculator
{
private System.IO.StringReader _reader;
public Calculator (string text)
{
_reader = new System.IO.StringReader(text);
}
public double Calculate()
{
return ExpressionValue();
}
//<expression>  ::=  <number>  |
        //                   "(" <expression> <operator> <expression> ")" 
private double ExpressionValue()
{
SkipBlanks();
char ch = (char)_reader.Peek();
int num = -1;
bool chIsNumber = CharIsDigit(ch, out num);
if (chIsNumber)
{
_reader.Read();
return num;
}
else if(NextCharIsOpenBracket())
{
ConsumeNextChar();
double leftExpressionVal = ExpressionValue();
char op = GetOperator();
double rightExpressionVal = ExpressionValue();
SkipBlanks();
if(!NextCharIsClosingBracket())
{
throw new ParseException("Missing closing bracket.");
}
else
{
ConsumeNextChar();
return PerformOperation(leftExpressionVal, op, rightExpressionVal);
}
}
else
{
throw new ParseException("Unexpected character, \"" + _reader.Peek() + "\" in input.");
}
}
//BNF: <operator>  ::=  "+" | "-" | "*" | "/"
private char GetOperator()
{
SkipBlanks();
char op = (char)_reader.Peek();
if(op == '+' || op == '-' || op == '*' || op == '/')
{
_reader.Read();
return op;
}
else if (op == '\n')
throw new ParseException("Missing operator at end of line");
else 
throw new ParseException("Missing operator. Expected +, -, * or /" +
                        " Found " + op ); 
}
// BNF: <number> ::= '0' |'1' |'2' |'3' |'4' |'5' |'6' |'7' |'8' |'9'
// Yes! only one digit at the moment.
private int GetNumber()
{
SkipBlanks();
char ch = (char)_reader.Peek();
int num = -1;
//bool chIsNumber = int.TryParse(CharToString(ch), out num);
bool chIsNumber = CharIsDigit(ch, out num);
if(chIsNumber)
{
ConsumeNextChar();
return num;
}
else if (ch == '\n')
throw new ParseException("Missing operator at end of line");
else 
throw new ParseException("Missing operator. Expected +, -, * or /" +
                        " Found " + ch ); 
}
private double PerformOperation(double leftVal, char op, double rightVal)
{
double result = 0;
switch (op)
{
case '+':
result = leftVal + rightVal;
break;
case '-':
result = leftVal - rightVal;
break;
case '*':
result = leftVal * rightVal;
break;
case '/':
result = leftVal / rightVal;
break;
}
return result;
}
private bool CharIsDigit(char ch, out int num)
{
string s = CharToString(ch);
return int.TryParse(s, out num);
}
private bool NextCharIsOpenBracket()
{
bool res = false;
char ch = (char)_reader.Peek();
if (ch == '(')
res = true;
return res;
}
private bool NextCharIsClosingBracket()
{
bool res = false;
char ch = (char)_reader.Peek();
if (ch == ')')
res = true;
return res;
}
private void ConsumeNextChar()
{
_reader.Read();
}
private void SkipBlanks()
{
while(CharToString((char)_reader.Peek()) == " ")
ConsumeNextChar();
}
private string CharToString(char ch)
        {
            return new string(ch, 1);
        }
}


    [Serializable]
    public class ParseException : Exception
    {
        public ParseException() { }
        public ParseException(string message) : base(message) { }
        public ParseException(string message, Exception inner) : base(message, inner) { }

        protected ParseException(
            System.Runtime.Serialization.SerializationInfo info,
            System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }
    }
}



Unit tests

Here are some tests that show it's limitations and workings.
Notice that a single digit input will work, if it is enclosed in brackets it will not. This is in line with the BNF grammar.
An expression such as 2+3 must be enclosed in brackets.
As you can see, I have not tested the code for missing brackets, spaces in strange places, odd characters


[TestFixture]
public class SimpleInputTests
{
[Test]
[ExpectedException (typeof(ParseException))]
public void Exception_if_empty()
{
Calculator calculator = new Calculator("");
calculator.Calculate();
}
[Test]
[ExpectedException (typeof(ParseException))]
public void Simple_bracket_and_one_digit()
{
Calculator calculator = new Calculator("(2)");
calculator.Calculate();
}
[Test]
public void Simple_addition_with_brackets()
{
Calculator calculator = new Calculator("(2+2)");
double answer = 0;
answer = calculator.Calculate();
Assert.AreEqual(4, answer);
}
[Test]
public void No_brackets_and_single_input_digit()
{
Calculator calculator = new Calculator("2");
Assert.AreEqual(2, calculator.Calculate());
}
[Test]
public void Simple_multiplication_with_brackets()
{
Calculator calculator = new Calculator("(2*5)");
double answer = 0;
answer = calculator.Calculate();
Assert.AreEqual(10, answer);
}
[Test]
public void Simple_division_with_brackets()
{
Calculator calculator = new Calculator("(8/4)");
double answer = 0;
answer = calculator.Calculate();
Assert.AreEqual(2, answer);
}
[Test]
public void Simple_subtraction_with_brackets()
{
Calculator calculator = new Calculator("(8-5)");
double answer = 0;
answer = calculator.Calculate();
Assert.AreEqual(3, answer);
}
[Test]
public void Single_digit_add_bracketed_addition_clause()
{
Calculator calculator = new Calculator("(3 + (4+1))");
double answer = 0;
answer = calculator.Calculate();
Assert.AreEqual(8, answer);
}
[Test]
public void Bracketed_addition_clause_add_single_digit()
{
Calculator calculator = new Calculator("((4+1) + 3)");
double answer = 0;
answer = calculator.Calculate();
Assert.AreEqual(8, answer);
}
[Test]
public void Random_complex_sum()
{
Calculator calculator = new Calculator("((4+(5-4)) + 2)");
double answer = 0;
answer = calculator.Calculate();
Assert.AreEqual(7, answer);
}
}
}