Softwareontwikkeling FAQ - Algemeen

Pagina: 1
Acties:
  • 6.980 views sinds 30-01-2008

Onderwerpen


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 23-05 15:21

NMe

Quia Ego Sic Dico.

Topicstarter
Mede-auteurs:
  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Anoniem: 3057

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:09

.oisyn

  • cutter
  • Registratie: November 2000
  • Laatst online: 29-05 16:43

cutter

  • drm
  • Registratie: Februari 2001
  • Laatst online: 19-05 13:58

drm

  • RobIII
  • Registratie: December 2001
  • Laatst online: 22-05 08:46

RobIII

Softwareontwikkeling FAQ: Algemeen

Inhoudsopgave
« · ^

Wat FAQ's op een rij
« · ^

Als je scripts of programma's zoekt ...
  1. HotScripts

    Hier kun je kant en klare scripts vinden voor allerlei verschillende toepassingen.
  2. SourceForge

    Open source projecten op allerlei gebieden.
« · ^

Links
Links voor applicatieprogrammeurs
  1. Programmers' Heaven
  2. programmingtutorials.com
  3. DevelopersDex
Links voor webscripters
  1. W3Schools
  2. irt.org
« · ^

Boeken
Voor boeken over allerhande zaken kun je terecht in [Alg] Centraal boekentopic - part II. Hierin staan talloze goede boeken genoemd met een breed scala aan onderwerpen. Een ander interessant topic om eens door te lezen is [OO/ALG] 3 boeken met meeste invloed op je werk/denken.

Kijk voor algemene boeken over het ontwerpen van applicaties in de algemene FAQ van Sofware Engineering & Architecture.

« · ^

Openmaken van exe's en decompilen
Dit is in principe gewoon illegaal (net als cracks, passes, warez etc) en voor ons daarom niet/nauwelijks na te gaan of er wel of niet illegaal gedrag getoond wordt. Daarom hebben we besloten het als illegaal te beschouwen en zijn dit soort topics niet gewenst.

cutter zei hierover het volgende:
Doordat artikel 6 van de Softwarerichtlijn en artikel 45m Aw stellen dat decompilatie onder omstandigheden is toegestaan, is iedere decompiler per definitie inzetbaar voor zowel wettelijk toegestaan, als voor inbreukmakend gebruik van software. De overweging bij de Auteursrechtrichtlijn geeft aan dat decompilers niet verboden zijn. Dat kan impliceren dat de zinsnede 'uitsluitend bestemd om de ongeoorloofde verwijdering of ontwijking van softwarebeveiliging te vergemakkelijken' in de Softwarerichtlijn, betekent dat omzeilingsmiddelen alleen onder de bepaling vallen, indien zij uitsluitend bestemd zijn om inbreukmakende handelingen te faciliteren. Wanneer zij tevens op basis van het auteursrecht niet te verbieden gebruik van software mogelijk maken, vallen ze er niet onder.
Decompilen mag voor het tot stand brengen van intercompatibiliteit, zorgen dat programma's (interfaces) met elkaar kunnen communiceren. Dat mag alleen als je zonder het decompileren de intercompatibiliteit niet tot stand kan brengen en je het proggie rechtmatig in je bezit hebt. Of je nu voor studie mag decompileren weet ik niet. Je mag wel proberen de achterliggende gedachten te achterhalen door het laden, in beeld brengen, de uitvoering, de transmissie of de opslag van het programma. Er wordt eigenlijk niet meer gesproken van decompileren maar van 'omzeilen van een technische voorziening' in de voorstellen voor een nieuwe auteurswet. Onder omstandigheden mag dat.
Kern van de door de commissie voorgestelde bepaling is dat de wetgever ingrijpt op het moment dat de betekenis en ratio van de beperkingen onder artikelen 16 (ten behoeve van onderwijs), 16b en 16c (privé-kopiëren), 16h (reprografisch verveelvoudigen), 16n (verveelvoudigen voor preserveringsdoeleinden), 17b (efemere vastleggingen door omroeporganisaties) en 22 (gebruik in het kader van gerechtelijke en bestuurlijke procedures) in het gedrang komt.
Dit zijn een aantal situaties wanneer decompilen zou mogen, maar die moeten nog verder uitgewerkt worden in een op de nieuwe auteurswet gebaseerde aanvullende regeling (ook wel Algemene Maatregel van Bestuur (AMVB) genoemd).

« · ^

Tips bij debuggen
Met dank aan MrX. :)
Het komt vaak voor dat er vragen gesteld worden opgelost hadden kunnen worden door een beetje debuggen. Ontluizen, zou je 't kunnen noemen. Vaak weet je niet precies waar de fout zit, maar wel ongeveer. Om achter de fout te komen kun je het beste even dit stukje als handleiding gebruiken bij het debuggen.

Wat gaat er fout?
Foutmeldingen, waarschuwing, etcetera. Waarschuwingen heb je nooit teveel. Dit betekent o.a. dat het bij C++ compilers handig is (bijvoorbeeld gcc of g++) met een Wall (warn all) parameter te werken, bij Perl met een use strict; en te parsen met de -w parameter en bij PHP met error_reporting op E_ALL.

Eveneens kan het handig zijn gebruik te maken van software die je de mogelijkheid geeft stap voor step (step) door je code heen te wandelen en zelf debug-informatie te leveren door gebruik te maken van watches (wat gebeurt er met bepaalde variabelen?)

Als dergelijke software niet beschikbaar is in jouw geval kan het handig zijn zelf dergelijke watches of step-by-step's te schrijven. Bij PHP kan dit heel eenvoudig door trigger_error()-aanroepen of eventueel gebruik te maken van die() of exit() in debugfase.

Als je bepaalde foutmeldingen niet begrijpt, kan het handig zijn de foutmelding gewoon te copy-pasten naar google of de search van GoT en even te kijken wie dergelijke foutmeldingen ook had. Mensen geven over het algemeen bij hun problemen wel de foutmeldingen op; zodoende kan je er ook altijd op zoeken. :)

Wat zijn de omstandigheden?
Ga na welke handelingen en stukken code de fout(en) en waarschuwing(en) hebben veroorzaakt. Bij waarschuwingen en foutmeldingen wordt bijna altijd wel een regelnummer en offset gegeven. Dan is het redelijk triviaal de fouten op te lossen. Bij Java en veel C++ compilers komt er zelfs een stacktrace bij kijken zodat je kan zien wat de allereerste oorsprong van de foutmelding of waarschuwing is.

Reproduceer de foutieve code
Isoleer het stuk code wat de fout veroorzaakt, door alle code die er geen invloed op heeft eventueel te commenten of tijdelijk te verwijderen. In sommige gevallen is het handig om enkel het stuk code te compileren wat de fout veroorzaakt, zodat je daarover debuginformatie naar je scherm kan printen.

Let, wanneer je het foutieve stuk code uitvoert, vooral op
  1. waarden van relevante variabelen
  2. calls naar externe functies/objecten/etc., die evt. onvoorspebaar of incorrect gedrag vertonen
  3. niet afgevangen condities (Null waarden, geen records gereturned, negatieve waarden, verkeerd type waarden, etc.)
  4. syntax vergissingen (bijv. "=" gebruiken als vergelijkingsoperator waar je "==" zou moeten gebruiken)
  5. correctheid van (loop) condities ('out of bounds' problemen, '>' dat '>=' zou moeten zijn, etc.)
SQL, geval apart
Fouten of foutmeldingen bij het gebruik van SQL heeft in 9 van de 10 gevallen te maken met het feit dat de query niet goed opgebouwd wordt.

Wanneer je een query doet aan een SQL server en je krijgt onverwachte resultaten terug, dan betekent dat meestal dat je query een syntax error of iets dergelijks bevat. Geef de SQL server ook de kans foutmeldingen te geven. Negeer foutmeldingen van de SQL server nooit. Als je dan niet in 1 oogopslag ziet wat het probleem is, open dan een directe connectie naar de database en voer de query handmatig uit en speel ermee tot die wel goed is voordat je de code aanpast.

Connecties tussen systemen
Met dank aan MrX voor dit stukje. :)
Als je van deel A naar deel B een connectie maakt (COM call, message queue, HTTP call, CORBA call, etc), zorg dan dat je direct voor de uitgang van systeem A en na de ingang bij systeem B alle waarden logt, zodat je precies kan vergelijken of deze overeenkomen en je zeker weet in welk deel het probleem zit.Als je het probleem nu nog niet ziet of kunt oplossen, isoleer dan precies de regel code die de fout triggert en haal er een buitenstaander bij, die een frisse blik op jouw code kan werpen.

Meer informatie
Meer informatie kun je vinden in dit topic: [ALG] Hoe pakt een programmeur debuggen aan?

« · ^

Richtlijnen voor nette code
Het is een goede gewoonte om jezelf wat conventies aan te leren als het gaat om het netjes opschrijven van code. Dit onderdeel geeft je wat richtlijnen, die je kunnen helpen bij het leesbaarder maken van je code.

De voorbeelden die wat minder leesbaar zijn, zijn Fout gemarkeerd en de leesbare voorbeelden Goed. Dit betekent overigens niet dat de foute manier altijd de slechtste manier is en de goede manier altijd de beste. Er zijn altijd meerdere wegen die naar Rome leiden. Onthoud dus dat het richtlijnen zijn en niet perse de manier. :)

Zet commentaar bij non-triviale code
Je code moet leesbaar zijn voor anderen. Dit betekent dat je in normaal Engels, (of normaal Nederlands, wat je liever hebt), bij je code neerzet wat daar de bedoeling is, als dat niet al uit de code opzich spreekt. Ook kan dit bij het debuggen van pas komen, als je een stuk code zoekt wat bepaalde logica uitvoert. Snel zoeken door code heen gaat nou eenmaal makkelijker op gestructureerd commentaar, dan op de taal zelf.

Naarmate je meer een ervaren programmeur wordt, wordt het lezen van code ook gemakkelijker. Toch geeft dat je geen vrijbrief om je code vrij te laten van commentaar. Je maakt het namelijk ook de mensen die later je code nog 's moeten lezen een stuk gemakkelijker.

Voorbeeld
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * interface MijnInterface
 *
 * Functie: geeft een voorbeeld van hoe je je code wat commentaar kan geven
 */
public interface MijnInterface {
   /**
    * Method sjakieSpef
    *
    * Parameters:
    *   String      woei  bladie bladie blah
    *   MijnClass   yay   yack yack yadayada
    *
    * Returns: String containing the spef of Sjaak
    */
   protected String sjakieSpef ( String woei, MijnClass yay ) {
      String return_value = "";

      // ...
      return return_value;
   }
   // etcetera
}


Schrijf code niet altijd zo kort mogelijk
Fout
Java:
1
2
3
4
String s = "Target" +
   + ((this.i>l&&this.i<u) ? " not":)
   +  " in range";
System.out.println(s);


Goed
Java:
1
2
3
4
5
if ( this.duidelijkeNaam < upperLimit && this.duidelijkeNaam > lowerLimit ) {
   System.out.println( "Target in range" );
} else {
   System.out.println ( "Target not in range" );
}


Inspringen
Spring na { in en spring terug voor de bijbehorende }. In Basic-achtige talen, betekent dat inspringen na een IF en terugspringen voor de bijbehorende END IF, etcetera.

Fout
Java:
1
2
3
if ( conditie ) {
voeruit()}else
{if(conditie2){ voeruit2();}}


Goed
Java:
1
2
3
4
5
6
7
if ( conditie ) {
   voeruit ();
} else {
   if ( conditie2 ) {
      voeruit2 ();
   }
}


Bij geneste functieaanroepen kun je vaak beter ook inspringen:
Java:
1
2
3
4
5
6
7
this.myFirstFunction (
   argument,
   argument,
   That.hisFirstFunction (
      anotherArgument
   )
);


Als je aan het debuggen bent, kan het nog wel eens van pas komen je code even op die manier uit te lijnen zodat je zeker weet dat de haakjes goed staan, oftewel, dat de nesting klopt.

Naamgeving
De naamgeving binnen code is een van de belangrijkste dingen voor het onderhoudbaar houden van je code.

Een naam is niet gauw te lang, hij is wel gauw te kort. Het is een hele goede gewoonte om in namen goed te beschrijven wat het voor iets is. Vaak kun je dit door bepaalde conventies te hanteren al wel vastleggen. Zo is het gebruikelijk om objecten en classnames met een Hoofdletter te laten beginnen en CamelCased te schrijven (elk nieuw woord in de naam laten beginnen met een hoofdletter):

Java:
1
2
3
4
class MyClass {
   public MyClass () {
   }
}


Bij methode en propertynamen is het gebruikelijk ook te camelCasen maar met een kleine letter te beginnen:

Java:
1
2
3
4
5
6
7
8
9
10
class MyClass {
   private int   isNoValue;

   public MyClass () {
       this.isNoValue = null;
   }

   public void doNothing () {
   }
}


In C++ en C heb je, iets meer dan in Java, vaak te maken met de scope van variabelen. Er is wat voor te zeggen om in je variabelenamen op te nemen wat de scope van de variabele is. Ook kan het handig zijn om het type variabele in de naam op te nemen.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
const int c_myConstantInt;
int g_myGlobalInt;

class MyClass {
   private int p_myPropertyInt;

   public MyClass ( int ) {}
}

MyClass::MyClass ( int a_myArgumentInt ) {
   int l_myLocalInt;
}


Ook heb je in C en C++ te maken met functienamen die niet tot een class behoren. 't Kan geen kwaad onderscheid te maken in de wijze van schrijven van de functies enerzijds en de methoden anderzijds.

C++:
1
2
3
4
5
6
int do_something () {
   // ...
}

int MyClass::doSomething () {
}


Meer informatie over descriptive naming kun je vinden in dit topic.

HTML en SQL in PHP
Bij PHP maakt het verschil wat de insteek is van je PHP document. Vele PHP-programmeurs maken verschil tussen de template-georienteerde pagina's enerzijds en de logica-georienteerde pagina's anderzijds. Probeer HTML zo veel mogelijk buiten de logica te houden en de logica zoveel mogelijk buiten de templates.

Bij template-georienteerde pagina's kun je op de volgende manier te werk gaan:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php foreach ( $news_items as $news_item ) { ?>

   <div class="news-item">
      <h1><?php echo htmlentities ( $news_item [ 'title' ] ); ?></h1>
      <div class="content">
      <?php echo $news_item [ 'content' ]?></h1>
      </div>
      <?php foreach ( $menu_item [ 'references' ] as $reference ) { ?>
         <?php echo $reference [ 'date' ]; ?>
         <a href="news_item.php?id=<?php echo $reference [ 'reference_id' ];?>">
            <?php echo $reference [ 'reference_title' ]; ?>

         </a>
         <br />
      <?php } // end foreach references ?>
   </div>
<?php } // end foreach news_items ?>


Je ziet hier dat de nadruk op de HTML ligt en niet op de PHP. Overigens kun je voor dergelijke dingen ook (andere) template-engines gebruiken.

Bij logica georienteerde pagina's kun je beter PHP als uitgangspunt nemen. Let op dat je ook SQL statements uitlijnt. Dat zijn vaak onleesbare lappen code, die echt wel uitlijning verdienen.

In dit voorbeeld prepareert de logica in de PHP een array $news_items, om aan de template van hierboven te voldoen. Vaak is het voor de onderhoud van je code beter om op een dergelijke manier de logica van de layout te scheiden, vandaar dit ik 't even wat uitgewerkt heb.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php
// Connect to local database 'drm'
mysql_connect ( 'localhost', 'drm', 'myl33tp4ssw0rd' );
mysql_select_db ( 'drm' );

// Create query:
//    select all public news items from `news_item`, including
//    their public references from table `news_item_reference`
$query = '
   SELECT
      `news_item`.`news_item_id`,
      `news_item`.`title`,
      `news_item`.`content`,
      DATE_FORMAT(\'%d-%m-%Y\', `news_item`.`date_created`)
         AS `date`,
      `news_item_reference`.`news_item_left` IS NOT NULL
         AS `has_references`,
      `reference`.`news_item_id`
         AS `reference_id`,
      `reference`.`title`
         AS `reference_title`
   FROM
      `news_item`
         LEFT JOIN `news_item_reference` ON(
            `news_item`.`news_item_id`
            = `news_item_reference`.`news_item_id_left`
         )
         INNER JOIN `news_item` AS `reference` ON(
            `news_item_reference`.`news_item_id_right`
            = `reference`.`news_item_id`
         )
   WHERE
      `news_item`.`is_public`=\'true\'
      AND   `reference`.`is_public`=\'true\'
   ORDER BY
      `news_item`.`date_created` DESC,
      `reference`.`date_created` DESC
';

// perform query
$news_items_result = mysql_query ( $query );

// initialize array to hold all news items
$news_items = array ();

// holds the id of the last fetched newsitem.
$last_news_item_id = -1;

// holds the currently fetched newsitem.
$current_news_item = false;

// fetch all newsitems from database
while ( $news_item_row = mysql_fetch_assoc ( $news_items_result ) ) {

   // if this item is a new news item in the set:
   if ( $news_item_row [ 'news_item_id' ] != $last_news_item_id ) {
      $last_news_item_id = $news_item_row [ 'news_item_id' ];

      // does not apply to the first iteration:
      if ( $current_news_item ) {
         // add the current item to the set
         $news_items []= $current_news_item;
      }

      // create new news_item
      $current_news_item = array (
         'title'       => $news_item_row [ 'title' ],
         'content'     => $news_item_row [ 'content' ],
         'date'        => $news_item_row [ 'date' ],
         'references'  => array (),
      );
   }

   // relation IS NOT NULL clause from query
   if ( $news_item_row [ 'has_references' ] ) {
      // add references to the current newsitem
      $current_news_item [ 'references' ] []= array (
         'reference_title' => $news_item_row [ 'reference_title' ],
         'reference_id'    => $news_item_row [ 'reference_id' ]
      );
   }
}

include ( './tpl/template.news_item.php' );
?>

[ Voor 205% gewijzigd door NMe op 21-12-2019 18:13 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Dit topic is gesloten.