Senior Engineering: Open The Door, Move Away

As part of my change of bubble this year, I officially gained the title of “Senior” Engineer. Which made me take the whole “seniority” aspect of the job with more seriousness than I did before. Not because I’m aiming at running up the ladder of seniority, but because I feel it’s part of the due diligence of my job.

I have had very good examples in front of me for most of my career — and a few not great ones, if I am to be honest. And so I’ve been trying to formulate my own take of a senior engineer based on these. You may have noticed me talking about adjacent topics in my “work philosophy” tag. I also have been comparing this in my head with my contributions to Free Software, and in particular to Gentoo Linux.

I have retired from Gentoo Linux a few years ago, but realistically, I’ve stopped being actively involved in 2013, after joining the previous bubble. Part of it was a problem with contributing, part of it was a lack of time, and part of it was having the feeling that something was off. I start to feel I have a better impression now of what it is, and it relates to that seniority that I’m reflecting on.

You see, I worked on Gentoo Linux a little longer than I worked at the previous bubble, and as such I could say that I became a “senior developer” by tenure, but I didn’t really gain the insight to become a “senior developer” in deeds, and this is haunting me because I feel it was a wasted opportunity, despite the fact that it taught me many of the things that I needed to be even barely successful in my current job.

It Begins Early

My best guess is that I started working on Gentoo Linux when I was fairly young and with pretty much no social experience. Which combined with the less-than-perfect work environment of the project, had me develop a number of bad habits that took a very long time to grow out of. That is not to say that age by itself is a significant factor in this — I still resent the remark from one of the other developers that not having kids would make me a worse lead. But I do think that if I didn’t grow up to stay by myself in my own world, maybe I would have been able to do a better job.

I know people my age and younger that became very effective leaders years ago — they’ve got the charisma and the energy to get people on board, and to have them all work for a common goal in their own way. I don’t feel like I ever managed that, and I think it’s because for the longest time, the only person who I had to convince to do something was… myself.

I grew up quite lonely — in elementary school, while I can stay I did have one friend, I didn’t really join other kids It’s a bit of a stereotype for the lonely geek, but I have been made fun since early on about my passion for computers, and for my dislike of soccer – I feel a psychiatrist would have a field day to figure out that and the relationship with my father – and I failed at going to church and Sunday school, which ones the only out-of-school mingling for most of the folks around.

Nearly thirty years later I can tell you that the individualism that I got out of this, while having given me a few headstarts in life when it comes to technical knowledge, it held me back long term on the people skill needed to herd the cats and multiply my impact. It’s not by chance that I wrote about teamwork and, without using the word, individualism.

Aside: I’m Jealous of Kids These Days

As an unrelated aside, this may be the reason why I don’t have such a negative view of social networks in general. It was something I was actually asked when I switched jobs, on what my impression of the current situation is… and my point rolls back to that: when I was growing up we didn’t have social networks, Internet was a luxury, and while, I guess, BBSes were already a thing, they would still have been too expensive for me to access. So it took me until I managed to get an Internet connection and discover Usenet.

I know there’s a long list of issues with all kind of social networks: privacy, polarisation, fake news, … But at the same time I’m glad that it makes it much more approachable for kids nowadays, who don’t fit with the crowd in their geographical proximity, to reach out to friendlier bunches. Of course it’s a double-edged sword as it also allows for bullies to bully more effectively… but I think that’s much more of a society-at-large problem.

The Environment Matters

Whether we’re talking about FLOSS projects, or different teams at work, the environment around an individual matter. That’s because the people around them will provide influence, both positive and negative. In my case, with hindsight, I feel I hanged around the wrong folks too long, in Gentoo Linux, and later on.

While a number of people I met on the project have exerted, again with hindsight, a good, positive influence in my way of approaching the world, I also can tell you now that there’s some “go-to behaviours” that go the wrong way. In particular, while I’ve always tended to be sarcastic and an iconoclast, I can tell you that in my tenure as a Gentoo Linux developer I crossed the line from “snarky” to “nasty” a lot of times.

And having learnt to avoid that, and keeping in check how close to that line I get, I also know that it is something connected to the environment around me. In my previous bubble, I once begged my director to let me change team despite having spent less than the two years I was expected to be on it. The reason? I caught myself becoming more and more snarky, getting close to that line. It wouldn’t have served either me or the company for me to stay in that environment.

Was it a problem with the team as a whole? Maybe, or maybe I just couldn’t fit into it. Or maybe it was a single individual that fouled the mood for many others. Donnie’s talk does not apply only to FLOSS projects, and The No Asshole Rule is still as relevant a book as ever in 2020. Just like in certain projects, I have seen teams in which certain areas were explicitly walked away from by the majority of the engineers, just to avoid having to deal with one or two people.

Another emergent behaviour with this is the “chosen intermediate person” — which is a dysfunction I have seen in multiple projects, and teams. When a limited subset of team members are used to “relate” to another individual either within, or outside, the team. I have been that individual in the first year of high school, with the chemistry teacher — we complained loudly about her being a bad teacher, but now I can say that she was probably a bigger expert in her field than most of the other chemistry teachers in the school, but she was terrible with people. Since I was just as bad, it seemed like I was the best interface with her, and when the class needed her approval to go on a fieldtrip, I was “volunteered” to be the person going.

I’ll get back later on a few more reasons why tolerating “brilliant but difficult to work with” people in a project or team is further unhealthy, but I want to make a few more points here, because this can be a contentious topic due to cultural differences. I have worked with a number of engineers in the past that would be described as assholes by some, and grumpy by others.

In general, I think it’s worth giving a benefit of the doubt to people, at first — but make sure that they are aware of it! Holding people to standards they are not aware of, and have no way to course-correct around, is not fair and will stir further trouble. And while some level of civility can be assumed, in my experience projects and teams that are heavily anglophones, tend to assume a lot more commonality in expectation than it’s fair to.

Stop Having Heroes

One of the widely known shorthands at the old bubble was “no heroes” — a reference to a slide deck from one of the senior engineers in my org on the importance of not relying on “heroes” looking after a service, a job, or a process. Individuals that will step in at any time of day and night to solve an issue, and demonstrate how they are indispensable for the service to run. The talk is significantly more nuanced than my summary right now, so take my words with a grain of salt of course.

While the talk is good, I have noticed a little too often the shorthand used to just tell people to stop doing what they think is the right thing, and leave rakes all around the place. So I have some additional nuances for it of my own, starting with the fact that I find it a very bad sign when a manager uses the shorthand with their own reports — that’s because one of my managers did exactly that, and I know that it doesn’t help. Calling up “no heroes” practice between engineers is generally fair game, and if you call up on your own contributions, that’s awesome, too! «This is the last time I’m fixing this, if nobody else prioritizes this, no heroes!»

On the other hand, when it’s my manager telling me to stop doing something and “let it break”, well… how does that help anyone? Yes, it’s in the best interest of the engineer (and possibly the company) for them not to be the hero that steps in, but why is this happening? Is the team relying on this heroism? Is the company relying on it? What’s the long-term plan to deal with that? Those are all questions that the manager should at least ask, rather than just tell the engineer to stop doing what they are doing!

I’ve been “the hero” a few times, both at work and in Gentoo Linux. It’s something I always have been ambivalent about. From one side, it feels good to be able to go and fix stuff yourself. From the other hand, it’s exhausting to feel like the one person holding up the whole fort. So yes, I totally agree that we shouldn’t have heroes holding up the fort. But since it still happens, it can’t be left just up to an individual to remember to step back at the right moment to avoid becoming a hero.

In Gentoo Linux, I feel the reason why we ended up with so many heroes was the lack of coordination between teams, and the lack of general integration — the individualism all over again. And it reminds me of a post from a former colleague about Debian, because some of the issues (very little mandated common process, too many different ways to do the same things) are the kind of “me before team” approaches that drive me up the wall, honestly.

As for my previous bubble, I think the answer I’m going to give is that the performance review project as I remember it (hopefully it changed in the meantime) should be held responsible for most of it, because of just a few words: go-to person. When looking at performance review as a checklist (which you’re told not to, but clearly a lot of people do), at least for my role, many of the levels included “being the go-to person”. Not a go-to person. Not a “subject matter expert” (which seems to be the preferred wording in my current bubble). But the go-to person.

From being the go-to person, to being the hero, and build up a cult of personality, the steps are not that far. And this is true in the workplace as well as in FLOSS projects — just think, and you probably can figure out a few projects that became synonymous with their maintainers, or authors.

Get Out of The Way

What I feel Gentoo Linux taught me, and in particular leaving Gentoo Linux taught me, is that the correct thing for a senior engineer to do is to know when to bow out. Or move onto a different project. Or maybe it’s not Gentoo Linux that taught me that.

But in general, I still think this is the most important lesson is to know how to open the door and get out of the way. And I mean it, that both parts are needed. It’s not just a matter of moving on when you feel like you’ve done your part — you need to be able to also open the door (and make sure it stays open) for the others to pass through it, as well. That means planning to get out of the way, not just disappearing.

This is something that I didn’t really do well when I left Gentoo Linux. I While I eventually did get out of the way, I didn’t really fully open the door. I started, and I’m proud of that, but I think I should have done this better. The blogs documenting how the Tinderbox worked, as well as the notes I left about things like the USE-based Ruby interpreter selection, seems to have been useful to have others pick up where i left… but not in a very seamless way.

I think I did this better when I left the previous bubble, by making sure all of the stuff I was working on had breadcrumbs for the next person to pick up. I have to say it did make me warm inside to receive a tweet, months after leaving, from a colleague announcing that the long-running deprecation project I’ve worked on was finally completed.

It’s not an easy task. I know a number of senior engineers who can’t give up their one project — I’ve been that person before, although as I said I haven’t really considered myself a “senior” engineer before. Part of it is wanting to be able to keep the project working exactly like I want it to, and part of it is feeling attached to the project and wanting to be the person grabbing the praise for it. But I have been letting go as much as I could of these in the past few years.

Indeed, while some projects thrive under benevolent dictators for life, teams at work don’t tend to work quite as well. Those dictators become gatekeepers, and the projects can end up stagnating. Why does this happen more at work than in FLOSS? I can only venture a guess: FLOSS is a matter of personal pride — and you can “show off” having worked on someone else’s project at any time, even though it might be more interesting to “fully make the project one’s own”. On the other hand, if you’re working at a big company, you may optimise working on projects where you can “own the impact” for the time you bring this up to performance review.

The Loadbearing Engineer

When senior engineers don’t move away after opening the door, they may become “loadbearing” — they may be the only person knowing how something works. Maybe not willingly, but someone will go “I don’t know, ask $them” whenever a question about a specific system comes by.

There’s also the risk that they may want to become loadbearing, to become irreplaceable, to build up job security. They may decide not to document the way certain process runs, the reason why certain decisions were made, or the requirements of certain interfaces. If you happen to want to do something without involving them, they’ll be waiting for you to fail, or maybe they’ll manage to stop you from breaking an important assumption in the system at the last moment. This is clearly unhealthy for the company, or project, and risky for the person involved, if they are found to not be quite as indispensable.

There’s plenty of already written on the topic of bus factor, which is what this fits into. My personal take on this is to make sure that those who become “loadbearing engineers” are made sure to be taking at least one long vacation a year. Make sure that they are unreachable unless something goes very wrong, as in, business destroying wrong. And make sure that they don’t just happen to mark themselves out of office, but still glued to their work phone and computer. And yes, I’m talking about what I did to myself a couple of times over my tenure at the previous bubble.

That is, more or less, what I did by leaving Gentoo as well — I’ve been holding the QA fort so long, that it was a given that no matter what was wrong, Flameeyes was there to save the day. But no, eventually I wasn’t, and someone else had to go and build a better, scalable alternative.

Some of This Applies to Projects, Too

I don’t mean it as “some of the issues with engineers apply to developers”. That’s a given. I mean that some of the problems happen to apply to the projects themselves.

Projects can become the de-facto sole choice for something, leaving every improvement behind, because nobody can approach them. But if something happens, and they are not updated further, it might just give it enough of a push that they can get replaced. This has happened to many FLOSS projects in the past, and it’s usually a symptom of a mostly healthy ecosystem.

We have seen how XFree86 becoming stale lead to Xorg being fired up, which in turn brought us a significant number of improvements, from the splitting apart of the big monolith, to XCB, to compositors, to Wayland. Apache OpenOffice is pretty much untouched for a long time, but that gave us LibreOffice. GCC having refused plugins for long enough put more wood behind Clang.

I know that not everybody would agree that the hardest problems in software engineering are people problems, but I honestly have that feeling at this point.

Computer-Aided Software Engineering

Fourteen years ago, fresh of translating Ian Sommerville’s Software Engineering (no, don’t buy it, I don’t find it worth it), and approaching the FLOSS community for the first time, I wrote a long article for the Italian edition of Linux Journal on Computer-Aided Software Engineering (CASE) tools. Recently, I’ve decided to post that article on the blog, since the original publisher is gone, and I thought it would be useful to just have it around. And because the OCR is not really reliable, I ended up having to retype a good chunk of it.

And that reminded me of how, despite me having been wrong a lot of times before, I still think some ideas stuck with me and I still find them valid. CASE is one of those, even though a lot of times we’re not really talking of the tools involved as CASE.

UML is the usual example of a CASE tool — it confuses a lot of people because the “language” part suggests it’s actually used to write programs, but that’s not what it is for: it is a way to represent similar concepts in similar ways, without having to re-explain the same iconography: sequence diagrams, component diagrams, entity-relationship diagrams standardise the way you express certain relationship and information. That’s what it is all about — and while you could draw all of those diagrams without any specific tool, with either LibreOffice Draw, or Inkscape, or Visio, specific tools for UML are meant to help (aid) you with the task.

My personal preferred tool for UML is Visual Paradigm, which is a closed-source, proprietary solution — I have not found a good open source toolkit that could replace it. PlantUML is an interesting option, but it doesn’t have nearly all the aid that I would expect form an actual UML CASE tool — you can’t properly express relationships between different components across diagrams, as you don’t have a library of components and models.

But setting UML aside, there’s a lot more that should fit into the CASE definition. Tools for code validation and review, which are some of my favourite things ever, are also aids to software engineering. And so are linters, formatters, and sanitizers. It’s easy to just call them “dev tools”, but I would argue that particularly when it comes to automating the code workflows, it makes sense to consider them CASE tools, and reduce the stigma attached to the concept of CASE, particularly in the more “trendy” startups and open source — where I still feel push backs at using UML, or auto-formatters, and integrated development environments.

Indeed, for most of these tools, they are already considered their own category: “developer productivity”. Which is not wrong, but it does reduce significantly the impact they have — it’s not just about developers, or coders. I like to say that Software Engineering is a teamwork practice, and not everybody on a Software Engineering team would be a coder — or a software engineer, even.

A proper repository of documents, kept up to date with the implementation, is not just useful for the developers that come later, and need to implement features that integrate with the already existing system. It’s useful for the SRE/Ops folks who are debugging something on fire, and are looking at the interaction between different components. It’s useful to the customer support folks who are being asked why only a particular type of requests are failing in one of the backends. It’s useful to the product managers to have clear which use cases are implemented for the service, and which components are involved in specific user journeys.

And similarly it extends for other type of tools — A code review tool that can enforce updates to the documentation. A dependency tracking system that can match known vulnerabilities. A documentation repository that allows full reviews. An issue tracker system that can identify who most recently changed code that affects the component an issue was filed on.

And from here you can see why I’m sceptical about single-issue tools being “good enough”. Without integration, these tools are only as useful as the time they save, and often that means they are “negative useful” — it takes time to set up the tools, to remember to run them, and to address their concern. Integrated tools instead can provide additional benefits that go beyond their immediate features.

Take a linter as an example: a good linter with low false positive rate is a great tool to make sure your code is well written. But if you have to manually run it, it’s likely that, in a collaborative project, only a few people will be running it after each change, slowing them down, while not making much of a difference for everyone else. It gets easier if the linter is integrated in the editor (or IDE), and even easier if it’s also integrated as part of code review – so those who are not using the same editor can still be advised by it – and it’s much better if it’s integrated with something like pre-commit to make it so the issues are fixed before the review is sent out.

And looking at all these pieces together, the integrations, and the user journeys, that is itself Software Engineering. FLOSS developers in general appears to have built a lot of components and tools that would allow building those integrations, but until recently I would have said that there’s been no real progress in making it proper software engineering. Nowadays, I’m happy to see that there is some progress, even as simple as EditorConfig, to avoid having to fight over which editors to support in a repository, and which ones not to.

Hopefully this type of tooling is not going to be relegated to textbooks in the future, and we’ll also be used to have a bunch of CASE tools in our toolbox, to make software… better.

Gli strumenti CASE per l’ingegneria del software

Nota 2020-09-27: questo articolo è stato inizialmente pubblicato su Linux Journal Italia nel numero di Ottobre 2006. La rivista non è più disponibile e non pare archiviata altrove, e ho quindi deciso di rendere l’articolo disponibile su questo blog, come già fatto per altri articoli scritti da me in passato. La versione pubblicata può essere scaricata dal mio sito, mentre questo post include il testo. Vi prego di essere pazienti riguardo i refusi — l’articolo originale è stato pubblicato su sei pagine, e non avendo più la copia della bozza disponibile, è stato recuperato tramite OCR.

L’ingegneria del software, la materia che si occupa di descrivere e migliorare il processo di produzione di nuovo software, descrive anche un’intera classe di software di supporto per assistere il processo di produzione e di sviluppo del software stesso.

Parliamo dei cosiddetti strumenti CASE (Computer Aided Software Engineering, ingegneria del software assistita dal computer).

Il contributo dato da questa classe di software alla qualità dei prodotti finali è spesso sottovalutato, poiché in passato lo sviluppo di questi strumenti era poco pratico o poco conveniente e il loro impiego non veniva considerato vantaggioso per diverse ragioni, a cominciare dal costo dei software disponibili (proporzionale alla difficoltà del loro sviluppo), e finendo con la quantità di spazio di immagazzinamento su memorie di massa necessario per memorizzare le informazioni.

Lo stesso sviluppo di tali strumenti era spesso troppo arduo, un singolo gruppo di sviluppatori non sarebbe mai riuscito a creare software CASE allo stesso tempo generico e dettagliato per adattarsi alle differenti necessità di altri gruppi di programmatori, sia perché aumentando la flessibilità di un programma spesso si finisce col renderlo troppo complicato per essere semplice da utilizzare, sia perché è necessaria la conoscenza dei diversi modi in cui il programma verrà utilizzato per sapere come scriverlo.

Ma come spesso accade nel mondo del software, bastano pochi anni perché un’idea che fino a poco tempo prima sarebbe stata considerata irrealizzabile diventi abbordabile, grazie ai cambiamenti che avvengono sia nel modo di sviluppare il software sia nel campo dell’hardware medio su cui il software sarà eseguito. Per questo motivo ad oggi ci sono diversi strumenti CASE che vengono diffusamente utilizzati nei processi di sviluppo del software, sia proprietario che libero, sia professionistico sia amatoriale.

Il contributo del software libero

Una delle ragioni primarie nell’espansione del software CASE è sicuramente legata al software libero. Per sua stessa natura, il software libero tende ad essere sviluppato da persone con storie personali diverse, provenienti non solo da nazioni e culture diverse (di cui si possono interessare i sociologi, ma non di sicuro sviluppatori), ma soprattutto da scuole di sviluppo e progettazione diverse. La maggior parte degli sviluppatori impara un metodo di sviluppo e di progettazione ricavandolo dai propri insegnanti, su carta o di fatto (uno sviluppatore che ha imparato a programmare sul campo da un programmatore più anziano avrà sicuramente un metodo di lavoro diverso rispetto ad uno studente uscito dall’università che ha imparato a programmare attraverso i suoi professori: il primo avrà un approccio più orientato alla funzionalità degli strumenti con cui sviluppa, mentre lo studente avrà un approccio più formale, considerando che la maggior parte dei professori utilizzano tale approccio, che quindi valuterà gli strumenti inizialmente per quello che gli viene detto vengono utilizzati).

A causa di queste differenze, e spesso necessario uniformare il metodo di lavoro all’interno di un progetto di software libero, e questo avviene solitamente tramite l’utilizzo di strumenti CASE che aiutino a standardizzare il processo d’insieme.

Un altro contributo dato dal software libero allo sviluppo degli strumenti CASE è relativo direttamente al lato tecnico dello sviluppo del software libero stesso. Come si è dichiarato in precedenza, difficilmente un gruppo limitato di sviluppatori riuscirebbe a sviluppare un software che si applichi a casi molto generali: lo sviluppo di un tale software richiederebbe molti mesi di analisi, interviste e prove pratiche per poter raccogliere dati sul metodo di utilizzo dell’applicativo, ma questo solitamente è un costo troppo alto per un’azienda che volesse vendere il proprio prodotto, poiché ai requisiti di risorse non corrisponde una certezza di introito, il software sviluppato potrebbe molto facilmente essere troppo generico per essere utilizzato in modo pratico, oppure si potrebbe finire con il crearlo troppo legato al processo di produzione delle grandi aziende, troppo complesso e intricato per i medi-piccoli sviluppatori che formerebbero il maggiore pubblico per un tale software; una soluzione e quella di sviluppare un software generico da modificare per il cliente di volta in volta, ma questo potrebbe essere troppo oneroso per i piccoli sviluppatori, e coloro che potessero permettersi una tale spesa potrebbero, molto probabilmente, sviluppare il software di supporto in casa.

Grazie agli ideali del software libero, è più semplice iniziare a sviluppare un software tagliato per un determinato scopo, sviluppato appositamente per un gruppo di sviluppatori, e aspettarsi che altri gruppi di programmatori estendano, astraggano o dettaglino tale software, riducendo la necessità di analisi e interviste. Inoltre lo sviluppo di soluzioni su misura diviene più pratico, poiché non e più necessario chiederne la modifica ai creatori originali, ma chiunque può modificare il software per come è necessario, dedicando un numero limitato di sviluppatori interni che già conoscono il flusso del processo nel proprio ambito.

Ma seppure il software libero ha una primaria importanza nella diffusione degli strumenti CASE, e difatti molti di tali strumenti sono disponibili come software libero, non si tratta sicuramente della sola ragione per cui questi strumenti sono ora più diffusi che in passato.

Molti strumenti CASE memorizzano informazioni durante tutte le fasi di sviluppo di un programma, quindi la quantità di spazio su memorie di massa di cui necessitano cresce con la crescita delle dimensioni del software (e di fatto un software solitamente cresce di dimensioni durante la sua vita, e mai diminuisce). Anche solo cinque anni fa era un sogno quasi impossibile avere un computer con due dischi rigidi da 240 GiB, mentre ora si tratta di una realtà molto comune; anche se i costi dei dischi rigidi professionali per server e workstation aziendali non sono scesi con la stessa curva di quelli per normali PC, si ha comunque un prezzo per MiB ben più basso del passato, che rende possibile I’immagazzinamento delle grosse quantità di dati generati dagli strumenti CASE.

Progettare, realizzare, mantenere

Esistono strumenti CASE per assistere a tutte le fasi del processo di produzione del software: alcuni sono pensati e realizzati per assistere i progettisti che lavorino prima dell’inizio dello sviluppo vero e proprio del software, altri sono pensati per aiutare la gestione del software dal momento in cui si inizia la sua programmazione per tutta la sua estensione di vita, mentre altri assistono il mantenimento sul medio e lungo termine.

Ci sono poi molti software che non si considerano spesso come strumenti CASE, come i compilatori, perché sono parte integrante del processo di sviluppo del software, o perché sono stati sviluppati prima che la definizione di CASE fosse coniata. Si tratta perlopiù di “assistenti” allo sviluppo, come estensioni o miglioramenti del compilatore o strumenti di debug. La loro presenza nella categoria degli strumenti CASE può essere messa in discussione, ma non ci sono dubbi che, facendo parte del processo di sviluppo del software, siano anche parte della più grande catena dell’ingegneria del software.

Ovviamente ci sono casi in cui, per supportare la produzione di un particolare software, si vanno ad utilizzare strumenti che non sono stati pensati e sviluppati per tale scopo. Anche se questi fanno parte di determinati processi di sviluppo, di un’azienda o di un gruppo di programmatori, non è ovviamente possibile considerarli strumenti CASE, nello stesso modo in cui un browser Web utilizzato per la ricerca di informazioni non possa essere considerato strumento di un’inchiesta giornalistica.

C’e poi da dire c e la maggior parte di questi strumenti non ha un risultato ultimo, perché quello di cui si occupano è fornire un supporto durante tutto il processo di sviluppo. Quando gli strumenti generano informazioni direttamente, si tratta solitamente di informazioni estemporanee che vengono utilizzate e rese già obsolete dagli sviluppatori. Gli strumenti più importanti, però, creano soltanto una grossa quantità di informazioni che continuano a venire utilizzate da quegli strumenti stessi, e da cui e comunque possibile recuperare dati più intelligibili (seppur spesso con dubbia utility) che possono essere utilizzati per creare statistiche e grafici utili nelle presentazioni.

Supporto alla progettazione

A seconda del metodo di sviluppo che si sta seguendo, la progettazione iniziale, prima di iniziare lo sviluppo di un software, ha una minore o maggiore importanza; in ogni caso, anche nei metodi di sviluppo agile e di programmazione estrema (XP, eXtreme Programming), in cui i programmatori si concentrano soprattutto sulle fasi di sviluppo e di test incrementale del software, una delle prime fasi del processo di sviluppo del software e appunto la progettazione (preceduta dalla raccolta di informazioni riguardo al software che si sta sviluppando).

Per riuscire a scrivere strumenti di supporto funzionali, utili e comprensibili da un vasto pubblico per la progettazione del software, è stato definito un linguaggio che può essere utilizzato per descrivere la struttura di un programma secondo una serie di aspetti, si tratta di UML (Unified Modelling Language, linguaggio di modellazione unificato). UML descrive come si possono realizzare una serie di diagrammi che a loro volta descrivono il software che si sta progettando. I diagrammi più comuni sono sicuramente quello delle classi (che descrive i legami di ereditarietà tra le classi e i loro membri), quello di attività (una versione modificata del classico diagramma di flusso (flow chart) pensata per descrivere il flusso delle funzioni di un programma) e quello dei casi d’uso (use-case) (che permette di definire il modo in cui diverse persone utilizzano un dato software).

Per quanto sia logicamente possibile realizzare i diagrammi UML con un foglio e una matita, o con un generico software di grafica, uno strumento CASE offre più di queste semplici funzionalità.

I software di progettazione UML, come Umbrello e bouml (come software libero) o Poseidon (proprietario). Questi programmi non sono solo programmi di grafica specializzati, ma forniscono supporto aggiuntivo, come la possibilità di definire una singola classe una sola volta e riutilizzarla nei vari diagrammi, delle classi e di struttura, correlandole a livello logico e grafico. Oltre a questo, quasi tutti i software di progettazione UML hanno una funzione, più o meno elaborata, per la generazione di codice a partire dai diagrammi disegnati; si tratta solitamente solo di uno scheletro delle classi definite nello schema, con i nomi e le firme delle funzioni, senza la loro definizione.

Per quanto nessun software e ancora abbastanza sofisticato dal riuscire a generare del codice che funzioni senza ritocchi qua e la, poiche i diagrammi UML sono solo delle descrizioni della struttura, dell’uso o del flusso dei dati, ma per esempio gli header con le dichiarazioni delle classi derivate dal diagramma relativo sono un buon punto di partenza per la loro implementazione, e un riferimento per gli utilizzatori di tali classi che possono iniziare lo sviluppo di altri componenti del software in parallelo, senza dover attendere la completa realizzazione delle loro dipendenze.

Supporto allo sviluppo

Quasi nessun software viene scritto immediatamente nella sua forma ultima, ma tende invece ad evolvere a partire da uno scheletro (o dal nulla) fino a diventare pronto per il rilascio. Molto spesso, poi, il codice sorgente del software rilasciato non rimane fermo, ma si evolve anche dopo il rilascio per la creazione di versioni successive, per la correzione di bug e così via.

Per questa ragione con il termine “sviluppo” non ci si vuole solo riferire alla fase di lavorazione che si pone tra la progettazione e la convalida, ma a tutte quelle fasi che partono nel momento in cui si inizia a lavorare al codice sorgente, comprese quelle necessarie per la correzione degli errori individuati nella fase di test e quelle necessarie per l’aggiornamento del software per adattarsi alle richieste dei committenti durante tutto l’arco di vita del suo supporto. E quindi di primaria importanza conoscere quali modifiche sono state effettuate nel tempo, il loro motivo e il loro autore.

Per questa ragione, uno dei più importanti strumenti di ingegneria assistita e sicuramente il software per la gestione del codice sorgente (SCM, Source Code Management), ovvero quel software che permette di salvare e visionare la storia di un insieme di file contenenti codice sorgente (o altro) memorizzando tutte le modifiche che avvengono tra una versione e l’altra dei file. Un simile risultato si ottiene utilizzando un metodo non-CASE, ovvero il backup periodico dei sorgenti (giornaliero, orario, o nel momento del rilascio del software), ma tramite l’uso di un SCM e solitamente possibile memorizzare assieme alle vane modifiche anche un commento relativo alle modifiche effettuate, e a seconda di quanto sofisticato sia il software SCM utilizzato e possibile riprendere i sorgenti come stavano ad un certo punto del tempo e iniziare uno sviluppo parallelo a partire da questi.

Il software SCM libero più conosciuto ed utilizzato sicuramente CVS (Concurrent Versioning System, sistema di versionamento concorrente), basato sul più datato RCS (Revision Control System, sistema di controllo delle revisioni), che espande con il supporto per la gestione contemporanea di pia file, l’accesso da parte di utenti multipli e tramite rete. CVS e stato sicuramente uno dei punti chiave nello sviluppo comunitario del software libero; grazie alla sua disponibilità e relativa semplicità di impostazione, e uno dei software più utilizzati per la gestione dei sorgenti di software libero e Open Source, specialmente perché negli anni sono nati e fioriti diversi servizi che forniscono agli autori di tale software spazio web e altri strumenti per la gestione dei progetti, tra cui anche SCM (, BerliOS, GNU Savannah, …). Purtroppo l’età di CVS si sta dimostrando un grosso punto a sfavore, mancando molte delle funzioni disponibili in altri software, come Subversion, tra cui la gestione dei cambiamenti su file diversi come una singola modifica.

Esiste poi una serie di software SCM “distribuiti”, che rimuovono la necessità di un singolo server a cui accedere per inviare le modifiche, e invece le spostano sui diversi computer su cui queste avvengono (e, volendo, su un server pseudo-centralizzato).

Anche se tutti (o quasi) gli SCM permettono di visualizzare le modifiche tra una versione e l’altra e recuperare le informazioni relative tramite il software stesso, solitamente tali informazioni vengono recuperate e visualizzate tramite più amichevoli interfacce web, come ViewVC, WebCVS, WebSVN, gitweb e così via. Questi software sono strettamente legati e dipendenti dal software SCM stesso, anche se sono solitamente sviluppati separatamente e da gruppi separati di sviluppatori.

Durante lo sviluppo, poi, e solitamente necessario avere a disposizione la documentazione delle interfacce interne ed esterne del software, (quelle esterne sono necessarie anche una volta che il software è stato completato), se esistono. Per quanto sia possibile scrivere tale documentazione separatamente, per facilitare questo compito sono stati sviluppati diversi software che interpretano i sorgenti ed estraggono i commenti lì presenti per generare una documentazione di riferimento, se formattati in modo opportuno. Solitamente questi software generano la documentazione in formati diversi, HTML tra questi in genere, ma possono anche generarla in un formato utilizzabile da un altro programma per fornire informazioni contestuali nel codice sorgente.

Purtroppo realizzare un software unico che possa utilizzarsi per documentare qualsiasi linguaggio e molto difficile, non solo perche non esiste un interprete universale che si adatti a tutte le regole di sintassi dei vari linguaggi, ma anche perche ogni linguaggio ha caratteristiche diverse (sintassi di chiamata, strutture dati, . . . ) che devono essere tenute in considerazione nella creazione della documentazione. Per questa ragione esistono diversi software che generano la documentazione a partire da sorgenti di diversi linguaggi.

Tra i software liberi disponibili e da segnalare Doxygen, che utilizza una sintassi compatibile a quella di JavaDoc e al software proprietario utilizzato per documentare le librerie Qt di Trolltech, limitato a linguaggi più o meno compatibili con C, C++ e Java, che ha la possibilità di generare diagrammi delle classi UML basandosi sul codice effettivamente scritto, permettendo un rapido-confronto tra la progettazione e la realizzazione effettiva.

Oltre a questi software di supporto strettamente CASE, ci sono altri strumenti che si possono considerare parte dei processi CASE anche se non vengono utilizzati solamente nel contesto dell’ingegneria del software, e anzi sono, per gli sviluppatori che li utilizzano, parte stessa dello sviluppo.

Si tratta di quegli strumenti utilizzati per il debug, ovvero per la ricerca e correzione degli errori di programmazione all’interno di un prodotto in via di sviluppo.

La fase di debug non pub essere saltata da nessuno sviluppatore, professionista o amatoriale, singolo o in gruppo, di software libero o proprietario, qualsiasi sia il metodo di sviluppo utilizzato.

Si tratta di parte integrante dello sviluppo del software e per questo e sicuramente l’attivita per la quale sono stati scritti più software di supporto.

II primo software importante per questa attività e il cosiddetto “debugger dinamico”, utilizzato per verificare lo stato di un processo in esecuzione determinato sul codice sorgente. Questo tipo di strumento e altamente dipendente dal linguaggio di programmazione utilizzato, dal compilatore o interprete scelto, e dal sistema operativo. Per quanto le funzioni principali siano molto chiare (fermare l’esecuzione, analizzare le variabili, eseguire passo-passo), con il tempo i vari debugger hanno iniziato a fornire funzioni avanzate, come interfacce grafiche o l’accesso remoto tramite seriale o TCP/IP.

Il software libero più utilizzato per questo compito è sicuramente GNU Debugger (gdb).

Oltre a questo, esistono due principali classi di strumenti che sono pensati per supportare tale attività, si tratta degli strumenti per l’analisi statica e l’analisi dinamica.

I primi sono utilizzati per analizzare i sorgenti del software durante lo sviluppo, alla ricerca di chiamate errate o problematiche, per evitare errori comuni, mentre gli strumenti di analisi dinamica sono utilizzati sul software in esecuzione per verificarne il comportamento, per cercare eventuali errori nella gestione della memoria o nell’utilizzo dei parametri forniti.

Mentre l’analisi statica viene eseguita sull’intero codice, l’analisi dinamica pub essere eseguita solo sulle parti di codice che sono realmente eseguite mentre lo strumento e attivo, quindi per quanto solitamente più sofisticata, non può considerarsi un metodo sicuro per la verifica di un intero software.

Bisogna però mettere le mani avanti quando si parla di questi strumenti, facendo una netta distinzione tra i linguaggi compilati e quelli interpretati, ovvero tra i linguaggi come C, C++ e Java (per quanto quest’ultimo sia parzialmente interpretato) e i linguaggi di scripting come Perl, Python, Ruby e PHP, utilizzati professionalmente soprattutto nella creazione di Web Applications (Pert, PHP e Ruby in particolare). Mentre per i primi sono disponibili molti software di analisi

sia statica che dinamica, per gli ultimi la cosa si fa molto più complessa, poiche non è solitamente possibile effettuare un’analisi statica di uno script interpretato, perche le variabili possono assumere valori e tipi di dato che cambiano al momento dell’esecuzione, e per l’analisi dinamica e difficile separare l’esecuzione degli script dall’esecuzione dell’interprete e della chiamata alle funzioni di libreria necessarie.

L’analisi dell’esecuzione dei software scritti utilizzando linguaggi interpretati, quindi, deve essere effettuata dall’intemo del programma stesso, solitamente senza software che la possa assistere.

Gli strumenti di analisi statica hanno avuto un ampio sviluppo dagli albori della programmazione moderna fino ad oggi, il software più conosciuto e sicuramente LINT, sviluppato appunto negli anni ’70 quando i compilatori C non effettuavano un rigido controllo sul tipo dei parametri passati alle funzioni, permettendo dunque di chiamare le funzioni di libreria con parametri diversi da quelli attesi (interi per stringhe e viceversa per esempio).

Si tratta però di un software ormai obsoleto, poiché tutti i compilatori moderni già fanno tale controllo, e buona parte dei controlli statici che venivano effettuati da LINT. Il compilatore diventa dunque anche un importante strumento di ingegneria del software che, correttamente utilizzato, permette di migliorare la qualità del software sviluppato.

Mentre il software di analisi statica per un dato linguaggio di programmazione sovente funziona su qualsiasi sistema operativo, salvo i normali problemi di portabilità del software, il software di analisi dinamica dipende anche molto dal sistema operativo (e dall’architettura hardware), si tratta quindi di software particolare, che net software libero e rappresentato da Valgrind (per GNU/Linux) e da DTrace (per Solaris e FreeBSD). Ma anche le librerie di sistema moderne hanno alcune funzioni di analisi che possono indicare se il programma sta comportandosi in modo corretto con la memoria.

Supporto al test e alla convalida

La fase di test e di convalida e spesso sottovalutata sia da programmatori amatoriali sia da professionisti; si tratta della fase in cui si va a controllare che il software sviluppato sia conforme ai desideri del cliente (o in generale degli utenti del software stesso). L’uso di software CASE per questa fase ha un’importanza maggiore che per le altre: non e solo un ausilio che semplifica il lavoro degli sviluppatori, ma può anche essere l’unico modo per avere dei risultati affidabili riguardo i test: se alcuni test fondamentali sono sempre effettuati manualmente non e impossibile ne raro che il test sia effettuato in modo leggermente diverso di volta in volta, rendendo i risultati inattendibili o addirittura inutili. Per questa ragione e importante che i controlli siano automatizzati il più possibile, e per questo sono stati sviluppati diversi software CASE per migliorare l’affidabilità dei controlli. Si deve pero sapere che più un controllo e complesso e avanzato, più è probabile che individui dei falsi positivi per codice scritto in modo poco ortodosso o comunque non consono.

Un esempio di software CASE per il supporto della fase di test si trova in quelle soluzioni per la creazione dei cosiddetti (test unit, unita di test ), come per esempio JUnit e C++Unit, che permettono di semplificare la scrittura di test in modo che possano eseguirsi in modo analogo anche se vanno a testare parti differenti del software. Le unita di test poi possono comporsi in “batterie di test di regressione”, che se eseguiti regolarmente dopo modifiche importanti ed estensive permettono di riconoscere subito errori nelle modifiche che possono essere più difficili da individuare successivamente.

Ma se i test di regressione sono pin parte dell’attività di debug che della fase di convalida, si possono scrivere unita di test pin complesse che verificano il comportamento delle interfacce esterne del software, piuttosto che singole funzioni o singoli componenti interni del software. In questo caso si tratta di un valido strumento CASE per la convalida, anche se molto spesso le funzionalità da convalidare richiedono l’intervento di un utente reale, specie per i software con interfaccia grafica complessa.

Supporto alla manutenzione

C’e un’altra classe di strumenti CASE che deve molto, per il suo sviluppo, al software libero: si tratta dei cosiddetti bug trackers, quei software, utilizzati sia da progetti di software libero che da aziende sviluppanti software di qualsiasi tipo (ma anche da alcune aziende che vendono servizi), che permettono di segnalare errori e richieste di funzionalità per un determinato software, di commentare sulle richieste, e di indicare la risoluzione, il risolutore e altre informazioni relative alle richieste. Solitamente tali software sono delle Web Applications, per permetterne un semplice accesso da parte di tutti gli utenti o clienti, anche se non mancano alcuni software che permettono di inviare le richieste ad un server centrale tramite particolari protocolli.

Il software libero più utilizzato per questo genere di supporto e sicuramente Bugzilla, sviluppato dal progetto Mozilla (autori del browser Firefox e del client di posta Thunderbird) per la gestione dei propri bug, ma successivamente utilizzato da molti altri progetti, grossi e non, come KDE, GNOME, FreeDesktop, Novell, Gentoo e altri ancora. Essendo software libero, pur non essendo di semplice installazione e gestione, quasi ogni installazione di Bugzilla e differente dalle altre; oltre alle modifiche alla veste grafica, che sono la parte pin semplice della personalizzazione, alcune installazioni permettono la segnalazione guidata dei bug, utilizzando pagine diverse da quella originale, che facilitano la categorizzazione delle richieste.

E anche vero che moltissimi progetti non utilizzano altri tracker a parte quelli forniti dal loro servizio di hosting (SourceForge, BerliOS e così via), poiché non possono permettersi un server dedicato per Bugzilla (che richiede molte risorse per funzionare adeguatamente). A causa delle richieste tecniche necessarie per far funzionare Bugzilla, e la sua complessa gestione, anche quei progetti che non utilizzano servizi di hosting integrati cercano quando possibile soluzioni alternative per la gestione delle richieste. Un altro software molto utilizzato e Mantis, di pin basso profilo, meno configurabile, ma molto pin leggero, non avendo particolari richieste in risorse o in dipendenze.

Similmente esiste un software chiamato Trac, che unifica in una singola applicazione un Wiki, un’interfaccia Web al software SCM Subversion e un sistema di tickets (equivalente ad un bug tracker). Per quanto meno elaborato di Bugzilla e Mantis, Trac può essere facilmente utilizzato per la gestione dei bug di progetti di media dimensione. Si tratta comunque non di un semplice software per la gestione dei bug ma piuttosto di un cosiddetto “ambiente CASE integrato”, ovvero di un software che permette di accedere, attraverso la stessa interfaccia, alle informazioni relative alle richieste, alla documentazione e alla storia dei sorgenti.

Ambienti integrati

Come si e visto in precedenza, esistono i cosiddetti “ambienti CASE integrati”, (integrated CASE environments), ovvero software che permette l’accesso, tramite una singola interfaccia, a diversi strumenti CASE. Un esempio e Trac, software che fornisce un Wiki, un’interfaccia a Subversion come software SCM, un sistema di ticket e anche un sistema di release dei file. Similmente i software utilizzati da SourceForge e da GForce e GNU Savannah (i primi due proprietari, il terzo software libero), forniscono diversi strumenti utili per I’ingegneria del software (gestione delle release, gestione dei bug e delle richieste, gestione della documentazione e così via), sotto un’unica interfaccia permettendo la collaborazione e la coordinazione tra sviluppatori.

Ma se la maggior parte degli ambienti CASE integrati sono Web Applications, per rendere più semplice la collaborazione tra diversi sviluppatori, esistono anche ambienti integrati di sviluppo (IDE, Integrated Development Environment) che forniscono un’interfaccia unica a strumenti CASE differenti, come possono essere i software per la scrittura dei sorgenti (editor di testo), i compilatori e gli strumenti SCM.

I software pin conosciuti per questi compiti sono sicuramente i software proprietari di Borland e Microsoft, che hanno iniziato lo sviluppo di tali ambienti, ma Eclipse di IBM e KDevelop del progetto KDE, entrambi esempi di software libero, stanno guadagnandosi un buon pubblico.

La maggior parte degli ambienti di sviluppo integrati forniscono funzionalità di supporto strettamente per lo sviluppo, e già il supporto per il software SCM e una funzionalità avanzata, non disponibile in tutti gli ambienti e non soprattutto non per tutti i software che possono utilizzarsi.

Quello che invece manca nella maggior parte degli ambienti di sviluppo e l’integrazione degli strumenti di supporto alla progettazione.

Non e dunque possibile avere un singolo ambiente CASE integrato, seppure lo sviluppo del software CASE e ora molto più avanzato che negli scorsi anni. Anche le diverse Web Applications che forniscono supporto CASE non sono integrate tra loro, seppure l’esteso uso di XML riesce a permettere una generica integrazione di tante applicazioni Web, nulla e stato sviluppato per permettere l’integrazione dei vari software per la gestione dei progetti sulla falsariga di SourceForge.

Per ciò che riguarda l’integrazione dei bug trackers, per quanto Canonical (l’azienda che finanzia to sviluppo della distribuzione Ubuntu) abbia in progetto lo sviluppo di un software, che si appoggi al loro già sviluppato LaunchPad, per l’integrazione di vari sistemi di tracking, nulla è ancora sviluppato che permetta semplicemente di collegare bug in diversi siti, ma Bugzilla già fornisce la possibilità di esportare i dati relativi ai bug tramite XML, il che fornisce uno spunto per l’utilizzo dei dati di un sito su un altro.

Tramite il giusto uso degli strumenti CASE elencati durante le vane fasi che compongono il processo di produzione del software e possibile far evolvere un software dalla sua origine fino ad un prodotto finale senza perdite di informazioni e senza richiedere la produzione di molta documentazione cartacea. La progettazione, la documentazione degli algoritmi, la documentazione delle interfacce, la storia del codice, degli errori e delle richieste segnalati saranno disponibili e, se viene usato un ambiente integrato, saranno pieni di riferimenti incrociati.

E dunque possibile, per esempio, sapere la ragione per cui e stata effettuata una modifica, perché il comportamento del software e stato cambiato in risposta alle richieste dei suoi utenti e così via; e possibile recuperare la documentazione prodotta durante la fase di progettazione e confrontarla con il codice che e stato realizzato; e possibile sviluppare il software in parallelo per affrontare problemi diversi, facendo evolvere due prodotti distinti a partire da una base di codice comune.

Purtroppo, il software di supporto CASE none ancora abbastanza sviluppato per conformarsi adeguatamente ad alcuni metodi di sviluppo che si discostano troppo dai metodi generali che l’ingegneria del software ha tracciato, perché per esempio c’e software che non possiede alcuna fase di progettazione complessa e semplicemente si evolve durante la fase di realizzazione partendo da una base molto semplice e ascoltando le richieste degli utenti; in tal caso il supporto CASE importante e quello relativo al software SCM e ai bug trackers, mentre il software di progettazione non avrebbe più ragione per essere usato.

Si tratta quindi di un campo di sviluppo dell’ingegneria del software ancora aperto all’innovazione, e in cui ogni sviluppatore ha la possibilità di portare nuove idee e nuove implementazioni, grazie alla grande quantità di software libero già disponibile cui contribuire. Software scritto da sviluppatori per gli sviluppatori.