Aller au contenu principal

Produire une trace d'exécution

Si un as un morceau de code, on peut souhaiter savoir dans quel ordre les instructions sont exécutées.

Principe

On veut accomplir 2 éléments principaux :

  1. indiquer quelles lignes de code s'exécutent dans quel ordre
  2. indiquer les effets de chaque ligne de code
  3. indiquer la pile d'appels

##Exemple simple

Code

Si on a le code suivant :

fun main() {
val a = 3 + 4
val b = a * 2
println("salut " + b)
}

Trace

On aura la trace suivante :

ligne exécutéeeffetpile d'appels
val a = 3 + 4a: 7main
val b = a * 2a: 7, b: 14main
println("salut " + b)a: 7, b: 14, affiche "salut 14"main

Dans le cas d'une séquence d'instructions, on peut voir que les instructions sont exécutées dans l'ordre de lecture du code. Simple!

Pour voir le code des tableaux markdown, ICI.

Note : pour chaque page de ce site, tu peux cliquer sur le bouton Éditer cette page en bas pour voir le code markdown.

Avec boucle

Code

fun main() {
for (i in 1..3){
if (i % 2 == 0) {
println("c'est pair " + i)
}
else {
println("ah ben ah ben, c'est impair " + i)
}
}
}

On voit que :

  • on n'indique que les lignes qui s'exécutent en vrai
  • certaines lignes s'exécutent plusieurs fois, c'est le principe de la boucle!
  • on appelle ce cheminement le flot de contrôle

Trace

ligne exécutéeeffetpile d'appels
for (i in 1..3)i parcourt l'interval 1, 2, 3main
if (i % 2 == 0)i: 1
i%2 vaut 1
main
println("ah ben ah ben, c'est impair " + i)i: 1
affiche "ah ben ah ben, c'est impair 1"
main
for (i in 1..3)i rendu à 2main
if (i % 2 == 0)i: 2
i%2 vaut 0
main
println("c'est pair " + i)i: 2
affiche "c'est pair 2"
main
for (i in 1..3)i rendu à 3main
if (i % 2 == 0)i: 3
i%2 vaut 1
main
println("ah ben ah ben, c'est impair " + i)i: 3
affiche "ah ben ah ben, c'est impair 3"
main

Avec fonction

Code

fun ma_fonction(a : Int, b: Int) : Int {
val c = a + b
return c
}

fun main() {
var mavariable = 3
var tavariable = 5
var z = ma_fonction(mavariable, tavariable)
var y = ma_fonction(4, 9)
print("z vaut " + z + " et y vaut " + y)
}

S'il y a des fonctions dans le code, la pile d'appels permet d'indiquer :

  • quand on entre dans le code d'une autre fonction
  • quelles sont les fonctions qui sont encore actives

Trace

ligne exécutéeeffetpile d'appels
var mavariable = 3mavariable: 3main
var tavariable = 5mavariable: 3
tavariable: 5
main
var z = ma_fonction(mavariable, tavariable)mavariable: 3
tavariable: 5
appelle ma_fonction avec 3→a et 5→b
main
val c = a + ba: 3
b: 5
c: 8
ma_fonction
main
return ca: 3
b: 5
c: 8, retourne 8
ma_fonction
main
var z = ma_fonction(mavariable, tavariable)mavariable: 3
tavariable: 5
z: 8
main
var y = ma_fonction(4, 9)mavariable: 3
tavariable: 5
z: 8
appelle ma_fonction avec 4→a et 9→b
main
val c = a + ba: 4
b: 9
c: 13
ma_fonction
main
return ca: 4
b: 9
c: 13
retourne 13
ma_fonction
main
var y = ma_fonction(4, 9)mavariable: 3
tavariable: 5
z: 8
y:13
main
println("z vaut " + z + " et y vaut " + y)mavariable: 3
tavariable: 5
z: 8
y = 13
affiche "z vaut 8 et y vaut 13"
main

Réseau

On veut faire la trace d'exécution lorsqu'on ouvre l'application client, en assumant que le serveur roule et que tout se passe bien.

Code client

interface Service {
@POST("plus100")
fun plus100(@Body nombre: Int): Call<Int>
}

object retrofit {
val service: Service = retrofit2.Retrofit.Builder()
.addConverterFactory(retrofit2.converter.gson.GsonConverterFactory.create())
.baseUrl("http://10.0.2.2:8080/")
.build()
.create(Service::class.java)
}

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
retrofit.service.plus100(42).enqueue(object : retrofit2.Callback<Int> {
override fun onResponse(call: retrofit2.Call<Int>, response: retrofit2.Response<Int>) {

if (response.isSuccessful) {
Toast.makeText(this@MainActivity, response.body()!!.toString(), Toast.LENGTH_LONG).show()
}
else{
Toast.makeText(this@MainActivity, "Error", Toast.LENGTH_LONG).show()
}
}

override fun onFailure(call: retrofit2.Call<Int>, t: Throwable) {
Log.i("Heille", t.message.toString())
}
})
}
}

Code serveur

@Controller
public class Controlleur {

@PostMapping("/plus100")
public @ResponseBody Integer plus100(@RequestBody Integer nombre) {
return nombre + 100;
}
}

Trace

ligne exécutéeeffetpile d'appels
super.onCreate(savedInstanceState)appelle la fonction onCreate de la classe parenteonCreate
setContentView(R.layout.activity_main)affiche le layout activity_main.xmlonCreate
retrofit.service.plus100(42).enqueue(object : retrofit2.Callback<Int> {appelle la méthode plus100 avec 42 -> nombre et lance en asynchrone la requête POST http://10.0.2.2:8080/plus100/ avec "42" comme corpsonCreate
return nombre + 100;nombre: 42
retourne 142 et renvoie une réponse HTTP avec "142" comme corps et le code 200 Ok
plus100
if (response.isSuccessful) {vérifie si la réponse response reçue du serveur est un succèsonResponse
Toast.makeText(this@MainActivity, response.body()!!.toString(), Toast.LENGTH_LONG).show()affiche "142" dans un ToastonResponse

Valider une trace

Afin de valider ta trace, tu vas utiliser le débogueur de ton IDE préféré.

  1. place un point d'arrêt sur la première ligne qui s'exécute
  2. lance l'exécution en mode débogage
  3. saute d'une ligne en une ligne pour voir si ta trace est correcte

Si tu te rends à la fin de l'exécution et que toutes tes valeurs étaient bonnes, tu as bien compris ce que fait le code.

Procédure pour faire un exercice

  1. ouvre ton repo d'exercices sur github.com
  2. crée un fichier avec le nom suggéré dans l'exercice en appuyant sur le bouton + puis Create new file
  3. dès que tu indiques un nom qui finit en .md on aura l'onglet code et l'onglet preview
  4. copie le code de l'exercice dans le fichier, tu peux utiliser un bloc de kotlin pour avoir la syntaxe colorée. Par exemple :
```kotlin
fun main() {
val a = 3 + 4
val b = a * 2
println("salut " + b)
}
```
  1. ajoute la trace d'exécution en dessous du code dans un tableau markdown. Par exemple :
| ligne exécutée  | effet                             | pile d'appels |
|-----------------|-----------------------------------|---------------|
| val a = 3 + 4 | a: 7 | __main__ |
  1. Tu peux utiliser des balises html </br> pour faire un retour de ligne, par exemple dans la pile d'appels.
  2. Crée-toi un projet kotlin ou Android pour valider ta trace en utilisant le débogueur.