Programming can be an interesting, rewarding, enriching, frustrating, time-consuming, and maddening endeavor. Who wouldn’t want to learn how to program?
Time and effort
One important thing to keep in mind is that becoming a proficient and knowledgeable programmer requires a significant amount of time and effort. Even after obtaining a BS or MS degree in computer science, the learning process never stops.
It is not enough to learn the syntax and semantics of one or two programming languages, as some books and online resources may suggest. Even if your focus is on creating dynamic websites or embedded systems, there are still concepts that may seem unrelated, such as frameworks, databases, and hardware basics, that are crucial to learning.
The field of computer science is vast and complex, and programming is only a small part of it. While a formal degree in computer science or a related field is not necessary to become a programmer, it can be helpful. Computer science programs typically have rigorous math requirements. It also generally requires more credits than the university minimum needed to graduate than non-STEM programs. Taking five or more years of full-time work to complete a BS is not unusual.
Other degrees will be just as useful and are called by various program names. They are sometimes outside a university’s engineering and applied science college, and sometimes part of the computer science department. Community colleges will have the first two years of a CS program and also other related degrees and certificates.
While it is impossible to know everything in this ever-expanding field, having a deep understanding of the basics and recognizing what you don’t know is a worthwhile goal. That way, when you run into a problem you will know where to look for solutions and can go from there.
There is nothing more frustrating than not knowing where to start with a problem that reared its ugly head and a formal education helps you to recognize both known and unknown unknowns.
Formal education can be expensive and time-consuming, but it can provide depth and breadth to your knowledge, access to knowledgeable mentors, and networking opportunities. It can also broaden your job opportunities in fields such as biology, engineering, chemistry, economics, and business. Most engineers and scientists dislike programming - and are frankly, bad at it - creating many job opportunities for programmers in these fields.
I would spend 12-16 hours a day inside and outside class working and learning. Seven days a week. When school was not in session I would still work on it 6+ hours a day, at least five days a week.
My BS and MS probably cost north of $100k in total, and that was at state universities. I got “lucky” and had VA Vocational Rehab that paid for my BS in its entirety, including all books, supplies, parking stickers, and a stipend to help live on. Luckily, I also qualified for Pell grants that I could use exclusively for living expenses. I was able to teach classes as both a senior in my last term and a graduate student which paid for most of my tuition + a stipend.
I would highly recommend at least some formal education. It will give you the depth and breadth that you need, and access to very knowledgeable people and will help start your networking to get a job. Being able to ask a professor or one of the better students is far more valuable than trying to get help online. There are great people online willing to share their time and knowledge, but there are also lots of people who can lead you astray.
I think it is important to not treat university like a job training program. It is a place to become a critical thinker with a much better understanding of the world around you.
Learning on your own is harder and just as time-consuming. It also makes it easier to miss or skip important topics.
There are no shortcuts.
There are also online “schools” such as Codecademy, among others. I am sure they are worth using, but I have no direct experience with them. I have talked to people that have gone through those programs and from what I can tell, they end up with a very narrow breadth and shallow depth of understanding. That is not a terrible thing, but it is limiting. I don’t have enough data to say that for sure, but it is just my impression.
Online programs might be better used to help fill in some gaps that you will have regardless of your educational path.
There is also Coursera. They have formal courses that award credit and some that don’t and many of the courses are from top universities in the US. There are some seriously challenging and useful courses here.
Most entry-level programming jobs that pay well require a BS, and increasingly an MS, from an accredited University.
If you don’t mind starting out with low-paying jobs, like barely over minimum wage, you don’t need a degree.
It is possible to get a good job without a degree with good experience. The more work history you have, the less relevant your education is. Or, you can contribute significant work to well-known open-source projects.
The burden of proof gets steep when starting out without a degree. Regardless of what one might think of job interview questions - which are mainly to see if you really understand what is going on - they are very difficult to answer without a good breadth and depth of knowledge. It is not “elitism”, it is being a professional. If you can’t discuss pointers, optimization, language design concepts, or algorithm analysis are you really a programmer?
At least teaching yourself is easy on your bank account. Sometimes, there is no substitute for a good book, but many of the top CS books often have free PDFs available. I will try to remember to put some links into the resources section for these books.
It is also a cheap field to work on a startup if you are willing to start very small and grow slowly. A decent computer and an internet connection can start a business. I know small companies that started this way and are still relatively small, but they are making good money: two programmers and a salesman, and those companies are bringing in 6-figures a month. They took no VC funding so are beholden to no one. I think there is a lot of freedom and opportunity in avoiding funded startups and the madness that comes with it.
You don’t have to push to be the next Google, Facebook, or Microsoft to have a lucrative career with your own business.
Programming is a sedentary activity. It’s very easy to get engrossed in your work and forget to move for hours. This can be compounded by unhealthy eating and drinking habits that are often associated with programming.
I’m bringing this up because it’s a serious concern. Unfortunately, it’s not uncommon for programmers to suffer from health issues like heart attacks, diabetes, and other diseases that are caused by a lack of movement and poor eating habits.
When working at a desk or computer, avoid eating while doing so to benefit your body, mind, and keyboard. It is not only a problem for programmers.
College students experience this sedentary behavior - “aka the freshman 15.” I remember spending 6+ hours nonstop in the computer lab and library every day. It is not healthy, and in retrospect, it made my coursework that much more difficult. I should have unplugged for a while and did anything else that didn’t involve sitting.
Every 2-3 hours get up and get moving for at least 30 minutes. Make it a habit. It also has the bonus of clearing your mind and helps to produce better work. There are stand-up desks and those horrify me even though they are not a terrible idea. That is because I can not physically stand still for more than a few minutes at a time. Companies would be better off in every way possible if they encouraged 30-minute walks in the morning and afternoon rather than making their employees stand for hours.
Unplugging yourself from a problem will often get your mind in a state where it can actually solve it. Personally, I think 30-35 hours a week, including meetings, is the optimal amount of time to spend programming, for both the employee and the employer. I wish I had the money to do a study to prove it.
There are some companies that expect their employees to work for 70 or more hours a week. These companies are not good to work for and should be avoided. Working for such companies can be harmful to your well-being and overall quality of life. It is a misconception that working for more hours will result in more productivity. In fact, people who work for such long hours tend to produce lesser output and the quality of their work also suffers. It is soul-sucking and life-threatening. Don’t be that guy or gal that drops dead of a heart attack at their desk at 55.
Programmers really need to unionize. Unions are for everyone who doesn’t want to be exploited.
“Besides a mathematical inclination, an exceptionally good mastery of one’s native tongue is the most vital asset of a competent programmer.” ― Edsger W. Dijkstra
You might read a lot of claims online that math is not needed to be a programmer. Programming is a mathematical discipline, and Computer Science is a branch of mathematics. A proper CS degree will have math requirements that you might never use in your CS coursework, but that is a function of CS being a branch of mathematics. Remember, a university is not a job training organization. Its purpose is to educate and graduate a well-rounded student who can think critically.
This will briefly list the topics that I think are the two most critical, along with other helpful topics. It is not an exhaustive list.
Arithmetic and algebra: None of the below is doable without a solid understanding of arithmetic and algebra. These are prerequisite topics. High school math often presents algebra as something advanced when it is a building block. It surprises many people when they find out that the first required math class in STEM programs is calculus. Calculus is freshman math: the very beginning of your exciting math journey.
Boolean Algebra: I am using this as a catch-all term for working with binary numbers, but it is also a specific topic. It is not common for a programmer to directly work with binary numbers, but the concepts are useful regardless of the type of programming you want to do. Everything from bit-twiddling to bit masks to conditional statements. We used this in digital design courses when we built digital circuitry. One of the most important uses was to minimize the number of logic gates. This directly transfers to if/else statements. It is easy to end up with an unwieldy, bug-filled, and brittle statement but it is also easy to reduce it to something simpler that is equivalent and easy to manage. I will add an article on this topic.
Discrete mathematics: This is a very broad topic that is vital to computer science. If we divide all math into discrete and continuous, the most relevant math for programmers falls under discrete.
This includes set theory, relations, functions, and many other topics. I can’t think of a CS topic that isn’t touched by discrete mathematics.
Probably the best, and most difficult, book is Concrete Mathematics. The term concrete is a play on words, blending CONtinuous and disCRETE and pokes fun at abstract mathematics. I do not recommend this book for us normal folks, as it can be brutally difficult as I have found out. If you can work through it, you will be doing very well and have a strong foundation.
There are lots of resources online and many well-written books on the subject. I don’t have specific recommendations but one that is written for beginners and focused on CS is the way to go.
The book I learned part of this topic is not one I would recommend. This book teaches loads of concepts from both discrete and continuous concepts but its primary purpose is to learn to read and write mathematical proofs. This is something that might interest you, but isn’t strictly necessary IMO unless you are planning on creating a lot of formal algorithms.
Linear Algebra: This is used in a lot of programming areas. Networking, AI, graphics, scientific programming, etc. It is actually kind of fun. I wish I had taken this course before I took integral calculus, it would have made it a bit easier, at least to check my work.
Probability and Statistics: Probability actually falls under discrete math, but I will put it here as it is often tied with statistics.
To give an example, for “artificial intelligence**” you need a metric ton of mathematical understanding: algebra, calculus, linear algebra, statistics, and information theory.
Abstract Algebra: Group and ring theory are used in applications such as cryptography. A lot of this stuff won’t be directly relevant unless you go into very specific disciplines.
**Don’t get me started on this term, there is no intelligence in “AI” programs.
Computer Science is no more about computers than astronomy is about telescopes
A computer is a tool that can express solutions to CS problems, but so can a pen and paper or whiteboard. I have lost count of the number of hours spent writing and debugging concepts on paper or the whiteboard. Just like you can learn a lot about astronomy without touching a telescope, one can learn a lot about computer science without a computer.
Obviously, it is required if you want to create programs that help solve problems, you will need a computer and need to be comfortable with it.
You don’t have to, but I highly recommend building your own. It is fun and educational, and you can often build something higher quality at a lower price than you can buy a Dell, Apple, whathaveyou. It shouldn’t come as a surprise that these companies cut corners all the time. Some top-notch computer component makers sell directly to retailers and us normal folks.
So, what is needed in a good computer for a programmer? Oddly enough, the requirements are somewhat similar to gamers. The big difference is that, except for certain cases, a super expensive high-powered video card is not required. I will add information about buying a computer and building one. If you have a gaming PC, you have a PC that is more than enough.
A nice desk and comfortable chair are musts. A bad chair can ruin you physically in no time.
Multiple monitors are useful, although with 34” or larger screens becoming inexpensive they are not quite as important. There is no such as too much screen space.
I will add an article on how to select computer parts to build your own machine.
Languages, Compilers, and Interpreters
It is not only the violin that shapes the violinist, we are all shaped by the tools we train ourselves to use, and in this respect programming languages have a devious influence: they shape our thinking habits.
It is practically impossible to teach good programming to students who have had prior exposure to BASIC: as potential programmers, they are mentally mutilated beyond hope of regeneration.
The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offense.
I would add Java, PHP, and in some ways, C++ and Python to the list of criminal languages.
There are so many over-engineered and soul-sucking languages out there. The trick is to avoid them at all costs.
Of course, one can make a lot of money with most of these languages. If all you care about is money, learn Cobol. It is one of the highest-paying languages, but there is a reason for it.
PHP will mostly keep you in the low-end of jobs. It is brain-rot at its worst. Avoid at all costs. Yeah, yeah, Facebook sort of uses it. AFAIR, it is only used for generating the HTML that gets sent to your browser and they had to develop their own dialect(ie add on to the language) to make it useable. They wasted a ton of time and money on PHP. The heavy lifting on Facebook’s systems is done by Java and Erlang, I believe.
I talk smack about Python, but it really isn’t that bad as long as it is not the highest-level language you know. If it is, you will be crippled in your understanding of computation.
The Java ecosystem(both third-party and native APIs, the virtual machine, and the security model) is first-rate. The language, while improved, is still stodgy and extremely bureaucratic. Think of a programming language designed by Vogons.
Unfortunately a lot of the tools created to make using this language picked up similar, awful traits. The language causes brain rot and is extremely verbose. A well-written Java program can be 100 times longer than the same program in a sane language. Luckily there are excellent languages that run on the Java virtual machine so there is never a need to actually write Java. Kotlin, Scala, JRuby, and Clojure are among the best options. I needed networking libraries offered by the Apache Foundation - written in Java - for my master’s project, but I didn’t want my project to expand to 100k lines of code or so. I used JRuby(Ruby that runs on the JVM) and got it done in about 8000 lines of Ruby code instead. It still took about 18 months of design and development, and if I had used the Java language, I would still be working on it nearly a decade and a half later.
There is a saying that is often misused: “It is a poor craftsman who blames his tools.” That does not mean that tools don’t matter. A master carpenter uses the best tools and materials that he can get his hands on for a reason. They aren’t going to use a hacksaw,dollar store hammer, and scrap plywood to get everything done. Yes, a programming language is very much a tool, but also a material. A lot of analogies can fall apart at some point, but the core idea is sound. Use the best tool for the job and poor tools are never the best for the job.
Don’t get married to a specific language. If the only tool that you have is a hammer, every job will look like a nail. It is really easy, and I am guilty of it, to force a new project into a language a person enjoys but isn’t entirely suited for. My master’s project is an example, I started it in Ruby despite knowing that it would take too long because it lacks the networking libraries that the Apache Foundation has. I wasted a fair amount of time before I smacked myself and used those libraries. Luckily for me, I didn’t have to change any existing code because I found JRuby. About 5% of my project ended up being written in C, and I also used some existing Python libraries that ran outside my main project. My two-year project would probably have taken four years instead if I had kept my tunnel vision and stuck with Ruby.
An often overlooked skill is ironically, learning to read others’ code. It might not be something that you do a lot of while learning but it is something that you do a lot of on the job. I will try to incorporate this into all of my programming articles.
The core idea is to learn multiple good languages that cover the various programming paradigms at multiple levels. Focus on concepts. Of course, you need to learn languages as you learn concepts, else how can you write programs and get that huge paycheck? If you do this would you start to see how a language makes some concepts easier and other concepts harder. What is easier or more difficult varies wildly across languages.
Learning all concepts in a single language will be very difficult and will cripple your mind. Each language approaches things in different ways and as you learn a different language, your mind will see things from different perspectives.
So, what languages should be learned, and what the heck does “highest level language” mean?
The computing scientist’s main challenge is not to get confused by the complexities of his own making.
Edsger W. Dijkstra
The idea of a high(or low) level language is an approximation of how far away it is, conceptually, from the CPU and memory system. Languages lie on a continuum. A very low language, like the various assembly languages, is about as close to the CPU as a programmer can get these days. CPU designers have been very successful in kicking programmers out of the CPU. Assembly language - something you should know a little about - is tied to a specific CPU family. Although some are a little higher level and can support multiple CPUs and run on multiple operating systems. The sane use cases for assembly are pretty small, but it is still a good thing to know the basics. If you are perverse and sadistic enough, you could make the next big social media platform in assembly. When I get to the “Hello World!” article, I might throw in an assembly implementation of it as a way to dissuade you from such twisted evil.
The next step up is generally considered to be the C programming language. It has been referred to as a portable assembler, but I never bought that description. It is quite a bit above assembly in abstraction, and assembly is far more of an abstraction than it used to be due to changes at the CPU level. However, you can embed assembly code into C, and there are very few languages that are low-level enough to do that. C is a universal language. Many, if not most other languages have a mechanism to embed C or call C directly without using high-level abstractions to do so. C has been the go to low level language since its inception. There have been attempts to replace it, which is probably needed but none have fully succeeded, despite some real success.
I will cover the concept of abstraction in another article. A simple example of abstraction is file systems in computers. They make it easier to understand where files are and how to access them, but the graphical representation of file systems bears no resemblance to how data is actually stored on hard drives. That abstraction makes computers far more user-friendly.
“Lisp has jokingly been called “the most intelligent way to misuse a computer”. I think that description is a great compliment because it transmits the full flavor of liberation: it has assisted a number of our most gifted fellow humans in thinking previously impossible thoughts.” ― Edsger W. Dijkstra
The highest-level language is generally considered to be Lisp. Lisp is not a language per se, but a family of languages that implement the Lambda Calculus. A mathematic cornerstone of computer science and equivalent to Turing Machines. Its syntax, such that it is, can be dizzying, and if you can understand that code is data and data is code and the consequence of that fact, that is close to as much Lisp as you need. Few other languages can be molded to your problem domain as well as Lisp. As Steve Yegge has pointed out, C is about as close as you can get to describing how computers work and Lisp is as close as you can get to describing computation.
Where the rest of the languages lay on the spectrum is a matter of debate. I would put C++, Rust, Java, Python, C#, and PHP in the lower half of the spectrum and Erlang, Elixir, F#, Haskell, Ruby, and Smalltalk, among others in the higher end. Sometimes programmers talk about this as the power continuum. Generally, you can do more with less code in the higher-level languages, but that doesn’t mean that they are better in all categories. This topic deserves its own post.
There is also the concept of Turing complete languages, which the vast majority are. This is also a good candidate for a separate post, but two languages being Turing complete does not mean that they are on the same level or can do things equally well. Some things can be computed and some things can not. If a programming language allows all programming containing the set of all things computable, it is Turing complete. It says nothing else about the quality, usability, or power of a language.
So again, what languages? The only two languages I would say are must learn are C and Lisp. C should be learned more thoroughly. Besides that, learn a functional language or two. Like Elixir, Haskell, or F#.
Object-oriented(OO) languages are very important but need a giant warning sticker. Some get bogged down in irrelevant details, like Java. Some miss the point about the Big Idea in object-oriented languages, like pretty much all of them except Smalltalk and Ruby. Honestly, Erlang(or Elixir) will teach you more about the Big Idea about object-oriented programming than most including C++, Java, and Python, despite them not being OO at all. Their processes and the communication between them hits on the Big Idea of OO. Logic languages like Prolog are good as mind-expanding languages. Of course, other types overlap with those already mentioned, like procedural, declarative, and imperative.
Ruby is a rock-solid OO language, but it can be used effectively as a functional and imperative language. You can write code that is structured like a C program. Ruby is less useful as a functional language but you get most of the great things that functional languages have. It is still an OO language. Erlang is a functional language and also declarative.
This will definitely be a series of articles.
If you really want to learn Windows programming, it is best to dive deep into MS-developed languages and .NET. C# and F# are both important here. Lots of other languages can be used on Windows, but these integrate better. Perl and Ruby integrate tightly into the Unix and Linux world, but can be used on Windows.
This long ramble is probably not helpful. I can clean it up and narrow it down as this series progresses.
tl;dr: Focus on learning concepts.
There are three basic choices: Windows, Unix, and Linux. The last two are closely related but not identical. Apple OSX is a Unix, so is a good choice if you don’t mind the outrageous cost and increasing restrictions of using an Apple computer. Outside of OSX, I would recommend Linux instead of Unix, due to it being more user-friendly, but there is nothing wrong with the other Unixes.
Being comfortable with Linux and the shell is a very useful skill. Learning the command prompt and PowerShell in Windows is also useful.
There are lots of great Linux versions - called distributions, or distros. My favorite is openSUSE. It is both powerful and meant for professionals but also newbie-friendly. I avoid anything that forces the Gnome desktop as I find that clunky, ugly, and unintuitive, but that is just a personal preference. The great(and bad) thing about Linux is the choice of different desktops - the graphical interface. I like KDE Plasma, but there are others based on Gnome and very lightweight and extremely simple interfaces. I personally dislike Debian distros and all of its many derivatives, like Mint and Ubuntu. I find them to always run behind the curve and I also find libraries packaged for them that are broken in one way or another. They are clunky.
openSUSE stays modern and very stable. It has some of the best tools you will find anywhere, from installing and managing your system to building a Suse-based distro(SuseStudio). It is easy and rock-solid. It has been my main distro for about 20 years now. There are commercial distros that sell support and whatnot. The biggest players are Red Hat and SUSE. Redhat also provides non-commercial distros. AFAIR, openSUSE is now a community project. There are two versions of openSUSE: Leap and Tumbleweed. Leap is a more standard setup. The current version is 15.5 and is like Windows 10 or 7, or whatever. Although it is easy to upgrade in place, so there is no need to start over. Tumbleweed is a rolling release. You get a constant stream of bug fixes, and minor and major releases without having to upgrade like in Leap or Windows. Tumbleweed is supposedly a little less stable, but I don’t have issues with it.
Some distros are pretty hands-off if you want to dive into and truly learn Linux like Arch.
Unless you are planning on learning programming in .NET, Windows is a poor OS for programming.
If you plan on installing Windows or already use it, there are two options: dual install or virtual machine. A dual install is having both OS installed on one system, and you can boot into either, but you need to reboot to get to the other. The advantage is better performance and direct access to hardware from both OSs, if you need it. I used to do this, but a virtual machine is more convenient. I can run multiple OSs at the same time, which actually is useful. I use VMWare Player which is free and supports more OS’s. It just runs better than Virtual Box in my experience. Virtual Box is open source, but I will never need to muck around in the source code. There are other options, but I have no experience with them.
Another reason I like the VM setup is that I like having music playing and audio card makers rarely bother to directly support Linux, so sound may or may not work, for varying definitions of works. The Windows sound subsystem is pretty bad these days, but that is another rant.
Most other hardware will work flawlessly in Linux, in fact, Linux can run on far more types of hardware than Windows.
As you go along, you will learn many tools. There is not anything specific you need to know before getting started except text editors.
To get started, a modern text editor is the way to go. It is simple, doesn’t hold your hand, but has features that are useful from day one like source code highlighting.
There are integrated development environments, which are text editors on steroids. They seem like something good to learn, but they aren’t really that useful and can be harmful to beginners. They do a lot of work for you and hide certain things like building and compiling, two things that will start off as a black box and if you always use an IDE will likely always be a black box. The best ones, from JetBrains, are very expensive, especially since they decided that you can only really rent them, sort of.
Version control like Git is something you will need to know before your first large, real project, but that can wait. It is indispensable in managing your source code. It tracks changes, lets you revert back, create development branches and merge them. There is a lot to learn to be a programmer, and not confusing yourself with things you don’t need today is a good thing to remember.
That is way more than enough for now
I am not sure where this is leading. It will start slow with basics and jump around. It will be a series of collections. Like conditionals, objects, networking, data structures, and their algorithms. Maybe some automata, and software design. The goal of this is to hopefully be a helpful resource and to also help clear my mind and get back into a programmer’s mindset.