The basics of programming – survival kit for junior programmers

Every once in a while I have this feeling, that I understand this stuff so well, I could easily teach it. And then I see a student, and I am wondering why they don’t get it. Why should I explain the basics again? And the basics of the basics. In one of those occasions it occured to me that those basics, well, they aren’t that basic at all. I mean, they are still the basics of the programming, but they are not easy at all.

So here is the plan: I am going to put together a survival kit for aspiring and junior programmers. One blog post per week. We’ll see how far we are getting with this.

All of those topics are covered and well-explained over the internet and in various books. So what does this series give? It is a survival kit: it lists the stuff that you should learn, how you can learn them efficiently. I am also going to explain what is that you don’t need to learn, i.e. which is not part of the basics. I am going to explain how to maintain a work-life balance in this crazy, overwhelming world. How to sustain this job: how to be a programmer in the long run. This is indeed a survival kit.

I intend to make this entirely bullshit-free. I am not going to promise that with these steps you can double your salary. That happens during the junior-medior transition anyway. I am not going to tell you how to land a job at a top-tier company because no way everybody can work at a top-tier company. I am not going to tell you what a professional programmer must do, because that might or might not match your values. On the other hand, I am going to explain why and how to be nice – even when it feels like you are surrounded with assholes.

These are the topics I would like to cover – from the top of my head. Please let me know in comments if there is anything you would like to hear about:

  1. Which programming language to learn and how to learn it
  2. When you can learn – i.e. don’t cut that much off of your sleep
  3. The art of doing one thing at a time
  4. Unit testing
  5. Writing the tests first
  6. Debugging, and exploring the world around us
  7. Auxiliary languages
  8. Auxiliary technologies
  9. Code reviews
  10. How to maintain your creativity (that is easy: consume culture)
  11. Learning frameworks
  12. Refactoring and design patterns
  13. Bibliography

If there is anything you would like to hear about, please let me know.

Posted in basics, programming | Tagged , , | Leave a comment

Deliberate practice with Lean poker

Last November Ivett invited me to participate at her Lean Poker event. I was a bit skeptic, as I stopped learning in my free time long ago. There is nothing wrong with learning in your free time, I just re-prioritized my life. In other words, I was sure that I was going to learn something, I just wasn’t sure it was going to be worth my time.

Spoiler: It was.

It was also company time.

I’ll explain briefly what Lean Poker is and what I learned. As Lean Poker is an event to practice, i.e. not frontal learning, you might learn something else.

So, what is Lean Poker? It is a competitive game where teams develop Poker Agents, and then those Poker Agents play against each other, using a well-defined network protocol. Easy to say, not so easy to do. Here are the things that we had to do:

  • Figure out how to collaborate (online)
  • Make sure that our Poker Agent is always functional, otherwise we’d loose in every round
  • Learn the details of the Texas Hold’em Poker
  • Learn the API of the common protocol
  • Follow state of the game, read the logs and figure out how to enhance our Poker Agent in small increments

This is a lot, and we only had 2×4 hours for this. Actually, I was sick on the second day, so I only got 1×4 hours. During this 1×4 hours we did all the stuff above. I believe, the rest of the team went on doing this.

So here are my highlights from the event:

Figuring out how to collaborate

Compared to my day-to-day development tasks, this was a fast-paced event. We found that creating a git workflow with review and whatnot would use too much time. Instead we decided to do mob programming:

  • one person is writing the code, they are responsible for writing code that compiles
  • everybody else gives advice, that can be either low level (this is complex enough, let’s write some tests) and strategical (let’s change the bidding algorithm)

So I got some experience with Mob Programming. Not applicable at my work right now, but if we’ll need to collaborate more closely, this is one good way to do it.

Making sure that the Poker Agent is always functional

We did a deploy-to-prod approach and looked at the logs. In some businesses this is OK, in some others it isn’t. I haven’t done anything like this in my career. I was a bit scared, but things were all right.

What I learned: testing in PROD can be OK – as long as the losses for a mistake are tolerable, you do watch the logs, and you have sufficient logging statements in your code.

Learn the API of the common protocol

Well, actually, we didn’t do that. Copilot did.

I am skeptic about AI generated code. However, I saw some good use-cases here. Copilot generated code for this API, so the learning curve was short. This is a clear win.

Copilot generated okay-ish code, based on the method names. This also helped us to deliver stuff quickly. That code was a little too verbose, and didn’t always work properly. We had to test it (that is always a good idea anyway), in a real-life scenario I would’ve cleaned it up before sending for review.

Instead of this craftsmanship, we had a generate-and-throw-away approach: in case the generated code wasn’t good enough, we tweaked a little, and the Copilot came up with new, better suggestions.

What I learned: Copilot can speed up some phases of programming.

Posted in Uncategorized | Leave a comment

Survival kit: (don’t always) find a solution on your own

The problem

There is this message that every developer is getting every once in a while. When they ask a question, a colleague might reply with something like ‘Find a solution on your own.’

I find this message especially toxic, because there is a little grain of truth in it. This little grain is that we are hired to solve problems, while building or maintaining things. So this sounds about right, and some of us might just start to find a solution on their own.

The toxic part is that it disimisses the colleague who asked for help. I am wondering, why don’t we assume that the person asking a question has a good reason to ask that question?

Some kind of valid questions

Here are some valid questions that developers might ask:

Junior developers might ask language- and framework-related questions that they could find the answer with google. If only they knew how to search and how to evaluate the search results. There is lots of bad advice on the web, how would they find the good answer? They will find it, eventually, but that takes time. It also involves senior developers, either at code review, or at the maintenance phase. Letting junior developers finding their own solution is how you can accumulate technical debt quicly.

More experienced developers might ask questions like, what does this module do? What is the code convention for this and that logic? They can find the answer, by reading the code, but that takes time. If there is another developer around, who knows the answer, then one one-hour walk-through can save weeks, even months.

Developers sometimes even ask about requirements, design documents, and so on. These things are usually documented, and the developers can find them. However, if there is a BA around who could point the developers to the right documentation, maybe even help to make sense out of it, that can save weeks or months of reading.

The point is that communication is a key activitiy in software development. We have to do it well.

The band-aid

There are lot of advices on how to ask a question properly. This blogpost is a survival kit for junior developers, so I’ll repeat them here:

  • Be specific: State the most concrete problem that you want to solve.
  • Explain what you tried so far and how that failed.
  • Finally, try to ask a question. In some settings you can also say ‘Can you help me with this?’

The real solution

On the other hand, we, as an industry, need to learn to respond to the questions properly:

  • If the question is not specific, ask them ‘What did you try so far?’
  • If you don’t have time, say so: ‘I am busy today. Can we have a call tomorrow at 10 am?’
  • If you don’t know the answer, just say it: ‘I don’t know.’
  • If you don’t know the answer, but you want to be helpful anyway, you can say ‘I don’t know. Let’s look at it toghether.’
  • If the question sounds totally off, say so, and ask for more details: ‘Something doesn’t seem right with this. Can you walk me through the details?’
Posted in programming, soft skills | Tagged , , , | Leave a comment

Survival kit: first day on the job

This is an actual survival kit: what should you bring on your first day of job, and how to prepare. A step by step guide.

  1. Sleep well if you can. I am generally an axious person, so usully I don’t. Anyway, sleep well, if you can.
  2. Dress well. I usually choose a shirt with jeans, or a polo shirt with jeans. It depends on the dress code too.
  3. Pen and paper to take notes. There will be lots of information. I have difficulty to remember every name at once, however, I found that it makes no sense to write them all down.
  4. Coffee, tea or any legal stimulant that you are addicted to. Unless I forget, I bring a coffee in a bottle. I drink a lot of them, but different companies have different ceremonies around coffee. Sometimes you have to go another building to buy a cup, sometimes you have to bring your own capsule, sometimes coffee means 30 mins of chitchat. I however, need coffee to avoid the migraine, so I bring it in a bottle, mixed with lactosefree milk.
  5. Snacks. Their lunch schedule might be different than yours. Paying attention and getting hungry, that is a bad combination. I know lot of people who are happy with 3 big meals a day. I on, the other hand, eat often, and eat a little. If I bring apples, then I’ll have healthy snacks. Otherwise I would buy chocolate bars. I think it’s also fine to bring sandwiches.
  6. A book to read. There can be lot of time off, while they are finding the paperwork, givinig you your computer, activating all your accounts. So bring a book, or anything else that lets you quietly kill some time.

If I missed something, please let me know in comments.

Posted in soft skills | Leave a comment

Survival kit: Refactoring

Refactoring – improving the design of existing code. This is the title of Martin Fowlers book. This book is so fundamental, even the IDE-s (Integrated Development Environments) support refactorings.

This is a screenshot of a refactoring context menu from IntelliJ:

Here are some refactorings supported by eclipse:

Some folks claim that you don’t even need to do refactorings manually. There is truth in that, however, it’s still a good idea to read that book. It is also a good idea to do a few refactorings manually. Chances are, you already did, and it went wrong.

Before diving deeper

The survival kit could end like this: don’t worry about getting the code right at the first attempt. You can always refactor later. If you don’t have tests, you can rely on the refactorings of your IDE. Advanced programmers can write their tests (I’ll cover the tests later).

Here is a good overview of code smells and refactorings here: https://sourcemaking.com/refactoring Just learn what options you have, and play with them.

I believe, this should help you to do the first steps of refactorings. In the rest of the blogpost you can read about tests, redesign, namings and legacy code.

What is refactoring?

Refacgtoring is the technique of changing the design of the code in small steps, without chaning the behavior. This sounds really good, but can we really differentiate between design and behavior?

Martin Fowler suggests that before starting to refactor the code, one should build a solid test suite set for the code to be refactored. Write good, expressive tests, he suggests. If that was easy.

If the tests are written after the code, the tests are likely to cover every possible output and side effect, regardless if those are inherent or just coincidental. This is the right practice, because with legacy code you can’t possibly know what the other subsystems are depending on.

They might depend on logging that look otherwise insignificant. They might depend on the existence of a method, as one can extend them with aspect-oriented tools, like AspectJ. In older versions of Ruby on Rails – Active Records, the dynamic finders generated SQL code based on a method name.

So you know, you never really know, unless you write the tests first, and you honor the contracts that the tests suggest.

You see, we have touched legacy code and test-driven development. I am planning to write about them later. For now let’s assume that somehow you have a solid test suite, and the test suite defines behavior. Everything else is design.

Even this assumption is inaccurate, because the tests depend on production code. That is one of the reasons why I prefer data-driven tests. A good set of test data is also always incomplete; the real logic is in our head. Maybe property-based testing can define the logic too. I am not yet familiar with that. Anyway, a good set of test data is decoupled from the classes and methods. So there it is, pure behavior, which must not be changed when you refactor. Everything else is malleable.

What we can still learn from the book

Each refactoring starts with a motivation. What is the goal when you are extracting a method? What is the goal when you are inlining a different method? All these give you a framework on how to think about code.

By now you probably know that I am not a big fan of thinking about code. I prefer evidence-based programming. However, the thinking part is inevitable. One must have a mental model, even though that mental model is almost always wrong. These wrong mental models help us to create a hypothesis, that we can test later. These give us ideas, that we must later inspect rigorously.

It is also a good idea to look at the mechanics. Martin Fowler shows the small steps. Those might feel to small at first, but he is not kidding. Baby steps let us make fewer mistakes, so in the end we can go faster. If you pay attention, you will see the possible problems that you might run into, when you are changing an existing code base.

Why didn’t you get it right in the first place?

A coworker or boss might ask you, why do you refactor? Why didn’t you get it right in the first place?

There is an answer for this question, but I only give them to juniors. Everybody else should know.

Here is the answer: it is difficult to get it right at the first attempt. Especially when you are beginner, you just can’t get it right. I find this kind of perfectionism toxic and paralyzing. The mantra is: fist make it work, then make it right (in small increments). For those who are extremely concerned about performance: once it is right, you can make it fast.

There is another reasons why you can’t get it right: requirements change. The design that was just perfect last month, that is likely in our way now. Why didn’t we foresee this change? Well, why didn’t the business foresee this change? Because it’s impossible. As developers, our task is to write code that works and it is easy to change.

When should you refactor?

The boook mentions two driving factors for refactoring:

  1. When the requirements change, and the old design is not helping you anymore.
  2. When you see code smells.

When the requirements change, and it seems to be difficult to implement the new requirements, then he suggests to first change the design to make it easy to implement the new requirement. Once this refactoring is done, you can add the new code.

When you see ugly code, then you can change that too for the better. In Test-driven development, there is a short cycle:

  1. write a failing test
  2. write code so the test passes
  3. refactor

There are other cases too, when you see ugly code. The general rule is to leave the code in slightly better shape than it was when you arrived. But take care, don’t rewrite the entire codebase. Only modify the methods that you have to modify for other reasons too.

One example: Renaming things

One can rename classes, methods and temporary variables. This is the safest choice. There are a few exceptions: when the classes and methods are part of a public API, then you have to support the old names and delegate the logic to the renamed classes / methods. As I mentioned before, Active Records dynamic finders generate logic based on the method name.

Otherwise, the rename refactorings are the safests. Names don’t modify the code structure (here is another lousily defined concept), but they help us to formulate our mental models. I found that good names can make programmers understand the otherwise complicated code. As long as the names are good, we tend to forgive the long methods, long classes, complicated if statements.

Unfortunately I am not very good at naming things. Anyway, here are some hints:

  1. One must not use one-letter variables, except for the index vars, i and j.
  2. Variable names must be expressive. source and target are better than array1 and array2.
  3. If there is a corresponding business term, the names should match that. Imagine, that you can translate business speak to code speak. You might even explain the code to a business analyst. Would be nice, wouldn’t it?

Say what you mean

There is a general advice in programming: say what you mean. Easier to say than done. It is nice to read code that experesses exactly what is should do. It makes programming look easy. But it is not.

Sometimes we have an epiphany, like, oh, I can express the requirements directly, and the code will work. This epiphany is a nice feeling to have. It is also nice to rewrite the code to this form. However, this is usually a redesign, not a refactor. In these cases usually we change the code behavior too, and we change it for the better.

I am not discouraging you from this change. Just remember, most likely it is not a refactor, so do it extremely cautiously.

Wrapping up

Refactoring changes the code design, while does not change the code behavior. This book defines a series of operations that do exactly this. I find it fascinating, because neither the behavior, nor the design is properly defined. However, these refactorings are part of our engineering culture, and they were proven reliable.

Practical advices: If possible, do automated refactoring. Aim to have a solid test suite. Do the changes in small steps, and run the tests frequently.

Learning about refactoring gives you better way to think about the code. I can give no advice on this, just read the book, and make some sense out of it.

It is also a good idea to learn about code smells. Just remember, you don’t have to fix all the code smells at once. Sometimes the smelly code is a good compromise. Sometimes you just don’t know better yet. Keep practicing, keep learning, and it’s going to be easier.

Further reading:

  1. The refactoring book: https://martinfowler.com/books/refactoring.html
  2. A book on TDD: http://codemanship.co.uk/tdd_jasongorman_codemanship.pdf
  3. JUnit recepies, oldie but goodie: https://www.manning.com/books/junit-recipes
  4. Test shapes and what matter really: https://martinfowler.com/articles/2021-test-shapes.html

Posted in basics, programming | Tagged , , , | Leave a comment

Survival kit: How to deal with pushback?

I know a lot of engineers whom I respect, and disagree with me about the stuff I am writing. Some think that unit testing is not necessary. Or it is a skill orthogonal to development, i.e. not needed – testers tests, developers develop.

I like these conversations. Those seasoned engineers have so many reasons against best practices. Just telling them that these are best practices, well, that won’t convince them. Luckily, these are just conversations, nobody has to convince anyone. On the other hand, these discussions help me to explain my ideas a little deeper.

This is actually nice that we there are so many opinions in this industry. This could be a liberal, multicultural paradise. Unfortunately it is not, everybody is having so strong opinions – holding to them loosely. (My opinion about this: LOL WTF. We should rather be nice to each other.)

So if you are trying to follow my ideas, you’ll definitely get some pushback. You’ll get it from your peers, your seniors and from your project manager. What can you do about it?

Arguing and understanding

You can hear things like, this is a meritocracy. Or you can always have a healthy technological debate. Most of this are usually not entirely true. They might be true, to some extent.

On the other hand, no tech firm can exclude the other decision making factors, like seniority, informal communication channels, time and budget constraints. As a matter of fact, they shouldn’t exclude these.

I used to be a junior programmer who argued too much. Nobody liked it, especially when I was right. This is how I made sure that other devs didn’t like me. So my advice is: don’t argue. At least, don’t argue that much.

On the other hand, the company culture should let you ask questions until you understand the reason behind the technical decisions. You don’t have to agree with those reasons, no need to internalize them. Just understand the logic and see how that works out.

Some people don’t really support this understanding. You should avoid them, if possible. I know, sometimes it’s impossible, say for instance, this is your first job as a junior developer, or you have been job hopping a lot already. If you can’t go away, then try to have as little technical discussion with those people, as possible. And leave as soon as you can. It’s unhealthy, not teaching you much, and hurting your career.

Learning and experimenting

I think in every prorgramming job there should be some room for learning, experimenting and failing safely. I know that won’t every company support that. In that case, my advice is to leave them if possible.

I mean, really, every day there should be ~30 minutes to explore a new approach. This is roughly one Pomodoro period. Some time that can be wasted on stuff like, what if I write a unit test for this? Can I really extract this method? Do 3-line methods really help readability? Would the State pattern make these if statements more readable?

Ideally, there should be someone with whom you can discuss your findings. That can be a senior developer, a fellow junior, or anyone else who is really curious about your findings.

This is how to do an experiment:

  1. Figure out what you want to try
  2. Write down, or at least mentalize your expectations
  3. See if your experiment fulfilled your expectations
  4. See if there are any other side effects
  5. Carefully come to a conclusion:
    Is this the right context for this technique?
    What worked well? What did not work well?
    What were the pros and cons?
    Is the technique wrong or how you applied it?

If your technique works for you, then you can add it to your merge requests (or pull request, or changeset, or whatever unit your company uses to review the code). Your team members will hopefully see the benefits. They might even slowly follow you.

On the other hand, if the technique doesn’t work for not, then all you wasted was 30 minutes. No need to worry about it.

Experimenting on other levels

This experimenting approach works on concrete levels too. When using Test Driven Development (TDD), one writes one little chunk of test, then one little chunk of production code, and then one does a little refactor.

The little chunk of test can be something as little, as a missing method. Baby steps. Seriously.

Those who find writing test first odd, they can write the test after the production code. They can too add the production code and the test in small steps. They can refactor their code too after each code and test iteration. That’s how we can avoid the big headaches.

Further reading

In the last section I mentioned lot of things that I haven’t covered yet. I am planning to cover them later. Anyway, here is a reading list:

  1. Martin Fowlers Refactoring is a classic. A must read for those who are unhappy with the quality of the code they write. Fundamental work, I can’t overestimate it: https://martinfowler.com/books/refactoring.html
  2. Jason Gormans practical guide to TDD, from beginner to advanced level: http://codemanship.co.uk/tdd_jasongorman_codemanship.pdf

Posted in basics, programming, soft skills | Tagged , , , , | Leave a comment

Survival kit: code quality and static analyzers

Quite often I see junior developers worrying about the logic they write, and not caring too much about the code quality. That’s just aesthetics, it’s quite subjective, they say. Not really surprising, I had the same mindset back then.

If is funny though, that the code quality is observable, while the logics lives mostly in our head. Yes, the code logics lives mostly in our head. It is not easy to observe them. It is difficult to observe them without implementation details, like class names, method names.

There are some advanced topics that focus on the code logics, like property based testing and formal verification. Those are advanced topics, unfortunately I am not familiar with them, so I’ll leavem them here as references for the curious.

A note on aesthetics and literature

I know that critics too tend to focus on the observable things. In case of poetry those are words, sentences, punctuation, rhymes, alliterations, similes, metaphors and so on. In case of prose they look at bigger things as well, like characterization, plot twists. Even in those cases they support their statements with text excerpts.

Back to the code

In case of code, there are some objectively measurable things. These are spacing, line length, method length, class length, unused imports, and so on.

Although these are objectively measurable, their assesment is still subjective to some extent. Humans decide whether a solution is good or bad. No wonder that coding standards change from one company to another. They change even more across languages.

On the other hand, this subjectivity is not a good basis to dismiss the quality concerns. As the developers agree on the coding standards, those are the guidelines to follow. Usually this makes the code more readable, easier to understand.

Counting spaces

Counting spaces, measuring line length, looking for tabs, looking for magic constants – these are all boring tasks. Luckily, there are static code analyzers that do this for us. In case of java those analyzers are typically checkstyle, pmd and findbugs. Sometimes they come together with sonarqube.

When a static analyzer complains about something, that can be annoying. They don’t even let you know how to fix the code, they just complain. What can you do about it?

You can look up how to fix the problems. You can take the hints seriously (Too long line? Make it two lines. Or three.) You can ask other developers. Just keep following their rules, and they will make good style your second nature. The quick and accurate feedback helps a lot.

It is also cool that the same rules apply to everyone. Really, the same rules apply to you and to the team lead. Isn’t it cool? Nobody will write you up for a missing null-check. Nobody will ask you to avoid some constructs that they use all the time. Static analyzers got your back – use them.

Aesthetics and logic

Finally, a good, coherent code base lets us focus on the logic. You know, the part of the code that lives mostly in our head, as usually we can’t observe it by itself. Although code logic is mostly imaginative, it is still real.

It’s unfortunate that different programmers have different understanding about this logic. Usually the team leaders / senior developers / architects help the team to have roughly the same mental model. Hopefully they do it without mentioning the o-word.

Exceptions

Sometimes there are exceptions. One can add exceptions to code like @SuppressWarnings("PMD"). One can even change the pmd rules. As those are exceptions, the developers should discuss them, and agree whether they make an exception or not. This should make sense: code aesthetics is for the programmers, not the machine.

Posted in basics, programming | Tagged , , , | Leave a comment

Survival kit: unit tests as repeatable experiments

There is a lot of confusion regarding unit tests. Do we deliver faster or slower with unit tests? Do unit tests finalize the code, or do they open it up for a change? Shall we have more test code than production code, or less? Shall we allow duplication in unit tests? What are the units anyway?

Correctness of the code

As unit tests are tests, let’s take a step back, and take a look at the correctness of the code. How do we know that our code is working well?

Some people think that software correctness is a yes or no question: is it working well or not? Some folks think it’s an array of yes or no questions: we can check which features work well, and which don’t.

Others would include the code quality into correctness. They are usually software architects and senior devs who review other peoples code, and they accept it if and only if the code is well written.

In my opinion correctness of the code is a collective illusion. As long as we all agree that the system is working well, the system is indeed working well. On the other hand, if we don’t agree, then trouble starts. How should we fix? Which part should we fix? How will we know that the system works well again?

Collective illusions are not that rare

I am not well versed about epistemology. I know just enough to differentiate between real science and pseudo science. So junior programmers with liberal arts major, feel free to recommend books in the comment section.

So, collective illusions are not that rare. Moreover, that something being a collective illusion, it does not make it any less real. Say for instance, gender is by definition is social construct. Maybe you and all your friend have different opinions about it, and that brings us to the next topic: the polarization of media in general, and social media bubbles in particular.

Due to the social media bubbles, people in the same neighbourhood can live in completely different relaities. When I’m writing this, some folks are convinced that the covid pandemic is fake, it’s just a hype, a hysteria, it’s only purpose is that the government should control us. Others think that the vaccines make you sick. No amount of scientific reason would convince them otherwise. Also, this reality is quite different from mine.

Here in Hungary, there are millions of people who are afraid of refugees coming to Hungary and take their jobs. Or their welfare. Those are uneducated people, easily manipulated by propaganda. Nevertheless, their reality is quite different from mine – whereas I think Hungary is not appealing, our economy is not strong enough for that.

Back to code correctness. This is really a touchy-feely subject. I think every experienced developer has a story about a customer, who wanted to creep in a feature as bug report. Customers too have stories about developers rejecting bug reports and demanding an official change request.

If this kind of disagreements escalate, then we end up with highly trained individuals discussing documents. They read the documents, add comments, send emails about the comments, and so on. Those individuals can be business analysts, project managers, product owners, sometimes even lawyers. The documents can be bug reports, specifications, sometimes contracts. Otherwise it’s not much different than rabbis to make sense out of the Talmud (or from Sulchan Alruch).

Collective illusions are not that new

Some postmodern writers deliberately play upon our cognitive illusions. Many writers play with guest texts: they take a text out of context, and put that into their works, either unchanged or in a damaged form – so they give different meaning to the same (or almost the same) text. I know one example where the write put the same text in the same book twice, with minimal changes. The book is “Bevezetés a szépirodalomba” by Péter Esterhazy. This book is not available in English. So, junior programmers with English majors, feel free to provide other examples in the comment section.

Mass propaganda is not that new. During the 20th century there were two big totalitarian regimes, the Soviet Union and the Nazi Germany, the Third Reich. These two inspired George Orwell to write 1984.

Bending the truth is not as new as 20th century. In the 17th century the Catholic Church imprisoned a scientist for disseminating the truth about our Solar System. At that point people believed that the Sun revolved around the Earth, but this is not important right now. It is more important that the Catholic Church new that Galilelis findings could have changed the peoples worldview, i.e. they would change a collective illusions. Collective illusions are real. (On the other hand, private illusions are called delusions.)

There is some hope (back to unit tests)

When we discuss the state of affairs in a real science, we are depending upon repeatable experiments. Unit tests are the experiments that programmers are writing and executing. So a unit test expresses what the programmer thins the system should do.

This is how programming connects to the real sciences. As doctors are trying to figure out whether a medicine safe and/or it works, they conduct experiments, like clinical trials. Programmers write and run unit tests. Testers also write and run tests, and that too connects software development to the real sciences. But we are focusing on unit tests now.

A practical question: What is a unit?

The term unit test is misleading. Some folks prefer another term: programming test. Still, we don’t know the unit: is it a method? Is it an object? Is it a collection of objects?

The answer is the ultimate programming answer: it depends.

When we are testing a LinkedList, it makes sense to add stuff, then retrieve it. In this sense the unit is an object, and we test it through several methods of that object.

When we are testing a FizzBuzz solution, we can test the generateFizzBuzzText() method by itself. In this case the unit is a method.

Let me tell the story how I learned to program. I wrote a little code in ANSI C to load some data from file. I wrote the program, then tested it, and it didn’t work. I asked a friend to help me to fix it. He looked at my code, and he rejected to debug it. I was disappointed. But he taught me an important lesson.

He said, this is not how we write program. Then how, I asked. He said, write a little code, and then check if that works.

Well, that little code that you want to check, that is a unit.

Well, it’s not that simple. Sometimes you keep those unit tests, because they feel like finished. Sometimes you grow your minimal unit tests into a meaningful chunk and then you keep it. Sometimes you copy and modify them, in other cases you change them into a data-driven test. There is no simple way to decide what to do. This comes with experience: you write unit tests, and then see how they work out for you. If you are lucky enough, you can also look at your colleagues unit tests and learn a trick or two.

How to write unit tests?

When you look into tutorials, you will find how to add the @Test annotation, what is the difference between assumption and assertion, how can you set up data, and so on. These are important things, but I see that juniors struggle with writing testable code.

There are a handful of ideas behind writing testable code:

  • If you have to decide between speed and testability, choose testability. Speed is usually not that important. In the cases it is, you can always go back to the slow parts of the code and think about it.
  • You have to write one little test and one little code, just after each other. So your code will be testable. Write the tests first, if you can. If you can’t TDD just yet, don’t worry: write one little test right after you wrote just enough code to test.
  • It’s OK to write short methods. Actually, it is good practice to write short methods.

Yes, unit tests change the way we write the code. This is a frequent phenomenon, that measurements change the behavior, just like a voltage meters change the voltage. Luckily, we don’t have to worry about that: in our case unit testing changes the code for the better.

Yes, but really, how to write unit tests?

A good unit test is organized into three parts: Arrange, Act, Assert. Sometimes they are called Given – When – Then. Say for intance:

  1. Given that the list is empty (Arrange an empty list)
  2. When I add one item (Act: add one item to the list)
  3. Then I want to see that the lists size is 1 (Assert that the size of the list is 1)

There are tools for writing unit tests. I am quite familiar with JUnit 4. JUnit 5 is around, but that is not too much different. TestNG is another test framework, not too different either. You should learn the one used in your current work environment. Nevertheless, I am linking a few tutorials at the end of the posts.

Writing unit tests is can be hard at first. So don’t worry too much if you fail at the first couple of attempts. Keep trying, and look at the tests the senior developers wrote.

Benefits of unit tests:

  • As we have just discussed, unit tests make code cleaner. (We’ll cover that in another post).
  • Unit tests make the distinction desired behavior (what does the system do) and incidental behavior (how the system does it). So unit tests make the system easier to change.
  • Unit tests protect against regressions (when we change one part of the system, and another part breaks)
  • Unit tests make us deliver faster – once we learned how to write unit tests.

Legacy code and unit tests

In this post we focused on writing new code. Quite often we see legacy code bases that don’t have too much unit tests. That is quite a different challenge, I am going to cover that in a different post.

Further reading

Posted in basics, programming | Tagged , , | Leave a comment

Survival kit: git

I am, to some extent, familiar with git. That’s the only distributed VCS which I’ve been using long enough. There are other distributed VCS-s too, like mercurial, Bazaar, Fossil. I am not familiar with them, so in tis post I’ll focus on git. I believe some of the lessons will be applicable to the other distributed VCS-s too. Feel free to tell your story in the comment section.

There is one roadblock that many developers share, and it’s the git. Developers stuck with git ask questions like these:

  • why do I have to learn this?
  • why is this so complicated?
  • why can’t keep using good old svn / CVS?

Reasons for git, other than that’s the company standard

Another thing that keeps folks back is that they don’t see the reason to use git. Probably they have been working in a peaceful environment, where nobdoy told them in the middle of a 2 weeks development, that hey, a bug came up, please fix it. So why use git:

  • You can quickly create new branches, so it supports the ‘fix this bug quickly’ workflow.
  • It supports local clones of the central repository. So if you work in a multi-site environment, git can help you to have a quick local-central repository.
  • As you work on a biggish feature, you can have your own babysteps in revsion history. This way you can be more brave and experiment with things – as you can always go back to the last state where everything worked.
  • If your company has cvs or svn, but you have to fix bugs quickly, you can still use git locally. It’s not trivial to do it, but it can be pretty useful.
  • Since git copies the repository to your machine, you can quickly bisect your version history when looking for the origin of a bug. Heck, git even has a bisect command.

    What is the bisect command? It is a binary search in the version history. I have only used it once, manually, with a remote central svn. It took three days, I spent most
    of this time waiting for svn.

Distributed version control and complexity: It is confusing that you can pull and push from and to any computer. Here is the secret: yes, you can pull and push stuff everywhere, but you don’t have to.

So far I have seen the traditional client-sever approach, just like with csv and svn. I have heard that multi-layer approach is also possible, where there is one repository per site. I haven’t worked yet with such environment.

Here is great overview by ern0.

Using the right client

One thing I see in common with those developers that they are trying to use a UI. The UI can show nice graphs, so far so good. And then the buttons. Commit, OK, that might be familiar. Checkout, that sounds familiar, but does something different than expected. And then there are lots of other buttons, like push, pull, fetch, branch. OMG.

How to get around this: use the command line. At least use it for a couple of months, until you know what the words mean. The command line has another advantage: all the tutorials and SO posts show commands. So if you use the command line, then other folks can help you.

Memorizing 6 (or 8) commands

Git has tons of commands, that might be scary. Don’t worry: there are roughly 8 git commands that you can get by with. The ones I am frequently using are:

  • pull – to get the changes from the server and apply them to my current branch, which is almost always master.
  • push – to publish my changes. Depending on the workflow it’s either the master branch, or a feature branch.
  • add – to specify what I want to include with the next commit
  • commit – to create local history
  • checkout – to go to branches, sometimes to undo things
  • reset – to undo things
  • branch – to create branches and to switch back and forth from branches
  • gitk – to look at the change graph on a UI – do you see what I did here 🙂

See, I am not a git pro. Not at all. I still haven’t learned the squash command. Instead of that I am resetting the branch with git reset –soft, and then create a new commit with the appropriate commit message. Then I review the changes. If they are not OK, then I make changes and ammend a commit (git commit –amend). When they are OK, then I push the changes. Hopefully the 15 minunte build starts now, and I can do some personal maintenance and/or learn something useful.

Further Reading

Posted in basics, programming | Tagged , | Leave a comment

Survival kit: Learn what you do: spiralic reactive learning

So, you started a job, they might or might not give you a training. And there you are, looking at technologies you hardly know. Half of the words are unknown to you, yet you are expected to do something at least. The colleagues seem to be confident with all of this. Some of them seem to be bored, talking about new tech they have just read about in their free time. What now?

What is reactive learning?

Sometimes learning is proactive: sometimes you learn things because you are interested in them. Those senior engineers are reading tech blogs so they can keep up with the tech world. Some folks learn new programming paradigm in order to collect them all. This can be fun, also useful. But not now.

Sometimes learning is reactive: you learn the stuff that you seem to need to know. I think this is the most effective way to learn. Programming is a craft, we can learn it by doing it. We can read a lot about the theory, about the concepts, the API-s – and we forget all of this, unless we spare some time to practice. If we are lucky, we can practice a little at work. If we are truly lucky, we have to practice every day. All we have to do is to find some time to read about the technologies, and whoa. Our brain is going to work like a sponge, digest the knowledge quickly and effectively.

When to learn

By default we learn at home, in our free time. Sometimes our employer send us to training, or grants us the fridays to learn, and that is really nice of them. But when they don’t, then what?

I suggest always get a good nights sleep. This is a best practice to avoid burnout. It also lets us perform well during the day.

We don’t do all the learning in our free time anyway. Say for instance, when we are browsing the API docs, or checking the Stack Overflow comments, in that case we are learning. When we are reading a short tutorial about feature branches, we are learning. When we are refactoring our code after a code review, we are learning.

When programmers learn, this can’t be only theory, nor can it be only practice. It is a ping-pong between these two. We learn a little theory, we apply it, then see how it works for us. If it didn’t work out well, then we think a little: was the theory wrong, or did we apply it improperly? I think this is the biggest advantage of reactive learning: we can practice at company time. When we do proactive learning, we must practice in our free time – some of us just don’t have that much free time.

But it’s not all. We can learn some theroy too, during company time. There are several ways of doing that:

  • Reading a book / tutorial when the CI server runs (A CI server is good for code quality and for mental health too! Ideally, the build should run 5-15 mins, so you can have a coffee, have a chat, or read a couple of chapters.)
  • Reading a book on the toilet break (much better for your mental health than social media)
  • Sometimes folks have off time, when they read news or social media. This is something that managers tolerate – to some extent. This time could go to books and tutorials too.

Why spirallic

As there is a lot to learn, we have to master them all. But we can go one by one. So at first learn a little bit of everything, just to get by. Find a tutorial. Read the getting started / quickstart stuff. When all covered, then read more profound stuff.

Ideally you can already get by with your main language, say, java. The second should be the version control, as we use it every day. By the time you covered that, you already have an idea of the relateive importance of the stuff you use. Sometimes the frontend server is more important, sometimes the ORM. If you are not sure, you can ask a senior developer from your team, or just pick one topic randomly.

Once you can get by with all the tools, then you can read more about them. If you are done with that too, then you can learn about clean code, refactoring, unit testing, TDD, SQL optimization. This is a lot, it can even take 2-3 years. By the time you finished, you might have to pick up another technology. The fun is endless.

If it feels like overwhelming, I assure you: it is. However, during this journey you will pick up one important meta-skill: you’ll know how to pick up new skills. As you go from one technology to another, patterns will emerge. Best practices, if you like. As you go, learning will be easier. Keep learning, and don’t forget to sleep well.

In the next posts we’ll see some of the basics: distributed version control, clean code, unit tests.

Posted in basics, java, programming | Tagged , , | Leave a comment

Survival kit: the obviousnesses

So many things are “obvious”, especially on stack overflow. Believe me, most of us learn these obviousities the hard way, like, erm, why does this simple SQL UPDATE run so long?

Still, some of us forget these incidents. All they remember is that before you run an UPDATE or a DELETE statement, you ought to check the data set with a SELECT, so you can make sure, you used the right predicates in the WHERE clause. This does not seem short, nor simple. Still, some folks say ‘you should obviously double-check the data set before the update’.

Yes, you should check it, but there is nothing obvious about it. These are the tips and tricks that come with experience.

There are lots of obviousnesses like this. Especially those seem to be obvious that we learn early in our career. We come from all sorts of backgrounds. So, while usually it’s the more experienced developers who annoy the juniors with it, sometimes the juniors will wonder, why doesn’t a senior know this or that basic. Oh, well, because it isn’t that basic.

Here is a list of obviousnesses from the top of my head:

  • how to run UPDATE or DELETE SQL (run a SELECT first with the same WHERE predicates. If you like the result, then you can run the UPDATE or the DELETE)
  • how to run a big select on prod (use a LIMIT clause)
  • how to delete a directory when you are the root (Run the pwd command first. Then run a find . | less to make sure you are deleting the right directory)
  • making small changes, and verify them one by one
  • saving the expected output, especially if we don’t fully understand the logic (i.e. testing tripledes, using standard jdk lib to do 3des)
  • in Swing, for positioning stuff, every control (button et all) must go on a jpanel, and then the jpanels go to the compound object
  • in HTML one must eliminate unnecessary divs. That just makes positioning easier. Nor do we have to deal with the margins, borders and padding of invisible elements – it’s easy to add just one more div with a component framework
  • padding, border, margin – they come in this order from inside out
  • Before optimalizing code, we have to measure it – and measure the whole app. It’s also nice to have speed goals.
  • We can optimize the architecture – in that case we don’t have to measure the app. In this case we measure stuff like round-trip time, latency, relative speed of components.

I think all of my readers can add a few obvious statements. Please help me expanding this list.

So what shall we do when someone uses the o-word too often? If that person is our boss or senior engineer, we’ll have to tolerate it. As they speak, we can imagine them in special clothes, so that brings a smile to our faces. Remember, it’s not a meritocracy. Especially not when the people claim it is.

Sometimes we can talk them out of the o-word. But that’s rare. People who have the self-awareness to listen to their juniors, they are not likely to use the o-word anyway.

If that person is at our level, or below, we can talk to them. Like, hey, this o-word, you know, obvious, this sounds truly arrogant. If it was truly obvious, you won’t have to explain it anyway. Please don’t humiliate your team members.

If you feel like using the o-word, just don’t. I’ll add a few less offensive synonyms, but we can’t handle this on this level. You have to get rid of the humiliating, arrogant tone that comes with it. This can be really your tone, your body language, or you full approach how you deal with other people. Anyway, here is a list of expressions instead of “obvious”:

  • As far as I can see
  • I think
  • Usually we do it like this
  • Therefore
  • So
  • I believe
  • This is from the top of my head
  • I have had a problem with this too, and the solution was…

So, in general: be nice, and keep learning.

Also, for fun, can you add other “obvious” lessons that you have learned so far?

Posted in basics, programming, soft skills | Tagged , , , | 1 Comment