Software Engineering from Scratch: A Comprehensive Introduction Using Scala
()
About this ebook
Learn software engineering from scratch, from installing and setting up your development environment, to navigating a terminal and building a model command line operating system, all using the Scala programming language as a medium. The demand for software engineers is growing exponentially, and with this book you can start your journey into this rewarding industry, even with no prior programming experience.
Using Scala, a language known to contain “everything and the kitchen sink,” you’ll begin coding on a gentle learning curve by applying the basics of programming such as expressions, control flow, functions, and classes. You’ll then move on to an overview of all the major programming paradigms. You’ll finish by studying software engineering concepts such as testing and scalability, data structures, algorithm design and analysis, and basic design patterns.
With Software Engineering from Scratch as your navigator, you can get up to speed on the softwareengineering industry, develop a solid foundation of many of its core concepts, and develop an understanding of where to invest your time next.
What You Will Learn
- Use Scala, even with no prior knowledge
- Demonstrate general Scala programming concepts and patterns
- Begin thinking like a software engineer
- Work on every level of the software development cycle
Who This Book Is For
Anyone who wants to learn about software engineering; no prior programming experience required.
Related to Software Engineering from Scratch
Related ebooks
Software Engineering for Absolute Beginners: Your Guide to Creating Software Products Rating: 0 out of 5 stars0 ratings.NET DevOps for Azure: A Developer's Guide to DevOps Architecture the Right Way Rating: 0 out of 5 stars0 ratingsSwift 5 for Absolute Beginners: Learn to Develop Apps for iOS Rating: 0 out of 5 stars0 ratingsFront-End Reactive Architectures: Explore the Future of the Front-End using Reactive JavaScript Frameworks and Libraries Rating: 0 out of 5 stars0 ratingsVisual Studio Condensed: For Visual Studio 2013 Express, Professional, Premium and Ultimate Editions Rating: 0 out of 5 stars0 ratingsSwift Quick Syntax Reference Rating: 0 out of 5 stars0 ratingsRegex Quick Syntax Reference: Understanding and Using Regular Expressions Rating: 0 out of 5 stars0 ratingsTest-Driven iOS Development with Swift 4 - Third Edition: Write Swift code that is maintainable, flexible, and easily extensible Rating: 0 out of 5 stars0 ratingsDeveloping Web Components with TypeScript: Native Web Development Using Thin Libraries Rating: 0 out of 5 stars0 ratingsGo for DevOps: Learn how to use the Go language to automate servers, the cloud, Kubernetes, GitHub, Packer, and Terraform Rating: 0 out of 5 stars0 ratingsPractical React Native: Build Two Full Projects and One Full Game using React Native Rating: 0 out of 5 stars0 ratingsClean Code in JavaScript: Develop reliable, maintainable, and robust JavaScript Rating: 3 out of 5 stars3/5Learn Kotlin for Android Development: The Next Generation Language for Modern Android Apps Programming Rating: 0 out of 5 stars0 ratingsThe Essential Guide to HTML5: Using Games to Learn HTML5 and JavaScript Rating: 0 out of 5 stars0 ratingsIntroducing Spring Framework: A Primer Rating: 0 out of 5 stars0 ratingsTest-Driven Development with React: Apply Test-Driven Development in Your Applications Rating: 0 out of 5 stars0 ratingsJavaScript Coding for Teens: A Beginner's Guide to Developing Websites and Games Rating: 0 out of 5 stars0 ratingsDeno Web Development: Write, test, maintain, and deploy JavaScript and TypeScript web applications using Deno Rating: 0 out of 5 stars0 ratingsPractical Oracle JET: Developing Enterprise Applications in JavaScript Rating: 0 out of 5 stars0 ratingsModern Front-end Architecture: Optimize Your Front-end Development with Components, Storybook, and Mise en Place Philosophy Rating: 0 out of 5 stars0 ratingsSubject Oriented Programming Rating: 0 out of 5 stars0 ratingsGeneric Pipelines Using Docker: The DevOps Guide to Building Reusable, Platform Agnostic CI/CD Frameworks Rating: 0 out of 5 stars0 ratingsPractical Machine Learning in JavaScript: TensorFlow.js for Web Developers Rating: 0 out of 5 stars0 ratingsRefactoring in Java: Improving code design and maintainability for Java developers Rating: 0 out of 5 stars0 ratingsPractical Data Science with Python 3: Synthesizing Actionable Insights from Data Rating: 0 out of 5 stars0 ratingsWeb Applications with Elm: Functional Programming for the Web Rating: 0 out of 5 stars0 ratingsTest-Driven iOS Development with Swift Rating: 0 out of 5 stars0 ratingsSoftware Defined Networking (SDN): Anatomy of OpenFlow Volume I Rating: 0 out of 5 stars0 ratings
Programming For You
Excel 101: A Beginner's & Intermediate's Guide for Mastering the Quintessence of Microsoft Excel (2010-2019 & 365) in no time! Rating: 0 out of 5 stars0 ratingsLearn to Code. Get a Job. The Ultimate Guide to Learning and Getting Hired as a Developer. Rating: 5 out of 5 stars5/5SQL QuickStart Guide: The Simplified Beginner's Guide to Managing, Analyzing, and Manipulating Data With SQL Rating: 4 out of 5 stars4/5Excel : The Ultimate Comprehensive Step-By-Step Guide to the Basics of Excel Programming: 1 Rating: 5 out of 5 stars5/5Grokking Algorithms: An illustrated guide for programmers and other curious people Rating: 4 out of 5 stars4/5Python Programming : How to Code Python Fast In Just 24 Hours With 7 Simple Steps Rating: 4 out of 5 stars4/5Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5C Programming For Beginners: The Simple Guide to Learning C Programming Language Fast! Rating: 5 out of 5 stars5/5Python Machine Learning By Example Rating: 4 out of 5 stars4/5Learn PowerShell in a Month of Lunches, Fourth Edition: Covers Windows, Linux, and macOS Rating: 5 out of 5 stars5/5HTML in 30 Pages Rating: 5 out of 5 stars5/5Linux: Learn in 24 Hours Rating: 5 out of 5 stars5/5SQL All-in-One For Dummies Rating: 3 out of 5 stars3/5Nostalgia and Videogame Music: A Primer of Case Studies, Theories, and Analyses for the Player-Academic Rating: 0 out of 5 stars0 ratingsRaspberry Pi Electronics Projects for the Evil Genius Rating: 3 out of 5 stars3/5JavaScript All-in-One For Dummies Rating: 5 out of 5 stars5/5SQL: For Beginners: Your Guide To Easily Learn SQL Programming in 7 Days Rating: 5 out of 5 stars5/5Python: Learn Python in 24 Hours Rating: 4 out of 5 stars4/5Problem Solving in C and Python: Programming Exercises and Solutions, Part 1 Rating: 5 out of 5 stars5/5PYTHON: Practical Python Programming For Beginners & Experts With Hands-on Project Rating: 5 out of 5 stars5/5Coding with JavaScript For Dummies Rating: 0 out of 5 stars0 ratings
Reviews for Software Engineering from Scratch
0 ratings0 reviews
Book preview
Software Engineering from Scratch - Jason Lee Hodges
© Jason Lee Hodges 2019
J. L. HodgesSoftware Engineering from Scratchhttps://doi.org/10.1007/978-1-4842-5206-2_1
1. Introduction
Jason Lee Hodges¹
(1)
Draper, UT, USA
Perhaps second only to witnessing the birth of a child, in my opinion there is no experience closer to pure creation than through the arduous efforts and subsequent yield of software engineering. In regard to such efforts, I have found that, in many cases, the amount of fulfillment perceived by an individual is directly proportional to the level of difficulty that they were required to overcome. That is to say, the harder something is, the greater the feeling of accomplishment once you succeed. There is no doubt that software engineering is a difficult discipline to learn and its limits are never-ending. But there is nothing more fruitlessly frustrating than spending tireless hours of energy learning something just to find out that its applications are limited.
That’s how I have felt on several occasions when wading through the bottomless lakes of software engineering topics over time. Granted, no topic on its own was useless – I was always able to extrapolate the theme and apply it in another area. However, the aim of this book is to spare you the misery of learning software engineering in a myriad of different ways that ultimately leaves the job of distilling the information usefully up to you. The following chapters will gently guide you through the landscape of computer science and software engineering methodologies and paradigms so that, once completed, you will have a holistic view of what is fundamentally relevant without wasting any time on what is not.
That being said, the study of software engineering takes a good amount of practice and self-discipline. It is advised that you read this book with a group and follow along together, hold each other accountable, help each other get unstuck, code with the examples (don’t just read them), and go through all of the exercises. It is important that by the end of each chapter you can accomplish the easy stuff in your sleep without needing to look it up. If you progress through each chapter as such, by the end of this book you should feel confident enough in the software engineering skills you’ve gained to comfortably write simple programs in an efficient, performant, and scalable manner.
I have found that the most effective way to learn to be a software engineer is to start with a baseline of context. So, in this chapter you will be presented with an abridged history of programming in order to build this context. After which you will be briefly introduced to the Scala programming language and why it is the ultimate teaching language.
Brief History of Programming
In order to properly introduce software engineering, it is necessary to first define programming and how it was derived. So, what is programming and what is code? A program, in its most basic form, is a set of instructions that tells a machine what to do. That program is written using code which is a series of language constructs or symbols that are written to form meaning to the machine. It is extremely important to understand that, despite the complexity of modern software engineering, all programs are made up of a series of very basic instructions that when combined together create increasingly more complex functionality.
To demonstrate this, let’s create a mental model of what a computer is and how it works. If you take the outer shell off of any computer and look inside, you will see a whole lot of wires and chips plugged into components that are soldered onto a variety of green silicon boards. But just like the complexity of software, the hardware can be boiled down to a series of basic components as well. For the purposes of this introduction, we’ll boil down a computer to a simple, small, green silicon board and that’s it. Not very useful yet. Next, let’s add to this mental model of a computer the notion that a computer really only interprets a basic program’s instructions in the form of whether or not a transistor on our green silicon board should allow electricity to flow through it or not. So, let’s put a transistor on our board. Effectively, the transistor is an on/off switch. A very basic program would give the machine a series of combinations of on
and off
instructions in an attempt to accomplish something. Perhaps, for the sake of example, allowing electricity to flow through a transistor would turn on a tiny light bulb. So next, we’ll add a light bulb to our model computer. By providing a series of on/off instructions, a programmer could communicate with that light in Morse Code, thereby providing meaning or application to their program. But, given a basic silicon electrical board with a transistor and a light bulb, how does the programmer provide the instructions to the machine?
Early historical programmers created a mechanism that they added to these electrical boards that consumed a spool of narrow paper with holes punched into it – these were known as punched tape. The paper was fed into the mechanism and it rolled the tape through it in a constant speed much like you see a printer operating today. As the paper tape went through the mechanism, the hole punches in the paper told the machine whether or not to allow electricity to pass through the transistor. Well, how did it do that? In our Morse Code model, let’s think of the tape as being able to conduct electricity (perhaps our tape is made of a thin copper sheet). We could then pass the tape through our transistor, complete an electrical circuit, and turn the light bulb on. If there is a hole in our electrical conducting tape, then it won’t complete the circuit, and the light bulb turns off. If we know how fast the gears of the input mechanism consume the tape and thereby complete the circuit, then we can punch enough holes in the tape to create a complete message in Morse Code with our basic machine. In fact, during the 1800s some telegraph operators used a similar method to send Morse Code messages.
As technology advanced, programmers went from manually punching holes to having machines store the on/off instructions on a disk instead of punched tape. But if there is no more punched tape and only instructions on disk, then how does the programmer tell the machine what instructions to store? This is when the code part of programming actually starts. In our Morse Code example, we physically decided whether or not electricity would flow through the transistor by providing it a mechanism to do so. Instead of physically creating something, programmers had to develop a symbol to represent on and a symbol to represent off, thereby effectively creating the bed rock of coding that we use today. The concepts surrounding said symbols, coding, and the idea for the modern computer came from many early mathematicians. One especially influential mathematician from the 1940s was named Alan Turing and many of his ideas percolated all throughout computer science, including Turing Tests
(a test to grade artificial intelligence) and Turing Machines
(which is essentially the computers we know today). Because early computing held its roots in mathematics, many of the first pieces of software tended to focus on mathematical applications, like your basic calculator. Because of that, the symbols that were used early on were numbers.
The symbol decided on for on
became the number 1 and the symbol decided on for off
became the number 0. This type of code is known as binary, which is a mathematical number system that dates back at least as early as 16th century Europe, long before the first computer was ever invented. Conversely, the number system that we were taught in elementary school was a ten-based (or decimal) system, where you count from 0 to 9 and then when you hit 10 you start back over at 0 in the ones spot and you add a 1 in the tens spot. Because 0 and 1 were used for on
and off,
early programmers were able to use a two-based (binary) system to represent other numbers. So you count 0, and then 1, and when you get to what we think of as 2, you start back over at 0 and add a 1 in front – just like in a ten-based system but you restart at 2 instead of 10 and you only ever use ones and zeros. Given this, the binary representation of basic decimal system numbers could be translated as shown in Table 1-1.
Table 1-1
A representation of decimal numbers in binary
Using binary to represent on and off electrical signals allowed for the ever-increasing complexity of mathematical equations to be carried out. But all binary was at its core (at least in this context of computer science) was an abstraction for on and off. So the next level abstraction from representing numbers in binary is representing alphabetical characters in binary. Ultimately, after a series of abstractions, programs were created that could interpret alphabetical characters and convert them to binary so that the machine could then interpret them as on/off instructions. The act of converting alphabetical characters to its binary representation is called assembling, and the programs that are written to do the conversion are called assemblers.
Once machines were able to understand alphabetical characters through assembly down to binary, combining alphabetical characters into words that then had further meaning or perhaps contained several steps worth of binary instructions in one word could be created. This was the basis for the first programming languages. Languages that are assembled down to binary are referred to as Assembly Language and are specific to the hardware architecture and operating system that a programmer is writing the program for. This represented challenges as assembly machine code written for one machine could not necessarily be used on a machine with a different architecture. High-level
languages were developed in an attempt to tackle this challenge.
Assembly Language is often referred to as a low-level
language since it is the least amount of abstractions away from the actual hardware. A one-step further abstraction from a low-level language is a high-level
language in which the same code can be compiled down to different architectures and executed across different types of machines. The program used to complete the conversion of a high-level language to machine code is typically referred to as a compiler. A compiler and an assembler are very similar in that they both take symbolic representations of logic (code) and convert them to binary machine code for computer hardware to execute. In actuality all assemblers are also considered compilers, but not all compilers are assemblers. Compilers usually have broader functionality that allows for writing symbols or languages in a much more abstracted, expressive, and powerful way, which is why they can be used for high-level languages. Assemblers, on the other hand, typically have a very narrow set of instructions to draw from in order to optimize for speed which is why they can only be used with lower-level languages.
One of the first programming languages that used a compiler was Fortran which was used to program IBM mainframes in the 1950s. Common predecessors that shortly followed and are still used today include Lisp and COBOL. Dozens of similar languages also popped up in the decades to follow. In the 1970s, however, came the emergence of C which is considered the most widely used programming language of all time. Many programming languages that followed C draw heavy influence from its standards and style, including Scala. Languages that draw influence or inspiration from C are known as the C family of languages, and they include but may not be limited to
C++
C#
Objective-C
JavaScript
Java (and its Java Virtual Machine variants like Scala, Kotlin, Clojure, and Groovy)
Python
Perl
So, if C is the most used programming language of all time, then why am I introducing you to software engineering in a different language? The basic answer is that introducing smaller concepts that are heavily abstracted away from the actual machine and working your way backward through the levels of abstraction is much easier than working with a less abstracted language like C. Does that mean that Scala is the most abstracted language then? Many would argue that it is not. Why, then, is Scala the ultimate teaching language for software engineering?
Why Scala?
Scala has not been the traditional language taught in most schools when it comes to introducing software engineering or programming. Most of the time when a developer is introduced to Scala, it is assumed that they have some programming experience or are at least familiar with the concepts introduced from other languages. What is unique about this book is that it will build up all of the fundamentals of software engineering in Scala assuming that you’ve never been introduced to programming or software engineering before.
That being said, it is important to note that this is not a book about Scala. The concepts taught in this book are not meant to demonstrate idiomatic Scala programming. Rather, the objective is to teach you software engineering concepts in the most digestible manner possible in an extremely flexible language that no other language can match. It is also relevant to point out that many of the topics in this book have entire books written about them. The intention of this book is not to cover these topics exhaustively, but rather mildly introduce them to you in a refined and curated fashion.
Often you might observe that introductory courses to programming might be taught in Python – especially courses that are intended for non-computer science majors who still need programming skills like scientists and statisticians. Some schools start with Python as an easy introduction because it reads a lot like English, is a concise and expressive language, and has many real-world applications. Its huge downside is that it is not a very good language if your application is reliant on strong performance. Because of the way Python was created, it’s code runs extremely slow compared to other languages. So, oftentimes, schools will take some of the basic concepts you learned in Python and then teach you Java as the next step. There are whole courses that are aimed at translating what you learned between the two languages. Java is extremely fast, in comparison to Python, so that solves that particular problem, but it is also a very verbose language and is only intended to fit into a very specific software engineering paradigm. So why isn’t there a happy medium you might ask? That’s where Scala comes in.
The name Scala
is derived from the expression Scalable Language.
It was developed by Martin Odersky in the early 2000s in an attempt to create a language that could scale to fit different use cases and grow with you as a developer or company. Because of this intent, along with the architecture on which it was created, Scala fits into several software engineering paradigms and therefor lends itself capable of teaching all the different paradigms in one language rather than bouncing back and forth between languages. This creates the benefit of allowing a developer to focus on learning new concepts rather than the mental overhead of learning the new syntax (the rules that govern the combination of symbols in a programming language – more on that to come later) of a language simply to demonstrate a concept that is only available in that language.
Because Scala fits into so many paradigms, you will often find criticisms of it as a language, suggesting that Scala is "everything and the kitchen sink" in one language. Others will say that it is hard to learn, or that it has a really long ramp-up time. While that is true – it can, in fact, be very complex because of all of the different things it can do and all of the different paradigms it can conform to – if you digest Scala in isolated partitions until you understand each concept before moving on to the next concept, it can add efficiency to your software engineering education in the long run. Additionally, if you learn Scala first, you will be very well positioned to transfer your knowledge and experience over to all the other languages (especially C family languages) as you will have learned concepts that are inherent to all of them, which will make you especially valuable as an engineer. Alternatively, if you were to go the traditional route and work through each paradigm one language at a time, it would take you much longer to achieve the same amount of value as an engineer.
Another reason why Scala is a good language to use as an introduction to software engineering is that it can be written in a very concise way – similar to Python but with the performance of Java. A concept that may take five to ten lines of code in other languages may only take 1 or 2 lines of code to demonstrate in Scala. Scale that out to an entire program and you could be saving hundreds or thousands of lines of code for a single application. This provides the benefit of getting the concept across to a new developer more quickly and also allows them to try it and understand it faster as they move throughout the concepts without sacrificing the runtime performance of the code.
Finally, Scala has been seeing an uptick in relevance in concurrency, latency-sensitive, big data, and machine learning/artificial intelligence projects lately. Having a core understanding of the language and all of the accompanying software engineering concepts will position a developer rather favorably when starting to dive into and learn more about these topics. These trends will continue to grow and dominate the software engineering industry in the near future and an engineer who doesn’t need to get caught up to speed on concepts that weren’t covered in their language or paradigm will be ahead of the game.
Because of all of these things, in my opinion Scala is the ultimate teaching language, and you should be incredibly excited to start learning software engineering using Scala.
Summary
In this chapter, you were briefly introduced to what a computer is and how a program works with a computer to provide applicable functionality. To demonstrate this functionality, the benefit of using Scala as an introductory programming language was established. In the next chapter, we’ll get your coding environment set up and ready to start programming.
© Jason Lee Hodges 2019
J. L. HodgesSoftware Engineering from Scratchhttps://doi.org/10.1007/978-1-4842-5206-2_2
2. Installing Everything You Need
Jason Lee Hodges¹
(1)
Draper, UT, USA
Okay, so now that you are excited about all of the different software engineering concepts that you can learn with Scala, the first thing you will need to do is install… Java. Wait, what? It may seem a bit misleading, but the Java Development Kit (JDK) is required for Scala since the Scala programming language is built off of the Java Virtual Machine (JVM). So, you will need to ensure that it is installed as a dependency before installing Scala.
Installing Java JDK
As of the time of this writing, you will need to ensure that you have the Java Development Kit or JDK version 1.8 or higher. You can check to see if you already have it installed by opening up a command line (in Windows cmd.exe or in macOS or Linux open up a terminal). From there, type the code listed on the first line in Listing 2-1, which will return to you on the second line the version of Java you have installed.
> javac -version
javac1.8.0_171
Listing 2-1
Command to check if the Java JDK is installed on your system
If you receive an error, then you don’t have the JDK installed, and you will need to install it before moving on to installing Scala. If you do have it installed, you can skip ahead to the installing Scala section. The steps to install Java vary slightly by operating system.
Installing JDK on Windows
If you are running a Windows operating system, you will need to navigate to the following Oracle web site to download and install the most recent JDK for Windows and run through the installer wizard.
www.oracle.com/technetwork/java/javase/downloads/index.html
There should be a button that says Download
with a reference to either the Oracle JDK or the Java Platform JDK (both will take you to the same page). From there, you will see a list of different operating systems for which you can download the JDK. Choose the download for Windows. Once the download is complete, you can open up the installer executable file and walk through the wizard. You should be able to choose all of the default installation configurations (unless you feel strongly otherwise).
You can verify that the installation worked correctly by clicking your start menu and search for cmd to open up a command-line terminal. From there, type in javac -version as you did at the beginning of this chapter. If a version number is returned, the installation worked correctly. If you encounter an error, then the installation did not work correctly and you will need to retrace your steps to ensure that you did not miss anything.
Installing JDK on MacOS
If you are on a MacOS system, the easiest way to install the JDK is using Homebrew, which is a command-line package installer. You can visit https://brew.sh for simple installation instructions. At the time of this writing, the installation instructions for Homebrew are simply to open up a terminal (you can hit command + space bar and search for terminal
) and type in the command shown in Listing 2-2.
/usr/bin/ruby -e $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)
Listing 2-2
Terminal command to install the Homebrew package manager
This command will prompt you to hit Enter/Return in order to confirm that it will install a number of directories on your computer. It will then ask you for your system password. Once that has been entered, it will automatically install everything you need to use the Homebrew package manager. This package manager can install most programs that you will need for development purposes on a Mac so it is a useful thing to have as a software engineer. You can browse some of the packages you can install with Homebrew by navigating to https://formulae.brew.sh . Verify that you have Homebrew installed correctly by typing in the command in Listing 2-3. If a version number is returned, then it was successfully installed.
>brew --version
Homebrew 1.8.3
Listing 2-3
Check that Homebrew was installed successfully
Once Homebrew is installed, all you need to do to install the JDK is type the two commands in Listing 2-4. The first command will update all the packages that Homebrew has a reference to on your computer. The second command actually does the installation.
> brew update
> brew cask install java
Listing 2-4
Install the Java JDK using Homebrew
You can verify that the installation worked correctly by typing in javac -version as you did at the beginning of this chapter. If a version number is returned, the installation worked correctly. If you encounter an error, then the installation did not work correctly and you will need to retrace your steps to ensure that you did not miss anything.
Installing JDK on Linux
For Linux-based operating systems (like Ubuntu or Debian), you can install Java through the built-in package manager apt-get. This package manager is very similar to Homebrew if you read through the section for MacOS-based systems. Most development-based packages that you might need to install as a software engineer can be managed through apt-get on a Linux machine, so it is a useful tool to be aware of.
To install the Java JDK on Linux, simply open a terminal (click your Home button and search for terminal) and type in the commands in Listing 2-5. The first command will update the package manager to ensure you have the latest package references. The second command actually does the installation. The first word, sudo, stands for Super User Do
and allows you administrator rights to the command that is about to be executed. It will prompt you for your administrator password.
> sudo apt-get update
> sudo apt-get install default-jdk
Listing 2-5
Commands to install JDK on Linux
You can verify that the installation worked correctly by typing in javac -version as you