Things to ask before you redo your website

« Chai Wallah | Blog Home | The priority list »

Things to ask before you redo your website

I don't do any consulting, but that doesn't stop people from asking me questions. The most common question people ask me when they want a new website is, "If you were in charge of this, who are the 2 or 3 people you’d want to be sure to talk to – to help think through the issues, help us figure out who should do the work, etc.?"

The second most common question people ask me,  "In addition to Apple’s site, are there 2 or 3 that you think are really appealing and work well for their business?"

I think these are perhaps the tenth and eleventh questions you should ask, not the first two. Here's my list of difficult and important questions you have to answer before you spend a nickel:

  • What is the goal of the site?
  • In other words, when it's working great, what specific outcomes will occur?
  • Who are we trying to please? If it's the boss, what does she want? Is impressing a certain kind of person important? Which kind?
  • How many people on your team have to be involved? At what level?
  • Who are we trying to reach? Is it everyone? Our customers? A certain kind of prospect?
  • What are the sites that this group has demonstrated they enjoy interacting with?
  • Are we trying to close sales?
  • Are we telling a story?
  • Are we earning permission to follow up?
  • Are we hoping that people will watch or learn?
  • Do we need people to spread the word using various social media tools?
  • Are we building a tribe of people who will use the site to connect with each other?
  • Do people find the site via word of mouth? Are they looking to answer a specific question?
  • Is there ongoing news and updates that need to be presented to people?
  • Is the site part of a larger suite of places online where people can find out about us, or is this our one sign post?
  • Is that information high in bandwidth or just little bits of data?
  • Do we want people to call us?
  • How many times a month would we like people to come by? For how long?
  • Who needs to update this site? How often?
  • How often can we afford to overhaul this site?
  • Does showing up in the search engines matter? If so, for what terms? At what cost? Will we be willing to compromise any of the things above in order to achieve this goal?
  • Will the site need to be universally accessible? Do issues of disability or language or browser come into it?
  • How much money do we have to spend? How much time?
And finally,
  • Does the organization understand that 'everything' is not an option?

Posted by Seth Godin on September 18, 2009 | Permalink

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83451b31569e20120a53be506970c

Listed below are links to weblogs that reference Things to ask before you redo your website:

» Is It a Website or a Tomato? from Bob Poole's Water Cooler Hangout
Something else occurred to me as I bit into that red, juicy, sweet, right-off-the-vine tomato yesterday. I could see that it was perfect, it felt plump and ripe in my hand, and when I closed my eyes I could smell... [Read More]

Tracked on September 18, 2009 at 08:47 AM

» 20 Questions to Ask before You Launch Your Content Project from Junta42 blog
As usual, Seth has done it again. I've taken Seth's questions to ask on launching your next website and adapted them a bit for content marketing. As you put your next content plan together, use these questions. You won't be... [Read More]

Tracked on September 18, 2009 at 08:52 AM

» Redesigning Your Website? Ask These Questions First!!! from Sales, Marketing & Advertising for the Plastics Industry
In Seth Godin's recent blog posting, 'Things to ask before redoing your website', he hits the nail on the head! Make sure you not only read this posting, but ask the questions and better yet, answer them ---- before you... [Read More]

Tracked on September 18, 2009 at 10:28 AM

» Redesign? Ask The Right Questions! from FutureNow's GrokDotCom / Marketing Optimization Blog
Seths blog post on Things to ask before you redo your website is amust read for everyone involved in online marketing.   Seriously.  If you havent seen it yet, go read it now. What I love most about this list is the way it s... [Read More]

Tracked on September 18, 2009 at 11:46 AM

« Chai Wallah | Blog Home | The priority list »

Loading mentions Retweet
Comments (0)

Consuming a WCF service using a native WWS client

I have been meaning to play with Windows Web Services ever since I heard Nikola Dudar talk about it at the MVP Summit earlier this year. It’s natively included with Windows 7, but can also be installed and used from older OSes (XP, Vista, 2003 and 2008). You can write native clients using WWS that can connect to a WCF service, and similarly you can write a WWS native service that can be consumed by a WCF client. It’s so compatible that you can replace either a WCF client or a WCF service with a WWS equivalent without the other party being aware of it.

One of the first things I did was write a very simple WCF service and then connected to it using a simple WWS client. I intend to write a detailed article on that in the next few days but I’ll go through the basic steps in this blog so I can use that as some basic raw material for my article.

The first thing I did was to create a very simple WCF service. Here’s the service interface :

    [ServiceContract]
interface IStringService
{
[OperationContract]
string Reverse(string s);
}

class MyStringService : IStringService
{
public string Reverse(string s)
{
return new string(s.Reverse().ToArray());
}
}

Here’s some slightly stripped out code that shows how the service is created and run.

WSHttpBinding binding = new WSHttpBinding();

// .. set properties on binding

Uri baseAddress = new Uri("http://localhost:8000/StringService");

using (ServiceHost serviceHost = new ServiceHost(
typeof(MyStringService), baseAddress))
{
ServiceMetadataBehavior smb =
serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
smb = new ServiceMetadataBehavior();

// .. set properties on smb

serviceHost.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex"
);

serviceHost.AddServiceEndpoint(
typeof(IStringService), binding, baseAddress);
serviceHost.Open();

Now there are two steps to do before we start writing the WWS native client :

  1. Use svcutil to generate WSDL from the WCF service
  2. Use the Windows WebServices compiler tool (wsutil) to generate proxies (c/h files).

Once you do this, create a native C++ console project, add the c/h files (and remember to disable precompiled headers for the C files). I am not going to show error handling code in the below code, but you need to check the HRESULT for error/success after every call. First thing is to declare some variables and also specify the service URL :

HRESULT hr = ERROR_SUCCESS;
WS_ERROR* error = NULL;
WS_HEAP* heap = NULL;
WS_SERVICE_PROXY* proxy = NULL;

WS_ENDPOINT_ADDRESS address = {};
WS_STRING url= WS_STRING_VALUE(L"http://localhost:8000/StringService");
address.url = url;

WS_STRING is a simple struct that has a WCHAR* (that will point to the string) and a ULONG that will represent the length. I’ve used the WS_STRING_VALUE macro to initialize the string there.

The WWS APIs provide rich error info through the WS_ERROR structure and so we create a WS_ERROR struct using the WsCreateError API call (using default arguments).

hr = WsCreateError(NULL,  0,  &error);
if (FAILED(hr))
{
//...
}

We also need to create a WS_HEAP object which represents an opaque heap structure (error handling not shown) :

hr = WsCreateHeap(2048, 512, NULL, 0, &heap, error); 

The next step is to create the service proxy :

WS_HTTP_BINDING_TEMPLATE templ = {};
hr = WSHttpBinding_IStringService_CreateServiceProxy(&templ, NULL, 0, &proxy, error);

WSHttpBinding_IStringService_CreateServiceProxy is a proxy function that was generated by wsutil. Internally it calls the WWS API WsCreateServiceProxyFromTemplate but it saves us the hassle of correctly and properly filling up the various arguments. Now, we open the service proxy (connects us to the service endpoint) :

hr = WsOpenServiceProxy(proxy, &address, NULL, error);

At this point we are ready to make calls into the service for which we again use the proxy functions that are generated by wsutil.

WCHAR* result;	

hr = WSHttpBinding_IStringService_Reverse(
proxy, L"Nishant Sivakumar", &result,
heap, NULL, 0, NULL, error);

if (FAILED(hr))
{
// ...
}

wprintf(L"%s\n", result);

WSHttpBinding_IStringService_Reverse is generated for us and is a pretty simple function to use, and it internally wraps the call to the WsCall WWS API function, including correctly wrapping up all the arguments and the return value. Well, that’s pretty much it. Once you are done, just call all the close/free APIs :

if (proxy)
{
WsCloseServiceProxy(proxy, NULL, NULL);
WsFreeServiceProxy(proxy);
}

if (heap)
{
WsFreeHeap(heap);
}

if (error)
{
WsFreeError(error);
}

I was absolutely thrilled when I ran the console app and it successfully connected to the WCF service. The native client is about twice as long (number of lines of code) as an equivalent managed WCF client would have been but that’s a small price to pay for the ability to consume a WCF service in pure native code. In a later blog entry I will write about how the WCF service itself can be replaced with an identical WWS service (both WCF and WWS clients will continue to work the same).


Loading mentions Retweet
Comments (0)

Rewriting a WCF service in WWS

In my last blog entry I had shown a WWS native client connecting to a WCF service. In this one I’ll talk about how the WCF service can be converted into an equivalent WWS service. Connecting clients (whether WWS, WCF, or other) would continue to behave the same. I am going to use the same c/h files that wsutil generated from the wsdl file. There is a function signature generated for us to match the service contract methods. In our case there’s just one - WSHttpBinding_IStringService_ReverseCallback. So the first thing is to add a method that matches this signature, and this will reverse a string just like the WCF service (except we write it in C or C++).

HRESULT CALLBACK Reverse(
__in const WS_OPERATION_CONTEXT* context,
__in WCHAR* s,
__out WCHAR** reverse,
__in_opt const WS_ASYNC_CONTEXT* asyncContext,
__in_opt WS_ERROR* error)
{
WS_HEAP* heap = NULL;

HRESULT hr = WsGetOperationContextProperty(
context,
WS_OPERATION_CONTEXT_PROPERTY_HEAP,
&heap,
sizeof(heap),
error);

if (FAILED(hr))
{
return hr;
}

hr = WsAlloc(
heap,
sizeof(WCHAR) * (wcslen(s) + 1),
(void**)reverse,
error);

if (FAILED(hr))
{
return hr;
}

wcscpy(*reverse, s);
wcsrev(*reverse);

return ERROR_SUCCESS;
}

I first use WsGetOperationContextProperty to get the heap and then use WsAlloc to allocate memory for the reversed string on this heap. We do not ever allocate memory using standard memory allocation mechanisms unless it’s memory we will have the option to delete/free when we are done using it. Instead we use the WWS heap which frees us from worrying about memory leaks - the memory will be released when the heap is reset or freed.

Now let’s get to creating the service. Again, I will not show the error handling code (to save space) but every HRESULT return value must be checked for success before proceeding further. The first thing is to create the error and heap objects just as we did when writing the WWS client.

WS_ERROR* error = NULL;
HRESULT hr = WsCreateError( NULL, 0, &error);
if (FAILED(hr))
{
// ...
}

WS_HEAP* heap = NULL;
hr = WsCreateHeap( 100000, 0, NULL, 0, &heap, error);
if (FAILED(hr))
{
// ...
}

The next step is to create a service endpoint.

WSHttpBinding_IStringServiceFunctionTable functions = { Reverse };

WS_STRING url = WS_STRING_VALUE(L"http://localhost:8000/StringService");

WS_HTTP_BINDING_TEMPLATE templateValue = {};

WS_SERVICE_ENDPOINT* serviceEndpoint;
hr = WSHttpBinding_IStringService_CreateServiceEndpoint(&templateValue,
&url, &functions, NULL, NULL, 0,
heap, &serviceEndpoint, error);
if (FAILED(hr))
{
// ...
}

Notice how we use the generated WSHttpBinding_IStringServiceFunctionTable to specify the list of functions (just one in our case). Now I use the proxy WSHttpBinding_IStringService_CreateServiceEndpoint to create the end point (and it internally calls WsCreateServiceEndpointFromTemplate). I have used default values for other arguments, but there is a lot of custom configuration that can be done. We’ll now create the service host:

WS_SERVICE_HOST* host;
const WS_SERVICE_ENDPOINT* serviceEndpoints[1];
serviceEndpoints[0]= serviceEndpoint;
hr = WsCreateServiceHost( serviceEndpoints, 1,
NULL, 0, &host, error);
if (FAILED(hr))
{
}

We only have one endpoint, but the service host can host multiple endpoints. While I have called WsCreateServiceHost with default arguments (basically passing NULL) it’s possible to set various service properties at this point. The last step is to open the service host.

hr = WsOpenServiceHost(host, NULL, error);

The above code will open the service and start listening on each of the endpoints (just one in our example). For a test console app, use a _getch() so the app won’t exit. Once the app’s done, close and free the service host :

WsCloseServiceHost(host, NULL, error);
WsFreeServiceHost(host);

And also free the heap/error objects :

if (heap)
{
WsFreeHeap(heap);
}

if (error)
{
WsFreeError(error);
}

You can now run the service and the WWS client from the last blog entry will connect to it and invoke the reverse function successfully. You can even write a simple WCF client and it’ll connect to this just as if this was a WCF service. I do agree that all these proxies, having to create/free structures, handling HRESULTs etc. may seem a tad foreign if you are coming from a pure C# or VB.NET world. But if you are not put off by C++, and keeping your service or client code native is important to you, then WWS sure seems to be a great way to do it. I do intend to research into WWS a little more in detail, so expect more blog entries and an article or two on the topic in future.

Loading mentions Retweet
Comments (0)

Using MSSQL to output time in days, hours and minutes

I was working on some code today where I wanted to output a time span in the format 1d 4h 36m (i.e. "1 day, 4 hours and 36 minutes.") I wanted a pure SQL solution so that I didn't have to worry about formatting later. Here's some example SQL that will format a time span by days, hours and minutes.

declare @startTime datetime
set @startTime = '2009-07-11 14:19:40.000'

declare @endTime datetime
set @endTime = getUtcDate()

select 
    convert(varchar(40), dateDiff(mi, @startTime, @endTime)/(24*60)) + 'd ' 
  + convert(varchar(40), dateDiff(mi, @startTime, @endTime)%(24*60)/60) + 'h '
  + convert(varchar(40), dateDiff(mi, @startTime, @endTime)%60) + 'm' as Format1
  , case
      when (((dateDiff(mi, @startTime, @endTime)/(24*60))) > 0) then
          convert(varchar(40), dateDiff(mi, @startTime, @endTime)/(24*60)) + 'd ' 
        + convert(varchar(40), dateDiff(mi, @startTime, @endTime)%(24*60)/60) + 'h '
        + convert(varchar(40), dateDiff(mi, @startTime, @endTime)%60) + 'm'
      when (((dateDiff(mi, @startTime, @endTime)%(24*60)/60)) > 0) then
          convert(varchar(40), dateDiff(mi, @startTime, @endTime)%(24*60)/60) + 'h '
        + convert(varchar(40), dateDiff(mi, @startTime, @endTime)%60) + 'm'
      else
          convert(varchar(40), dateDiff(mi, @startTime, @endTime)%60) + 'm'
    end as Format2
  , convert(varchar(40), dateDiff(mi, @startTime, @endTime)/(24*60)) + ':' 
  + right('00' + convert(varchar(40), dateDiff(mi, @startTime, @endTime)%(24*60)/60), 2) + ':'
  + right('00' + convert(varchar(40), dateDiff(mi, @startTime, @endTime)%60), 2) as Format3
NOTE:
Make sure to keep the dateDiff() time in minutes. If you switch to hours (or days) you'll have rounding issues you'll have to work around. By sticking to using minutes for the equations, you avoid the rounding issues.

When you run this query in Microsoft SQL Server, you'll see that it outputs 3 columns—Format1, Format2 and Format3.

Format1 always outputs the time span in format 0d 0h 0m, even when the days or hours are 0. In my case, I really wanted to ignore days if no days have passed and hours if we're still under 60 minutes. This lead me to create Format2.

Format2 still uses the 0d 0h 0m format, but it will drop off days if less than 24 hours old and drop hours if less than 60 minutes has passed. This leaves you strings like "6d 4h 52m", "4h 10m" or "3m". In my case, this was the best formatting for my uses.

Format3 is an alternative format that places the time span in the format d:hh:mm. While I'm not using that formatting currently, some people may find it useful. This also shows off how you can force the hours and minutes to output as a digit value (i.e. 0:02:01 = 0 days, 2 hours and 1 minute.)

Hopefully this will prove useful to some of you.

Loading mentions Retweet
Comments (0)

MonoDevelop 2.2 Beta 1: We go cross platform.

« Mono Survey Time! | Main | CodePlex Foundation »

MonoDevelop 2.2 Beta 1: We go cross platform.

MonoDevelop goes cross platform.

Since the beginning of time, man has yearned to get a cross platform .NET IDE. Homer's Odyssey described one man's effort to achieve such a thing. And it was not until today, September 9th of 2009 that the world can test out such a tool.

With this release MonoDevelop leaves its cozy Linux nest and embarks on a wild adventure into the hearth of MacOS and Windows. The MonoDevelop team made this one of their major goals for this release: to turn our loved IDE into a cross platform IDE.

If you are curious about the details, check out the What is new in MonoDevelop 2.2 page.

MonoDevelop on Windows

We are not only bringing MonoDevelop to OSX and Windows as a plain GUI port, but we are also providing installers, deep operating system integration and support for native debugging on each platform.

MonoDevelop on MacOS X

In addition to becoming a cross platform IDE, there are many new features in MonoDevelop.

For instance, MonoDevelop can be used to develop ASP.NET MVC applications on OSX and Linux and Silverlight applications on OSX and Linux.

Debugger

MonoDevelop now has integrated debugger support. Not only it is able to debug Mono applications, it also can work as a frontend to GDB to debug native applications.

In addition, on Linux it is possible to debug ASP.NET pages.

New Add-ins

New exciting add-ins: ASP.NET MVC, Silverlight and iPhone (for use with MonoTouch).

Policies

A common problem that we face as open source developers is that not every project uses the same coding style. Different teams use different coding conventions. MonoDevelop now supports policies to describe how files should be edited and what defaults should be used in each:

Editor Improvements

My favorite new feature is Dynamic Abbrev (Alt-/) a feature that we brought from Emacs and that fills me with joy. That being said, for the non-Emacs lovers there are plenty of features that you asked for, and that we implemented:

  • Extensive refactoring support. And I mean, it is extensive.
  • Code templates.
  • On the fly formatting.
  • Acronym Matching in Code Completion
  • XML Documentation Shown in Code Completion
  • VI mode for those users hooked up on VI commands, they can now use those within MonoDevelop.

Another pretty cool feature is the code generation support that is triggered with Alt-Insert. When you press Alt-insert it will popup a context sensitive dialog box that offers a few options of code that could be generated at this point: ToString methods, Equals/GetHashCode methods all based on existing fields and properties.

Why go Cross Platform?

Going cross platform means that developers will have the same tool across all of the operating systems they use: Windows, Mac and Linux.

.NET developers that have been enchanted by OSX will be able to continue developing software with their favorite programming languages while enjoying OSX and will be able to go back and forth between Windows, OSX and Linux as needed. This also means that they can work with developers in other platforms, regardless of the personal choices of other team members.

As many of you know, the number of contributors to a project is linked to the number of users of that project. By expanding our market presence from Linux, we expect to get contributions, fixes, improvements, bug reports, code and add-ins from developers in other platforms.

We intend to make MonoDevelop the Eclipse of the .NET community. Just like Eclipse became the foundation for Java development, we hope that MonoDevelop will become the foundation for .NET development, and hopefully for much more than that.

A multi-system IDE

We are not religious when it comes to supporting other programming languages [1]. We want to embrace not only .NET-based projects like Gtk#, Silverlight, ASP.NET, Boo, C#, F#, Visual Basic and Windows.Forms. We are also embracing other developer platforms like Python, C/C++, Vala, and we want to expand our presence to work with the Flash, PHP, Ruby, Rails, Flex and any other communities that need a cross platform IDE.

[1] we are just religious about the fact that C# is a better programming language to build an IDE than Java is.

Loading mentions Retweet
Comments (0)

Why You Should Switch from Subversion to Git

14 September 2009

Why You Should Switch from Subversion to Git

By Scott Chacon

Kevin and Gary show at FOWA London

You may have heard some hubbub over distributed version control systems recently. You may dismiss it as the next hot thing, the newest flavor of kool-aid currently quenching the collective thirst of the bandwagon jumpers. You, however, have been using Subversion quite happily for some time now. It has treated you pretty well, you know it just fine and you are comfortable with it – I mean, it’s just version control, right?

You may want to give it a second look. Not just at distributed version control systems, but at the real role of version control in your creative toolkit. In this article, I’m going to introduce you to Git, my favorite DVCS, and hopefully show you why it is not only a better version control system than Subversion, but also a revolutionary way to think about how you get your work done.

Now, this isn’t really a how-to on Git – I won’t be going over a lot of specific commands or get you up and running. This is a list of arguments on why you should be seriously considering Git if you’re currently using SVN. To learn Git, there is a free online book called Pro Git that I wrote that will walk you through Git step by step, should this article entice you. For each point I make here, I will be linking to the appropriate section of that book, should you want to find out more about that specific feature of Git.So, first we’re going to look at the inherent advantages of distributed systems over centralized ones. These are things that systems like Subversion simply cannot do. Then we’ll cover the powerful context switching and file crafting tools that are technically possible to do with Subversion, but which Git makes easy enough that you would actually use them. These tools should completely change the way you work and the way you think about working.

The Advantages of Being Distributed

Git is a distributed version control system. So what does “distributed” actually mean? Well it means that instead of running `svn checkout (url)` to get the latest version of your repository, with Git you run `git clone (url)`, which gives you a complete copy of the entire history of that project. This means that immediately after the clone, there is basically no information about that project that the server you cloned from has that you do not have. Interertingly, Subversion is so inefficient at this that in general it’s nearly as fast to clone an entire repository over Git as it is to checkout a single version of the same repository over Subversion.

Now, this gives you a couple of immediate advantages. One is that nearly every operation is now done off data on your local disk, meaning that it is both unbeliveably fast and can be done offline. This means that you can do commits, diffs, logs, branches, merges, file annotation and more – entirely offline, off VPN and generally instantly. Most commands you run in Git take longer to type then they do to execute. Now stop for a moment and try to remember how many times you’ve gone to get a cup of coffee while Subversion has been running some command. Or jot down a quick list of occasions on which you’ve wanted to commit but didn’t have an internet connection or couldn’t connect to your corporate VPN.

The other implicit advantage of this model is that your workflow does not have a single point of failure. Since every person working on your project has what is essentially a full backup of the project data, losing your collaboration servers is a minor inconvenience at best. Imagine for a moment your SVN server having a hard drive corruption – when was your last backup and how many hours will it take to get to the point where your team can start working again? In Git, any team member can push to any server where every member has SSH access and the whole team can be easily up and running in a matter of minutes.

The final advantage I’ll cover of distributed systems are the incredible workflows that are now available to you. Git does not depend on a centralized server, but does have the ability to syncronize with other Git repositories – to push and pull changes between them. This means that you can add multiple remote repositories to your project, some read-only and some possibly with write access as well, meaning you can have nearly any type of workflow you can think of.

You can continue to use a centralized workflow, with one central server that everyone pushes to and pulls from. However, you can also do more interesting things. For example, you can have a remote repository for each user or sub-team in your group that they have write access to, then a designated maintainer or QA team or integrator can then pull their work together and push it to a ‘gold’ repository that is deployed from.

An example distributed workflow involving several Git repositories

You can build any sort of heirarchical or peer-based workflow model with Git that you can think of, in addition to being able to use it as a centralized hub as in SVN. Your workflow can grow and adapt with your business model.

You can also use it in other ways – an interesting example of this is deploying on the Ruby hosting company Heroku. To deploy to their systems, you simply push to your ‘heroku’ remote repository. You can develop and collaborate on other remote repositories, but then when you actually want to deploy your code to running servers, you push to the Heroku Git repository instead. Imagine trying to do that with Subversion.

Lightweight Branches: Frictionless Context Switching

Before I begin explaining this, which is actually my favorite feature of Git, I need you to do me a favor. Forget everthing you know about branches. Your knowledge of what a ‘branch’ means in Subversion is poisonous, especially if you internalized it pre-1.5, like I did, before Subversion finally grew some basic merge tracking capabilities. Forget how painful it was to merge, forget how long it took to switch branches, forget how impossible it was to merge from a branch more than once – Git gives you a whole new world when it comes to branching and merging.

In Git, branches are not a dirty word – they are used often and merged often, in many cases developers will create one for each feature they are working on and merge between them possibly multiple times a day, and it’s generally painless. This is what hooked me on Git in the first place, and in fact has changed the entire way I approach my development.

When you create a branch in Git, it does so locally and it happens very fast. Here is an example of creating a branch and then switching to your new branch to start doing development.

$ time git branch myidea
real	0m0.009s
user	0m0.002s
sys 	0m0.005s

$ time git checkout myidea
Switched to branch "myidea"
real	0m0.298s
user	0m0.004s
sys 	0m0.017s

It took about a third of a second for both commands together. Think for a second about the equivalent in Subversion – running a `copy` and then a `switch`

$ time svn copy -m 'my idea' https://svn.example.com/trunk \
  https://svn.example.com/svn/branches/myidea
real	0m5.172s
user	0m0.033s
sys	0m0.016s

$ time svn switch https://svn.example.com/branches/myidea
real	0m8.404s
user	0m0.153s
sys	0m0.835s

Now the difference between 1/3 of a second and 13 seconds (not to mention the time it takes to remember each long URL) may not seem huge at first, but there is a significant psychological difference there. Add to that the fact that your network speed, server load and connectivity status are all factors in Subversion, where it always takes 1/3 of a second in Git and that makes a pretty big difference. Also, branching is considered a fast operation in Subversion – you will see even more pronounced speed differences in other common operations like log and diff.

However, that is not the real power of Git branches. The real power is how you use them, the raw speed and ease of the commands just makes it more likely that you will. In Git, a common use case is to create a new local branch for everything you work on. Each feature, each idea, each bugfix – you can easily create a new branch quickly, do a few commits on that branch and then either merge it into your mainline work or throw it away. You don’t have to mess up the mainline just to save your experimental ideas, you don’t have to be online to do it and most importantly, you can context switch almost instantly.

Now, once you have work on a couple of branches, what about merging? If you’re from the world of Subversion, you may cringe at that word, ‘merge’. Since Git records your commit history as a directed graph of commits, it’s generally easy for it to automatically figure out the best merge base to do a 3 way merge with. Most Subversion users are used to having to figure that out manually, which is an error prone and time consuming process – Git makes it trivial. Furthermore, you can merge from the same branch multiple times and not have to resolve the same conflicts over and over again. I often do dozens of merges a day on certain Git projects of mine and rarely have even trivial merge conflicts – certainly nothing that isn’t predictable. Raise your hand if you’ve ever done a dozen branch merges on a Subversion project at least once a week and didn’t end each day by drinking heavily.

As an anecdotal case study, take my Pro Git book. I put the Markdown source of the book on GitHub, the social code hosting site that I work for. Within a few days, I started getting dozens of people forking my project and contributing

copy edits, errata fixes and even translations. In Git, each of these forks is treated as a branch which I could pull down and merge individually. I spend a few minutes once or twice a week to pull down all the work that has happened, inspect each branch and merge the approved ones into my mainline.

The Network Graph for the Pro Git project

As of the time of writing this article, I’ve done 34 merges in about 2 weeks – I sit down in the morning and merge in all the branches that look good. As an example, during the last merge session I inspected and merged 5 seperate branches in 13 minutes. Once again, I will leave it as an exercise to the reader to contemplate how that would have gone in Subversion.

Becoming a Code Artist

You get home on Friday after a long week of working. While sitting in your bean bag chair drinking a beer and eating Cheetos you have a mind blowing idea. So, you whip out your laptop and proceed to work on your great idea the entire weekend, touching half the files in your project and making the entire thing 87 times more amazing. Now you get into work and connect to the VPN and can finally commit. The question now is what do you do? One great big honking commit? What are your other options?

In Git, this is not a problem. Git has a feature that is pretty unique called a “staging area”, meaning you can craft each commit at the very last minute, making it easy to turn your weekend of frenzied work into a series of well thought out, logically separate changesets. If you’ve edited a bunch of files and you want to create several commits of just a few files each, you simply have to stage just the ones you want before you commit and repeat that a few times.

$ git add file1.c file2.c file3.c
$ git commit -m 'files 1-3 for feature A'
$ git add file4.c file5.c file6.c
$ git commit -m 'files 4-6 for feature B'

This allows other people trying to figure out what you’ve done to more easily peer-review your work. If you’ve changed three logically different things in your project, you can commit them as three different reviewable changesets as late as possible.

Not only that, which is pretty powerful in itself, but Git also makes it easy to stage parts of files. This is a feature that has prevented coworkercide in my professional past. If someone has changed 100 lines of a file, where 96 of them were whitespace and comment formatting modifications, while the remaining 4 were significant business logic changes, peer-reviewing that if committed as one change is a nightmare. Being able to stage the whitespace changes in one commit with an appropriate message, then staging and committing the business logic changes seperately is a life saver (literally, it may save your life from your peers). To do this, you can use Git’s patch staging feature that asks you if you want to stage the changes to a file one hunk at a time (git add -p).

These tools allow you to craft your commits to be easily reviewable, cherry-pickable, logically seperate changes to your project. The advantages to thinking of your project history this way and having the tools to easily maintain that discipline without having to carefully plan out every commit more than a few seconds before you need to create them gives you a freedom and flexibility that is very empowering.

In Subversion the only real way to accomplish the same thing is with a complicated system of diffing to temporary files, reverting and partially applying those temporary files again. Raise your hand if you’ve ever actually taken the time to do that and if you would consider the process ‘easy’ in any way. Git users often do this type of operation on a daily basis and you need nothing outside of Git itself to accomplish it.

Not Just for Teams of Coders

I hear from individuals all the time that this could not possibly be worth switching because they don’t work in large teams or don’t collaborate with other people at all. Or perhaps you’re not really a programmer, but a designer or a writer.

Well, on the individual versus a team front, I would argue that nearly everything I love about Git, much of which I’ve written about here, I love because it helps me, not because it helps my teammates. Screw them.

Local branching and frictionless context switching is entirely useful to an individual and probably the most unique and revolutionary feature of Git. In fact, I very often use Git like you might use RCS – just fire it up on some local directory and check stuff in every once in a while, having no remote repositories at all. Creating commits as logically seperate changesets is also helpful to you to remember why you did something a month ago, so those tools are also helpful on an individual level and finally, speed and backups are always a good thing, team or individual.

If you’re not really a software developer, I’ve already listed an example of using Git to collaborate on a book. Pro Git is being published by Apress, a major publishing company, and most of the writing and review of the book was done in Markdown using Git to collaborate. All the errata and translations are being handled in Git branches. You don’t know real writing bliss until you merge in a technical reviewers or copy editors modifications with something as simple as `git merge`.

In Closing…

In closing, this is really just the tip of the iceburg of awesome that is Git. There are tons of fantastic and powerful features in Git that help with debugging, complex diffing and merging and more. There is also a great developer community to tap into and become a part of and a number of really good free resources online to help you learn and use Git. The few things I’ve mentioned here are simply the features that most changed the way I think about working and version control. They are the major reasons I could never go back to a system like Subversion. It wouldn’t be like saying to me “you have to use a Toyota instead of a Mercedes”, it would be like saying “you have to use a typewriter instead of a computer” – it has forever changed the way I approach and think about creating things.

I want to share with you the concept that you can think about version control not as a neccesary inconvenience that you need to put up with in order to collaborate, but rather as a powerful framework for managing your work seperately in contexts, for being able to switch and merge between those contexts quickly and easily, for being able to make decisions late and craft your work without having to pre-plan everything all the time. Git makes all of these things easy and prioritizes them and should change the way you think about how to approach a problem in any of your projects and version control itself.

35

Enjoy this article?

If you liked this article, feel free to re-tweet it to let others know. Thanks, we appreciate it :)

This post was written by

Scott Chacon

Scott Chacon is a Git evangelist and Ruby developer working on GitHub.com. He is the author of Pro Git by Apress, the Git Internals Peepcode PDF as well as the maintainer of the Git homepage and the Git Community Book. Scott has presented at RailsConf, RubyConf, Scotland on Rails, Ruby Kaigi, OSCON and a number of local groups and does corporate training on Git across the country.

We love .net Magazine

We're big fans of .net so they've hooked us up with a rad deal: Save 50 percent on your subscription.

Loading mentions Retweet
Comments (0)

How to Debug in PHP

15 September 2009

 

How to Debug in PHP

By Kieran Masterton

Nobody enjoys the process of debugging their code. If you want to build killer web apps though, it’s vital that you understand the process thoroughly.

This article breaks down the fundamentals of debugging in PHP, helps you understand PHP’s error messages and introduces you to some useful tools to help make the process a little less painful.

Doing your Ground Work

It is important that you configure PHP correctly and write your code in such a way that it produces meaningful errors at the right time. For example, it is generally good practice to turn on a verbose level of error reporting on your development platform. This probably isn’t such a great idea, however, on your production server(s). In a live environment you neither want to confuse a genuine user or give malicious users too much information about the inner-workings of your site.

So, with that in mind lets talk about the all too common “I’m getting no error message” issue. This is normally caused by a syntax error on a platform where the developer has not done their ground work properly. First, you should turn display_errors on. This can be done either in your php.ini file or at the head of your code like this:

<?php
ini_set('display_errors', 'On');

Tip: In these code examples I omit the closing (?>) PHP tag. It is generally considered good practice to do so in files which contain only PHP code in order to avoid accidental injection of white space and the all too common “headers already sent” error.

Next, you will need to set an error reporting level. As default PHP 4 and 5 do not show PHP notices which can be important in debugging your code (more on that shortly). Notices are generated by PHP whether they are displayed or not, so deploying code with twenty notices being generated has an impact upon the overhead of your site. So, to ensure notices are displayed, set your error reporting level either in your php.ini or amend your runtime code to look like this:

<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);

Tip: E_ALL is a constant so don’t make the mistake of enclosing it in quotation marks.

With PHP 5 it’s also a good idea to turn on the E_STRICT level of error reporting. E_STRICT is useful for ensuring you’re coding using the best possible standards. For example E_STRICT helps by warning you that you’re using a deprecated function. Here’s how to enable it at runtime:

<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL | E_STRICT);

It is also worth mentioning that on your development platform it is often a good idea to make these changes in your php.ini file rather than at the runtime. This is because if you experience a syntax error with these options set in your code and not in the php.ini you may, depending on your set up, be presented with a blank page. Likewise, it is worth noting that if you’re setting these values in your code, a conditional statement might be a good idea to avoid these settings accidentally being deployed to a live environment.

What Type of Error am I Looking at?

As with most languages, PHP’s errors may appear somewhat esoteric, but there are in fact only four key types of error that you need to remember:

1. Syntax Errors

Syntactical errors or parse errors are generally caused by a typo in your code. For example a missing semicolon, quotation mark, brace or parentheses. When you encounter a syntax error you will receive an error similar to this:

Parse error: syntax error, unexpected T_ECHO in /Document/Root/example.php on line 6

In this instance it is important that you check the line above the line quoted in the error (in this case line 5) because while PHP has encountered something unexpected on line 6, it is common that it is a typo on the line above causing the error. Here’s an example:

<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);


$sSiteName = "Think Vitamin"
echo $sSiteName;

In this example I have omitted the semi-colon from line 5, however, PHP has reported an error occurred on line 6. Looking one line above you can spot and rectify the problem.

Tip: In this example I am using Hungarian Notation. Adopting this coding standard can aid with debugging code while working collaboratively or on a piece of code you wrote some time ago. The leading letter denoting the variable type means that determining a variable type is very quick and simple. This can aid in spotting irregularities which can also help highlight any potential logic errors.

2. Warnings

Warnings aren’t deal breakers like syntax errors. PHP can cope with a warning, however, it knows that you probably made a mistake somewhere and is notifying you about it. Warnings often appear for the following reasons:

  1. Headers already sent. Try checking for white space at the head of your code or in files you’re including.
  2. You’re passing an incorrect number of parameters to a function.
  3. Incorrect path names when including files.

3. Notices

Notices aren’t going to halt the execution of your code either, but they can be very important in tracking down a pesky bug. Often you’ll find that code that’s working perfectly happily in a production environment starts throwing out notices when you set error_reporting to E_ALL.

A common notice you’ll encounter during development is:

>Notice: Undefined index: FullName in /Document/Root/views/userdetails.phtml on line 55

This information can be extremely useful in debugging your application. Say you’ve done a simple database query and pulled a row of user data from a table. For presentation in your view you’ve assigned the details to an array called $aUserDetails. However, when you echo $aUserDetails['FirstName'] on line 55 there’s no output and PHP throws the notice above. In this instance the notice you receive can really help.

PHP has helpfully told us that the FirstName key is undefined so we know that this isn’t a case of the database record being NULL. However, perhaps we should check our SQL statement to ensure we’ve actually retrieved the user’s first name from the database. In this case the notice has helped us rule out a potential issue which has in turn steered us towards the likely source of our problem. Without the notice our likely first stop would have been the database record, followed by tracing back through our logic to eventually find our omission in the SQL.

4. Fatal Errors

Fatal Errors sound the most painful of the four but are in fact often the easiest to resolve. What it means, in short, is that PHP understands what you’ve asked it to do but can’t carry out the request. Your syntax is correct, you’re speaking its language but PHP doesn’t have what it needs to comply. The most common fatal error is an undefined class or function and the error generated normally points straight to the root of the problem:

Fatal error: Call to undefined function create() in /Document/Root/example.php on line 23

Using var_dump() to Aid Your Debugging

var_dump() is a native PHP function which displays structured, humanly readable, information about one (or more) expressions. This is particularly useful when dealing with arrays and objects as var_dump() displays their structure recursively giving you the best possible picture of what’s going on. Here’s an example of how to use var_dump() in context:

Below I have created an array of scores achieved by users but one value in my array is subtly distinct from the others, var_dump() can help us discover that distinction.

<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);


$aUserScores = array('Ben' => 7,'Linda' => 4,'Tony' => 5,'Alice' => '9');
echo '<pre>';
var_dump($aUserScores);
echo '</pre>';

Tip: Wrap var_dump() in <pre> tags to aid readability.

The output from var_dump() will look like this:

array(4) {
["Ben"]=>
int(7)
["Linda"]=>
int(4)
["Tony"]=>
int(5)
["Alice"]=>
string(1) "9"
}

As you can see var_dump tells us that $aUserScores is an array with four key/value pairs. Ben, Linda, and Tony all have their values (or scores) stored as integers. However, Alice is showing up as a string of one character in length.

If we return to my code, we can see that I have mistakenly wrapped Alice’s score of 9 in quotation marks causing PHP to interpret it as a string. Now, this mistake won’t have a massively adverse effect, however, it does demonstrate the power of var_dump() in helping us get better visibility of our arrays and objects.

While this is a very basic example of how var_dump() functions it can similarly be used to inspect large multi-dimensional arrays or objects. It is particularly useful in discovering if you have the correct data returned from a database query or when exploring a JSON response from say, Twitter:

<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);


$sJsonUrl = 'http://search.twitter.com/trends.json';


$sJson = file_get_contents($sJsonUrl,0,NULL,NULL);
$oTrends = json_decode($sJson);


echo '<pre>';
var_dump($oTrends);
echo '</pre>';

Useful Tools to Consider when Debugging

Finally, I want to point out a couple of useful tools that I’ve used to help me in the debugging process. I won’t go into detail about installing and configuring these extensions and add-ons, but I wanted to mention them because they can really make our lives easier.

Xdebug

Xdebug is a PHP extension that aims to lend a helping hand in the process of debugging your applications. Xdebug offers features like:

  • Automatic stack trace upon error
  • Function call logging
  • Display features such as enhanced var_dump() output and code coverage information.

Xdebug is highly configurable, and adaptable to a variety of situations. For example, stack traces (which are extremely useful for monitoring what your application is doing and when) can be configured to four different levels of detail. This means that you can adjust the sensitivity of Xdebug’s output helping you to get granular information about your app’s activity.

Stack traces show you where errors occur, allow you to trace function calls and detail the originating line numbers of these events. All of which is fantastic information for debugging your code.

Tip: As default Xdebug limits var_dump() output to three levels of recursion. You may want to change this in your xdebug.ini file by setting the xdebug.var_display_max_depth to equal a number that makes sense for your needs.

Check out Xdebug’s installation guide to get started.

FirePHP

For all you FireBug fans out there, FirePHP is a really useful little PHP library and Firefox add-on that can really help with AJAX development.

Essentially FirePHP enables you to log debug information to the Firebug console using a simple method call like so:

<?php
$sSql = 'SELECT * FROM tbl';
FB::log('SQL query: ' . $sSql);

In an instance where I’m making an AJAX search request, for example, it might be useful to pass back the SQL string my code is constructing in order that I can ensure my code is behaving correctly. All data logged to the Firebug console is sent via response headers and therefore doesn’t effect the page being rendered by the browser.

Warning: As with all debug information, this kind of data shouldn’t be for public consumption. The downside of having to add the FirePHP method calls into your PHP is that before you go live you will either have to strip all these calls out or set up an environment based conditional statement which establishes whether or not to include the debug code.

You can install the Firefox add-on at FirePHP’s website and also grab the PHP libs there too. Oh, and don’t forget if you haven’t already installed FireBug, you’ll need that too.

In Conclusion …

Hopefully during the course of this article you have learned how to do your ground work by preparing PHP for the debugging process; recognise and deal with the four key PHP error types and use var_dump() to your advantage. Likewise, I hope that you will find Xdebug and FirePHP useful and that they will make your life easier during your development cycle.

As I’ve already mentioned, and I really can’t say this enough, always remember to remove or suppress your debug output when you put your sites into production after all there’s nothing worse than all your users being able to read about your errors in excruciating detail.

Got a great debugging tip to share? Do you use a great little PHP extension that makes your bug trapping life easier? Please tell us about them in comments below!

25

Enjoy this article?

 

If you liked this article, feel free to re-tweet it to let others know. Thanks, we appreciate it :)

This post was written by

Kieran Masterton

Kieran Masterton is a Web Developer with over a decade of experience building sites for large media organisations like BSkyB and Future Publishing. Currently he's building indie film distribution and user-generated-screening site OpenIndie.com with co-founder and filmmaker Arin Crumley. For regular updates about this project and others follow Kieran on Twitter.

We love .net Magazine

We're big fans of .net so they've hooked us up with a rad deal: Save 50 percent on your subscription.

Loading mentions Retweet
Comments (0)

Down Verne, Down!

 

Great Cause, creepy ass picture – maybe it’s just me.

 

Loading mentions Retweet
Comments (0)

Lance Armstrong Foundation Challenge: 24 Hours of Booty

 

 

Please join me in support of the millions of people whose lives are affected by cancer. I am participating in an extraordinary event next Saturday and Sunday, September 26th – 27th  by joining other cyclists to ride our bicycles for 24 consecutive hours to raise cancer awareness and support for noteworthy charities, including The Lance Armstrong Foundation.  Such an extraordinary event needs an extraordinary name: The “24 Hours of Booty!”

Donate

Would your company like to sponsor this event perhaps ?  Think of it: I wear shirts or jerseys with your logo. Acting as 24-hour billboards for the company, and any gift provided by the you is a charitable gift that is 100% tax-deductible. Not a bad deal.  Hurry though, time is of the essence.

WHAT IS 24 HOURS OF BOOTY?
The 24 Hours of Booty is the one and only 24-hour road cycling charity event in the country.  This unique and exciting event is fully supported on a traffic-free, gently rolling loop, known for years as the “Booty Loop,” in the event’s originating city of Charlotte, North Carolina.  The event is now hosted in two locations: in both Charlotte, North Carolina and Columbia, Maryland, on each city’s unique Booty Loop.  Each city’s Booty Loop is closed to traffic to host cyclists from around the country as they ride in honor and support of the cancer community.  The goal of the 24 Hours of Booty is to provide an extraordinary event that is safe, fun, and open to all levels of cycling ability, while bringing cancer awareness to the community and raising funds for noteworthy cancer charities. 

To watch videos, read personal testimonials, and learn more about the 24 Hours of Booty, please visit the website at http://www.24hoursofbooty.org/

CHECK OUT ALL THE EXTRORDINARTY CHARITIES
The 24 Hours of Booty is a non-profit organization that directs fundraising to national and local cancer initiatives.  Recipients include:

The Lance Armstrong Foundation (LAF) - http://www.livestrong.org/
The Lance Armstrong Foundation (LAF) provides the practical information and tools people with cancer need to live life on their own terms. The LAF serves its mission through advocacy, public health and research.

The Ulman Cancer Fund for Young Adults (UCF) - http://www.ulmanfund.org/
The Ulman Cancer Fund for Young Adults (UCF) was established in 1997 by Doug Ulman, a three-time cancer survivor who now serves as President and CEO of the Lance Armstrong Foundation. The UCF's mission is to support, educate and connect young adults affected by cancer.

Johns Hopkins Medicine - http://www.johnshopkins.org/

At Johns Hopkins, The Sidney Kimmel Comprehensive Cancer Center has active programs in clinical research, laboratory research, education, community outreach, prevention, and control.  It has dedicated to better understanding human cancers and finding more effective treatments.

The Brain Tumor Fund for the Carolinas - http://www.btfcnc.org/
An organization dedicated to increasing public awareness of the impact of brain tumors along with providing support for the development of comprehensive treatment strategies and cooperative biomedical research efforts.

The Keep Pounding Fund
Honoring the late Carolina Panthers player and coach Sam Mills and former player Mark Fields, this fund benefits the Blumenthal Center for Cancer Research at Carolinas Medical Center.

Please help me meet my fundraising goal of $500.00 USD by making a tax-deductible contribution to “24 Hours of Booty”.  If you have any questions, please contact me at livestrong [at] jadedgeek [com] .

On behalf of all those whose lives are affected by cancer, I thank you for supporting the 24 Hours of Booty, the event’s participants, and ultimately the cancer community.  With your donation, we can make a positive impact on our local cancer community and the cancer community abroad.  Your generosity and support make a tremendous difference.

Loading mentions Retweet
Filed under  //  cancer   lance armstrong   livestrong  
Comments (0)