Browse Tag: learning

A crab reading a book

How I Learned Rust

One question that has come up a few times is “how did you learn Rust?”

I am sharing my path with Rust and the other languages I have experimented with.

I want to emphasise that it is great for any developer to take some of these first steps into other languages.

Once I started on this path, I developed much faster in my primary language and what I was learning.

By learning other languages, I found I could separate the language-specific ideas from the underlying software design principles, making me a better designer and bringing new ideas back to the table.

My Background

First, I wanted to highlight some things that impacted my choices and the elements I spent more time on, as this will be different for you and affect how you approach this.

  1. When coming to Rust, I had already worked in several other languages, and at least in Javascript, I had a significant code base written, so I had gained familiarity with a text-based approach.
  2. I did a bit of C++ and computer architecture at university, so while my systems understanding was poor, I had some fundamentals.
  3. I’m rubbish at working on toy projects on the side.
  4. I am quite unstructured – skimming through the basics quickly and jumping back and forth as needed.
  5. I work for myself, so I don’t have to ask permission.

Getting Started – Do I Want To Learn This

At this point, I started exploring Rust around 4 years ago, so my memory is vague.

I wanted to pick up another systems language to expand what I could deliver to customers. But memory issues in C++ made me nervous.

I kept hearing about Rust on hacker news and decided to look further. My first question is, “do I think this is worth investigating more?”.

I don’t remember exactly, but I suspect this looked like this:

* Finding some basic tutorials and guides to understand the syntax and mental models.

* Following some of these to get something basic working with every shortcut possible.

* Finding libraries related to my work and looking at them on GitHub. Can I make sense of them?

Confirming My Interest – Minor Side Projects

My next step was to ensure my understanding of the fundamentals. I tried to reach a point of knowing what I don’t know and looking for places in my business which would exercise them.

They always have to be a little real to me. Otherwise, I struggle to work on them.

A couple of early examples:

  • I wanted to understand the industrial libraries, and we had issues with a Modbus system – so I created a small application which printed the values from the Modbus device to the command line.
  • I needed to write a LabVIEW driver for a TCP device I didn’t have, so I wrote a simulator in Rust. This project let me experiment with TCP.

In each case, I would know which bit of Rust I wanted to learn (let’s say lifetimes), and so if I hit a problem which needed another part that I didn’t know already, I would either work around it or park the project until I learned it.

This focus was critical:

  • I chose a language feature I wanted to learn.
  • I sidestepped other features I didn’t know.
  • I worked on problems I was already familiar with, so I didn’t also need to learn how to solve the main problem.

This combination meant each experiment had a singular learning goal; otherwise, I tended to get overwhelmed.

Also, note from the examples that they could all be thrown away when I was done – that takes the pressure off!

Committing – Could I do this in Rust?

For the next year or so after deciding I liked Rust, the question was, could I do this in Rust?

Answering this looked like taking projects I had already done, or was doing, in LabVIEW and _designing_ them in Rust. Generally, I didn’t build them all, but I would use the playground or a small project to work out:

  • How would I structure this bit in Rust?
  • What would the types look like in Rust?
  • Is there a library to do x in Rust?

Each of these might have just been a 20-line example solving the major issue in Rust. But it helped me build confidence, especially with lifetimes, which tripped me up the most in these experiments.

This stage also involved absorbing myself in the Rust community, lurking forums, reading blog posts – anything I could to build confidence or find the sharp edge which would stop it from working.

First Steps – Rust Components

At this point, I was convinced I could solve most problems in Rust with enough effort! Now, I needed to gain experience in building larger pieces of code.

Simple questions like how do I structure this in a project? What about CI? Can I be productive?

So, I started looking for changes in projects which could be done in Rust. Not building a whole project but just components of a project where Rust had a clear benefit.

In the end, the key projects that formed this were:

  • A device server in Rust – We needed to use some C++ APIs anyway, so I built a component in Rust which could interface to the device and communicate with LabVIEW through TCP.
  • A web backend in Rust – This was an easier choice as LabVIEW is not an option anyway, so this was displacing Node.js, which was my preferred language for this.
  • Migrating G CLI to Rust for the launcher made it easier to make it cross-platform.

I had to be realistic with my experience and accept I had to take on the additional cost. So, I charged what I would have charged with LabVIEW but allocated double the time to complete it.

I also had to be prepared to throw it away if it didn’t work. However, I did enough prototyping up front to be confident this wouldn’t be the case.

Again, there was a clear benefit to the project to having a separate component anyway. If it was a more minor addition that was just as good as LabVIEW, I stuck with that.

Today – Rust Projects & NI Libraries

That brings me to now – I have confidence that I can do _almost*_ anything I do in LabVIEW in Rust. This confidence means that Rust is now my default in the future.

Rust will be the choice for greenfield projects unless there is a compelling reason not to (and these exist, such as customer commitment to LabVIEW due to other developers or needing to prepare to make the relevant APIs in Rust).

I continue in LabVIEW for existing projects, but a couple have some compelling benefits in Rust. For these, I’ll be migrating new components to Rust with a long-term goal to replace LabVIEW in one case due to significant product benefits.

I’m also working on preparing integrations with key technologies in Rust. I’m working on an FPGA interface library (since I will still use LabVIEW FPGA) and a TDMS library. You can already find my crates for NI System Configuration API and LabVIEW interoperability on crates.io (the Rust package manager)

* .net integration and UIs are still a weak spot.

Learning New Programming Languages

Over the last few years I’ve expanded the programming languages I’ve worked with. There have been business and technical requirements driving this but it has been remarkably beneficial to my skills as a developer as well.

By learning other languages I’ve found two huge benefits that stretch across all my development:

  • It has taught me to think about problems in different ways. Different languages often have different approaches and mentalities to problem which can cross-pollinate for better code across the board.
  • It has shown me what is common and important in software design. For example coupling and cohesion is important everywhere and different languages may be able to teach you something different about why.

So how have I started on these languages?

Picking the Problem and the Language

For me, this has been a gradual process so it hasn’t been an option for a big-bang swap over. Taking weeks out to learn the language through formal methods.

Instead I’ve either been problem-led or language-led. That is, sometimes I’ve had a problem I’ve needed to solve which existing languages weren’t great at, or I’ve decided I want to learn a language so I’ve looked for problems it can solve.

The problem and the language are symbiotic. Certain languages are good at certain classes of problems and so matching when you are first learning makes it far easier to pick it up. You will also get more support and more done in a short amount of time.

The Best Problems

There are a few problems that I’ve found as a good way to get started:

  1. They should be real problems – maybe this is a personal preference but I struggle without having a real goal or comparison in mind.
  2. They should be small – At least to start taking more than a day at a time on a project like this is challenging and you don’t want to end up taking 6 months to see if you can make progress.
  3. You should understand the problem well – You really want to make the work about the language. I’ve made this mistake a lot, for example trying to learn Rust on embedded systems when I didn’t know much about either. It becomes hard to know if you are struggling because of the language or the problem.
  4. They should be off the critical path. I don’t think you have to wait to be an expert before using a language in production, but to start with you don’t want a project depending on your work. They should be tangential to the main project so if you don’t get finished it doesn’t impact any projects.

Let me give you some of my stories which will make some of these examples clearer.

Committing to Rust

I’m very excited about a language called Rust. Compared to LabVIEW, it has a much broader reach. Using Rust allows me to work on high performance embedded systems across multiple platforms with modern tooling.

In this case I decided first on it as a language and wanted to evaluate whether I should commit to it as a core part of my work. After working through the basic exercises in the Rust book, I started looking at how I could evaluate it properly.

The first thing I used it for was a device emulator. For testing a project we wanted to fake a device which normally I would do with a simulated class. However since I wanted to try rust I tried (and succeeded!) in writing a basic simulator in Rust, streaming random data over the network.

If this had failed, I would have fallen back to a simulated class but it worked well while never putting the project at risk. It also isn’t something that ended up in production.

I’ve also built some prototypes in Rust.

Another interesting example that was my final test before committing to Rust as a primary language was to rewrite some processing code from another project. The fascinating thing with this was that it showed me a totally different way to approach it. This approach will make it back to the final project in C for a big performance boost!

Learning Python

Python has been another interesting exercise but one where the problem leads for me.

I originally picked up Python supporting some code from a customer which let me see where it’s strengths lie.

The nice thing with Python is the speed of development so I’ve found it great for prototypes or quick scripting.

So to learn it better I started by just using it for prototyping some data analysis. I had a customer that needed to do some data exploration and I knew this is a strength of Python. So I fired up a notebook and worked my way through the problem (with a lot of Google-fu to understand Pandas).

In this case the notebook provided a report and was not used again afterwards. So there is no risk of having to support the code in the long term.

I then move on to using it to script some system testing. Again this wasn’t on the critical path of the project, but supplemented the main application.

Getting to Production

So we aren’t collecting languages for the fun of it. How do we get to using these in production? I’ve followed a few patterns to help which boil down to taking on gradually more risk.

  • Starting with testing and support utilities allows you to get longer term experience of running the language without putting the main project at risk.
  • Look for smaller components that fit the language really well. For example you might just call the processing routines in Python from LabVIEW.
  • Whats the difference between prototype and production ready code? Often error handling. Make sure you have a good grasp on how that works in the new language first.
  • Test, test, test! This should go for all production code anyway, but make sure you use good testing procedures around the new code and the integration to catch problems early.
  • Be prepared to throw it away. Don’t bet the project on it the first time. I had this recently where I developed the UI in a new web framework but I couldn’t get it quite right. So I had to throw it away and rewrite in LabVIEW.

I hope this helps give you some ideas on how to take on that next language and quickly get to writing useful code.

I’ve really enjoyed this journey and it gets easier and easier over time. I can now choose languages to fit the problem I have instead of the other way around and have learnt so much in the process.

What to Do When Development is Quiet

Having worked for myself (and by myself mostly) for a few years now I feel lucky that I have had some training for the “new-normal”.

Right now things look OK for me – My current projects can largely be worked on remotely. But what if you can’t?

So here is my general plan for a quiet development period:

1. Work on processes and automation.

Look back at your development processes. Now is a great time to cast a critical eye over them.

In particular look for opportunities for automation such as CI or code scripting. The work you put in on that now will pay off for years to come.

2. Do experimental refactoring

Not expecting to be able to deliver code for a few months? Now might be a great time to work on those refactoring jobs that always get pushed back because “deadlines”. (Use source control in case it doesn’t work!)

3. Learn, learn, learn

It’s a great time to learn a new language, technology or skill so you can come out of this stronger.

Money may be tight but there are some great learning platforms out there.

I joined the ACM which gets you access to O’Reilly’s e-learning platform including their books and video courses.

I also use Pluralsight when picking up new technologies (I’ve been learning SaltStack at the minute)

For software engineering, I’ve always liked the look of Construx online learning as well.

EDIT: LabVIEW Learning

If you are already a competent LabVIEW developer I would use this as a chance to look outside LabVIEW a bit more. You will probably learn that in normal circumstances anyway and I find it hugely valuable to increase your world view. But I should mention resources here as well:

  • Since I posted this, I’ve seen that NI has announced that all their online learning is available for free until the end of April: https://learn.ni.com/training
  • There was an excellent book released recently 🙂 https://www.hive.co.uk/Product/Richard-Jennings/LabVIEW-Graphical-Programming-Fifth-Edition/24023115
  • Nicola Bavarone (thanks!) offered the great suggestion of looking at the badges on ni.com (https://learn.ni.com/badges). I’ve found these good for identifying gaps in my knowledge.

4. Give Back to the Community

Everyone is going to be in a bit of a funk. Wouldn’t a great new open-source tool make everyone feel more positive? Or perhaps try some teaching yourself. Recording some videos and put them on youtube to share your expertise.

What do you do that I’ve missed?

How to Learn or Teach LabVIEW OOP

Last week was the European CLA summit and it was fantastic. If you are an architect in Europe and you didn’t go make sure to get your boss to budget it in for next year – I find it hugely valuable every year.

An interesting conversation I had a few times is about how to learn or train others on using LabVIEW Classes & OOP.

If you follow the NI training then you learn how to build a class on Thursday morning and by Friday afternoon you are introduced to design patterns.

Similarly when I speak to people they seem keen to quickly get people on to learning design patterns – certainly in the earlier days of adoption this topic always came up very early.

I think this is too fast. It adds additional complexity to learning OOP and personally I got very confused about where to begin.

To some extent I started again with my understanding following something like this process (in fact I still have to finish step 6) and I feel like it has made me a stronger developer. Thats why I share it here – it worked for me!

Step 1 – The Basics

Learn how to make a class and the practical elements like how the private scope works. Use them instead of whatever you used before for modules. e.g. action engines or libraries. Don’t worry about inheritance or design patterns at this stage, that will come.

Step 2 – Practice!

Work with the encapsulation you now have and refine your design skills to make objects that are highly cohesive and easy to read. Does each class do one job? Great you have learned the single responsibility principle, the first of the SOLID principles of OO design. Personally, I feel this is the most important one.

If your classes are large then make them smaller until they do just one job. Also pay attention to coupling. Try to design code that doesn’t couple too many classes together – this can be difficult at first but small, specific classes help.

Step 3 – Learn inheritance

Use dynamic dispatch methods to implement basic abstract classes when you need functionality that can be changed e.g. a simulated hardware class or support for two types of data logs. I’d look at the channeling pattern at this point too. Its a very simple pattern that uses inheritance and I have found helpful in a number of situations. But no peeking at the others!

Step 4 – Practice!

This stage is harder than the last. You need to make sure:

  • Each child class should exactly reflect the abstract methods. If your calling code ever cares which sub-class it is calling by using strange parameters or converting the type then you are violating LSP – the Liskov substitution principle – The L of solid.
  • Each child class should have something relevant to do in the abstract classes. If it has methods that make no sense this is a violation of the interface segregation principle.

Step 5 – Finish SOLID

Read about the open-closed principle and the dependency inversion principle and try it in a couple of sections of code.

Open-closed basically means that you leave interfaces (abstract classes in LabVIEW). Then you can change the behavior by creating a new child class (open for extension) without have to modify the original code (closed to modification). This goes well with the dependency inversion principle. This says that higher level classes should depend only on interfaces (again abstract classes). This means the lower level code implements these classes and so the high-level code can call the lower level code without a direct dependency.

This goes well with the dependency inversion principle. This says that higher level classes should depend only on interfaces (again abstract classes). This means the lower level code implements these classes and so the high-level code can call the lower level code without a direct dependency. This can help in places where coupling is difficult to design out.

I leave these principles to the end because I think they are the easiest to write difficult to read code. I’m still trying to find a balance with these – following them wholeheartedly creates lots of indirection which can affect readability. I also think we don’t get as much benefit in LabVIEW with these since we don’t tend to package code within projects in the same way as other languages. (this maybe a good topic for another post!)

Step 6 – Learn some design patterns

This was obviously part of the point of this article. When I came back to design patterns after understanding design better and the SOLID principles it allowed me to look at the patterns in a different way. I could relate them to the principles and I understood what problems they solved.

For example, the command pattern (where you effectively have a QMH which takes message classes) is a perfect example of a solution to meet the open-closed principle for an entire process. You can extend the message handler by adding support for new message types by creating new message classes instead of modifying the original code. This is how the actor framework works and has allowed the developers to create a framework where they have a reliable implementation of control of the actors but you can still add messages to define the functionality.

Once you understand why these design patterns exist you can then apply some critical thinking about why and when to use them. I personally dislike the command pattern in LabVIEW because I don’t think the additional overhead of a large number of message classes is worth the benefit of being able to add messages to a QMH without changing the original code.

I think this will help you to use them more effectively and are less likely to end up with a spaghetti of design patterns thrown together because that is what everyone was talking about.

Urmm… so what do I do?

So I know this doesn’t have the information you need to actually do this so much as set out a program. Actually, all the steps still follow the NI course on OOP so you could simply self-pace this for general learning material.

This doesn’t really cover SOLID very much from memory but if you google it you will find a HUGE number of resources on this, or you can get the book “Agile Software Development” by Robert Martin which I believe is the text that first coined the term SOLID (the principles already existed but this brought them together).


By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close