Should I focus on developing real, working software or small exercises?
February 19, 2021 7:11 AM   Subscribe

Three months ago I posted a question about how to learn computer programming. I received terrific advice which I followed. I'm now coding in .NET with C#. I built a working Winforms application which stores and retrieves user data in SQL Server, and now I'm learning XAML so I can rebuild it in WPF. Now I'd like to follow up and ask: am I doing too much too soon?

One of the biggest surprises (and disappointments) in programming has been how relatively little numerical logic is involved compared with brute memorization of syntax for all the reference libraries, e.g. LINQ returns an IGrouping which is an IEnumerable which is a List, so you can do this with it but not that; first you have to cast...

I feel like I'm just diving deeper and deeper into new reference libraries and learning about theoretical constructs without really spending much time in fundamentals. Like, what are all the things you can do with an INT32, with a string, etc. Or maybe I should spend time getting really good with inheritance and interfaces until I intuit the polymorphic principles and don't have to think so hard every time I implement one. Or, maybe I just keep plowing ahead and piece together what I can and assume the fundamentals will just sort of develop.

What prompted me to post was a website I was reading about MVVM, and how I need to implement ICommand and INotifyPropertyChanged. I thought, "I didn't even know those interfaces existed. I'm buried in interfaces, but I haven't written a For loop in two weeks." My end goal is to design software, preferably as an independent contractor, but potentially working for someone else. Is this what the process looks like, or should I spend more time on smaller mock projects, coding exercises and whatnot?
posted by jwhite1979 to Computers & Internet (19 answers total) 7 users marked this as a favorite
 
I have a degree in computer science. Before I started that degree, I was already a self-taught programmer and getting paid to write code.

I learned a lot from my course, and have very occasionally even put some of it into use.

But I graduated alongside a lot of people who, despite all they'd learned about theoretical foundations, clever algorithms, data structures etc - had no experience of doing the sort of day to day software development that companies actually pay money for.

It sounds like you're practicing exactly that - learning the sometimes boring, but practically essential, details of real world tools which will eventually let you quickly and fluently develop working software that people will pay you for.

Given your stated goals, I think your approach is good, and lot better than many.

My guess is that occasionally you'll run into a task that you don't know how to approach, where you find you need to dig a bit deeper into the fundamentals to discover the answers. But you'll be arriving at those points with a motivating example that you already understand - which can be a much better opportunity to learn, in my view, than trying to slog pre-emptively through theoretical exercises without understanding why they're useful.
posted by automatronic at 7:40 AM on February 19 [5 favorites]


Are you learning? Are you getting overwhelmed?

If you are learning, and you are NOT feeling overwhelmed, then you're doing fine.
posted by kschang at 7:41 AM on February 19 [1 favorite]


One thing I'd recommend if you're doing this as a step towards a software development job is to write automated tests. It's something I rarely do if it's my own side project that I'm doing for fun (depending on the complexity/fluidity of the side project), but it's definitely something yd need to be able to do in a dev job.

If you are applying for jobs and can point to a repo that has a project with tests, that can help you (assuming the code is also in good shape and demonstrates good principles).
posted by kokaku at 8:21 AM on February 19 [5 favorites]


As a dev/admin, this is very much what the real world work looks like.
Aside from foreach loops, the only time I need to dip into the fundamentals is when I'm doing something like calculating tax rates or recurring payments. Aside from that it's mostly working with the libraries.
posted by Eddie Mars at 8:30 AM on February 19 [5 favorites]


Response by poster: @kokaku: That's a really good point. As far as I understand it, MVVM makes unit testing possible by separating controls from logic. But this actually reveals what I mean when I say I feel I'm lacking in fundamentals: I don't know why unit testing is impossible when controls are involved. Can't you just run a test to ensures when you pass "Foo" into the control, "Bar" is returned? I suppose when I start writing the unit tests I'll be able to better get my head around it
posted by jwhite1979 at 8:31 AM on February 19


I have a couple of different trains of thought here:

1) It really depends on what kind of project you're working on. A lot of software development really is gluing different APIs together and slapping a UI on top of it, and in that case, what you describe is exactly how it goes. The APIs are doing the fundamentals for you, and that's a good thing, because you don't want to reinvent the wheel. However, if you're working on embedded code with hardware constraints or on a unique business problem that needs to run quickly at high volume, then, yes, you're going to need to know about ints vs uints and big O notation. I can say that I have been writing software professional for about 15 years (very successfully, I might add), and I'm still a little fuzzy on some things people might consider "fundamental."

2) Anything you can do with Linq you can do with for loops and lower level code. If you're wanting to get more familiarity with the basics, you could tell yourself that you won't use Linq or other higher level features. But when I get a job candidate in .Net who doesn't use Linq, I start to question how familiar they are with the stack and how up to date their skills are.

3) Re: unit testing controls. Give it a try, see what happens! Though I can explain a little more -- if you unit test at the control level and it fails, did it fail because the data got corrupted in the control? Or when you passed the data to the business logic? Or in the business logic itself? Whereas a unit test of just the business logic isolates the business logic as the source of the failure.
posted by natabat at 8:53 AM on February 19


This is a pretty common way to learn programming; you start at an arbitrary point in the stack building real projects, and learn other adjacent systems on-demand. Like, your question "why can't I unit test UI components the same way as other classes?" has a complex answer which requires diving down into WinForms and Windows internals. But in answering that question, you'll gain more insight into GUI toolkits in general.

Another more "fundamental" area you could investigate is learning more about SQL, the query language, and deeper into how databases are organized.

You could also do something like CodeWars, LeetCode, etc to sharpen your C# skills. But in most business domains, 99% of the time you will be writing database queries, or binding components together with duct tape and Elmer's glue.
posted by RobotVoodooPower at 10:27 AM on February 19 [3 favorites]


I think probably the greatest learning opportunity would actually be to have someone review your code, which is tricky outside a work context. I don't have a formal CS background and a lot of the conceptual stuff (i.e. how does MVVM (or I guess separation of concerns more broadly--I know nothing about MVVM) help with unit testing) I learned because someone sat me down and said "You're Doing It Wrong. Do X, not Y, because Z".

It's hard to develop good software engineering habits off on your own, but you definitely can get good at debugging, understanding error messages and googling by just plugging away trying to figure things out as you go. I have definitely solved problems in a matter of minutes that have stumped colleagues because I know how to google and then apply what I found on StackOverflow or wherever to my situation, even though I didn't google up a complete answer.
posted by hoyland at 10:59 AM on February 19 [1 favorite]


Response by poster: @hoyland: I'm in serious want of that sort of mentor. Unfortunately, I don't actually know people who code at this level. The company I work for has an automation department that uses VBA to program equipment, and there's sometimes a little SQL going on, but very little. I asked the department head what he could tell me about mapping objects from an SQL query, and he told me he didn't think it could be done. I later got to tell him about ORMs, and he was really excited for me.

I'm a single dad in my forties with two toddlers, an $1150/month apartment, and a job where I didn't clear $35k last year. I get up at 2:30-3:00 AM and sit down at the computer and hack away bit by bit, cringing every time my question is Downvoted on StackOverflow and wishing for someone who knows Dapper inside and out to pass on his/her wisdom.
posted by jwhite1979 at 11:19 AM on February 19


Best answer: I reckon developing a whole application to solve some kind of toy real world problem is a great way to structure learning. Your approach sounds fine. A great deal of professional programming work is being able to understand and reuse existing libraries or components. A great deal of practical real world business programming is cobbling together some application with a UI, a database, and some kind of backend layer that can call other software systems to trigger stuff to happen.

Once you've got something working to solve some kind of toy real world problem, another learning exercise is to think of some slight change to the problem. E.g. if your original problem was to make a simple application with a database and a UI where users can enter and retrieve and edit records describing types of equipment -- maybe the next thing could be to add functionality for a basic inventory system and extend the UI so users can store how many pieces of each type of equipment there are. Quite a lot of programming work is modifying existing programs, and once you start trying to rework code you (or others) have already written, you can start to learn a lot about how to structure code that is flexible or inflexible to change.

Different contexts lead to different kinds of programming work. You can't learn all of it, and there's no need to. For any given context you can draw on relevant prior experience / some knowledge of fundamentals, but then you'll need to learn more about the specific kinds of tools or approaches that are relevant to that context and that niche. Some of this will be related to how the software is delivered (e.g. "throwaway" script that only serves to produce a one-off report; desktop software run on one person's computer; desktop software deployed to 200 users in the same company; software deployed as service running 24/7 in company data centre processing 100 customer transactions per second that costs the business $y,000 for each minute it is not operating; embedded software deployed into cars that costs $xx,000,000 if it needs to be recalled with a critical bug fix, etc)

Here's some examples of different kinds of software work I've seen from personal experience, across ~12 years. Each of these niches involves learning stuff that is largely irrelevant to the other niches. You can learn a lot of this on the job once you get a foot in the door working on software in a particular niche:

People doing scientific computing in an applied math / physics simulation niche may never develop a user interface and never learn what a SQL database is, but they may write a lot of numerical code to perform a bunch of complex linear algebra calculations in parallel across a high performance cluster of thousands of machines.

People building and maintaining web services in the bowels of a large old financial institution may never develop a user interface but will spend a lot of time designing and documenting APIs for web services to be called by web services, and writing web service code to consume APIs exposed by other web services. There's likely to be a fair bit of SQL, some message queues, communicating using events. Integrating with existing software systems that are 20 or 40 years old. Much of the work will be understanding and modifying existing code, not building new applications. Lots of security requirements -- implementing access control, encrypting data, masking sensitive data, logging everything that happens so it can be audited afterwards. Likely no numerical logic.

People writing software to help large companies solve logistics challenges (e.g. routing vehicles, helping to plan where the company should expand operations and build new infrastructure) are likely to need to know a bit of SQL to pull in data from existing systems, how to import and export and process geospatial data, how to express routing problems using graph theory and then apply pathfinding algorithms to find shortest or cheapest paths, dynamic programming or linear programming techniques to solve optimisation problems to figure out which is the most profitable subset of options to build. Lots and lots of layers of code for input data validation and output post-processing / report generation.
posted by are-coral-made at 1:14 PM on February 19 [1 favorite]


Best answer: >> My end goal is to design software, preferably as an independent contractor, but potentially working for someone else. Is this what the process looks like

Yes. What you describe is a pretty accurate description of how the practical "writing code" activity of a software development job in a business context works. Figuring out how to reuse the existing frameworks / open source library / internally-developed library to do most of the work, and integrating it with other software components to get the job done quickly, cheaply and reliably.

When you have a job in a team as a software developer, much of your time will not be spent on the "writing code" activity. To operate as a member of a team working on a larger professional software project, you'll need to get familiar with ways of collaborating on software with others. This is a mix of mindset, "best practices", tools that can be used to implement best practices, as well soft skills like how to communicate your ideas, graciously accept criticism, negotiate scope and schedule. You don't need to know all of this to start, you can learn a lot of this on the job as a junior developer.

As long as you've got a foot in the door and start working in a team that are doing most of these practices, and you have one or more experienced software developer colleagues who are good role models and are willing to spare a bit of time to help you learn, you'll do fine. Once you're in this environment you will learn a hell of a lot in the first 1 - 2 years.

non "writing code" activities:

- using version control (probably git) to track changes and share work with the team
- writing and maintaining automated tests, including unit tests and some other styles of heavier testing to confirm that multiple components or services can integrate and work together in a few scenarios. it is reasonably likely you will spend more time writing test code than non-test code.
- maintaining "continuous integration" systems to re-run the test suites whenever anyone changes the code
- code review -- how to organise and document your work to make it relatively quick and easy for someone else to review, making changes in response to reviewer feedback
- code review -- how to review other people's code
- code review -- how to negotiate situations where the reviewer and reviewee strongly disagree about the code's logic / correctness / structure / style
- structuring code in a way that is possible to test and flexible to future change
- using an issue tracker to track progress of work on bugs / features / an endlessly growing low-priority of ways the code could be reorganised to make it easier to change or understand
- communicating and getting team buy-in for solutions to problems -- how to informally or formally describe the problem you are trying to solve, list a few alternative solutions, describe the design of your recommended solution to the problem in detail, and get feedback on that proposal (before e.g. spending two weeks building something that your collegues think is a bad solution, or isn't solving the right problem)
- some amount of understanding of or ability in release engineering, releases processes, operations, production support. (i.e. how to make controlled changes to promote the software from running in development / test conditions, to software that's running and being used "in production" by the business to do business critical work, while minimising disruption and risk to business)


One possible way to gain exposure to some of these practices before getting a job is to find an existing open source project that you can contribute to. E.g. if when you are building an application you find a small open source library that is useful to you, and you identify the open source library has a bug or has a bit of a gap in functionality that you would like and that other people would also want, you could try to contribute to that open source project. If the open source project is hosted on github.com that could expose you to writing an issue (describing a bug or a feature request), communicating with the maintainer(s) of that project to see if they agree with you that the change is a good idea, figuring out how to run the project's automated test suite, making your change to the existing software, sharing it for code review in github's 'pull request' interface, getting code review on your change from the project's maintainer, getting asked to write more unit test cases to go with your new feature / bug fix, etc.
posted by are-coral-made at 1:36 PM on February 19 [3 favorites]


I think folks above have given you a good "drink from the fire hose". Maybe these random comments will just add one more perspective based on my 45 years.
- I know of companies today that pay people to learn COBOL (which is what I have spent most of my time coding in) because that's what they need. I realize that's not what you're shooting for, but it just goes to show you that employer needs can be inscrutable.
- But I also know Assembler (both mainframe and 8086) and VB.Net and CICS (very high volume transaction processing)
- Don't forget macro processing (or preprocessing) such as C uses. So you have compiled languages, interpreted languages, embedded languages and then some have preprocessors, so it goes: code including macros -> preprocessor -> compilation -> execution. Often the preprocessor is used to customize systems for different clients or target operating systems, etc. So then the macros become full partners in the code base and must be version controlled in git or what have you.
- I didn't see "middleware" mentioned in this thread, but that may be just an old fashioned term. To me it means software coded expressly to act as glue between two existing systems. To some extent you could say that first class systems expose APIs so that middleware can leverage those systems in combination with home grown or different vendor packages. A non-trivial amount of my work over the years has been gluing systems together.
- On the one end of computers you have doctors, researchers, engineers using software as a tool. On the other end you have game programmers, where the software is the ultimate product. And somewhere in between you have programmers who are like (IMO) carpenters and metal workers, doing project/job/client specific work. I remember reading a book on carpentry where the author said that in evaluating a prospective employee he asked them to build a sawhorse while he watched. He expected the person to build one that was easy to throw in a pick up truck, was sturdy, would stand up in weather and last for years. I don't think they pay me to be a genius or a geek, but rather as a problem solver and communicator and fabricator.
- Yeah, I agree with others about 80-20 rule. Most of what I learned in college I don't use, but I do recognized linked lists, state machines, Shell sorts and binary trees when I see them. Conversely most of what I read on-line these days sounds great, but isn't always practical. I got nothing against Test Driven Design, but in a sufficiently complex system I think it just doesn't scale.

I hope this was of some help. I'm just an old guy and wish you all the best!
posted by forthright at 2:55 PM on February 19 [2 favorites]


If you want to work in a modern team, also spend some time learning how to build and deploy your examples, preferably to AWS. I just have an AWS account with the same creds I use for shopping and an alert for when my spend hits $5/ Month. In my large firm (16000, about 3000 developers) we are running hard away from data centers and separate database, network, Linux teams etc that do parts of things for you. Many devs struggle with this transition and you will be doing yourself a favor if you know git plus some build and deploy tool and a little bit of AWS. if you learn to set up the AWS stuff with code (cloud formation or terraform - we prefer the latter), even better. All the cloud stuff is fun and the basics aren’t that hard. Running terraform apply and having servers and stuff magically created in seconds is very empowering :-)

Also as said above, use some issue tracker to plan out your work in sprints or do Kanban (limit work in progress to a few things ). That seems silly if you are alone, but all teams require Jira or Azure DevOps or similar, and you can use that to not get overwhelmed. E.g. focus on AWS for 2 weeks, git and builds two weeks, Rds databases two weeks, etc.

You should be able to pull down a LOT more money if you get that first job. In the US at least (non Silicon Valley) entry level programming jobs are double what you’re making. BTW I taught myself programming at 27 and got a job and am now 51, and the CS degree stuff rarely comes up for business programming.

Also I learned SQL from the yellow Dummies book and surprisingly, immediately knew more about SQL than most developers. It’s a lost art!
posted by freecellwizard at 3:27 PM on February 19 [1 favorite]


> I'm in serious want of that sort of mentor. Unfortunately, I don't actually know people who code at this level.

See if there are local tech community groups you can join. Networking opportunities & a way to learn from folks. There's often local programming / tech related interest groups organised on meetup.com . I appreciate it might be challenging to get time to attend in person events after work at 6pm as a single parent dad & also holding down the day job, not to mention covid. Some of these groups will also communicate online (messages, mailing lists, links to online presentations) so it may also be possible to network a bit even if you can't get to in person events.

> The company I work for has an automation department that uses VBA to program equipment, and there's sometimes a little SQL going on

One angle might be to see if you could convince your company into letting you invest some work time in activities outside the workplace to develop your programming skills - training or attending local tech community events. If you can tie it to some work outcome they care about (help fix work problem xyz / reduce manual processing time through better automating abc) you might be able to sell it to the boss.
posted by are-coral-made at 4:01 PM on February 19 [1 favorite]


Best answer: I’m a product manager and part time script kiddie. I work closely with legit software engineers at a unicorn. There is lots of good advice above. Here is mine:

Watch live coding in YouTube or Twitch. Start here: https://github.com/bnb/awesome-developer-streams. If you don’t have access to mentors these people are the next best thing.

Random ramble: A surprising amount of professional enterprise software development consists of algebra and no more. It’s not until you need to start shaving milliseconds off of ElasticSearch queries or ingesting millions of documents through an enrichment pipeline when the hard core software engineering starts. Most of the really really hard stuff is slowly being abstracted away by extremely bright people at Amazon and Google. Training a image recognition model is nearly trivial these days. Don’t get me wrong, software is difficult but things are becoming a lot easier and day to day a lot of software engineers are simply chewing through stories in JIRA and not always having to go into uncharted puzzle palaces without a hefty tool belt available. With that said, not all work is greenfield and untangling monolithic technical debt and bugs is hard and comes with the territory when you are professionally developing software. A lot of times the human language will be the hardest language you have to deal with day to day as you collaborate via slack and GitHub.

Create a personal web based project using Azure or Google Cloud or AWS. Wire up a database. Add basic CRUD with some APIs / Lambdas. Read up on MVC. Break shit. Fix it. Break it again. Deploy it to “prod”.

Embrace Stackoverflow and Google during the above project. It’s the secret everyone knows about. By the time I finish a personal project I have googled hundreds of things. “How to host my images on a CDN”. “How to create a signed URL for Google Cloud Storage”. “Remove trailing period from string in python”. “Strip path from url in JavaScript”. “Create unique list in python”. “Wildcard sub domain on digital ocean”.

Keep a dev journal. You are going to create some mud balls of code and configuration and command line madness to get stuff done. After finding solutions, write down what you did and where you found your answers.

Comment you code. Leave yourself todos and notes and reminders and reprimands.

Pull down GitHub repos and Gists and play with them and study how others do things. Pull up side by side windows in VS Code of a code snippet. Modify the code. See what happens in the browser, command line, postman, etc.

Read HackerNews and Dev.to. Read the Pragmatic Programmer. But spend more time writing code and tests and tools.

Most importantly just write code and have fun. You will get better with practice and making plenty of mistakes. Hit me up in my profile if you want any more advice or want me to ask some questions of the real deal engineers I work with.
posted by jasondigitized at 10:03 PM on February 19 [1 favorite]


Lots of great advice above, it sounds like you're doing fine. And it gets better! Over time you'll be able to spend less time reading API documentation, and more time building stuff and working on interesting problems.

More specifically on the tech you're working with:

Good luck with MVVM; if you get frustrated and/or confused it's not your fault, it just has a lot of... baggage.

It's best to treat a lot of MVVM as sensible guidelines, but not firm rules. For example if moving code out of your code-behind requires a super-obscure and complicated WPF databinding feature that you will never use again, IMHO that's an OK time to violate MVVM purity and leave some logic in your code-behind.

The core interfaces used in .NET MVVM were designed a long time ago, and if they were redone today they'd probably look different. Notably, it's weird that ICommand isn't generic and has no understanding of async operations.

I've recently found the new Microsoft.Toolkit.MVVM package to be useful, you might too.
posted by ripley_ at 8:26 AM on February 20 [1 favorite]


Response by poster:
For example if moving code out of your code-behind requires a super-obscure and complicated WPF databinding feature that you will never use again, IMHO that's an OK time to violate MVVM purity and leave some logic in your code-behind."
You're my hero this morning.
posted by jwhite1979 at 2:45 AM on February 21


Best answer: You already have a lot of good answers, but I might as well pile on.

First, congrats! It sounds like you've come a long way pretty quickly.

> One of the biggest surprises (and disappointments) in programming has been how relatively little numerical logic is involved compared with brute memorization of syntax for all the reference libraries.

Yup. I'm a math major who got into programming professionally. "You must really use your math background", people frequently say. I would respond that no, not really any of the knowledge is relevant, but the way of thinking and approaching problems is useful. You don't say much about the application you wrote, but I'm guessing it's a typical CRUD application (in the self-deprecating lingo). These are really common... you have some data to manage and you need a UI to interface with it.

First of all, looking back you probably can't think of a place to put any numerical logic even if you wanted to force it. And that's pretty typical of the crud app. You normally do very little with the data itself, besides showing it to the user. Maybe you have some reporting that requires min/max/sum/average, but in that case you would just tell sql to SELECT SUM(amount) FROM whatever. The value these applications provide are in 1) making a usable UI for users 2) enforcing data validation as early as possible (e.g. telling the user about an invalid date before SQL complains about it) 3) applying business logic.

CRUD applications are ubiquitous, and you could make a good living working on those. Of course there are applications that are more numerically-oriented if that intrigues you. Any sort of modeling is going to be math-heavy. Or any sort of optimization algorithm.

The other point I wanted to make is that so far, your tools are C#, the .Net Framework, and SQL Server. You should get to know your tools, what they can do, and what their limits are. That doesn't mean memorizing the LINQ api, but it does mean understanding it and why it's there. Though I will add that the most common parts of LINQ should seem natural enough that you don't need to memorize them. If you know what Select() or Where() does, you know what you need to give it - there's only one thing that makes any sense. If you're like me, you don't use IGrouping or SelectMany() enough for those to have clicked. I know SelectMany() can flatten a collection of collections.

Having someone review your code would be a great benefit. There's a Code Review stack exchange site if you have a particular self-contained example you want feedback on. I would assume that anyone who has posted here wouldn't mind taking 15 or 30 minutes to look over some code, as long as you've made it easy (like posted to GitHub). If you do ask for feedback, make sure you've done your best polishing to it. It's a waste on both ends for you to get back notes on things you wouldn't do in "real" code.

You can learn a lot about C# and .Net just by playing around. For SQL, the best practices are harder to discover on your own, so I would do some reading on database design. Things like foreign keys, the various "normal forms", transactions, ACID, how to migrate the schema for the next version of your product.

Good luck!
posted by Horselover Fat at 2:24 PM on February 22 [3 favorites]


Response by poster: Thank you all for sharing your experience. I picked up a copy of C# in a nutshell, and I'm going to spend a few weeks with it before diving back into my project. After reading 20 pages or so, I feel like the lights are coming on and revealing all the stumbling blocks I've been navigating around. "Oh, so THAT'S what's really going on with a Lambda expression!" "Oh, that's why I can't implicitly cast a double to an int!"
posted by jwhite1979 at 9:52 AM on February 26


« Older What do we know about the Russian and Chinese...   |   Good way to say Farewell in these times Newer »

You are not logged in, either login or create an account to post comments