Wednesday, 17 October 2012

The Customer, The Manager, The Developer and the Hack

The Customer, The Manager, The Developer and the Hack

In this post I am going to release my anger and rant about how hard it can be for a Developer,  We are well known most of the time for taking pride in our work.  Seen as these people glued to a computer screen in the early hours of the morning.

We like to write clean, readable and might I say beautiful code.  In every company I have previously worked for I take pride in writing beautiful code.  However there was one company I had previously worked for that made me do everything but write beautiful code.

The Customer

The customer to any business is king.  The problem with this analogy is that the customer is then seen to be always in the right and most sales people become 'Yes' men.  In my previous experience as a Freelancer I found that customers although correct sometimes needed their hot air ideas shot down.

Some would ask for features that were pointless, out of date or would confuse the consumer of the system.  Such a scenario is Integrating a full eCommerce solution to sell 3 products when 3 PayPal buttons would be suffice.

The company I worked for took price in being what they coined : The Customers Advocate.

I still am not entirely sure what this meant but from observation I found it meant that the Company agreed with the customer on everything,  If a manager says this is Illeagil the customer would respond I want it.  The company would then go and do it for them.

In the software development arena this produces software known as Bloatware.  To the team it leads to Dis-Harmony and disloyalty to both the customer and the manager.

Why I hear you ask?.... Because when the manager tells the developer to produce a solution,  The developer will agree.  However then the manager speaks to the customer upon the solution being complete and the manager and the customer then pick holes in it.  They then blame the developer for these holes when it was the lack of Scoping / no Scoping from the manager with regards to what the customer actually wanted.

Manager

When the Manager of the Project sides completely with the Customer and Ignores advice from the Developers on the team the project is destined to collapse.

In one project I worked in the manager stood on the side of the Customer so much that the Customer took advantage of this.  They started asking for unreasonable requirements going so far as to request entirely new features all while screaming saying they want it on the Budget Original and On Time.

This approach meant this forced developers into a really tight position asking themselves two questions:
  • How can the team write Good quality code when we don't have the time to ensure the quality.
  • How can the team keep the Project under budget when new requirements are added but are not being charged for.
The approach of Managers in regards to these problems is (Hack It)

The Developer

The developer is the one who knows their skills,  they generally know how long it will take them to do a specific task and with more understanding of requirements the Developer can ensure they get the work right first time round.

I was the developer in this company I found it difficult to add a feature to a code page when the code for that page contains 2000+ LOC with of largely redundant or repeated code.

An example of what I seen was this:
  • No Page Design Patterns
  • Vague Function Names that Often did something different to what was said on the tin.
  • Over Use of Sessions instead of other methods of persisting data.
  • Absolutely no validation.
  • Incorrect naming of Controls (e.g. this.TextBox1.text in place of this.txtAmount.text)
  • Repeated code blocks
  • In once case over 20 lines of 'IF' statements. (I reduced this to 5.)
  • Incorrect Code Placement of Logic (PageInit/PageLoad/CreateChildControls) were not used properly.
I took to the task of compressing the code in each page I worked on.  I don't know if this helped or not but I remember being told 'Less LOC less Bugs' so I at least attempt to practice this as best I can.

On one project for this company the customer set a Deadline for the following week.  This would be reasonable however,  The customer did not provide us with the layouts, images or other information we needed.

Again as a developer I thought tell you manager that this is unreasonable for the customer to demand such a request when we don't have the tools to do it from them.  The approach of the manager was to bury their head in the sand saying.   'Just do it as best you can'.

This leads to the collapse of many software projects.  A manager who keeps saying yes is responsible for the demise of the project.  However they can only be responsible when the developers themselves have proven and alerted the manager time and time again of problems.

In this project I suggested to the Manager we need a re-write or at least a major re-factoring I was told no to both of these and as I said above the manager said 'Hack It'.


The Hack

I think all developers know what I am talking about here.  When a Manager / Customer says to do something  and the developer then tries to say Its not possible.

I do not take keen to hacking in any extent its a bad way to be.   I can understand why hacking is relevant to projects that are Legacy but this project was both UnComplete and Brand new.  I told the manager the code base left by others needed re-written and the customer needs to be told NO both requests were denied.

Hacking both brings down the Integrity of the code and greatly increases the chances of Bugs and makes it a nightmare to manage.  I only use this approach if all other avenues are blocked and after reasonable debate.


Conclusion

The previous company I worked for practised this approach for every project.  This lead to the company to have severe problems retaining staff in the Development Team (e.g. Many wrote crap and left).

It also put everyone on the team under un-reasonable amounts of stress and pressure and also made Developers loose faith in their Manager, The Customer and also at times other members of the team.

I don't know what ever happened with this project that I worked on I can only imagine the company got stung once again by the tail of the customer and that the Project Collapsed.


Help I'm in this position?  What do I do?

If any developer sees themselves in this position my advice is to run for the hills as fast as you can.  It will hurt more when the company collapses when you were part of it than leaving because you wanted to do things right.

Monday, 8 October 2012

SQL Get Start of Day

SQL Get Start of Day

As many of you know SQL can be fun when you are dealing with records in the database.  One common thing that I have always been required to do is to get Records where their date is greater than the start of the day.

Imagine this Scenario.

DateLogged = '2012-10-08 00:00:00.000'

If I run the following command

Select GetDate()

This Returns: '2012-10-08 12:59:11.887' 

So how can I go about building a query that will get me this date?

Simple!, We basically need to tell SQL to get us the first second of the day or earlier.

select dateadd(second,0,dateadd(day,datediff(day,0,getdate()),0)

This Returns: '2012-10-08 00:00:00.000'

Start of Day x Number of Days Ago Excluding Weekends

Now the next problem I have had is getting a record that was added say 3 days ago but I want SQL to Ignore the weekend. 

Imagine this scenario

DateLogged = '2012-10-05 00.00.00:000'

To get this date I can achieve this by running the following command

select dateadd(weekday, -3, GetDate())

This Returns: '2012-10-05 12:59:11.887'

However this is not what I want, so if we adapt the sql above.

select dateadd(second,0,dateadd(weekday,-3,dateadd(day,datediff(day,0,getdate()),0)))

This Returns: '2012-10-05 00:00:00.000'

Obviously I do not believe this is the most efficient way of doing this but it is rather dynamic.

Monday, 1 October 2012

SagePay Server Integration the Easy Way Part (2 of 3)

SagePay Server Integration the Easy Way Part (2 of 3)

Previously I blogged about integration of SagePay in this feature I am going to show and hopefully explain how to integrate my dll.

At a minimal level we need to adjust our web.config file to include the new instructions so the SagePay Dll will work properly.

Step 1.  Modify the Connection String

Firstly we must create a connection to our SQL Database.
  <connectionStrings>
  <clear />
  <add name="LocalSqlServer" connectionString="[YourConnectionString]"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

Please note that for the sake of the dll we are using the name 'LocalSqlServer'  you may get an error from your machine saying that this is already used.  This is because 'LocalSqlServer' is held on Machine.Config.  To get past this we add the 'Clear' tag.

Step 2. Modify your App Config

Since we have created the Connection String we also need to add values to the Application Config.  Please update these fields from your SagePay information.
<appSettings>
    <add key="Vendor" value=""/> //This is your vendor code given to you by sagepay
    <add key="TxType" value="PAYMENT"/> //We want payment however we can also set this for Token in which the system would need to be altered just slightly.
    <add key="AccountType" value="C"/>  //We want to support recurring payments so we set our account type to 'C'
    <add key="NotificationUrl" value="http://mysite.com/notificationPage.aspx"/> //This is the place where SagePay posts back updates.
    <add key="FailureUrl" value="http://mysite.com/orderFailed.aspx"/> //This page posts back when an order is failed.
    <add key="SuccessUrl" value="http://mysite.com/orderSuccess.aspx"/> //This page is the page that posts back when the order is successful
    <add key="VPSProtocol" value="2.23"/>
    <add key="SagePayConnectionType" value="SIMULATOR"/>
</appSettings>

Step 3. Create the Database Tables.

For all this system to fall together we need a database.  We will call our table 'Transactions' this is the recommended specification from SagePay however I have added some additional fields to make things easier from my own projects.

CREATE TABLE [dbo].[Transactions](
 [TransactionId] [uniqueidentifier] NULL,
 [ForeignId] [nvarchar](38) NULL,
 [OrderID] [nvarchar](38) NULL,
 [Description] [nvarchar](100) NULL,
 [TransactionType] [nvarchar](100) NULL,
 [Amount] [decimal](18, 2) NULL,
 [Currency] [nvarchar](max) NULL,
 [VPSTxId] [nvarchar](38) NULL,
 [SecurityKey] [nvarchar](10) NULL,
 [TxAuthNo] [bigint] NULL,
 [Status] [nvarchar](15) NULL,
 [StatusMessage] [nvarchar](255) NULL,
 [RelatedVPSTxId] [nvarchar](100) NULL,
 [RelatedVendorTxCode] [nvarchar](40) NULL,
 [RelatedSecurityKey] [nvarchar](10) NULL,
 [RelatedTxAuthNo] [bigint] NULL,
 [AVSCV2] [nvarchar](50) NULL,
 [AddressResult] [nvarchar](20) NULL,
 [PostCodeResult] [nvarchar](20) NULL,
 [CV2Result] [nvarchar](20) NULL,
 [GiftAid] [bit] NULL,
 [ThreeDSecureStatus] [nvarchar](50) NULL,
 [CAVV] [nvarchar](32) NULL,
 [AddressStatus] [nvarchar](20) NULL,
 [PayerStatus] [nvarchar](20) NULL,
 [CardType] [nvarchar](15) NULL,
 [Last4Digits] [nvarchar](4) NULL,
 [Created] [datetime] NULL,
 [InitialPayment] [bit] NULL,
 [TransactionComplete] [bit] NULL,
 [IsReOrder] [bit] NULL,
 [OriginalTransactionId] [uniqueidentifier] NULL,
 [IsRefunded] [bit] NULL,
 [IsVoided] [bit] NULL
) ON [PRIMARY]
ALTER TABLE [dbo].[Transactions] ADD  CONSTRAINT [DF_Transactions_TransactionId]  DEFAULT (newid()) FOR [TransactionId]
ALTER TABLE [dbo].[Transactions] ADD  CONSTRAINT [DF_Transactions_GiftAid]  DEFAULT ((0)) FOR [GiftAid]
ALTER TABLE [dbo].[Transactions] ADD  CONSTRAINT [DF_Transactions_LastUpdate]  DEFAULT (getdate()) FOR [Created]
ALTER TABLE [dbo].[Transactions] ADD  CONSTRAINT [DF_Transactions_FirstPayment]  DEFAULT ((0)) FOR [InitialPayment]
ALTER TABLE [dbo].[Transactions] ADD  CONSTRAINT [DF_Transactions_TransactionComplete]  DEFAULT ((0)) FOR [TransactionComplete]
ALTER TABLE [dbo].[Transactions] ADD  CONSTRAINT [DF_Transactions_IsReOrder]  DEFAULT ((0)) FOR [IsReOrder]
ALTER TABLE [dbo].[Transactions] ADD  CONSTRAINT [DF_Transactions_IsRefunded]  DEFAULT ((0)) FOR [IsRefunded]


This is everything we need to do to hold everything together.  In the next blog post I will include the DLL and also how to integrate this to your own applications.  Alongside a sample.

SagePay Server Integration the Easy Way Part (1 of 3)

SagePay Integration the Easy Way

I was recently asked to integrate a billing platform for a product that my company was selling to a client.  After evaluating several different payment gateways such as PayPal, Google Cart and RealEx Payments I decided to settle on SagePay.

PayPal and Google Cart offer brilliant integration scripts with a vast knowledge base for help.
RealEx was a rather poor system in that it offered virtually no support to developers.  I had even found flaws in several parts of their documentation that took 3 days for them to confirm.  Many developers can agree this is a waste of time when projects have deadlines.

So I decided to integrate SagePay.

SagePay for those of you who do not know acts as a simple payment Gateway for processing transactions.  It does not store shopping carts it also has a good title as it is linked in part to the Sage Software Company.

SagePay has 3 Types of Integration
  • Forms
  • Sever
  • Direct
  • Token
After viewing their samples for each of these I decided that Server would offer the best integration with most functions however it would also remove the onus on the eCommerce company to need numerous security checks.

From experimenting from their examples I found that most code was repetitive however it was heavily engrained in each of their sample forms with no actual Code Library to Use.

Over the next 3 posts throughout the week I will show how to integrate with SagePay through a small .dll library I have created.  As well as storing the information about these transactions to the database.

Keep Tuned.