I find graphs and some applied algorithms like depth first, breath first search, shortest paths etc very useful. Object orientation is also a really common concept.
You definitely should understand the Big-O notation and Big-O estimations of algorithms - what it is, how it is used, why it is important, how you compare two algorithms given their Big-O estimations, how you build Big-O estimations for the simple algorithms.
It is clearly a good understanding of Object-oriented programming, good guiding principles like SOLID Principles and following established patterns and practices.
If you look at SOA, or DDD, they all ultimately fall back to some form of OOP concepts.
I would recommend you to get some good OOP books and alos pick a rich language like C# or Java to begin with
Rule 1: Software is Knowledge Capture. Software means something. If you're unclear on the meaning, spend more time talking to users to understand what they do.
Algorithms and Data Structures are two sides of the same coin. Algorithm depends on data structure, data structure depends on algorithm.
Unlearn bubble sort as quickly as possible. Seriously. All modern languages (Java, Python, etc.) have collection classes that implement a better sort than bubble sort. There are absolutely no circumstances under which you should ever use bubble sort for anything. You should be looking for a collection class that includes a sort method. Better, you should be looking for a algorithm which avoids sorting entirely.
You must learn several languages.
Programming language (Java, Python, etc.)
Shell language.
Database language (SQL)
Presentation languages (HTML and CSS)
Other data representation languages (XML, JSON)
You must learn several data structures.
Sequences (lists, tuples, files)
Hierarchical (like XML and HTML documents, as well as the basic file system)
Relational (like databases, and the file system with hard and soft links thrown in)
Maps (or Indexes or Associative Arrays) including Hash Maps and Tree Maps
Sets
Plus some algorithmic complexity analysis. Sometimes called "Big O". Why a bubble sort is bad is that it's O ( n ^ 2 ), where a quicksort is O( n log n ).
Learning to use a programming language in a descent way is something you can learn as you go, but It's virtually impossible to invent all the widely used Algorithms by yourself.. One really should at least be aware of what can and can't be done with some problems.
For example one simply can't write some programs with bubble-sort and expect it to be considered good, no matter how fine the code is.
I think it's essential to understand the basic theory behind multi-threading, without this it can be difficult to even see that there can be a problem, until you're debugging on a live server at 4 o'clock on a sunday morning.
Structure and Interpretation of Computer Programs. If you understand this book, everything else can be built easily on that foundation. If you have trouble with the concepts in the book, you may be a software developer but not a computer scientist.
"if the only tool you have is a
hammer, you treat everything like a
nail". (Abraham Maslow)
The most important principle, IMO, is to know many different programing paradigms, languages and inform yourself well about the tools on your disposal. Any problem can be solved in almost any language you choose, be it full blown mainstream language with its huge default library or small specialized language like AutoHotKey. The first job of programmer is to determine what to use according to the specification of the problem. Some concepts provide better approach to topic, whatever your main goal may be - sophistication, obfuscation, performance, portability, maintance, small code size ...
Otherwise you will finish like some of programmers who desperately try to do something in a 1 language they specialized, while the problem could be trivial to solve in different programming context.
This advice goes along with todays tendency for multi-language projects (take web applications for example, which may involve several languages in single application, like C#, JS, CSS, XPath, SQL, XML, HMTL, RegExp.... and even different programming paradigms (for instance, C# introduced recently some concepts from functional programming paradigms, lambdas).
So, the basic thing is constant learning, forever :)
I think 3D-Graphics is something everyone should learn. Or at least how to properly use homogeneous vectors and matrix-transforms.
It can be helpful not only for creating 3d-applications but also in mechanic fields like inverse kinematics on robots, calculating moments and a lot of other stuff.
I didn't fully understand linear algebra until i had read 3d-graphics, one of the best courses I've ever taken even though our teacher was bad.
Since machines with multiple cores (both CPU and GPU) are becoming the standard, I would say to include Distributed Algorithms (from multiple threads to multiple machines). It is critical to understand multi-threading and distributed processing. Sorry that the link doesn't really provide a lot of help.
I see several good CS concepts identified but little talk about Math.
I suggest that you look into discrete mathematics. It has a wide range of useful problems starting with logical proofs which help you write conditions in code. Graph theory and combinatorics also help with complex problem resolution and algorithm optimization.
While we are on the subject of math, linear algebra is typically a prerequisite for advance computer graphics classes.
Alot of good responses have been mentioned here already, but I wanted to add a subset of what is important, but hasn't been covered so far.
After 15 years of post-undergrad professional Software development, I find that I regularly use some of the following concepts from in school:
General OO concepts, and modern programming language features (classes, data hiding, etc).
Algorithm performance metrics (Big O notation). When designing an algorithm, performing a Big O analysis to determine the cost of the algorith, and looking at more efficient alternatives in bottleneck areas.
Linked lists and other complex data structures.
Fast sorting, and different sorting concepts.
Trees and fast tree manipulation.
If your language/platform doesn't support Garbage Collection, memory allocation and cleanup are critical, and would be added to the list.
Software Development Life Cycle - The requirements gathering, design and analysis, implementation, testing, and support and maintenance sequence. This along with methodologies such as Waterfall and Agile where these steps are put into practice is also an important thing to learn.
I'm not going to tell you any specific concepts to study, but would instead recommend that you do a lot of light reading across a wide range of topics. Don't worry about getting an in-depth understanding of each subject you read about - at this point, it's more important that you're able to recognize what kind of problem you're looking at, so that you can do some just-in-time studying when you're actually faced with it. In other words, it's ok if you don't know how to solve a combinatorics problem, as long as you know enough to look up "combinatorics" when you need to see how many ways you can arrange a set of objects or pick a subset.
Wikipedia is a pretty good resource for this sort of wide-ranging browsing, especially if you're just skimming to begin with. An even better one, especially if you find Wikipedia too academic or inaccessible, is the C2 wiki. (This is, interestingly enough, the original wiki invented by Ward Cunningham).
Knowledge of distributed VCS systems. Has tried out Bzr/Mercurial/Darcs/Git
Build Automation
Can setup a script to build the system and also documentation, installers, generate release notes and tag the code in source control
Automated testing
Understands and is able to setup automated functional, load/performance and UI tests
Problem Decomposition
Use of appropriate data structures and algorithms and comes up with generic/object-oriented code that encapsulate aspects of the problem that are subject to change.
Systems Decomposition
Able to visualize and design complex systems with multiple product lines and integrations with external systems. Also should be able to design operations support systems like monitoring, reporting, fail overs etc.
I upvote Discrete math. Computer science is abstraction. learning to think like a Mathematician is very helpful.
I also wanted to add to what S.Lott said about languages. Learning a bunch of TYPES of languages is important too. Not just compiled vs scripting. But functional (ML, Lisp, Haskell) logical (Prolog) object oriented (C++, Java, Smalltalk) imperative (C, Pascal, FORTRAN even).
The more programming paradigms you know, the easier it is to pick up new languages when the hot new language comes along!
LOGIC - I just overstate the importance of logic in programming. You said you did Mechanical Engineering so you must know how much mathematics can make your life easier.
Propositional Logic, First-Order Logic, Second-Order Logic: these are very powerful tools. Probably the most (and only) important things I've learned at university. Logic is like the heavy artillery of a programmer - lots of very complex problems (as well as the less complex ones) become much simpler once you have put them into an organized, logical form. It's like what Linear Algebra is for Mechanical Engineers.
I think a good understanding of how a compiler works is good to know. Aho has the classic book on concepts used in creating a compiler. The title is Compilers: Principles, Techniques, and Tools. Its nickname is the Dragon Book. In order to really understand that book, you should have an understanding of formal languages. Hopcroft has a good book on that - Introduction to Automata Theory, Languages, and Computation.
Well the can of worms is open now! :)
I started out in Electrical Engineering.
Relational Database Design: Keeping track of data is like Arnold in "Kindergarden Cop". It can be total chaos. It must be controlled. How to keep your data, in the fewest locations, with the fewest duplications of information. How to keep your data light, and easily accessible. How to control data growth and integrity.
User Interface (UI) Design: This is how the User must access the data we're keeping track of. Most UIs are designed by developers. Thus, most UIs, unfortunately, parallel the database design. Users don't care about the data design at all. They simply want, what they want. They want to get it easily. Usually this demands great separation from the data design and the User Interface. Learn to separate the "engineering" you from the "southern-hospitality" you.
Object Oriented Programming: Many languages boil down to this format.
Parallel Processing - Multi-Threading: Many processors make the work fast! Parallel computers have been around for decades. They've been on our desktops for some time now. With the event of "cloud computing", massive parallel processing is not only manditory but also preferable. It is incredibly powerful! There is a lot of job potential for parallel developers.
Understanding Business Rules: This helps you make a lot of your logic, table-based. Many IFblock conditions can sit in business rule tables. To change the logic, just change the information in a table. Little/No recoding. Little/No recompiling.
Events Supervise...Methods do the work: Keep things separate in your code. It makes it easier for others to make updates in the future. It also somewhat parallels the Model/View/Controller (MVC) framework.
If you are going to teach big-O at least explain that it describes how the time for an algorithm scales with larger inputs - it doesn't mean that an algorithm will take less time.
As an example, building pyramids is O(n), while sorting photographs of them is O(n ln n) at best. So it's quicker to build another pyramid than tidy your holiday snaps.
Students need to have an idea of how long an operation on a register, in cache, in main memory, on disk, on the net takes. Many taught only on very high level languages have no concept.
(this was a comment that someone wanted to discuss)