The criteria I recommend are:
These two are actually very famous in industry. I still want to share with you, in case some of you may not know. There are too many classic technical articles from these two blogs.
Joel is co-founder of StackOverflow, and he wrote a nice book: Joel on Software.
Paul Graham was a well-known Lisp programmer and then became an investor, I love his book:
Hackers & Painters: Big Ideas from the Computer Age
I remember I found this blog when I tried to finish all the SICP exercises in 2008. There are almost all the answers to SICP exercises with detailed explanations!
What is commendable is that the author Eli Bendersky has always insisted on writing his technical experience, and this blog is continuously updated. The quality of the content is very high, with both theory and code. For instance, he wrote the Raft series: Implementing Raft: Part 0-Introduction, which is simply a model of technical writing.
This blog is maintained by an Italian developer, and the content is mostly on front-end and web development.
I admire this blog because he keeps blogging almost every day! What he wrote may not be in depth, but it is useful to many people. I used SEO tools to read the data of this website, and the organic traffic brought by Google is very high.
I recommend everyone who want to start with writing to read these two articles:
Every developer should have a blog. Here’s why, and how to stick with it
I wrote 1 blog post every day for 2 years. Here’s 5 things I learned about SEO
This blog covering a wide range of fields. This author deeply inspired me to learn programming by understanding internal principles: Get better at programming by learning how things work . Of course there are many other technical articles such as: Diving into concurrency: trying out mutexes and atomics
And the author has made a lot of fancy e-books: wizard zines
He wrote a book on programming language implementation in 6 years, with the spirit of craftsmanship: Crafting “Crafting Interpreters”
All the pictures here are drawn by hand, all details on font, color, alignment, etc., all these details are almost perfect, and the final book is an artwork. A technical book can be so beautiful!
The content involves development, personal growth, etc.
Among them, the concept of Learn In Public (swyx.io) touched me a lot, and there are many awesome podcasts on this blog.
BoostVision
has developed the best screen mirroring tools for Andriod and IOS, and their blog share alot of tricks for this feilds: 2 Tricks to Set Up a Roku Remote on Smart Phone
That all for today, if you like it please tell me, I actually have more to share with you. 🙌
See you!
]]>This time, we will build a small Web application for movie seat booking. After finishing, we will have a cute demo looks like this:
onMount
Because we need to keep the selected seat status after page refreshing, we need to use localStorage
to store selected seat indexes , then reloading them when page in reloaded. In Svelte
, we need to use onMount
to hook up a function to reload data:
|
The function populateUI
will do 3 things:
|
If we changed the selected movie, we need to update the price for a single movie , so another event hookup in HTML:
|
The function updateSelected
will update new selected movies count. Here, a tricky part is use css selector
to get elements:
|
How do we calculate the total price of movies? A nice feature comes from Svelte may help us reduce code complexity :
|
With this snippet, it means whenever count
and moviePrice
changed, total
will be updated accordingly , nice and simple!
That’s all, the whole code for this demo is at: sveltejs-apps (github.com)
]]>I will follow the project list of vanillawebprojects, try to re-implement the projects with Svelte.
I think this is a good way to practice front-end development skills.
Ok, let’s go to the Svelte Form Validator project.
It’s a simple form validator, which will be commonly used in registration UI.
Let’s create the project directory with the following command:
|
Access http://localhost:5000 will show the demo HTML page.
The basic structure of a Svelte component is like this:
|
Here, let’s begin with some JavaScript variables, which will be used in validation.
|
Then we will bind the variablesw in HTML elements with bind:value
attribute, and hook the handleSubmit
function to the on:click
event.
|
Compared with vanilla JavaScript, we don’t need to use getElementById
to get the HTML elements. The code will be shorter as well. The core logic to do validation is like this:
|
To make code shorter, we can use the required
attribute to avoid manual checking:
|
The refactor code commit is at this.
That’s all, the whole project is at : form-validator for your reference.
]]>Usually, you may copy the keyword from error message and search on Google, try to find some missing packages we need to install. But we have a better an unified solution, apt-file
is for fixing this kind of issue.
Let’s install apt-file
firstly with these command:
|
Then search the header file with it:
|
Ok, we get the package name we are missing, install it with apt-get
and problem will be solved.
|
Another useful command to list files installed by a DEB package:
|
ssh
session, here there are three ways to achieve this. I suggest to learn a terminal multiplexer in long term, it’s really useful when you have long time working on Linux/Unix system.nohup
The best and simplest way is:
|
It was made specifically for this, by default it will log stdout to nohup.log
, if standard output is not a terminal, logs will be appended to ~/nohup.log
. If you want to specify the output log into a different file:
|
More details can refer to man nohup
. What nohup
does, is to effectively separate the process from the terminal:
EOF
).nohup.out
, so the program won’t fail for writing to standard output if the terminal fails, so whatever the process writes is not lost.SIGHUP
(thus the name).If you already have started the program and don’t want restart it, we can use ctrl+z
to stop current execution and then use bg
to resume it and switch the running program to background (We can use fg
to pull the job to frontground)
Finally we use disown
to remove the process from the shell’s job control.
So, even you logout from a ssh
session, the program will still keep running in background.
|
We have three choices for this, [[screen]], [[tmux]], and [[byobu]].
screen
and tmux
is mostly used ones. On Ubuntu or Debian system, we install it with:
|
Byobu is an enhancement for the GNU Screen, you can install it with this commands:
|
From my user experience, tmux
will be enough for daily usage, if you would like to have a try, refer to this guide: Gentle Guide to Get Started With tmux | Pragmatic Pineapple 🍍
The fundamental building block of warp
is the Filter
, they can be combined and composed to express rich requirements on requests.
But it’s actually not easy to use if you are not familiar with it’s concept, and the type system will also scare some beginners.
For example, I actually spend some time to figure out how to use Cookie for authorization.
Suppose we have defined a Struct to represent the User:
|
And we have a logic to authorize whether the login request has a valid username and password, the detail implementation depends on your code:
|
The question is how to set a Cookie in response and how to verify each request after authorization.
When a user send login request and passed the authorization, we use reply
with with_header
to set a cookie to store a token, which will be used for later requests:
|
To authorize request, we need to implement a filter
in Warp, and use it like this, here we use Filter::untuple_one
to unroll nested tuple layers from extractions.
|
And the auth_validation
will call another built-in filter warp::cookie
to extract the token
from request header:
|
Even I have spent some time writing code in Rust, I still need to learn some new concepts or some details in a Web framework such as Warp. From my experience, there are some unnatural part for users who used to some other programming languages. For example, the return type of a filter:
|
It’s just not so easy to say what this mean? And why we need to call untuple_one
with the filter?
I know we must obey the rules of type system, and we need to add more annotations when writing Rust code, it’s just not so easy for learning as other programming languages.
Even so, I’m still having fun with it for it bringing some new things for programming.
]]>The reason is, I never found Front-end programming interesting. I thought front-end is only manipulate the HTML elements, and provides some styles for the UI of web. I found CSS is trivial and there is not logic behind the css code. We must remember a lot of stuff to write CSS. I don’t want to remember …
Until recently, I have done more work in front-end. My career don’t involve front-end much , but I have spent some time to learn it by myself. The motivation behind it is my side-project.
I finished several projects in my spare time, and got more interests on it. Here are some of my projects:
So, with about one year experiences of practice, I improved much on it. I found these rules for learning front-end as an experienced programmer. It also may help for beginners:
This is always my #1 role of learning programming.
I guess I still won’t have learned frontend programming without my side-project. I have some desire on my side-project, I tried to finish it with perfection in my mind.
Learning frontend is the extra credits of finishing my projects. So, if you don’t have much desire on learning frontend(or programming), maybe you need to find some thing which interested you, try to find those things attract you desire. For instance, if you want to develop a game, you may need to learn Game programming or something like C++ programming.
When you begin to get hands dirty with your keyboard, other things will follow.
If you don’t find any good project to start with, here are some learn-by-doing style of courses:
Learn to Code (freecodecamp.org)
It’s the best time for learning programming right now. Compared with 10 years ago, we have many many open-source projects to learn.
As as a beginner in front-end, I get much fun and interests when I played all the demo of this project: Mini projects built with HTML5, CSS & JavaScript..
I read the source code of each sub-project, and try to do some modification on them. After finish it, I learned a lot.
When you want to go deeper about front-end, there are actually a lot of theory stuff need to learn. For these essential knowledge, I would suggest you to learn by reading some classic books, such as:
There are many videos for learning Web development, it’s only helpful when you are starting without any experience. If you have got some learning experience, you should step out relay on watching those videos. Because almost none of them will teach you deeper skills and knowledges. Classic books and other authoritative materials will be helpful.
]]>Several days ago, I came across John Carmack’s post on learning programming. His advice is truly helpful for programming beginners and worth more reading.
This reminds me to spread other great quotes in mind, which from great programmers and computer scientists.
Some of them help me understanding more on computing, some of them are principles I’m trying to apply to my daily work, and some of them are funny 🙌.
Complexity is anything that makes software hard to understand or to modify.
-–John Ousterhout
All problems in computer science can be solved by another level of indirection.
– David Wheeler
The power of these statements can be seen in the domains of software development, design patterns, architecture and hardware design. The computing world is a combination of different abstraction layers, operating system, networking model, distribution system and graphic libraries are all abstractions, in different levels.
As software engineers, reduce the complexity of abstractions is our key task in development.
Simplicity is prerequisite for reliability.
– Edsger Dijkstra
Walking on water and developing software from a specification are easy if both are frozen.
– Edward V Berard
Design is the art of arranging code to work today, and be changeable forever.
-– Sandi Metz
There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
– C.A.R. Hoare.
The Dutch computer pioneer Dijkstra, had many profound insights on computing complexity and algorithms. He is possibly one of favorite computer scientist in world wide. One of his most cherished habits was in creating amazing articles with a fountain pen.
Simplicity doesn’t mean doing less; rather, it’s a way to keep your software maintainable.
When you start writing code, you tend to make it very complex. As you become an experienced programmer, you will find keeping things simple is the surest way to build complex systems.
The ability to make complex things simple is what sets apart a great programmer from an average one.
Make it work, make it right, make it fast.
– Kent Beck
When in doubt, use brute force.
——Ken Thompson
The sooner you start to code, the longer the program will take.
—— Roy Carlson
If you can’t write it down in English, you can’t code it.
—— Peter Halpern
Get your data structures correct first, and the rest of the program will write itself.
—— David Jones
Don’t write a new program if one already does moie or less what you want. And if you must write a program, use existing code to do as much of the work as possible.
—— Richard Hill
We better hurry up and start coding, there are going to be a lot of bugs to fix. 😏
– Anonymous
I’m always happy to follow these principles when programming. These advice helped me to save a lot of time. Remember, do the right thing at proper time. Make sure you have a good design before you start writing the code, otherwise you will most likely to rollback the finished work.
Before optimizing, use a profiler to locate the “hot spots” of the program.
—— Mike Morton
In non-I/O-bound programs, less than four per cent of a program generally accounts for more than half of its running time.
—— Don Knuth
Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.
Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified.
—— Don Knuth
Premature optimization means starting to optimize a program without “hot spot” tracing. You won’t fix performance issue and introduce bugs in this way of optimization.
Programs must be written for people to read, and only incidentally for machines to execute.
-– Hal Abelson and Gerald Sussman. Structure and Interpretation of Computer Programs
It’s harder to read code than to write it
– joel spolsky
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
– Martin Fowler
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
– Rick Osborne
Don’t comment bad code. Rewrite it.
– Brian Kernighan
Good code is its own best documentation. As you’re about to add a comment, ask yourself:
‘How can I improve the code so that this comment isn’t needed?’
– Steve McConnell (Code Complete)
If the code and the comments disagree, then both are probably wrong.
—— Norm Schryer
When explaining a command, or language feature, or hardware widget, first describe the problem it is designed to solve.
—— David Martin
Code is like humor. When you have to explain it, it’s bad.
-– Cory House
Do you have trouble in reading the code written by yourself two years ago?
A single piece of code will be read hundreds, maybe thousands of times, by different programmers.
Good programmers will write easy to understand the code, and don’t care whether the machine can run(this is compiler or interpreter’s job).
Comments will help much on making code readable. But too much of comments also will not help. If the code is self-explanatory, there is no need for comments. Even if you do need a comment, the comment should be about why you did it, not about what you did.
When writing code, it is better to be clear than to be clever. “Be cleaver” is something like: condensing multiple lines of code into one, using those tricky algorithms, or using some obscure feature of programming language to accomplish a task in a novel way. Tricky code will make it hard to maintain.
Testing can show the presence of bugs, but not their absence.
—— Edsger W. Dijkstra
If debugging is the process of removing bugs, programming must be the process of putting them in.
– Edsger Dijkstra
Testing leads to failure, and failure leads to understanding.
– Burt Rutan
It takes 3 times the effort to find and fix bugs in system test than when done by the developer. It takes 10 times the effort to find and fix bugs in the field than when done in system test. Therefore insist on unit tests by the developer.
– Larry Bernstein
There is no doubt on the importance of testing. I’m afraid to maintain a code base which don’t contains enough test cases. We should try to find bugs in development phase as many as possible.
Unit testing, integrated testing, fuzzing testing are all good practices to improve the coding quantity. From my experience, the testing code is also document for code, which helpful for others understanding code.
Embrace testing, it will save you much of time.
Of all my programming bugs, 80% are syntax errors. Of the remaining 20%, 80% are trivial logical errors. Of the remaining 4%, 80% are pointer errors. And the remaining 0.8% are hard.
—— Marc Donner
The first step in fixing a broken program is getting it to fail repeatably.
—— Tom Duff
Programming is like sex. One mistake and you have to support it for the rest of your life.
– Michael Sinz
Debugging is a last-ditch effort to save the code. Debugging code is more difficult than writing code. Because when we need to debug, it means the error have escaped from coding, reviewing, and testing.
Usually, finding out the root cause of a bug is much harder than fixing it. If you reproduced a bug, you almost finished 80% of work.
I’m a fan of Printf Debugging(a.k.a Caveman Debugging).
The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.
-— Brian Kernighan, “Unix for Beginners” (1979)
Debuggers don’t remove bugs. They only show them in slow motion.
– Anonymous
Don’t reapeat yourself. Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
– Andy Hunt and Dave Thomas
I’m not a great programmer; I’m just a good programmer with great habits.
– Kent Beck
Lazy programmers are good programmers, who want to do avoid duplication and won’t do thing reputably.
If there is a lot of repetition in the code, it is likely that we should spend time to refactor the code. Most repetitive tasks are better suited to be done by machines, so we should let it be automated.
The most disastrous thing that you can ever learn is your first programming language.
– Alan Kay
A language that doesn’t affect the way you think about programming is not worth knowing.
― Alan J. Perlis
Programming languages, editors, libraries, all are tools for programmers. Pick out the tools you will use frequently, we should know them well, polish them, and make them to be productive.
The only way to learn a new programming language is by writing programs in it.
– Dennis Ritchie
The first principle is that you must not fool yourself and you are the easiest person to fool.
―- Richard P. Feynman
Avoid “cookbook programming”, where you copy and paste bits of code that you have found to make something work. Make sure you fully understand what everything it actually doing, and that you are comfortable applying the techniques in other situations.
– John
Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter.
– Eric S. Raymond
Programming isn’t about what you know; it’s about what you can figure out.
– Chris Pine
Theory is when you know something, but it doesn’t work. Practice is when something works, but you don’t know why. Programmers combine theory and practice: Nothing works and they don’t know why.
– Anonymous
When I learned programming, I was also anxious about knowing the details, the programming language syntax, IDEs, frameworks, etc.
We have a ton to learn. This way of learning will make beginners frustrated.
Instead, don’t learn details, learn the essentials and concepts, apply them in practice. Problem-solving is the skill we end up using most. Finally, don’t lose your curiosity on your learning journey.
That’s all, hope you enjoy it and share with us your favorite programming quote.
]]>The hottest new tech of last week is Github Copilot. It seems like almost all programmers are playing or waiting to play with this new fancy AI coding assistant.
Some say this is an innovative game-changer that will totally change the world of programming!
But I am not so optimistic about it. From my perspective as an old-school programmer, this kind of tool looks fancy but is not as helpful as some people claim. Not to mention, it will be no substitute for real programmers.
Let me explain.
Think about it. How much time do you spend on coding?
In fact, in most software companies, the time we spend on writing code is not a high proportion of the overall software development cycle — even less than a quarter of it.
We spend much more time on requirements analysis, technical design, testing, debugging, and team collaboration.
Software engineering is hard, mostly because of the high complexity of the real world. We can’t change this — over time, abstractions in computing are inevitable. No project ever failed due to slow coding.
Coding faster will not make you a better programmer. Abstraction, design, and the experience of real-world engineering are what will make you a better software engineer.
Some older programmers type slowly due to poor eyesight, but they write bug-free code.
Years ago I was fascinated by this kind of programming aid. There’s a popular template system in Emacs called snippets. We define our own templates and functions, then a shortcut generates a code template and we just fill in the rest.
It looks cool, really cool. It makes me into a super programmer, like in the movies!
But, after I got deep into it, I realized it wasn’t as useful as I thought. Coding speed is not my bottleneck, and I spend less time on coding as my career develops.
tabnine is a similar AI programming assistant tool with Copilot, which generates part of the code based on your previous inputs. Copilot will even makes suggestions based on your comments, the name of the function, and so on.
The problem is, when I’m coding with it, I need to constantly review whether the auto-completion is right.
This is a distraction for me. Imagine you are an experienced and solid programmer — this AI tool that you are pair-coding with is a naïve and occasionally dumb one. No, I don’t want it!
From my experience, the best way to make me program faster is:
Shortcuts, variable completion, class attributes, and method names completion are all helpful for coding faster — they will help your typing catch up with thinking.
But code generation is a different thing. It will distract you, even more than 50% of the completion catches your coding intention, the other nonsense part will slow you down.
Of course, if the codebase contains a lot of repetitive pieces or logic, this kind of tool can definitely speed up your coding. For example, most front-end programming, and web programming contains lots of similar CRUD logic.
But I don’t believe this stuff will make a fundamental change to programming. And, at least for me, I won’t be coding faster with it.
Copilot will help to reduce duplicated tasks, like searching code from the Web. As a beginner to learn programming, it may help you, since when you type some keywords, the code snippet will show up in front of you.
However, let me remind you that copying and making it work is not a good way to improve your coding ability or quality of your work.
Instant code suggestions may make you happy when coding, but they will not help you in the long term.
Programming a craft, just like writing and painting. We are writing source code to express ideas. Do you think it’s a good idea to let an AI assist a learner in what the next sentence or paragraph will be?
Word completion will help, but sentence auto-completion will become a burden.
It’s the same as writing. If we want to be better at programming, the only way is to code and read a lot.
John Carmack, when talking about learning programming says:
Avoid “cookbook programming”, where you copy and paste bits of code that you have found to make something work. Make sure you fully understand what everything it actually doing, and that you are comfortable applying the techniques in other situations.
There are several extra risks come with AI coding assistance:
Potential bugs. If the user didn’t pay attention to review the generated code, it will be a nightmare.
The copyright and ownership issue of code. If a code snippet is generated from GPL authorized code base and is adapted by a commercial company. Whose fault is it if it does not work? And who is the owner when the code is generated?
Security. Is it possible for hackers to train some code snippets intensively and induce attacking code to users?
Of course, as a new thing, Copilot may also bring some benefits in some scenarios.
To make this tool more useful, we may trend towards writing more meaningful names and better documents.
Interviewing may be easier, if we are allowed to use it.
It may give you a feeling that someone is always there for you and you are not so alone when programming. Maybe it’s a better feeling than a little yellow duck!
When you begin to learn programming in Rust, your probably first frustration will be the compilation errors from the string.
Rust’s string design is somehow different from most programming languages that have a single string type. Both the Unicode-safe string design and unique ownership mechanism make string in Rust is somehow counterintuitive for beginners.
But, don’t freak out!
Actually, the string data structure is more complicated than most programmers give credit for. And Rust is focused on safety, the compiler will tell you the potential issues about string when you are coding. It’s better to keep safe in development phase, otherwise, you may be lost in debug night.
So, let’s have a bit dive into string in Rust.
In Rust, String
is simply a vector of u8
. We can find its definition in source code.
The String
type is provided by Rust’s standard library, it is a growable in size and heap-allocated, mutable, string type. When a String
variable goes out of scope, the buffer will be freed automatically.
|
We can create a String
in several ways:
|
Rust’s character and string types are designed around Unicode. String
is not a sequence of ASCII chars, instead, it is a sequence of Unicode characters. A Rust char
type is a 32-bit value holding a Unicode code. String
use UTF-8 to encode Unicode characters into a vec
|
And .len()
method will return the length measured in bytes, not in chars.
|
The most un-natural of string is indexing
related operation. For instance, you can not just use s[i]
to fetch the i-th
individual char from a string. Rust strings don’t support indexing?
Why?
Because UTF-8 is a variable-width encoding format, each ASCII character in a string is stored in one byte, while other characters may take up multiple bytes. So, in this format, index into the string’s bytes will not always correlate to a valid Unicode scalar value.
For a string which contains with ASCII character and non-ASCII character, the s[1]
means a invalid value.
Instead, we need to access chars with a iterator.
|
But, if you know your string is all ASCII chars, you may use the non-panicking version of get
and get_mut
to access or modify a part of string in O(1) time. get_mut
will return a &mut str
, but it still very restrictive, the only operations available on &mut str
are make_ascii_uppercase
and make_ascii_lowercase
, which modify the text in place and affect only single-byte characters.
|
If you want to more freedom to modify specific bytes in a String
, you need to convert it to a mut vec<u8>
:
|
Ok, we talked about much about String
right now. Just remember, strings in Rust are guaranteed to be valid UTF-8, and get more familiar with String
API if you are confused. UTF-8 Everywhere is a best reference for you to learn why Rust choose UTF-8 as encoding format for some good reasons.
str
, on the other hand, is a primitive type for compiler, it is also called string slice
. We usually use it in the borrowed form: &str
.
|
Essentially, the compiler treats it as a fat pointer
, which means: &str
is made up of two components: a pointer to some bytes, and a length.
We can use the method as_ptr()
to get pointer and len()
to get the length of it.
|
The relationship between String
and &str
is like std::string
and char*
in C++:
String
is like a std::string
, it owns the memory and does all the dirty job of managing memory.&str
is like a char*
(but with length), it points us to the beginning of a chunk with the contents of std::string
.Why &str
need to store the length, this is because we can use use &str
to pointer to specific part of a String
. Let’s have a example:
|
The corresponding diagram is like this:
There are two principles to follow:
Use String
when you need to own the memory. For example, you created a string in a function and need to return it.
Use &str
when you want an immutable reference to a String variable (or a string literal in your code).
Remember, Rust will follow move
for String
when you passing it as parameter to a function:
|
This program will report out this error message:
This is because v
is moved to the function func
and we can not read it in the scope of main anymore. The checker follow the rules of Rust ownership. Rust has this super powerful feature called deref coercing which allows it to turn any &String
to a &str
.
|
So, when you are designing a API which only need to access a string as read-only mode, &str
is the best choice.
But when you need to modify the content of a String
, you can not pass a &mut str
which you may think is reasonable. &mut str
does exists, but it is not very useful, because a slice cannot reallocate its referent. When you need to modify the content of a string, you need to pass &mut String
as parameter, like the above set_char_inplace
example.
In the scenario of struct
, in most cases, you need to own the string, so String
is almost a better choice compared with &str
. If you want to use &str
as a attribute in struct
, you need to handle the lifetime issue.
|
Except for above two kind of strings, Rust also provide other kinds of string-like types for special scenarios. Please check out the reference about them, and here are some general rules we can follow:
String
and &str
for Unicode text.std::path::PathBuf
and &Path instead.Vec<u8>
and &[u8]
instead.OsString
and &OsStr
.std::ffi::CString
and &CStr
.