Pages

Monday, November 27, 2017

Absolutely no Fixed Bid Contracts - Ever!

I got a job from a client and it was a fixed bid.  We pay you x dollars and you finish the work.
BUT...

  • The scope was ill-defined
    • the "spec" for the project was "replace our existing system", not an objective set of criteria.  Therefore any variation between their old system and the new one could be considered incorrect.
    • If there are features that we cant see from the 300 screen shots we have, then we'll have to do them all to be "finished"
    • because there is no objective spec, this will end up where all fixed bid contracts end up
      • the client will expect us to "finish" the project forever, because if they ever accept the work, then they will have to pay more for changes.
      • the client will always have a giant list of 'fixes' whenever we show them the completed work.
      • we will continue to push them to go live, and they will have every inclination to manufacture more and more changes, even if they are not in the original project.
  • The estimate was based on a very simplified version of the work
    • we showed the client a mockup with all the bells and whistles, and gave them an estimate.
    • the client liked it, but wanted the work much, much cheaper.
    • we offered a simplified approach to lower the cost.
    • they didn't really listen and kept expecting everything at the lower cost.

This week I will finish the project.  I will build it to the demo server and the client will look at it.  We have exhausted ALL the hours assigned to the work.  They are going to have a list of things they want "fixed" before going live.  At that point we will want more money, but as far as they are concerned, it's a fixed bid.  They get whatever they want for the agreed price. 

Welcome to slavery.  Working free forever and never getting paid again.

Unless a project is less than 10 hours, NEVER accept a fixed bid contract.  It's a no-win scenario.

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, November 9, 2017

MVC ActionLink will not Accept Markup (easy fix!)


I needed to make a button that included a glyphicon.  The glyphicon looked like this:  
<i class="fa fa-plus"></i>  
If you use this in @Html.ActionLink() you'll see the markup in your page, not the glyphicon.

There is a way around this:

Replace your @Html.ActionLink() with this...

<a href="@Url.Action("Index","Customers",new { CompanyID = Model.UniqueId }, null)" class="btn btn-warning"><i class="fa fa-plus"></i></a>

Yeah, it's a lot more text, but Url.Action() does most of the heavy lifting.  Another requirement I had was that the QA website URL includes a folder. i.e. in development the URL is http://localhost:34238/ and in QA it's http://website.com/projectname/.  This prevents me from just hard coding the link to /Customers/Index...  Url.Action takes care of this as well.



Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, September 21, 2017

Cool Little Batch File to Log Your Crappy ISP

 Tried this in Windows 10.  I just spent all day with the internet winking on and off, and wanted to get a feeling for the extent of the outages.  Also sometimes they were hard down, and other times the DNS servers just stopped working.

Enjoy...


@echo off
cls
set Address=google.com
set ThisDate=%date%A
echo %ThisDate%

:Loop
timeout /t 60

if  "%date%" NEQ "%ThisDate%" (
echo %date% >>logfile.log
set ThisDate=%date%
echo %ThisDate%
)

echo %time% >>logfile.log

echo Pinging %Address%
%SystemRoot%\system32\ping.exe -n 1 %Address% | %SystemRoot%\system32\find.exe "TTL=" > NUL >> logfile.log

if %ERRORLEVEL% EQU 0 goto :Loop

echo Error Detected! >>logfile.log
echo Error Detected! 

echo Trace route %Address% at %date% %time% >> logfile.log
tracert %Address% >> logfile.log

echo .
echo . >> logfile.log

goto Loop
pause Somehow, I got out of the loop


Of course, you can ping another site besides Google, and you can test more or less frequently than 60 seconds.

The log file grows forever unless you rename it, and looks a lot like this:
Thu 09/21/2017 
15:55:28.70 
Error Detected! 
Trace route google.com at Thu 09/21/2017 15:55:40.74 
Unable to resolve target system name google.com.
. 
15:56:10.16 
Error Detected! 
Trace route google.com at Thu 09/21/2017 15:56:22.19 
Unable to resolve target system name google.com.
. 
15:56:52.15 
Reply from 172.217.4.142: bytes=32 time=18ms TTL=54
15:57:22.17 
Reply from 172.217.4.142: bytes=32 time=18ms TTL=54
15:57:52.13 
Reply from 172.217.4.142: bytes=32 time=18ms TTL=54
15:58:22.11 
Reply from 172.217.4.142: bytes=32 time=17ms TTL=54
15:58:52.18 
Reply from 172.217.4.142: bytes=32 time=18ms TTL=54



Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, June 23, 2017

Found on Job Postings...

"must be familiar with Software Development Life Cycle"... 

No two companies use the same one, and most exclude several steps from the map. For instance, if your SDLC does not include the eventual phase-out of your application, then it's incomplete. It's ludicrous to think that any software we develop is going to perform forever, so the phase out - especially of corporate software - is a reasonable part of the plan.  

 
...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, May 25, 2017

Naming Conventions

50% plus of the grief I have with software - especially Microsoft software - comes from when things are named inconsistently.  If you're going to pop a message to a developer - or user - that says:

Missing reference to Microsoft.SqlServer.Types

That what needs to happen is adding something named Microsoft.SqlServer.Types to someplace called References. I see this all the time.  Different apps call the config screen Config, Settings, Options, or Preferences.  Some apps have more than one of these.  So when you pop a message that says:
Unable to connect: check URL in settings
And your app only has Options, not settings, and the URL you are looking for is labelled "Address", not "URL", you leave your users confused and unsure what your messages mean.

The right way to design, is with consistency and uniformity.  I tend to call web pages "Page" and WinForms, "Forms".  Imagine this menu:
Notice how some reports are called "Report", some are called "Summary", some are called "Form", Some are called "Screen".  Note that the capitalization is inconsistent.  Note that the last two reports could be the same thing, who knows what the difference is until you generate the reports.

This all looks unprofessional.

If you're going to call something an "Options Form", make sure that every single place it's referenced it is called that. This includes:
  • Menus
  • Title Bars
  • Help Files
  • Emails to the client.
  • Support Phone Calls
  • Support Emails
  • Forum Posts
  • Help Tickets
  • Agile Sprints
  • Release Notes
  • Ads and Website References
  • Knowledge-base Article
  • Any employee tattoos that reference the app.
If you're calling Winforms "forms", then use that throughout.  If you're calling them "screens", then use that.  Even if your user says "Hey I was looking at the inventory page and I found a bug", your support people should answer in the format "Show us where on the inventory form you encountered this..."





...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, May 5, 2017

How to Check for any Changes in Table Data.


I am having a problem where some sneak process is changing the wrong
data in my inventory table. I wanted to discover how and when this was
happening, so I created a copy of my inventory table (on my local
machine, like this:
Select * from [dbo].[Inventory] into [dbo].[InventoryBASELINE]
Now I can check for discrepancies, like this...
select * from [dbo].[InventoryBASELINE] IB where CHECKSUM(*) <>
isnull((select CHECKSUM(*) from [dbo].[Inventory] I where IB.ID=I.ID),0)
union all
select * from [dbo].[Inventory] I where CHECKSUM(*) <> isnull((select
CHECKSUM(*) from [dbo].[InventoryBASELINE] IB where IB.ID=I.ID),0)
order by ID

This will show me any rows that are different, missing, or added between
my baseline table and my current table.
If I only cared about a few columns, I could use CHECKSUM(Customer, Qty,
Style) any columns I care about in all 4 checksum functions.

Friday, March 31, 2017

The Annoying Things About Visual Studio

As I work with VS, day in and day out, there are certain things that just annoy and frustrate me.  I will share them so the zero people who read this blog might have a snicker.

In General

  1. If you have an older app, say one that uses .net Framework 4.5.1, and you try to edit it on a machine that has a newer version, you CAN'T.  There is no way to install an older version of the framework alongside the newer version so you don't have to check 800 user machines for a framework update.
  2. Intellisense just quits 3 or 4 times a day without reason or warning.
  3. Editing a function name from the default (something like button1OnClick) to a real name (like LoadData) causes the designer to barf horribly,
  4. In Entity Framework, there are many objects that are created, named, and maintained by the framework.  Now and then you'll see an error message that some object you NEVER CREATED, DON'T KNOW ABOUT, and CAN'T EDIT has failed.
  5. The error messages most often have nothing to do with the problem, are too cryptic, and have a link to generic (useless) answers on the msdn site.

Desktop Apps

  1. When you are debugging, and you pooch the password, you get a massive error message, something about not being able to load System.Sql.Dll.
  2. In datagridview, CellChanged fires off for every cell while you are loading the data initially - and even when the column headers are being drawn, not just as you'd expect, when the data is - you know - changed.
  3. Now and then a form will get changed by the IDE in such a way that it will not compile.  This can happen even if you have not opened or edited the form.
  4. They took away built in installer building, and force you to use cryptic and dysfunctional third party installers to build your projects - unless you want to put all your clients stuff on their stupid, insecure "cloud".

Web Sites

  1. in MVC, there is no solid linkage between things.  A dropdown on a page named Customers will automatically find a list named Customers if there is one in the ViewBag.  This means the code looks like there is no list associated with the dropdown, you just have to know that if anything fills this list, it is used automatically, just because it's named the same.
  2. In an asp.net build, sometimes you need to build/deploy the dll's and sometimes you can just copy up the .cs files, presumably the webserver compiles for you.  I have no idea when one is required and when the other is.
  3. Also, isn't having a compiler in your webserver really dangerous?
  4. There is a script that will create the necessary tables for login, but there is no easy way to figure out how to force it to use SQL server instead of the default Access mdf database.

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Saturday, March 4, 2017

system.data.pdb not loaded

There are some helpful pages about this, but I find that just stopping and recompiling the app usually fixes this.
...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Share This!

Contact Us

Name

Email *

Message *