The mind of a CIO and Blockchain Enthusiast

Andrew Baker

  • Follow Us on Twitter!
  • LinkedIn
  • Subcribe to Our RSS Feed

Banking and the Functional Cup of Tea...

I havent finished this article, so please accept the abrupt ending... will be done in a few weeks (honest)

The Preamble:
 
This should be a short blog explaining why technology functionalisation is part of the "axis of evil". This opening statement is deliberately aggressive as I would dearly like fans of functionalisation to not read the rest of this article (and also not post annoying replies citing "Henry Ford"). That said, I would imagine it will take an army of functional fans to summon up any feedback; and even then you will probably spend so much time fighting over control of the keypad that you don't actually get to submit anything...

The article below describes how you would experience a cup of tea, should it be made by a heavily functionalised bank...


The Cafe: Deciding the Org Structure
 
As any entrepreneur worth his salts will tell you, if you want to be successful you need a BIG FAT top heavy organisational structure. Critically, the more mundane the operation is the more "global" you need to make the roles titles in order to hire all those big hitters we need! Out the blocks we will need:


1) Global Head of Stirring (the title is deliberately ambiguous as we may expand into coffee one day).
2) Head of Milk Sourcing and Provisioning (reporting into Global Head of Dairy Products)
3) Head of Heated Containers (the kettle).
4) Head of natural resources (fills kettle with water).
5) Global head of payments (till/card machine).
6) Head of Procurement EMEA (buys Indian tea bags)
7) Global Head of DevOpps (need to assure the board that we have a central "agile" function)
 
I could go on, but my suspicion is that you get the point...
 
The Customer Experience...
 
So "Ann" walks up to the Cafe and gives a warm, "morning all" greeting to the team. A great crowd of people shuffle around to greet her. Ann scans hopefully for some eye contact, but a functional deadlock starts to bite down manifesting itself in an awkward few minutes of chronic naval gazing. It quickly becomes clear there is a gap in our org structure; we need a Global Head of Customer Service. The team proceed to huddle around for a quick fight to determine whose fault this omission is. But as luck would have it, the head of dev opps is on form today. He quickly decides we need to recruit someone. Sadly the team also omitted HR in their org structure and so we quickly find ourselves back gazing at navels. A few more minutes of awkward silence pass before Ann steps in to break the deadlock. "I would like a cup of tea please". A collectively internalised "yes!" can be seen across the facial estate of this motley crew. They finally have their requirements AND they even managed to save two head count!


Now its time for the team to feast on an "alignment banquet" before they begin work. The only question is.... do they need a 3 or 4 day offsite? Then the dev opps dude sticks his nose in again; "I know, we could just make the tea" he chirps. "I mean you all have your strategy documents, your 90 day plans, your BRDs, your KPIs and its all been approved by exco!". The silence is back; but this time it feels different. There is the mild menace of pending activity in the air. The team are on the brink of execution.<sarcasm>Something really could just happen - it could, for real, it really could</sarcasm>.

Without warning the team spring into action - just 20 mins after the initial engagement. The stress is palpable as people start to stumble and bump into each other. Thirty minutes of manic disconnected activities pass and the tea is almost ready. But where is the milk? Oh dear, the head of Milk Sourcing and Provisioning is on leave. Another 15 mins of "alignment" chatter passes and the Ann reaches over to grab the tea and pours the milk in herself!

"That will be nineteen thousand, three hundred and fifty pounds please", says the head of payments, "oh and no cards please - the charges are excessive...". Ann takes a slurp of the cold tea and spits it out, before grumbling a few choice words and heading off.


 
The Conclusion

If you like functionalisation, please google the word "myopic". You will notice the chart of the usage of this word ramps up at exactly the same time that misguided accountants took Henry Fords principles and scaled it to create expensive, highly brittle, dysfunctional, low creative organisations. But there's hope.... in 2008 you can see fintechs enter the landscape and start to slay the myopic functional status quo :)


 

 
 

Running Corporate Technology: Smart vs Traditional

The Truth

 

Before we get started, what lies beneath is actually a rant. It's not even a well disguised rant and the reason for this is two fold. Firstly, I don't expect many people to read this, so the return on the effort required to dress it up would be low. Secondly, I wrote this for my benefit to relieve frustration - nothing to do with trying to educate or for some greater good thingy. So if you continue to read this article, you are essentially paying my "frustration tax"... So thanks for that :)

 

The Models

 

Large corporates will tend to confuse a poorly structured organisation, with poorly performant staff. My view is that you should first look to structure your organisation for success and only if after completing this, can you begin to see if there are any residual people issues. There are broadly two fundamental models of organising tech inside a corperate (and various states in-between).  To assess which world you live in, I have described the general characteristics of the two models below:

 

Model A:

 

  1. You will spend a number of months collating voluminous documents containing all possible requirements for the product over the next n years. This is often mistaken to be a "strategy document".
  2. You believe in developing technology away from your customer in "the center". One day you feel you will “extract synergies” and “economies of scale” if you do this.
  3. You believe each business head should have a “single face off” into technology. This "engagement manager" (aka human inbox) attempts to use "influence" by routing escalation emails through the organisations hierarchy to try generate outcomes.
  4. Your central functions haven’t quite delivered yet, cost a small fortune, have top heavy management structure, BUT will “definitely deliver next year”. These functions manage using “gates and governance” and often send out new multi-page “Target Operating Model” documents which nobody reads/understands.
  5. You believe you can fix technology with manually captured metrics like SLAs, OLAs, KPIs etc etc. You have hundreds of these measures and you pay a small army to collate these metrics each month. These measures always come back as “Green”, but you are still unhappy with the performance of your technology teams. You feel that if you could just come up with that “killer metric” that would show how bad technology really is; you could then finally sign an outsourcing deal to "fix it".
  6. You ask for documents from technology showing exactly what will be delivered over the next 3-5 years time horizon. You believe in these documents and feel that they are valuable. Historically they have never been close to accurate. You will likely see an item in 2022 which states "Digital Onboarding of Customers" - this is around the same time that the rest of the world will be enjoying the benefits of teleportation!
  7. You hire an army of people to track that technology are “delivering on time”, they are not delivering on time and you still don't know why. To scale output you hire more people to track why technology is not delivering on time.
  8. You are constantly underwhelmed with what eventually gets delivered. It doesn’t do anything you really wanted it to and your customer feedback is lackluster at best.
  9. There are clear lines of distinction between technology and the business. Phrases like “I could make my budget... if I could only get some delivery from tech” are common place.
  10. The products delivered have all the charisma and charm of a road traffic accident.
  11. You believe, if you can just get the governance right and capture the requirements, then you will get the product you wanted.
  12. Your engagements with technology will take the form of “I need EVERYTHING from product X delivered by by date X. How much will it cost?”. When you get the reply a few months later, you will ALWAYS reply “that's crazy!”. You will then cycle requirements down until you get beneath a “magic” number (that’s unknown to technology). This process and take years.
  13. Your teams spend more time in meetings or delivering static documents, than delivering business value.
  14. You layer governance meetings with various disconnected management teams, all with competing interests. This essentially turns an approval process into a multi-week/month attrition circus. The participants of this process have to explain and re-explain the exact same business case in multiple formats and leave the process with zero added insights, but minus a chunk of morale.
  15. If you ever looked at any documents signed related to technology spend, there are likely to be dozens of signatures on the documents and nobody quite recalls why they signed the document and who owns the actual decision for the spend.
  16. You direct as much technology spend as possible through a project governance process. This gives the illusion of a highly variable tech spend, focused on strategic investments. Your aggregate technology spend is nothing short of intergalactic. Funding abruptly expires at the end of each project and the resources promptly vanish. Most of your products are immature/half finished, you have a high number of (expensive) contractors, you leak IP, you love NDAs, nobody knows how to maintain or improve the products in production (as the contractors that delivered it have all left) and if you ever tried to reduced the SI spend, the "world will end". 
  17. You can’t quite understand why everything in technology costs 10x what it would if you gave it to a start up.
  18. Technology is a grudge purchase, and internal technology spend is an absolute last resort. Most of the people in your technology teams have never written a line of code. You urge your CIO to sign outsourcing documents with a "low cost location". You believe this will give you a 20px reduction in costs over 5 yrs. All the previous attempts to do this have failed. Next time will be different as this time you will capture the correct SLAs to fix technology. You use expressions like "we are a bank, not a technology company". 
  19. You believe all the value stream is created in the selling of the digital artefact; not the creation of the artefact itself. Your solution to poorly designed artefacts that are hard to sell is to hire more sales staff.
  20. You fear open source and prefer to use multimillion dollar vendors for basics like middleware (please see Spring), business process management and databases. You build everything in your own data centre as you believe the "it's a regulatory requirement". It takes you several months to deliver hardware, or a engage with your vendors.
  21. You actively promote Monoculture. You believe that "do it once, everywhere, for everything, forever" is a meaningful sentence. You install single instances of monolithical services that everyone is force to use. These services are not automated and so generate hugely painful backlogs, both for maintenance and adding new services. You can never upgrade these monoliths without asking everyone to "stop what your doing and retest everything". Teams spend a chunk of their time trying to engineer ways of "hacking" these monoliths in order to be able to deliver value to customers.
  22. You believe that most things in software are "utilities" and therefore belong in the center. You never look to prove that you get any benefits from this centralisation like lower costs, better quality or faster delivery times. The consumer of this service and the service provider will now both hire managers to work the functional boundary.
  23. In response to chronic stability issues you create various heavily populated central functions to solve things like "Capacity Management", "Service Management", "Change Management", "Stability Management". You can prepend the words: "We are really bad at " to any of the above. Every time there is an outage the various management functions lead a charge into the application teams to report on what went wrong. The application teams spend more time speaking to the various functions than solving the actual issue. Getting a route cause is lengthy, as none of the various teams cannot agree on one version of the truth and there is infighting as each of the various areas looks to abstract themselves of any responsibility. You have effectively created a "functionally gridlock".
  24. The business tend to export poor unilateral technology decisions to technology, and technology exports poor unilateral business decisions back. Technology will add arbitrarily points of friction/governance layers, change freezes, make material spend decisions and freeze hiring on critical products. Business will in turn sign low grade technology deals and hand them over the fence to technology to "make good" the decision.
  25. Your technology leaders will slavishly stick to their multiyear strategies; irrespective of how painful these choices may prove to be. If any innovation or alternatives are discovered during the sluggish execution of these strategies, they will resist any attempts to alter direction and try something new. 
  26. Bonus is assigned in a single amorphous blob at the top of the function. Both performing and non performing technology teams are equally "punished" with a low grade aggregate pot. Business, customer feedback and product quality have close to zero influence on either the pot size or its distribution. There are obvious advantages to hiring lower performing candidates and just a few rockstars/key men (as you would not be able to cover fair compensation for teams of high performers). It is highly likely that your organisation institutes some kind of bell curve on PD grades which further enforces that you can only have a rationed percentage of "A players". This serves to foster the "key man" culture, ignoring the benefit of creating highly performing teams and creates a built in mechanism for "bonus casualties".
  27. In an attempt to create efficiencies within an inefficient structure, you will tend to triplicate (find superficially similar products and artificially force them together at great expense, reduced output and increased cost/complexity). See The Triplication Paradigm
  28. Alignment costs cripple your organisation. You often find yourself aligning, re-aligning and then aligning again. Minutes are tacitly approved, then disputed, memories of what was agreed between the various functional areas are diverse. You periodically get back in a room with the same people, to discuss the same subjects and cover the same ground. Eventually you will tend to yield - resigning yourself to doing nothing (or find a "work around").
  29. Your organisation believe rules will protect quality and consistency (the scaled efficiency model). Your process-focused culture will drive out the high-performing employees. When the market shifts quickly due to new technology, competitors, or business models, you can’t keep up and lose customers to competitors who adapt. You are slow-moving, rule-oriented and over time will grind "painfully into irrelevance".

 

Model B:

 

  1. Business and technology is a pure partnership, with product development often starting with a sentence similar to, “I have x USD - work with me to get an MVP out in 3 months."
  2. You realise the centre is not the place for client centric delivery. Technology is seen as an intimate collaborative process. 
  3. You believe in self organising and self navigation. No layering, no aggregation, no grand standing.
  4. Your central functions are thin, cheap and deliver scaled learning to the business facing teams. Other teams want to talk to them to share success, they are non political, encourage collaboration and do not sell gates and governance. The functions serve using the "zero wait" principle (i.e. they run with you to help, or let you run ahead). They NEVER block. 
  5. You have no manual metrics like SLAs, OLAs, KPIs etc. You just talk to the customer and fix what’s broken. All your products have comprehensive dashboards showing machine generated metrics, that would help track issues.
  6. You have no idea what you will be doing in 3 - 5 years.
  7. You have zero people tracking/reporting delivery. If you need to look in the rear view mirror, get it yourself from Jira.
  8. You are constantly flawed with the innovative solutions your teams have come up with. You could actually sell your products to other companies!
  9. There are no clear lines of distinction between technology and the business.
  10. The products delivered are designed iteratively with the customer at the centre, they have an “inspired” experience.
  11. You don’t believe in any governance, except macro finance.
  12. You neither read nor write requirements documents. Product documentation is developed after the fact and where possible is automated (eg Swagger).
  13. You teams reject most meetings, have a 15 min daily standup, use instance messaging groups, phone calls etc etc.
  14. Approval always sits at the lowest federated level, ideally with a single person or product owner.
  15. If you ever looked at any documents signed relating to technology spend, there would be single signatory. This person would be the actual decision maker, not an arbitrary person high up in the organisational hierarchy.
  16. You have zero projects. You work with finance at a macro level, not micro. Everything is a product and your variable tech spend is low. You have a high number of permanent staff and encourage internal mobility. Changing existing products is easy. You can’t remember when you last signed an NDA.
  17. You are able to both compete with and partner with start-ups. Your teams review start-up investments and find often find them “lacking”.
  18. Big outsourcing deals are never considered. You either buy and build (e.g. frameworks, cloud platforms) or build (with focus on open source). You actively recruit world class developers. You encourage a policy of "eat what you kill" to decommission expensive vendor solutions that are choking investment in the rest of the estate.
  19. You believe value is created equally in both selling and creation of digital artefacts; and you reward symmetrically.
  20. All new products are developed in the cloud, with an open source first approach. Your teams even share back to the wider open source community, e.g. https://twitter.com/donovancmuller. Your developers are proactively trained in security, you anonymising data, carry out automatic penetration testing as a part of your CI and hardware is just a debate about the efficient consumption of compute (e.g. serverless compute https://aws.amazon.com/lambda/details/).
  21. You actively encourage scaled learning, width of thought and interop - not points of singularity.
  22. You have have no system issues and therefore no central functions to track, the teams are empowered to solve the customer experience end to end. 
  23. All decisions (technology or business) are co-authored and validated as a single product team.
  24. Pay is dealt holistically, can often include revenue share and you are incentivised to hire the best and create the best products. There are no bell curves, good feedback is not rationed.
  25. Your technology leaders will not publish strategy documents, but instead focus on scaled learning, constant iteration, experimentation and prototypes. They will tend to evolve their strategies as they go and will actively look to absorb new ideas and constantly course correct.
  26. You pay zero for alignment; you have self organising teams that own their customers and stacks end to end.
  27. You believe in accountability, empowerment and Learning at Scale. You have principles, but no rules or heavy processes to "protect" quality/output.

 

I appreciate this article might be provocative, and that's by design. The main point from the above is that the incumbent tech status quo in most corporates is not really challenged. Instead the tendency is to continuously draw and then redraw functional boundaries - in the process traumatising staff, relearning the exact same lessons and creating an internal talent vacuum. It's interesting that the removal of these boundaries altogether is rarely questioned. In fact, in response to failed tech strategies most corporates will actually choose to scale these failed strategies - rather than question the validity of the approach. This is my view is a material mistake - technology is all about intimacy, and to get it right you need to embed it into your companies DNA.

To summarise, if you build an institution with "padded walls" you would expect a certain type of individual to be comfortable living there. Similarly, if you build a corporate that does not reflect it's customer, if the roles of the leaders of this organisation are so generic it's not clear what sits where and who does what, if layering your successful teams is culturally acceptable - then the staff working in this organisation will typically be staff that don't care about details like the customer and being successful. This, I would argue, is not a long term game plan.

The DAO Ethereum Recursion Bug: El Gordo!

Brief Introduction

The splitDAO function was created in order for some members of the DAO to separate themselves and their tokens from the main DAO, creating a new ‘child DAO’, for example in case they found themselves in disagreement with the majority.

The child DAO goes through the same 27 day creation period as the original DAO. Pre-requisite steps in order to call a splitDAO function are the creation of a new proposal on the original DAO and designation of a curator for the child DAO.

The child DAO created by the attacker has been referred as ‘darkDAO’ on reddit and the name seems to have stuck. The proposal and split process necessary for the attack was initiated at least 7 days prior to the incident.

The exploit one alone would have been economically unviable (attacker would have needed to put up 1/20th of the stolen amount upfront in the original DAO) and the second one alone would have been time intensive because normally only one splitDAO call could be done per transaction.

One way to see this is that the attacker performed a fraud, or a theft. Another way, more interesting for its implications, is that the attacker took the contract literally and followed the rule of code.

In their (allegedly) own words:

@stevecalifornia on Hacker News - https://news.ycombinator.com/item?id=11926150

"DAO, I closely read your contract and agreed to execute the clause where I can withdraw eth repeatedly and only be charged for my initial withdraw.

Thank you for the $70 million. Let me know if you draw up any other contracts I can participate in.

Regards, 0x304a554a310c7e546dfe434669c62820b7d83490"

 

The HACK

An "attacker" managed to combine two "exploits" in the DAO.

1) The attacker called the splitDAO function recursively (up to 20 times).

2) To make the attack more efficient, the attacker also managed to replicate the incident from the same two addresses (using the same tokens over and over again (approx 250 times).

Quote from "Luigi Renna": To put this instance in a natural language perspective the Attacker requested the DAO “I want to withdraw all my tokens, and before that I want to withdraw all my tokens, and before that I want to… etc.” And be charged only once.

 

The Code That was Hacked

Below is the now infamous SplitDAO function in all its glory:

 

function splitDAO(
uint _proposalID,
address _newCurator
) noEther onlyTokenholders returns (bool _success) {
...
// Get the ether to be moved. Notice that this is done first!
uint fundsToBeMoved =
(balances[msg.sender] * p.splitData[0].splitBalance) /
p.splitData[0].totalSupply;
if (p.splitData[0].newDAO.createTokenProxy.value(fundsToBeMoved)(msg.sender) == false) // << This is
the line the attacker wants to run more than once
throw;
...
// Burn DAO Tokens
Transfer(msg.sender, 0, balances[msg.sender]);
withdrawRewardFor(msg.sender); // be nice, and get his rewards
// XXXXX Notice the preceding line is critically before the next few
•http://hackingdistributed.com/2016/06/18/analysis-of-the-dao-exploit/ Question: So what about Blockchain/DLs?
totalSupply -= balances[msg.sender]; // THIS IS DONE LAST
balances[msg.sender] = 0; // THIS IS DONE LAST TOO
paidOut[msg.sender] = 0;
return true;
}

The basic idea behind the hack was:

1) Propose a split.
2) Execute the split.
3) When the DAO goes to withdraw your reward, call the function to execute a split before that withdrawal
finishes (ie recursion).
4) The function will start running again without updating your balance!!!
5) The line we marked above as "This is the line the attacker wants to run more than once“ will run more
than once!

 

Thoughts on the Hack

The code is easy to fix, you can just simply zero the balances immediately after calculating the fundsToBeMoved. But this bug is not the real issue for me - the main problem can be split into two areas:

  1. Ethereum is a Turing complete language with a stack/heap, exceptions and recursion. This means that even with the best intentions, we will create a vast number of routes through the code base to allow similar recursion and other bugs to be exposed. The only barrier really is how much ether it will cost to expose the bugs.
  2. There is no Escape Hatch for "bad" contracts. Emin Gun Sirer wrote a great article on this here: Escape hatches for smart contracts

 

Whilst a lot of focus is going in 2) - I believe that more focus needs to be put into making the language "safer". For me, this would involve basic changes like:

  1. Blocking recursion. Blocking recursion at compile and runtime would be a big step forward. I struggle to see a downside to this, as in general recursion doesn't scale, is slow and can always be replaced with iteration. Replace Recursion with Iteration
  2. Sandbox parameterisation. Currently there are no sandbox parameters to sit the contracts in. This means contracts the economic impact of these contracts are more empirical than deterministic. If you could abstract core parameters of the contract like the amount, wallet addresses etc etc and place these key values in an immutable wrapper than unwanted outcomes would be harder to achieve.
  3. Transactionality. Currently there in no obvious mechanism to peform economic functions wraped in an ATOMIC transaction. This ability would mean that economic values could be copied from the heap to the stack and moved as desired; but critically recursive calls could no revist the heap to essentially "duplicate" the value. It would also mean that if a benign fault occured the execution of the contract would be idempotent. Obviously blocking recursive calls goes some way towards this; but adding transactionality would be a material improvement.

 

I have other ideas including segregation of duties using API layers between core and contract code - but am still getting my head around Ethereum’s architecture.

The Triplication Paradigm

Introduction

 

In most large corporates technology will typically report into either finance or operations. This means that it will tend to be subject to cultural inheritance, which is not always a good thing. One example of where the cultural default should be challenged is when managing duplication. In finance or operations duplication rarely yields any benefits and will often result in unnecessary costs and/or inconsistent customer experiences. Because of this, technology teams will analyse all incoming workstreams for convergence opportunities. If any seemingly overlapping effort is discovered, this would then typically be extracted into a central, "do it once" team. Experienced technologists will likely remark that it generally turns out that the analysis process is very slow, overlaps are small, the cost of extracting them are high, additional complexity is introduced, backlogs become unmanageable, testing the consolidated "swiss army knife" product is problematic and critically, the teams are typically reduced to crawling speed as they try to transport context and requirements to the central delivery team. I have called the above process "Triplication", simply because is creates more waste and costs more than duplication ever could (and also because my finance colleagues seem to connect with this term).

The article below attempts to explain why we fear duplication and why slavishly trying to remove all duplication is a mistake. Having said this, a purely federated model or abundant resource model with no collaboration leads to similarly chronic issues (I will write an article about "Federated Strangulation" shortly).

 

The Three Big Corporate Fears

 

In any large corporate three fears will dominate tech spend:

  1. The fear of doing something badly.
  2. The fear of duplication.
  3. The fear of doing nothing at all.

Most corporates focus on fear 1) and 2). They will typically focus on layers of governance, contractual bindings, interlocks and magic metric tracking (SLA, OLA, KPI etc etc). The governance is typically multi-layered, with each forum meeting infrequently and ingesting the data in a unique format. As a result these large corporates typically achieve fear 3).

Most start-ups/tech companies worry almost exclusively about 3) - as a result they achieve a bit of 1) and 2). Control is highly federated, decision trees are short, and teams are self empowered and self organising. Dead ends are found quickly, bad ideas are cancelled or remediated as the work progresses. Given my rather bias narrative about - it won't be a surprise to learn that I believe 3) is the greatest of all evils.

For me, duplication is generally a positive thing if you manage it properly. You will often see divergence and consolidation in equal measure as the various work streams mature. The key to managing duplication is to enforce scarcity of resources and collaboration. If however, there is no collaboration and an abundance of resources are thrown at problems, you end up with material and avoidable waste.

Triplication happens when a two or more products are misunderstood to be "similar" and then attempted to be fused together. The over aggregation of your product development streams will yield most of the below:

1) Cripplingly slow and expensive to develop.

2) Risk concentration/instability. Every release will cause trauma to multiple customer bases.

3) Unsupportable. It will take you days to work out what went wrong.

4) Untestable. The complexity of the product will guarantee each release causes distress.

5) Low grade client experience.

 

Initially these problems will be described as "teething problems". After a while it becomes clearer that the problem is not fixing itself. Next you will likely start the "stability" projects. A year or so later after the next pile of cash is burnt there will be a realisation that this is as good as it gets. At this point, senior managers start to see the writing on the wall and will quickly distance themselves from the product. Luckily for them, nobody will likely remember exactly whom in the many approval forums thought this was a good idea in the first place. Next the product starts to get linked to the term "legacy". The final chapter for this violation of common sense, is the multi-year decommissioning process. BUT - its highly likely that the strategic replacement contains the exact same flaws as the legacy product...

  

The Conclusion

 

To conclude, I created the term "Triplication" as I needed a way to succinctly explain that things can get worse when you lump them together without a good understanding of why your doing this.  I needed a way to help challenge statements like, "you have to be able to extract efficiencies if you just lump all your teams together". This thinking is equivalent to saying; "hey I have a great idea...! We ALL like music, right?? So lets save money - lets go buy a single CD for all of us!"

The reality for those that have played out the triplication scenario in real life, is that you will see costs ballon, progress grind to a halt, revenues fall of a cliff and the final step in the debacle is usually a loss of trust - followed by the inevitable outsourcing pill. On the other hand collaboration, scarcity, lean, quick MVPs, shared learning, cloud, open source, common rails and internal mobility are the friends of fast deliverables, customer satisfaction and yes - low costs!

READ THIS NEXT: SOLID principles.

High Performance Timer

Below is a sample class containing a high performance timer:

 

Example usuage:

PerformanceTimer pf = new PerformanceTimer(true);

float timeMs = pf.GetTimeMs();

 

using System;

using System.Runtime.InteropServices;

 

 

///

/// This class can be used to gather accurate performance timings.

///

public class PerformanceTimer

{

 

[DllImport("kernel32.dll")]

internal static extern bool QueryPerformanceCounter(ref long lpPerformanceCount);

 

[DllImport("kernel32.dll")]

internal static extern bool QueryPerformanceFrequency(ref long lpFrequency);

 

#region Private Variables

 

private bool _isRunning = false;

private long _startTime = 0;

private long _frequency = 0;

private float _elapsed = 0;

 

#endregion Private Variables

 

#region Constructors

 

///

/// Default constructor - does not start timer immediately.

///

public PerformanceTimer()

{

}

 

///

/// Constructor with option to start timer at same time.

///

///Whether to start timer immediately.

public PerformanceTimer(bool startTimer)

{

if ( startTimer )

{

Start();

}

}

 

#endregion Constructors

 

#region Public Properties

 

///

/// Returns True if the timer is currently running.

///

/// To change the running state use the Start and Stop methods provided.

public bool IsRunning

{

get{return _isRunning;}

}

 

#endregion Public Properties

 

#region Public Methods

 

///

/// Starts the performance timer running.

///

public void Start()

{

QueryPerformanceFrequency(ref _frequency);

QueryPerformanceCounter(ref _startTime);

_elapsed = 0;

_isRunning = true;

}

 

///

/// Stops the performance timer running.

///

public void Stop()

{

// Call procedure that will set internal elapsed variable, then turn running flag off.

GetTime();

_isRunning = false;

}

 

///

/// Returns the time elapsed since "Start" was called (in seconds). If the timer

/// is not running the time elapsed between the last start and stop time is returned.

///

/// A float representing the time ellapsed (in seconds)

public float GetTime()

{

if (_isRunning)

{

long endTime = 0;

QueryPerformanceCounter(ref endTime);

 

_elapsed = (float)(endTime - _startTime) / _frequency;

return _elapsed;

}

else

{

return _elapsed;

}

}

 

///

/// Returns the time elapsed since "Start" was called (in milliseconds). If the timer

/// is not running the time elapsed between the last start and stop time is returned.

///

/// A float representing the time ellapsed (in milliseconds)

public float GetTimeMs()

{

if (_isRunning)

{

return GetTime()*1000;

}

else

{

return _elapsed*1000;

}

}

 

///

/// Override ToString to display time nicely formatted.

///

/// Returns the time formatted as a string.

public override string ToString()

{

return String.Format("{0:0000.000}s ", GetTime());

}

 

#endregion Public Methods

}

 

 

Hint: Registry Key to Enable and Disable USB Devices

Below are the registry settings to enable and disable USB storage devices:

Enable USB:

------------

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies]

"WriteProtect"=dword:00000001

Disable USB:

------------

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies]

"WriteProtect"=dword:00000000

Returning a distinct list of items from an Excel Range

Below is code to return a distinct list of items from an excel range.

Option Explicit

'Purpose : Returns a list of distinct items from a range.

'Inputs : rngReturnDistinctListFrom. The range to return the distinct list from

' rngItemsAlreadyReturned. The range containing the values already returned.

'Outputs : Returns the first distinct item which has not already been returned in the rngItemsAlreadyReturned range.

'Author : Andrew Baker

'Date : 25/03/2000

'Example usuage:

'

'=FirstDistinctItem(A1:A1000,B$1:B1)

'Where:

'A1:A1000 is a list containing the items to return a distinct list of

'B$1:B1 is the list containing the distinct items already returned.

Function FirstDistinctItem(rngReturnDistinctListFrom As Excel.Range, rngItemsAlreadyReturned As Excel.Range, Optional bIgnoreBlanks As Boolean = True) As Variant

Dim avItemsAlreadyReturned As Variant

Dim vCell As Variant

FirstDistinctItem = ""

avItemsAlreadyReturned = rngItemsAlreadyReturned.Value

For Each vCell In rngReturnDistinctListFrom

If (bIgnoreBlanks = False Or (bIgnoreBlanks And vCell <> "")) = True Then

If (ArrayHasItem(avItemsAlreadyReturned, vCell) = False) Then

FirstDistinctItem = vCell

Exit Function

End If

End If

Next

End Function

'Purpose : Checks to see if a value is already in an array.

'Inputs : avInArray. The array to evaluate.

' vValueToCheck. The value to look for in the array.

'Outputs : True. The array contains vValueToCheck

' False. The array does not contain vValueToCheck.

'Author : Andrew Baker

'Date : 25/03/2000

'Notes : The array can be any size or shape as this function

Function ArrayHasItem(avInArray As Variant, vValueToCheck As Variant) As Boolean

Dim vThisItem As Variant, lThisRow As Long

On Error GoTo ErrExit

If ArrayNumDimensions(avInArray) = 1 Then

'Faster than for each loop

For lThisRow = LBound(avInArray) To UBound(avInArray)

vThisItem = avInArray(lThisRow)

'Check for arrays in arrays

If IsArray(vThisItem) Then

'Search an array in an array

If ArrayHasItem(vThisItem, vValueToCheck) Then

'Found item

ArrayHasItem = True

Exit For

End If

ElseIf vThisItem = vValueToCheck Then

ArrayHasItem = True

Exit For

End If

Next

Else

For Each vThisItem In avInArray

'Check for arrays in arrays

If IsArray(vThisItem) Then

'Search an array in an array

If ArrayHasItem(vThisItem, vValueToCheck) Then

'Found item

ArrayHasItem = True

Exit For

End If

ElseIf vThisItem = vValueToCheck Then

ArrayHasItem = True

Exit For

End If

Next

End If

ErrExit:

On Error GoTo 0

End Function

'Purpose : Calculates the number of dimensions in an array

'Inputs : avInArray. The array to evaluate.

'Outputs : The number of dimensions the array has.

'Author : Andrew Baker

'Date : 25/03/2000

'Notes :

Function ArrayNumDimensions(avInArray As Variant) As Long

Dim lNumDims As Long

If IsArray(avInArray) Then

On Error GoTo ExitSub

Do

lNumDims = UBound(avInArray, ArrayNumDimensions + 1)

ArrayNumDimensions = ArrayNumDimensions + 1

Loop

End If

ExitSub:

On Error GoTo 0

End Function

Finding the most recently updated file in a directory (using LastModified time)

The code below is optimised to quickly find the most recently used file in a specified directory and returns its full name.

Option Explicit

Private Const MAX_PATH As Long = 260

Private Const INVALID_HANDLE_VALUE As Long = -1

Private Const FILE_ATTRIBUTE_ARCHIVE As Long = &H20

Private Const FILE_ATTRIBUTE_COMPRESSED As Long = &H800

Private Const FILE_ATTRIBUTE_DIRECTORY As Long = &H10

Private Const FILE_ATTRIBUTE_HIDDEN As Long = &H2

Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80

Private Const FILE_ATTRIBUTE_READONLY As Long = &H1

Private Const FILE_ATTRIBUTE_TEMPORARY As Long = &H100

Private Const FILE_ATTRIBUTE_FLAGS = FILE_ATTRIBUTE_ARCHIVE Or FILE_ATTRIBUTE_HIDDEN Or FILE_ATTRIBUTE_NORMAL Or FILE_ATTRIBUTE_READONLY

Private Type FILETIME

dwLowDateTime As Long

dwHighDateTime As Long

End Type

Private Type SYSTEMTIME

wYear As Integer

wMonth As Integer

wDayOfWeek As Integer

wDay As Integer

wHour As Integer

wMinute As Integer

wSecond As Integer

wMilliseconds As Integer

End Type

Private Type WIN32_FIND_DATA

dwFileAttributes As Long

ftCreationTime As FILETIME

ftLastAccessTime As FILETIME

ftLastWriteTime As FILETIME

nFileSizeHigh As Long

nFileSizeLow As Long

dwReserved0 As Long

dwReserved1 As Long

cFileName As String * MAX_PATH

cAlternate As String * 14

End Type

Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long

Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long

Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long

Private Declare Function SearchTreeForFile Lib "imagehlp.dll" (ByVal sFileRoot As String, ByVal InputPathName As String, ByVal OutputPathBuffer As String) As Boolean

Private Declare Function FileTimeToLocalFileTime Lib "kernel32" (lpFileTime As FILETIME, lpLocalFileTime As FILETIME) As Long

Private Declare Function FileTimeToSystemTime Lib "kernel32" (lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) As Long

'Purpose : Performs a recursive search for a file or file pattern.

'Inputs : asMatchingFiles See outputs.

' sRootPath The path to begin the search from eg. "C:\"

' sSearchFor The file name or pattern to search for eg. "Test.xls" or "*.xls"

' bRecursiveSearch If True searchs all subfolders in sRootPath for matching files.

'Outputs : asMatchingFiles A one based, 1d string array containing the paths and names of

' the matching files. SEE NOTES.

' Returns the number of matching files.

'Author : Andrew Baker

'Date : 02/10/2000 15:11

'Notes : Example:

' FileSearch asFiles, "C:\", "*.ocx", True 'Populates asFiles with all the .ocx files on your C: drive

'Revisions :

Function GetMostRecentFileName(ByVal sRootPath As String, Optional sPattern As String = "*") As String

Dim tFindFile As WIN32_FIND_DATA

Dim lHwndFile As Long

Dim sItemName As String, sThisPath As String

Dim dtMostRecentLastMod As Date, dtThisFileMod As Date

Dim sMostRecentFile As String

Dim tThisFileTime As FILETIME

Dim tThisFileSysTime As SYSTEMTIME

On Error Resume Next

If Right$(sRootPath, 1) <> "\" Then

sRootPath = sRootPath & "\"

End If

'Get handle to folder

lHwndFile = FindFirstFile(sRootPath & sPattern, tFindFile)

If lHwndFile <> INVALID_HANDLE_VALUE Then

'-------Found a matching file, loop over other matching files

Do

If (tFindFile.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) = False Then

'Found file

sItemName = Left$(tFindFile.cFileName, InStr(1, tFindFile.cFileName, vbNullChar) - 1)

If Len(sMostRecentFile) = 0 Then

sMostRecentFile = sRootPath & sItemName

Else

tThisFileTime = tFindFile.ftLastAccessTime

FileTimeToLocalFileTime tThisFileTime, tThisFileTime

FileTimeToSystemTime tThisFileTime, tThisFileSysTime

dtThisFileMod = DateSerial(tThisFileSysTime.wYear, tThisFileSysTime.wMonth, tThisFileSysTime.wDay) + TimeSerial(tThisFileSysTime.wHour, tThisFileSysTime.wMinute, tThisFileSysTime.wSecond)

If dtThisFileMod > dtMostRecentLastMod Then

sMostRecentFile = sRootPath & sItemName

dtMostRecentLastMod = dtThisFileMod

End If

End If

End If

Loop While FindNextFile(lHwndFile, tFindFile)

'Close find handle

lHwndFile = FindClose(lHwndFile)

End If

GetMostRecentFileName = sMostRecentFile

End Function

'Demonstration routine

Sub Test()

Dim sMostRecentFile As String

sMostRecentFile = GetMostRecentFileName("\\ldnpsm020161\FTP\Compliance")

Debug.Print sMostRecentFile

End Sub

Tip: Fixing issue with windows and menus not drawing (bouncing explorer.exe)

I have seen a problem in Windows (since Win2k) which I have never had the time to get to the bottom off. The sympton of the problem is that menus stop appearing and you can't get new applications to appear + you can't even get the task manager to display itself. Ultimately you end up rebooting. Anyway, I have found that if you bounce the explorer.exe process the problem disappears.

So save the following script into a file on your desktop called "RestartExporer.Bat" and run it when you box starts to die:

taskkill /F /IM explorer.exe

start c:\winnt\explorer.exe

Returning the difference between two times in milliseconds

The code below returns the time difference in milliseconds between to times.

'Purpose : Returns the difference between two time variables in ms.

'Inputs : startTime The start time (eg 12:01:49.637)

' endTime The end time (eg 12:01:49.640)

'Outputs : Returns the difference between two time variables in ms.

'Author : Andrew Baker

'Date : 31/12/2000 13:51

'Notes :

'Revisions :

Public Function TimeDiffMs(startTime As Variant, endTime As Variant) As Variant

Dim startDateTime As Double, endDataTime As Double

Dim dStartMs As Double, dEndMs As Double

Dim lPos As Long

Dim dNumMsInDay As Double

On Error GoTo ErrFailed

If startTime = endTime Then

TimeDiffMs = 0

ElseIf Len(startTime) = 0 Or Len(endTime) = 0 Then

TimeDiffMs = 0

Else

lPos = InStr(startTime, ".")

If lPos Then

dStartMs = CDbl(Mid(startTime, lPos + 1))

startTime = Left(startTime, lPos - 1)

End If

lPos = InStr(endTime, ".")

If lPos Then

dEndMs = CDbl(Mid(endTime, lPos + 1))

endTime = Left(endTime, lPos - 1)

End If

dNumMsInDay = 24# * 60# * 60# * 1000#

startDateTime = (CDbl(TimeValue(startTime)) * dNumMsInDay) + (dStartMs)

endDataTime = CDbl(TimeValue(endTime)) * dNumMsInDay + (dEndMs)

TimeDiffMs = endDataTime - startDateTime

End If

Exit Function

ErrFailed:

TimeDiffMs = Err.Description

Err.Clear

End Function