Think Like a Programmer: Coding Concepts for Non-Developers | Brian Holt | Skillshare

Think Like a Programmer: Coding Concepts for Non-Developers

Brian Holt, Front-end Developer

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
8 Lessons (25m)
    • 1. Introduction

    • 2. The Javascript Console

    • 3. Start with Data

    • 4. Thinking with Variables

    • 5. Understanding Conditionals

    • 6. Using Patterns

    • 7. Applying Automation

    • 8. Conclusion


About This Class

This class explores high-level software development concepts so students can apply them to their day-to-day. We'll review a few ways to approach problems and break them down using technique programmers use. Students will also get some insights into working better with developers.

This class is for anyone curious about software development, including designers, marketers, product managers, small business owners, and anyone who works with programmers. 

No prior knowledge is required, and the class assumes no prior programming experience.

No software is required as all the exercises can be completed on paper (or in a Google Doc or something similar).


1. Introduction: Welcome to Think Like a Programmer, where designers, marketers, product managers, or really anyone who's curious live development processes will get to see what's behind the curtain. In this course, we'll run through some high level problem solving concepts and learn how you can apply them to your own day-to-day work. In addition, you'll get some insights into working more effectively with programmers. My career started in graphic design, but as I learned programming in tandem I found that I could apply concepts like automation to my own day-to-day and make my work easier and I hope to show these things with you. Let's get started. 2. The Javascript Console: The code examples in this course have done in Javascript. You can follow along if you'd like to get a feel for reading code. All web browsers have Javascript built into them and a tool called the console for interacting with that. Javascript powers many of the rich interactions you see on the web today. These are things like flipping through product images on Amazon, liking posts on Facebook, videos are auto-play on YouTube and so many more. We won't dive deep into JavaScript, but it's the perfect language to follow along with. Open the console by right-clicking on any page, selecting "Inspect", and then clicking on the "Console" tab. Here you can do anything in Javascript, simple math. You can write messages. You can access anything in the JavaScript API to do something like speedup of video. Most Javascript to do in the console isn't permanent. If you feel like you threw with something, you can refresh the page and it will reset. 3. Start with Data: When tackling a problem, programmers start with data. It's a way to quickly identify some of the moving pieces within the work. When we speak about data, we're actually talking about the known value. In software, the piece of data is the saved value. It's what the program has on record which makes it the source of truth. Using data where known values will always be easier to understand than working with unknown values. That's why we start with it. Programmers are always looking to make problems as tangible as possible in order to reduce complexity. For example, considering simple math, it's easy to understand that one plus one equals two because we're working with actual values. If one of those values disappear, one plus something equals two, the problem becomes slightly more difficult. Or in deadlines, it's so much easier to plan when you know the real deadlines. That's why we start with data as much as possible. In programming languages, data is classified by its type, and a type is just a way to define what kind of data we're working with. Programming languages differ in how they categorize types, but most of them agree on some form of the following four: numbers, strings, booleans and null values. Numbers are for any kind of number. This includes positive, negative, and decimal numbers. Strings are for words, whether one or many and are always wrapped in quotes. Booleans are for either or scenarios, specifically whether something is true or false. For example, a checkbox, whether it's complete or incomplete. You can think of it like a switch. Is it on or off. Null values is data that explicitly states there is no data. A null value is used when data isn't present, like before something has been saved. It represents a known empty value. Some programming languages use slightly different names or include additional types, but these four can be considered high-level types, they're called primitive types. It's useful to arrange data in a format to make it easier to work with. These arrangements are called data structures. The data structures simply accepts arbitrary data and puts it into a specific format. The type of structure developer chooses depends on what they intend to do with it and the patterns of programming language. These are the two most common data structures; lists and objects. Let's jump into the JavaScript console to see what these look like. A list is a simple way to wrap a collection of data. For example, you might have a list of months. When they are in a list, you can apply an effect to all of them, like making them uppercase. Each entry analyst has given an index which provides a way to access a specific value if you know the index. Intuitively, indexes start from zero instead of one. Which means if we want to access march in our list, we need to use two even though it's the third value. Likewise, if we want to access January, we need to use zero. Let's start restricted to single levels that can be nested to hold much more data, like including the number of days within the month. Now that we have nested lists, it becomes a little more difficult to access the data that we want. An object is a structure that assigns data to keys, which makes it easy to call the correct value. If we turn a list of months into an object, it's much easier to access the value we want. If we want March, we can call it by its key, March. Now we have its name value, and it days value. In an object, it's a little more difficult to apply an effect like when we made everything uppercase, but it's still possible. A database is where actual data is stored. It is the source of truth. Anything in the database is the real representation of what the system holds. A database might sound like a challenging concept, but it's simply a collection of tables, like an Excel table. Each entry in a database is represented in a row, and each property as a column. Getting data from a database is most commonly done with SQL, which stands for Structured Query Language, and written S-Q-L. It allows programmers to write statements that collect data in a requested data structure in order to display it, update it, remove it, and add to it. SQL is extremely fast, but arranging data can be complicated. Well, a single table could maybe hold all the data in an application. If the application is small, the more data that's added to the table, the slower the SQL runs. Putting all the data on a single table is considered a really bad practice because of this reason. Programmers break concepts into their own table. This can add complexity because programs will need to write a query that runs across multiple tables to get the requested data. This is partially what can create an expensive request, but it's very dependent on the specific system setup and there are techniques to optimize performance. When working with web applications, the Internet connection also plays a role in delivering data. When more data is requested, more data must be sent over the Internet. If the connection is slow and there is a lot of data to send, the web page can time out or crash. It's best to only send the necessary data. Let's look at an example. This table represents comments and is modeled from Instagram. There are four columns of properties, ID, user ID, photo ID, and comment. The last column are the comments that appear on the post. The first column, the ID column, allows us to access the right comment. It works just like accessing an entry in a list. Columns two and three hold the User ID and photo ID. As I mentioned, we could contain all the user information and photo information right on this table, but it's a bad practice. Instead we include only the User ID and photo ID. When we want to access information about the user, like their name in avatar, we have the correct ID to query, and then we make a query on the user table. In addition, when we update or delete a comment, we're not affecting the user or photo table, which means the query can run faster. Thinking about data in this way can tell a story. Let's look a little closer at the content to see what's happening here. Look in the user ID comment, does anything stand out to you? The first two rows have the same ID, which means these comments are from the same user. If we look over at the photo ID comment, we also see the first two rows have the same ID. That means this user has commented on the same photo twice. If we carry on inspecting the photo ID column, we see two more users have commented on the same photo. Knowing a bit about types, data structures and databases will help them working with developers. But thinking about data as the actual value should bring clarity to work even outside of programming. Here's some tips. First, think about what you'd like to do and where it might go in the future. Put thought into what you expect to be working with and how you expect to get it. Finally, think about what you're certain of and what you're unsure of. For exercises, I want you to think about the data required to create this Instagram screen, and also identify the independent concepts that have their own database table. We've already identified comment of part of the others. Add your answers to your project, and I'll see you in the next video. 4. Thinking with Variables: Dealing with concrete data is the simplest way to work through a problem. But sometimes you don't have real data to work with, or there are many possible options for that data. When this is the case, programmers use variables to move forward. Variables in programming might be a little different from how you think about them in everyday life. In programming, a variable is an abstraction. It's like a container that holds information. It's a way to speak about something without being concrete about it, or when the actual value is unknown. It can also be a convenient way to reference something without explicitly saying it each time. In addition, variables can change or might hold a different value than expected. But we don't need to care about it at that moment. Variables are used all around us, even outside of programming. There are many different parts that make up a song, a verse, pre-chorus, chorus, interlude, etc. Each of these parts are variables, hold a value, but we can reference them by their abstracted name. If we want to know the contents of it, we access the information by name. In addition, some parts, like the chorus are reused but they hold the same content. Instead of calling it chorus one and chorus two, we simply call it chorus. Deadlines within a project might be named with variables instead of, or in addition with their actual dates, Beta release, Alpha release, go live date, etc. This allows us to think about the work that is contained within the milestone. Designers use variables all the times, name colors. Instead of calling a color bytes RGB or hex value, we might call it light blue, blue, or dark blue. In programming, variables is one of the first tools we use. In our list example, I assigned the list of months to a variable called Months, so I can reuse it over and over without needing to rewrite the content over and over. When we made the month names uppercase, a changing variable was made. I can make each month uppercase without caring about which one it actually was. Many applications have a variable called current user. It allows programmers to write one application, but provide unique experiences to different people. Current users assigned to your profile, once you log in so that you get your own content. If we didn't have variables, programming would probably be impossible. Outside of programming, thinking with variables can help you move your work forward. Use variables to break down work into smaller pieces, even when something is unknown, abstract a concept or part of the discussion away. You don't need to think about it right now. Highlight what data is unknown. What questions need to be asked. Name a concept to something that feels a little more tangible. Focus on a specific piece of the problem in isolation and make progress on a project without having all the answers. There are two big challenges when working with variables. Determining whether a variable is flexible or fixed, and giving it the right name. For determining a state, ask, will it change? Should it change? Can I make that decision later? Knowing the difference can simplify problems you're working with and identify boundaries. Where to ask questions and what you must work with. Naming variables is often considered one of the most difficult task in programming. If a variable is named wrong, it can lead to very confusing code for someone else or even yourself later. Sometimes misnamed variables encouraged thinking about a concept in the wrong way, which can mean the product or feature turns out wrong or less than ideal. Since variables are a form of communication, miscommunication can creep in through misnamed variables but you can rename your variables whenever. To consider if you have the right name, ask yourself, is there a simpler way to describe it? If people continually need clarification for the variable consider that it might be named wrong. Also consider how do you describe it? Is there are simple or shorter way to do it? Is it's name too vague? Do others understand what it represents? Hyper specificity can be good and is common in some programming language. Don't necessarily shy away from that. You want to make sure that it feels like you're actually speaking about the right thing. Think about the abstracted data in this Instagram feature and add your ideas to your project. I'll see you in the next lesson. 5. Understanding Conditionals: Data can change depending on the circumstance. You might want to sell a product at a reduced price between two dates, or only allow certain person to see content. Conditional statements allow developers to write these cases encode, think of a conditional statement as a fork in the road. There are two paths that someone might take. Those paths might join again, or they might stay divergent, they might break into smaller paths. A conditional statement creates divergent paths from moving through a system, or a program. It's an if else statement in its simplest form, which creates two paths and in a more complex form, it could have stages or states. Conditions are everywhere in the real world. A simple form is insecurity. Either you have the key to open the car, or you don't. If you have the key you can drive it. Otherwise you can't use the car. A shared train track where multiple trains will arrive on the same platform has many divergent paths. There can be a local train that visits every stop, an express train that skip stops, another might end up at a different destination. This is a more complicated set of conditions and you can find state conditions and choice, like the choice of pizza toppings. You get to choose what goes onto it with a series of yes or no options. In the end, you still have a pizza, but there are a series of minor conditionals which results in different outcomes. In programming conditions create divergent paths for different users. We use conditions for restrictions if the user is logged in, so then the page otherwise send them to the login screen. We use conditions for settings, or user preferences, just like the toppings on a pizza that can be a series of independent switches that deliver a unique experience. We use conditions for simple things too, like, if else statements, if there is a notification, show the bell, otherwise don't. In user experience design, we think about states a lot. The playing state, partial state, error state and ideal state. All of these states need to be accounted for it to complete a design and they are made up of several conditions based on the user of the system. What makes understanding conditionals useful at work? Well, you're able to identify things that are co-dependent. You can get a handle on a work flow and then divergent possibilities within it and spot what could go wrong and what risks are plausible. A control flowchart is a great tool to visualize conditionals. As for basic shapes, an oval, which indicates the beginning or the end. Arrows which indicate the direction to move. A diamond that indicates a decision point or conditional and rectangles that indicate a step in the process. You can use other shapes and colors along with the legend to group related types of activities. Here's some tips for working with conditions, since they always increase complexity. Consider if the conditional is necessary at all and if you're beginning to write nested conditionals, which is a path that lives within another path, try to move the condition to a higher level. If it's necessary, explore the best way to express it. Should it be a true or false value, or can it be preferences? Finally, to find the right balance between appropriately exhausting the path to its end and getting lost in the weeds. Consider how closely related the conditional path is to your original problem. I want you to create a flowchart of Instagram's like a photo feature. Try to start as early as possible and map out as many divergent paths as you can think of then shut in your project, if you get stuck in nested conditions, consider if the path can be broken into its own flowchart. If that's the case, simply give the step a title and focus on the liking of photo feature. I'll see you next time. 6. Using Patterns: Identifying patterns is essential in programming. Developers break problems into small pieces, solve that problem, and raise the pattern to build larger systems that together make up an entire application. In short, patterns create systems. Using a pattern provides a consistent way to do something many times over and over and it's predictable and repeatable with a pattern, you can create a system which allows you to leverage and reuse work and you can use that pattern and apply it to many different situations. Patterns are all around us. On doors, we instinctively know one to pull a handle or push a flat panel to open or close it. It's irritating when we need to push a door handle because the predictability of the pattern is broken. We know that turning the screw left will loosen it and turning it right, we'll tighten it, and designers use patterns in their design systems and style guides using components, color choices, and behaviors provides a way to consistently create on-brand interfaces. Patterns are extremely important in programming. Working with a pattern enables a team of developers to work together towards the same goals. A function is a small piece of code that completes a task and reusable functions are simple patterns. For example, a function that can make a word uppercase is reusable. It doesn't matter what word it receives, but it will make it uppercase. Programmers also use different paradigms in order to solve problems. For example, a functional paradigm is a way of organizing code with small, reasonable functions. Whereas an object-oriented paradigm treats the pieces to the program as objects and they hold their own internal data. Each have pros and cons to them, but knowing when to use one can make solving a problem easier. Best practices and standards are also patterns. We learn from others experiences and apply their knowledge to our application, some examples of best practices are; the single responsibility principle. It means every piece of code should only be responsible for one thing, and it keeps code isolated, and maintains its focus. The Dry principle, which stands for don't repeat yourself. It essentially means avoid doing the same thing over and over and it encourages thinking about problems in the abstract to identify pieces that are common in order to turn it into a pattern. It also establishes a source of truth for tackling the problem. Because if you're not repeating yourself, there's only one way to do it and that reduces confusion. Another one is, you're ain't going to need it. It means don't build the thing until you know you need it. It reduces work to its essentials in order to move forward and it restricts overbuilding. In practice, it can also make problems feel more concrete because we often strip away some of the unknowns to build the simplest thing that works, there are many other patterns programmers use. Patterns help us to think about problems in different ways and create better workflows. Using patterns in your own work can be tremendously useful. When problems feel too large, looking for similarities is a great way to break it down into manageable pieces. Identifying recurring problems can provide an opportunity to think about things at a higher level to create the right way to do it. Finally, patterns help enforce consistency or fixed inconsistency, which causes confusion or sloppiness. The easiest way to start using patterns is to ask yourself if you've done something similar before or if you expect to do this work again. When you're comparing two problems, ask yourself, what are the differences? Try to think about the parts as variables. If you find many similarities, you probably have an opportunity to make a pattern. Sometimes two patterns can look like they're one and that's a bit of a tricky situation. Using our data and variable approaches can help with this. What kind of data are you working with? What do you expect to do with it? If the differences are big enough, then you probably have to patterns. A rule of thumb is don't try to force something into a pattern. Finding the right pattern should feel like unlocking achievement, though it can be a little difficult getting there. Finally, if you're the only person who knows how to do something, writing down instructions is a great way to turn yourself into a pattern. With good instructions, many tasks can be accomplished by anyone. These can even serve as a reminder for yourself in the future. In this lesson, I'd like you to identify the patterns Instagram uses that are also used in other applications. For example, liking a photo is an Instagram, but liking a comment is on Facebook and liking in a video is on YouTube. The pattern of liking is common in most social media apps. Share your work and your project. Then let's jump into our last lesson, automation. 7. Applying Automation: Automation is a powerful tool in a programmer's belt. It allows programmers to do work in batches significantly faster, with much less effort. At its core, automation simplifies work, it reduces repetitive tasks, and perform sequences of events. What does that mean practically? Doing less work with the same results, doing it faster, and being more efficient. We often think about robots when we hear the word automation, but there are many real-world examples of doing less work with the same results. Traffic lights, as opposed to four-way stop signs, speedup the repetitive task of needing to inspect the intersection. This automation allows many vehicles to pass at once without requiring them to stop individually. Another form is an alarm clock. Once it's set, it'll automatically alert you at the appropriate time, so you don't need to be manually checking it. Can you imagine checking the clock every hour in the night in order to be on time for work? Automation allows you to sleep. In addition, you can program a sequence so it only alerts you Monday through Friday. Marketing drip campaigns are less physical form of automation. It's created once and applied to many people in sequence. They'll get a welcome email when they sign up and after some time, get another email, and it carries on through the entire campaign automatically. In programming, we have many types of automation and sequencing; from loops, like when we loop through a list of months to make them uppercase, to background jobs, which will notify user when they've been mentioned. All applications involves some level of automation, otherwise, everything would need to be completed manually, which would require an enormous team. How can you apply automation at work? First up, look for roadblocks and inefficiencies in processes so that you can remove them. Anytime work needs to stop, consider if the reason is required, can the process improve so it doesn't need to stop? For example, if a designer is sending a proof to you, so you can post it to the client, can the designer instead post it directly to the client? Next, learning keyboard shortcuts will help you work faster. When I'm learning them, I tend to focus on one per week, and I write it down so I can quickly reference it. Anytime I'm about to use the command, I stop and use the shortcut instead. Soon I know the shortcut well enough I no longer need to reference it. Finally, try to batch work together so you can focus on the group as one thing. Batching will probably help identify which parts can be automated. Automation is really about reducing the number of things you need to do so you can focus on more meaningful tasks. To apply automation, we first need to identify candidates. These are what I think about. What am I doing that's tedious? Can I reduce the number of steps? Is something error prone? What takes a lot of my time? In the last exercise, I'd like you to identify the sequence of events when someone posts a comment on an Instagram photo. What happens to the comment? Who knows about the comment? You can do this on a control flow chart with just rectangles, but if you're feeling ambitious, think about what can go wrong in the sequence too. 8. Conclusion: Thanks for taking my course. If you have any questions or any clarification on anything, please reach out to me in the community. Until next time, see you.