Na pytanie zadane w tytule chyba najłatwiej byłoby odpowiedzieć:
Jest to jednak odpowiedź jak w dowcipie z matematykiem:
Balonem na wycieczkę wybrali się fizyk z chemikiem, jednak w wyniku zażartej dyskusji na temat wyższości jednej nauki nad drugą, zgubili się. Lecieli tak już kilka godzin nie wiedząc gdzie są, wreszcie zobaczyli na ziemi człowieka. Postanowili się więc zapytać:
- Panie! Gdzie jesteśmy?
Po pewnej chwili padła odpowiedź:
- W balonie!
Na to fizyk do chemika:
- mmhm... Ten który nam odpowiedział to musi być matematykiem, odpowiedź jest w stu procentach przemyślana, w stu procentach prawidłowa i ... w stu procentach niepotrzebna!
Nie chciałbym więc, by mój artykuł został uznany za nie potrzebny i nie odpowiadający na postawione pytania. Dodatkowym utrudnieniem jest fakt, że zadane pytanie jest mało precyzyjne i trudno stwierdzić jakiej odpowiedzi może oczekiwać je zadający...
Zastanówmy się więc z jakimi kosztami możemy mieć do czynienia. Może to być koszt licencji jaka ma być udzielona kupującemu lub koszt wytworzenia oprogramowania. W pierwszym przypadku należy zrobić badania rynku, znaleźć podobne produkty, spróbować ocenić ile klient jest w stanie zapłacić, na podstawie tych informacji można oszacować cenę licencji na użytkowanie. Co jednak należy zrobić gdy chcemy sprzedać kod źródłowy, pomysł i licencję na dalszy rozwój tego oprogramowania? Wtedy znaczącym elementem wyceny jest oszacowanie kosztów wytworzenia oprogramowania. Jak to zrobić? Wydawałoby się to na pierwszy rzut oka proste - analizujemy ile przepracowaliśmy (my lub nasz team) nad tym oprogramowaniem: ile godzin, dni, czy miesięcy, mnożymy to przez pewną stawkę i mamy koszt. Takie szacowanie może być jednak trudne, zwłaszcza gdy tworzenie tego oprogramowania było dodatkowym zajęciem, skąd więc wziąć choćby przybliżony czas poświęcony na wytworzenie. Poza tym jak przekonać potencjalnego kupca, że to oprogramowanie tyle kosztuje?
Tutaj z pomocą przychodzą odpowiednie metody wyceny (to dobrze, że już ktoś przed nami miał taki problem ;) ). Jedną z tych metod jest COCOMO lub COCOMO II (COnstructive COst MOdel II) (ew. informacje w polskiej Wikipedii dostępne są tutaj: http://pl.wikipedia.org/wiki/COCOMO). Spotkałem się z wykorzystaniem tej metodologii na stronie udostępniające open source'owe oprogramowanie Argo UML, którego kod źródłowy (ponad 600 tys linii w Javie) został oszacowany na ponad 9 mln. dolarów. Ciekawe wyliczenie ;).
Jak posługiwać się więc tą metodologią? Najważniejszym jest fakt określenia ile linii kodu ma nasze oprogramowanie, później z wykorzystaniem pewnych równań i współczynników (takich jak komplikacja projektu, zaawansowanie grupy programistycznej, kosztu roboczo-godziny) wyliczamy ostateczny koszt.
W wyliczeniach może pomóc nam kalkulator, np. dostępny tutaj: http://www.cms4site.ru/utility.php?utility=cocomoii.
Co sądzicie o tej metodologii? (zapraszam do dyskusji przy pomocy komentarzy)
Zapraszam do przeczytania kontynuacji tego artykułu.
Na koniec chciałbym zadać jeszcze jedno pytanie: Jak wyznaczyć ilość linii w oprogramowaniu? (często jest to o tyle trudne, że trzeba zliczyć dane pochodzące z kilkuset plików).
Moją propozycją jest poniższy kod napisany w C# (domyślnie zlicza tylko pliki *.CS ale modyfikacja tego jest bardzo prosta). Jak go używać? Wystarczy tylko wskazać katalog w którym to oprogramowanie znajdzie wszystkie pliki *.CS i policzy w nich linie.
W ramach ćwiczenia zapraszam do policzenia linii w poniższym kodzie i wyznaczenie jego kosztu. Ja wolę nie liczyć, bo się jeszcze okaże, że rozrzutny jestem ;).
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
namespace CodeBaseCosts
{
class Program
{
[STAThread]
static void Main( string[] args )
{
FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog();
if ( folderBrowserDialog1.ShowDialog() == DialogResult.OK )
{
ulong count = CountLines( folderBrowserDialog1.SelectedPath, ".cs" );
Console.WriteLine( "directory:{0} - lines={1}", folderBrowserDialog1.SelectedPath, count );
}
Console.WriteLine( "end" );
Console.ReadLine();
}
private static ulong CountLines( string directoryPath, string extension )
{
ulong count = 0;
try
{
Console.Write( "." ); // progress bar ;)
// 1. get the information of the directory
DirectoryInfo directoryInfo = new DirectoryInfo( directoryPath );
// 2. get content of the directory and go through each subdirectory
foreach ( DirectoryInfo d in directoryInfo.GetDirectories() )
{
count += CountLines( d.FullName, extension );
}
//3. loop through each file in the directory, and add lines
foreach ( FileInfo f in directoryInfo.GetFiles() )
{
if ( f.Extension == extension )
using ( var reader = File.OpenText( f.FullName ) )
{
while ( reader.ReadLine() != null )
{
count++;
}
}
}
}
catch
{
//it is possible that we receive an exception (e.g. directory cannot be accessed due to access privilidges
// we do nothing, we just skip this node.
}
Console.WriteLine();
return count;
}
}
}







