Idealism is what precedes experience; cynicism is what follows...

Showing posts with label Best Practices. Show all posts
Showing posts with label Best Practices. Show all posts

Monday, July 21, 2008

Workaholics United : Consider All Factors (CAF)

In any situation, certain givens define the range of how we perceive it. By expanding the scope of considerations with a conscious effort, we can increase the span of our attention to aspects that might have otherwise been missed.

Consider All Factors (CAF) is an attention directing tool designed to do this. During a defined interval of time, you mentally list every consideration about a topic you can think of, as opposed to just the first few that come to mind.
An example

A shy person is invited to a party. His default reaction is to think, “I’m just not an extrovert.” For this exercise he decides to enrich his perspective by considering other factors in that social situation:

* Body language
* Greetings
* Response to questions
* Questions to ask others
* Dressing for impact
* First impressions
* Smiling
* Who’s there that I already know?
* Purpose of attending
* Anxiety created by unfamiliarity

Some considerations arguably overlap: first impressions, dressing for impact, smiling. It doesn’t matter, and would be counterproductive to censor new angles on what might be thought of as the same theme, since the only way to really know is in hindsight. In this case, the person might not have previously paid any attention to the role of personal appearance in creating good first impression, despite that factor being obvious to others.

By consciously distributing cognition around a topic, he gives himself new things to think about. The consideration “purpose of attending” might contrast with going to the party simply because he was asked, instead of having a deliberate focus to guide to his behavior. The consideration, “anxiety created by unfamiliarity” is interesting. One strategy for overcoming his social apprehension is to familiarize himself with everyone in the room, making as many introductions as possible to avoid being confronted with a crowd of strangers.
Other examples

We can “do a CAF” for a couple of minutes on just about any topic, either for better planning or simply for its own sake as a mental exercise. Doing a CAF on apartment hunting might yield:

* Commute to and from work
* Length of lease
* Rent
* Total move-in cost
* Impression of landlord
* Square footage
* Aesthetics
* Noise level of surrounding area
* Walking distance to amenities (e.g. stores, parks)
* Parking
* Consensus with other decision makers
* Furniture
* Pets
* Terms of rental agreement

Again, some overlap. Pets and lease length would be covered in the rental agreement, but isolating “terms of rental agreement” as a separate item might prompt the apartment hunter to look more carefully for unreasonable clauses instead of taking the contract for granted. Notice that the apartment hunter has also factored in “impression of landlord” as a conscious consideration rather than leaving it as an afterthought or subliminal intuition.

Starting a exercise program:

* Type of exercise
* Clothing
* Equipment
* Schedule
* Home, gym, personal trainer?
* Fitness goals (e.g. weight, running distance)
* Handling eventual decline in discipline or enthusiasm
* Nutrition
* Documenting progress

This person has identified a decline in discipline and enthusiasm as something to deal with before its onset. It’s much easier to plan for setbacks in advance than trying to address them while they’re happening.

And now to the essence of my point... If you apply CAF to a software programming task, and the benefits become much more apparent. Make it a habit to perform a CAF at the inception of a programming assignment, and you will experience that your estimates will be closer to actual outcome and that your solution quality will increase because you become able to handle many issues pro actively, which may in other cases have become problems and forced you to do hacks-tweaks in order to get the code to conform to functional requirements within your estimated time frame.

The more you practice the CAF operation, the easier it gets, and less inclined you are to be satisfied with accepting the first considerations that immediately come to mind. When you think about a new topic, you’ll begin to instinctively ask yourself, “What am I missing?”

Sunday, July 20, 2008

Estimation : Off-The-Cuff Estimates

Project teams are sometimes trapped by off-the-cuff estimates.

A projectmanager on a team asks, for example, "How long would it take to implement this component", while showing the developer a wireframe. The immediate response is typically, "I don't know. I think it might take a week. I'll check into it", and of the developer is to his/her desk to investigate the functional requirements further. Back at the desk the developer looks at the design and code for the component, back at the desk the developer notices a few things forgotten when the PM asked the question, adds up the changes and decides that it would take about 3 weeks. The developer hurry over to the PM's desk to update the first estimate, but the PM is in a meeting and therefore not to be found. Later that day the PM suddenly appear at the developer's desk and happily notifies the developer (before this can get a word out): "Since it seemed like a small project, I went ahead and talked to the customer about it. He was very excited about it and can't wait to see the component next week. Can your start working on it today?".

I have found that the safest policy is NOT to give off-the-cuff estimates. Using intuition and guessing as basis of software estimates are almost always related with cost and schedule overruns.

One of the errors people commit when estimating solely from personal memory is that they compare the new project to their memory of how long a past project took, or how much effort is required. Unfortunately peoples sometimes remember their estimate for the past project rather than the actual outcome of the past project. If they use their past estimate as the basis for a new estimate, and the past project's actual outcome was that it overran its estimate, guess what? The estimator has just calibrated a project overrun into the estimate for the new project.

While guessing and intuition most definitely are positively correlated with project overruns, another less recognized fact is that the use of documented facts are negatively correlated with project overruns. In other words, there is a world of difference between giving the PM an off-the-cuff estimate versus saying, "I can't give you an answer of the top of my head, but let me go back to my desk, check a few notes, and get back to you in 15 minutes. Would that be OK?".

While this is a simple point, off-the-cuff estimates is one of the most common errors that project teams make. So in order to become a better software engineer, we need to stop delivering off-the-cuff estimates !

This blog post is the first in a long series about estimation I will be doing. Estimation is probably the single most important skill next to actual programmatic skills for a programmer, and even for non-programmers estimation is one of the most frequently performed activities, however also one of the skills that we pay the least attention to.

First step in becoming a better estimator is to realize that off-the-cuff estimates are invalid and errorprone, and should be replaced by a structured analysis of the entity being estimated based on documented facts.

Workaholics United : Playing the Percentages

Whenever management lays down some new policies for customers or employees, there will inevitably be some degree of blowback. Any change, from moving to a outsourcing to India to moving furniture from one department to another, disrupts our sphere of comfort.

Since I can’t get away with simply saying, “Well, that’s different from what I’m used to,” I would be inclined to gather some negative results designed to invalidate the new policy. One time I was asked to implement an email autoresponder with text I disagreed with. After a few days, I got a couple of complaints from customers, so I argued to the boss that we should scrap the autoresponder. Referring to the complaints, he asked the question I’d come to expect from him:

“What percentage of the time does this happen?”

I sighed, knowing that not only had I been shot down, but that he was right in principle. I felt foolish telling him that I had received three complaints out of hundreds of email exchanges.

With any new project, some things are bound to go wrong. A zero-defect mentality is a zero-action policy. For practical goal realization, the operative principle should be to contain risk, not eliminate it. A certain amount of risk analysis is healthy. The trick is to identify the point of diminishing returns where further steps to reduce risk are actually attempts to eliminate risk, which is unrealistic.

There’s no formula for determining that point, only an intuition or an arbitrary definition that involves asking an answer certain questions:

* How seriously would the problem impact this?
* What percentage of the time does the problem happen?
* What percentage is acceptable?
* Is the problem irreversible?
* What other problems could happen?
* What steps could be taken to fix the problem?
* What steps could be taken to prevent the problem without abandoning the project?
* What problems would result from abandoning the project?
* Does the positive impact of success outweigh the negative impact of failure?

Psychologically, risk is “contained” when it’s given precisely the amount of attention appropriate to it, not more. The focus is predominantly on the likelihood of a negative outcome rather than the details of it. Problems are converted into projects, defined in terms of successful outcomes and next actions.

Recognize the difference between creating slack and being a slacker. Define your margin for error and embrace the art of strategic failure as a practical price to pay for accomplishing bigger goals.

Saturday, July 19, 2008

21 laws of Programming

1. Any given program, once deployed, is already obsolete.
2. It is easier to change the specification to fit the program than vice versa.
3. If a program is useful, it will have to be changed.
4. If a program is useless, it will have to be documented.
5. Only ten percent of the code in any given program will ever execute.
6. Software expands to consume all available resources.
7. Any non-trivial program contains at least one error.
8. The probability of a flawless demo is inversely proportional to the number of people watching, raised to the power of the amount of money involved.
9. Not until a program has been in production for at least six months will its most harmful error be discovered.
10. Undetectable errors are infinite in variety, in contrast to detectable errors, which by definition are limited.
11. The effort required to correct an error increases exponentially with time.
12. Program complexity grows until it exceeds the capabilities of the programmer who must maintain it.
13. Any code of your own that you haven’t looked at in months might as well have been written by someone else.
14. Inside every small program is a large program struggling to get out.
15. The sooner you start coding a program, the longer it will take.
16. A carelessly planned project takes three times longer to complete than expected; a carefully planned project takes only twice as long.
17. Adding programmers to a late project makes it later.
18. A program is never less than 90% complete, and never more than 95% complete.
19. If you automate a mess, you get an automated mess.
20. Build a program that even a fool can use, and only a fool will want to use it.
21. Users truly don’t know what they want in a program until they use it

Sunday, June 15, 2008

The benefits of Functional Design

In continuation of my latest post regarding easily maintainable systems, I will start by writing about the benefits of Functional Design.

A functional design assures that each modular part of a computer program has only one responsibility and performs that responsibility with the minimum of side effects on other parts. Functionally-designed modules tend to have low coupling as concrete side-effect and more importantly, they scale much better than other types of designs.

The advantage for implementation is that if a software module has a single purpose, it will be simpler, and therefore easier and less expensive, to design and implement.
Systems with functionally-designed parts are easier to modify because each part does only what it claims to do.

Since maintenance is more than 3/4 of a successful system's life, this feature is a crucial advantage. It also makes the system easier to understand and document, which simplifies training. The result is that the practical lifetime of a functional system is longer.

In a system of programs, a functional module will be easier to reuse because it is less likely to have side effects that appear in other parts of the system.

The Standard way to assure functional design is to review the description of a module. If the description includes conjunctions such as "and" or "or", then the design has more than one responsibility, and is therefore likely to have side effects. The responsibilities need to be divided into several modules in order to achieve a functional design.

To perform Functional Design is quite easy, you can start by defining packages/namespaces based on Use Cases as can be illustrated by the following package definition:

com.hello.usermanagement.createUser

The package above would then contain all the classes which makes up the concrete use case implementation. In the case of a Flex application it would contain at least the Command and Event, but depending of the lines drawn in architecture - possibly the forms and UI objects as well.

This should be seen in contrast to having the Command in a namespace called Commands and the Event in a namespace called Events.

Functional Design has one limitation, and that is that you need an underlying set of baseclasses which implement all your Boilerplate code and thus faciliate that your concrete namespaces dont need to be to highly coupled to other parts of the system on the same level.

Maintenance is more than 3/4 of a successful system's life

A frequent question is why we as developers prefer to make quality code and why we hate to hack together a system in order to meet a business objective, typically a unreasonable deadline or an unreasonable amount of time allocated to a project.

The answers is pretty simple, us developers spend apr. 3/4 of our working life maintaining systems - not defining them.
This is the reason why quality in application design becomes desirable at the cost of immediate productivity.

I will address this issue in a series of blogposts where I try to define what I consider to be the constitution of a well implemented system design and what defines an easily mantainable system...

Low Coupling

If I should choose only one thing from the knowledge I gained from my software engineering classes at university, I would have to go with "Low Coupling / High Cohesion"...

However, it appears that not all have been introduced to universal truth of the objective regarding implementing this in system design and architecture.

Coupling can be "low" (also "loose" and "weak") or "high" (also "tight" and "strong"). Low coupling refers to a relationship in which one module interacts with another module through a stable interface and does not need to be concerned with the other module's internal implementation. With low coupling, a change in one module will not require a change in the implementation of another module. Low coupling is often a sign of a well-structured computer system, and when combined with high cohesion, supports the general goals of high readability and maintainability.

Systems that do not exhibit low coupling might experience the following developmental difficulties:

* Change in one module forces a ripple of changes in other modules.
* Modules are difficult to understand in isolation.
* Modules are difficult to reuse or test because dependent modules must be included.

The concept of coupling is usually related to the concept of cohesion: low coupling facilitates high cohesion, and vice versa. For example, one approach to increasing cohesion is functional design, which seeks to limit the responsibilities of modules along functionally-related boundaries. Modules with single responsibilities tend to communicate less with other modules, which typically causes the side-effect of reduced coupling.

Low coupling may also reduce performance, and a highly-coupled system is sometimes desirable to achieve maximum efficiency. Regardless, in many modern computing systems, the cost of reduced performance is often seen as a worthy trade for the benefits to the software development process that result from low coupling.

If you have no idea what I am talking about or would like to read more about how to obtain this in Flex, there is a pretty good article @ adobe.com that describes it pretty well and in great detail...

Check it out...
http://www.adobe.com/devnet/flex/articles/loose_coupling.html

Mock Frameworks, not for everyone and everytime

A frequent question is when should I use a mock object framework ?
However, if you have to ask "when", the answer is probably "not now". I feel that mock object frameworks are something you have to evolve into.

First, we can talk about mocks in general. Some people have a misconception that mock objects are only useful if you need to simulate interaction with a resource that is difficult to use in unit tests - like an object that communicates with an SMTP server. This isn't true.

* The real object has nondeterministic behavior
* The real object is difficult to setup
* The real object has behavior that is hard to trigger
* The real object is slow
* The real object is a user interface
* The real object uses a call back
* The real object does not yet exist

If we were to step back and generalize this list, we'd say test doubles are useful when you want to isolate code under test. Isolation is good. Let's say we are writing tests for a business component. We wouldn't want the tests to fail when someone checked in bad code for an auditing service the business component uses. We only want the test to fail when something is wrong with the business component itself. Providing a mock auditing service allows us to isolate the business component and control any stimuli the component may pick up from its auditing service. When you start feeling the pain of writing numerous test doubles by hand, you'll know you need a mock object framework.

Mocks aren't just about isolation, however. Mocks can play an important role at any time if employed correctly. Mocks can be powerful technique for identifying types in a system based on the roles that objects play … In particular, we now understand that the most important benefit of Mock Objects is what we originally called interface discovery.

Using a mock object framework allows a continuous, top-down design of software. But Aren't Mock Object Frameworks Complex?

This is another question I've been asked recently. Mock object frameworks are actually rather simple and expose a small API. There is complexity, though, just not in the framework itself. As I said earlier, I think there is a path you can follow where you evolve into using mock object frameworks. The typical project team using a mock object framework is experienced with inversion of control containers. Trying to get up to speed on all these topics at once can be overwhelming.

There is also some complexity in using mocks effectively. In Mocks and the Dangers of Overspecified Software, Ian Cooper says:

"When you change the implementation of a method late in the implementation process, mocks can break because you now make additional or different calls to the dependent component that is being mocked. … The mocks began to make our software more resistant to change, more sluggish, and this increased the cost to refactoring. As change becomes more expensive, we risked becoming resistant to making it, and we risk starting to build technical debt. A couple of times the tests broke, as developers changed the domain, or changed how we were doing persistence, without changing the test first, because they were frustrated at how it slowed their development. The mocks became an impedance to progress."

Mock object frameworks make interaction based testing easy, but can also lead to the problems Ian outlines. Here a couple more reads on this topic:

* Guidelines to Using Interaction Based Testing
* Why Mock Frameworks Suck

In summary – mock object frameworks aren't for everyone. You'll know when you need one!

Saturday, June 14, 2008

Be your own toolsmith and instrument your applications

Any craftsman is only as good as his or hers tools allow him to be. I am not saying that a poor craftsman will become great with good tools, but a great craftsman will become poor if the tools does not match the skillset of the craftsman.
Historically I have always been a relentless early adopter in regards to programming languages and platforms, I have therefore often lacked proper toolsupport in order for me to accomplish working with the new technology and still remaining highly productive. It has thus become as a second nature for me to instrument the systems I work on with build-in highlevel tools to aid development.

I never thought about this consciously until I read Dave Colletas article about some tools they have build into Buzzword in order to debug the application.
His article made me think that its perhaps not as widely an adopted technique than I was walking around thinking.

Check it out...
http://www.colettas.org/?p=234

Adobe Flex : Coding Standards

In this months edition of the Adobe Edge newsletter, there is a an excellent article about coding standards in the Adobe eco-system.

Check it out...
http://www.adobe.com/newsletters/edge/june2008/articles/article6/index.html

Adobe Flex : Remember that the MXML inherits from the base logic class.

What this means is that as you add children components to the MXML and you want the ActionScript Logic to manipulate them you have to make sure the ActionScript has them declared. To declare them you have to define properties in the ActionScript class whose name matches the component id you use in the MXML. For example, look at the Button id in the MXML above and notice that I have a public property in the ActionScript with the same name. The property must be public in the ActionScript class and you should mark them as [Bindable] so that if you have other components binding to them the change watcher system still operates as expected.

This works because the MXML file is an extension of the base logic class and the components with the matching id is equivalent to overriding the properties in the ActionScript. You may wonder why the properties have to be public and not protected if this is an override. The issue is that the MXML components are not part of the MXML class, they are children of the MXML class. Since they are children they do not have access to the ActionScript class’ protected methods and the compiler will see their id as a duplicate name for the MXML class, which is invalid. If the method is public, the compiler interprets this MXML component id as an override and it works. So, long story short… always make the properties [Bindable] public.

Adobe Flex : Never try to manipulate the children components from the ActionScript constructor

This is a common mistake made by developers using this pattern. For example, you try to set the button label in the constructor. If you tried this you would get a null value error for the button since it has not been created yet. MXML creates the children components in the initialize() phase so the best way to work around this is to override initialize(), call super.initialize() first and then you can start accessing children components.

Adobe Flex : Coding Conventions

The Adobe Flex Team has taken the initiative to create a Coding Convention for Flex solutions.
Its not yet complete, and some places they still have some TBD's... however, the stuff thats already available should be read and understood by every Flex developer.

We are not following all of them rigidly on my team, however.. we will use the Coding Convention from Adobe to assess the places where we defer and check their validity in contrast to the Adobe Coding Convention.

Check it out...
http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions

Adobe Flex : Never try to removeChildren() that are defined in MXML

This is a mistake that sometimes works when you try it but in most cases this just causes a lot of heartache. Usually the heartache occurs after you have been doing this for a while and you then have to go back and fix a lot of code that was dependent on the first removeChild(). Unfortunately I have seen this first hand and its not a pretty sight. If you are doing a lot of children manipulation then you will want to move away from MXML declaration and handle the children creation/removal all in ActionScript.

Adobe Flex : Event/Action binding in MXML and AS

Try to avoid mixing and matching MXML and ActionScript event/action binding. This is also more of a recommendation then a requirement. If you start binding the creationComplete or click events in MXML try to bind them all in MXML. If you bind your events in ActionScript try to bind all of them in ActionScript. Once you start mixing and matching it can be hard to track down code flow later on. You may find yourself wondering why an event keeps triggering because you left it in MXML and forgot about it. In my above example I bind the click event. You can easily do this in the initilize() method using addEventListener(). Use what works best for you.

Adobe Flex : The Code-Behind Pattern

The Flex code-behind pattern is a design pattern that is not known or used by a lot of developers. The initial concept of the pattern was based on the ASP.NET development pattern where the layout is handled in a main file and a secondary “backing” file handles all the logic. The goal of the pattern is to create a clear separation of logic and layout.

When you first learn Flex there is often confusion between what MXML is and how it relates to ActionScript. We tend to think of it as different entities, but the reality is MXML is just an abstracted form of ActionScript. MXML is a declarative XML syntax that is converted by the compiler into an ActionScript class. This is an important concept to understand because this is the root of why the compiler throws an error when trying to have a MXML file and an ActionScript File with the same name in the same package. The MXML file is really just an ActionScript class and therefore we have a conflicting namespace error.

To help visualize this, imagine the root node of the MXML file is the same as an extends statement.

When we use something like this in MyApp.mxml:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
...
</mx:Application>


We are really saying:
public class MyApp extends Application

So why do we need an MXML syntax if it just becomes ActionScript. As you are probably well aware, doing complex layout in ActionScript takes a ton of code, especially when you get into the world of nested layout. It can be done in code but why would you want to? XML is all about parent/child hierarchies and by using this as a layout language you can quickly define complex organizational structures that would have taken hundreds of lines of code if you did it all in ActionScript. Now that we have a better understanding of the MXML/ActionScript relationship we can start talking about how the pattern is implemented.

When looking at Adobe’s MXML examples we often see them using the tag to define any ActionScript that is required to make the MXML example work. This approach is fine for simple examples but once we begin development of a larger application using Flex, having all the MXML logic in a single tag becomes unwieldy. Even if the code is written by the most organized developer, once you hit 300+ lines of ActionScript with 100 lines of MXML it becomes hard to see the forest from the trees.

One way to solve this is to use the source attribute in the tag and set it to an external AS file. This helps because you now have separated all your ActionScript out of the MXML but now you have externalized AS files that aren’t really classes, that sit in the file structure and you can’t extend from them.

The Code-Behind pattern is a solution to this issue. The first step is to create an ActionScript class that extends the base type that you want your MXML file to be. For example, a Canvas:
package com.hello.demo
{
import mx.containers.Canvas;

public class MyComponentLogic extends Canvas
{

}
}

I have now created a Class in the com.hello.demo package that extends from Canvas. This is my backing logic class that my MXML extends from. Note that I have used the postfix “Logic” to create a unique name. If you recall, our MXML and AS have to be different names. I prefer the “Logic” postfix but you can use “Base” or “Backing” or any other postfix/prefix you like. Now, you can create the MXML file. In this example let’s assume the MXML component is in the same package as the ActionScript:
<MyComponentLogic
xmlns="com.hello.demo.*"
xmlns:mx="http://www.adobe.com/2006/mxml">
...
</MyComponentLogic>

This code would be in an MXML file called MyComponent.mxml. The MXML now extends from the ActionScript and we can begin to start laying out content and adding logic as needed.

Some alternatives to the technique I describe here, is to use the Supervising Controller pattern or the ViewHelper. However, a sidenote to the Supervising Controller is that you should probably choose to call the classes for ...Presenter instead if ...Controller as the use of Controller seems to put some people of if they are not familiar with this pattern and leading them to think they are FlowControllers or ApplicationControllers. Read more about the Supervising Controller pattern at Martin Fowler's excellent website... http://martinfowler.com/eaaDev/SupervisingPresenter.html

Friday, June 13, 2008

SVN : Frequency of Update&Commit cycles

Its very disputed indeed, however I have experienced that some practices in using SVN results in less conflicts than others.
The practices which yield the best results depend highly on the method in the organization and the general practices of the team.
Every opinion I share in this post is therefore based on the notion that it works in the company I work for and the current team I am working in as well as the codebase we are working on.

During a development cycle I will probably end up updating every hour or so. This is not a conscious activity, but more of a habit as it has proven to allow me to experience long periods of no conflicts or merges.
I should perhaps point out that I work as an architect on a system with about 10 developers and a codebase of apr. 3500 classes divided into vast amounts of modules and libraries. Our SVN is configured with positive assertiveness so we let the SVN assume that conflicts will not appear and that if they do, merges will be possible. This works well for us.

The single most important rule of SVN engagement on my slate is the "Update Prior Commit" dictating that I always run an update before I execute a commit. SVN will warn you anyways, but it gives me a second to think about what I am committing which I have think gives me some percentages in regards to preventing SVN errors.

I would say that anyone in our organization should commit at least every day and should update at least a couple of times per day. This is due to the very lively nature of our current codebase which kinda means that we don't have any very stable areas in the codebase except for our core classes.

If the task at hand is too big to be committed every day, it should be branched and hence committed every day. This practice has a couple of times proven to work as an invaluable backup when disks have malfunctioned or users have caused Error-40's (In case you don't know I what I am referring to with "Error-40", ask a computer-saavy Dane - (s)he will tell you :-) )

(to be continued)

Sunday, June 08, 2008

State Machines : The C in PureMVC

I have some difficulty figurering out how to combine the notion of a statemachine workflow with the PureMVC notion of commands as the primary work-units. Using states seems to defy the need for commands and if not in direct conflict only because one could imagine using the statechange events to trigger commands. However, the ladder seems to create additional complexity in return of no other benefit than being able to use a statemachine workflow as the primary driver in a strict PureMVC system without removing logic from the commands.

Cliff Hall started a working group with this focus, but it appears that they too have had some difficulty cornering the right way to combine this.

Check it out...
http://forums.puremvc.org/index.php?board=25.0

State Machines : Windows Workflow Foundation

Windows Workflow Foundation has buildin support for building state-machine workflows to be used from any dotNet based host.

I will explore this in the upcoming weeks in relation to my effort to contribute to the further development of State Machine support in the PureMVC framework.

Check it out...
http://msdn.microsoft.com/en-us/netframework/aa663328.aspx

State Machines : Basic Thoughts

There is one important decision to make when creating a new workflow. Will the workflow be a sequential workflow, or a state machine workflow? Windows Workflow provides these two types out of the box. To answer the question, we have to decide whois in control.

A sequential workflow is a predictable workflow. The execution path might branch, or loop, or wait for an outside event to occur, but in the end, the sequential workflow will use the activities, conditions, and rules we've provided to march inevitably forward. The workflow is in control of the process.

A state-machine workflow is an event driven workflow. That is, the state machine workflow relies on external events to drive the workflow to completion. We define the legal states of the workflow, and the legal transitions between those states. The workflow is always in one of the states, and has to wait for an event to arrive before transitioning to a new state. Generally, the important decisions happen outside of the workflow. The state machine defines a structure to follow, but control belongs to the outside world.

We use a sequential workflow when we can encode most of the decision-making inside the workflow itself. We use a state machine workflow when the decision-making happens outside the workflow.

My Network