4 ms·
I feel that this hints at a fundamental division between two ways that different programmers approach problems. I’m the opposite to you - I tend to think logic
by pansa2 5y ago
I feel that this hints at a fundamental division between two ways that different programmers approach problems.
I’m the opposite to you - I tend to think logic-first. So, for example, when thinking about a parser I’d start by writing code to read tokens. I’ve struggled to follow tutorials that instead start by defining types to represent an AST.
Different approaches to problem-solving also lead to different preferences in terms of programming languages. In particular, I’m perfectly happy working in dynamically-typed languages for small-to-medium projects. Many programmers seem to be opposed to dynamic languages on principle - I believe that’s related to thinking types-first.
- exdsq 5y agoHow can you approach a problem with logic before knowing what that logic will manipulate? For example you say you'd start writing code to read tokens but a token is a type
- pansa2 5y ago`Token` isn’t a type that a parser has to define - it comes from the previous stage (the lexer), or could even just be `string`. When writing a parser it’s already defined - so do you start the parser by working with the types you already have, or by immediately defining more types? I’d write a parser by first writing code to open a file (for example) to get a collection of tokens, then loop through them and decide what to do for each one. I’d use those decisions to guide my design of the output types. Others, it seems, start by designing the output types up front and use that to guide the design of the program logic.
- eru 5y agoIn something like Haskell, you often write your parsers via parser combinators. So you wouldn't be writing loops (or their Haskell equivalent) at all.
- eru 5y agoI suspect the difference depends on what your types can provide? So in something like Haskell the types are strong enough that going with a types first approach makes a lot of sense. Often once you have the types laid out, many functions will only have a handful of sensible implementations that are even possible at all. In something as primitive as C or Go (before generics) types don't tell you much at all. So laying them out first doesn't give you much at all. You might make a mental (or physical) note of what you are trying to achieve on what data, and then start coding. In Haskell you could express a lot of the content of that note in the types; but in C and Go many or even most things are done via side-effects, and their type system doesn't track these at all.
- shpongled 5y agoIndeed, I do a lot of Rust/ML-style programming, so the type-directed approach comes naturally.
- eckesicle 5y agoI do quite a few interview each week, and one of our problems highlight the differences in these two approaches quite clearly. Inevitably, those candidates that layout their types, and think about the structure before they start coding come up with convoluted interfaces, leave unused class/struct/type member variables, duplicate data, or are simply unable to complete the problem because they've coded themselves into a rabbit hole. The best candidates decide what the public interface will look like, create the method signatures that they need and then start coding the logic. They add parameters/member variables only when they discover they're needed. In the end they arrive at a minimal and feature complete solution, rarely getting stuck on the way there. I've changed my own style of thinking about a problem as a result of this. Now I code outside-in, instead of inside-out.
- zarzavat 5y agoYou should start with the most difficult (non-obvious) part first. If the most difficult part of the problem is the algorithm, then start with that and figure out the types along the way. If the most difficult part are the types / data representation then start with that and worry about the algorithms later. If both are difficult, then they need to be considered together and come up with a holistic solution. These are the kinds of problems that often take a two or more rewrites before you come up with something you're happy with.
- lewantmontreal 5y agoSome people call it the top down method. Start with the end result of what you want the program to be, in this case the public api methods.
- Tainnor 5y agoThat's a straw-man. You can code type-first without going down the overabstraction rabbit-hole.
- Beltalowda 5y agoI think the problem isn't so much "where you start", but rather if you stop and backtrack along the way. What I mean is that if you have "convoluted interfaces, unused class/struct/type member variables, duplicate data" etc. then you started with some approach but never stopped for a minute along the way to redesign things using the knowledge you've learned from the first implementation pass. I sometimes end up with a messy and crappy solution on my first try, but it does work (sort-of) and then I just start from scratch again, liberally copying stuff over but also deleting/changing a lot of stuff, as needed.