• 开源镜像
  • 开源沙龙
  • 媛宝
  • 猿帅
  • 注册
  • 登录
  • 息壤开源生活方式平台
  • 加入我们

开源日报

  • 2018年10月23日:开源日报第229期

    23 10 月, 2018

    每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg


    今日推荐开源项目:《空手写 HTML 流,请指教 Sketch2Code》传送门:GitHub链接

    推荐理由:这是 Microsoft AI Lab 项目下的一个子项目,兴许你们可能见过图片转换为 HTML 的项目,这个项目把手写识别加入了进来,这就意味着可以手画的网页草稿也可以被转化成 HTML 代码了。除了这个之外他们还有其他七个项目,比如图片风格转换和对屏幕截图进行情报分析之类的项目,有兴趣的可以去了解一下。


    今日推荐英文原文:《I Didn’t Accept Job Offer at Facebook. Here’s Why.》作者:Wajahat Karim

    原文链接:https://hackernoon.com/i-didnt-accept-job-offer-at-facebook-here-s-why-fd6fce49a26b

    推荐理由:有的时候,工作并不是一切,被工作蒙蔽了双眼看不到工作外的东西并不算太好

    I Didn’t Accept Job Offer at Facebook. Here’s Why.

    You might think I am crazy. Maybe I am. Maybe I ain’t.

    “space gray iPhone 6 with Facebook log-in display near Social Media scrabble tiles” by William Iven on Unspla

    I woke up at around 5:30 AM in morning. I was feeling very sleepy as I slept late at night. But it was no time for laziness as I had to get ready for traveling. I made tea and ate some bread as quick breakfast, got shower, locked my home and called Uber. Uber took me to a bus stop where I booked a seat in a bus. The bus was late about 20 minutes, but I left Karachi — the city of lights — at 7:20 AM. It was 4–5 hour travel depending on the traffic, roads, and speed of the bus.

    Throughout whole journey, I was peeking outside window and watching trees go behind. But my mind wasn’t in that bus. It was somewhere else. I was lost in the thoughts of a decision I have made a day ago. A choice I have taken. I was thinking about it all the time. I was thinking that whether it was right thing to do or it was the right time for the decision or it was the right opportunity to pursue or it was right to say no to one of the largest company in the world.

    The hard part is not making the decisions. It is the living with those decisions.

    I wasn’t sure about my thoughts and feelings. Maybe I was a little guilty or maybe I couldn’t believe the opportunity which knocked my door or maybe this was all just a dream or maybe this wasn’t such a big deal which I was making it. But I was sure of one thing though that I already made a decision and now I had to live with it. And in that bus, I was thinking of how to make comfortable and remove guilt out of my mind.

    Image Credit: https://www.brainyquote.com/quotes/roy_e_disney_170949

    I reached to my hometown at about 11:00 AM. It was quick and I didn’t expected that too early to reach. I got in a rickshaw and traveled about 10 minutes more to reach my home. I knocked the door. My wife opened it. We greeted each other and smiled. I hadn’t come home for last 2 weeks. I sat in lounge. My wife brought me a glass of water. I was still looking around to find my father but he wasn’t there inside.

    After few minutes, he entered home and stepped inside. He was surprised to see me and we made this big lovely hug. And it was that awesome smile of my father seeing me at home in front of his eyes which made me forget all about that big decision I made and it removed all my guilt. Now I was all sure and confident that I made the right decision and some things are invaluable and can’t be materialized enough to compare with opportunities.


    The decision? What decision?

    “person in yellow coat standing on top of hill” by Justin Luebke on Unsplash

    But what was the decision which I am mentioning in this story over and over again?

    Well, as you read in the title of the story. It was about a job offer at Facebook. I feel very lucky and fortunate that Facebook has considered me for a job in their team. Due to some confidentiality, I cannot disclose the details such as role, responsibilities, location, salary, and perks etc. But what I can share you here is that I was very close to the job at Facebook.

    I feel very lucky and fortunate that Facebook has considered me for a job role in their team and the company.

    I am very grateful to Facebook and its recruiting team for this great opportunity and their consideration. As a developer, it’s really a great honor and prestigious moment that you can write code which will run on billion (not millions with m) users’ devices. And I feel sorry to say NO and not accepting the job. The decision has nothing to do with job, type, or anything like controversies surrounding Facebook for last few months.


    It was the decision all about choosing family over career and happiness over money. It was about that smile. It was that about moment. It was about that weekend with my family. It was about that time I spent sharing meals, jokes, thoughts, and TV shows with my family and father. It was about that walk with my father to the grave of my mother to meet her.

    If I had accepted the job at Facebook, I would have traveled half world and would be living in a rented apartment and trying to see my family and my father through a video call with low-speed internet. For me, these things are more important to me than my career, growth, and money. And before you say that I can take my father with me, then let me tell you that due to some medical circumstances it’s not possible. So choice is very clear to me. And I am very happy with it.

    When your values are clear to you, making decisions becomes easier. ~Roy E. Disney

    Are you insane? Are you crazy? Are you stupid? Why? Seriously man? You should go?

    These are the reactions I am getting from my circle when I tell them that I got a job at Facebook and I had to decline it. And before you judge me or misjudge me by thinking or saying these same reactions to realize me that who declines such kind of company and job offer, I believe that there are some things and some values which are more important to me than my career, money, growth etc. I only know that it’s the biggest opportunity I have ever gotten in my career and I never even imagined or dreamed about it. So saying no to it was one of the hardest and toughest decision of my life, which took me days to make it and then few more days to accept the fact that I did it.

    For many, getting a job at Facebook isn’t any big deal at all. But, for me, this is really huge and unimaginable. I am just an ordinary guy living in Karachi, Pakistan which is said to be the 4th most least livable country in whole world. And I love this city and country more than anything.


    How did I get the opportunity?

    For those, who are curious that how did I got this kind of huge opportunity? Ever since I have started doing open source contributions since last 7–8 months, I have been getting job opportunities all around the globe. It’s a good feeling to get international recognition of your work and being appreciated.

    100 Days Of Code in Open Source
    What I got in 100 days and what you can get from Open Source?android.jlelse.eu

    I would advice my colleagues, friends, and developers from my country, Pakistan, to do more and more open source work and avail these kinds of opportunities it possibly for them. I would be more than happy to help in anyway I can.


    Wajahat Karim is a graduate from NUST, Islamabad, an experienced mobile developer, an active open source contributor, and co-author of two books Learning Android Intents and Mastering Android Game Development with Unity. In his spare time, he likes to spend time with his family, do experiments on coding, loves to write about lots of things (mostly on blog and medium) and is passionate contributor to open source. In June 2018, one of his library became #1 on Github Trending. His libraries have about 2000 stars on Github and are being used in various apps by the developers all around the globe. Follow him on Twitter and Medium to get more updates about his work in Writing, Android and Open Source.

    Wajahat Karim (@WajahatKarim) | Twitter
    The latest Tweets from Wajahat Karim (@WajahatKarim). Android Developer. UI/UX Designer. Blogger. Writer…twitter.com

    Also, if you have any questions you’d like him to answer, contact him through his website at wajahatkarim.com with DEAR WAJAHAT in the subject line.


    每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg

  • 2018年10月22日:开源日报第228期

    22 10 月, 2018

    每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg


    今日推荐开源项目:《Java 设计模式 java-design-patterns》传送门:GitHub链接

    推荐理由:这个项目里收录了大量的 Java 程序设计模式,在阅读它们之前你可能需要了解一些诸如 YAGNI 之类的简单概念。这些设计模式下面都写有适用于哪些场景,根据这个来选择可能适合自己的来使用吧,如果事先没有做好计划就开始设计的话很容易让代码变得一团乱,应该想办法避免这种情况的发生。


    今日推荐英文原文:《11 Material Design UI Component Libraries for 2018》作者:Jonathan Saring

    原文链接:https://blog.bitsrc.io/11-material-design-ui-component-libraries-for-2018-b3d2c9962a2f

    推荐理由:React,Vue 和 Angular 上的 UI 组件介绍,不过文章开头提到的 Material Design 也是很值得一看的。这是一个设计系统,能够让你直接使用里面提供的组件或者是自定义它们中的一些参数;也可以说它是一种设计的规范,旨在为不同平台的用户提供统一的体验。

    11 Material Design UI Component Libraries for 2018

    Useful React, Vue and Angular UI component libraries built with Material Design.

    Google’s Material Design is a specification for a unified system of visual, motion, and interaction design that adapts across different devices.

    With the rise of React, Vue, Angular and Web components, Material Design becomes a popular way to style the building blocks of our application’s UI.

    To help you get started, we’ve gathered some of the finest UI component libraries in the open source community, implementing Material Design.

    Tip: using Bit components from any of these libraries can be easily shared, discovered and developed right from any project (!). It’s open source, so you can just give it a try and create a shared component collection for your team.

    Bit – Share and build with code components
    Bit helps you share, discover and use code components between projects and applications to build new features and…bitsrc.io

    Every component will be presented with a live UI playground, test and build results, auto-managed dependencies and can even be installed via NPM.

    A React Hero UI component made individually available with Bit

    1. React Material-UI

    A widely popular (40k stars) set of React components implementing Google’s Material Design. Perhaps the most popular UI component library on earth, MUI has 1000 contributors and provides an out-of-the-box framework to compose a React application using a well-crafted set of UI components.

    mui-org/material-ui
    React components that implement Google’s Material Design. – mui-org/material-uigithub.com

    2. React Toolbox

    React toolbox is a set of React components implementing Google’s Material Design with the power of CSS Modules. With over 8K stars and over 225 contributors, this library v2 is still under development and integrates into your bundler (webpack/other) workflow. Note that CSS-Modules is required.

    react-toolbox/react-toolbox
    A set of React components implementing Google’s Material Design specification with the power of CSS Modules …github.com

    3. React material-components-web

    A UI kit of Modular and customizable Material Design UI components for the web. Developed by a team at Google, it’s widely popular in the community with 11K stars and 300 contributors. Components are built to be production-ready consumable as individual packages (also perfect with Bit). The library even provides integration with other JS frameworks and libraries.

    material-components/material-components-web
    Modular and customizable Material Design UI components for the web – material-components/material-components-webgithub.com

    4. React MD

    A material design implementation in React with 2K stars and a set of fully accessible UI components and Sass files oriented for the web. The library comes with built-in customizable themes and a bunch of useful dev scripts. Here’s a useful example of kicking things off with webpack 2 configs.

    mlaursen/react-md
    React material design. Contribute to mlaursen/react-md development by creating an account on GitHub.github.com

    5. Vuetify

    A 14K stars Material UI component framework for Vue.js 2. It aims to provide clean, semantic and reusable cross-platform components, supporting all modern browsers, including IE11 and Safari 9+ (using polyfills). You can try the vue-cli Webpack SSR template to play with next-gen SEO websites.

    vuetifyjs/vuetify
    Material Component Framework for Vue.js 2. Contribute to vuetifyjs/vuetify development by creating an account on…github.com

    6. Vue Material

    At 7K stars Vue Material is a Simple, lightweight library built according to the Google Material Design specs to the pixel. The library’s components support all modern web browsers, and out-of-the-box themes are provided. There’s even a fully-featured webpack setup template. Take a look.

    vuematerial/vue-material
    Material design for Vue.js. Contribute to vuematerial/vue-material development by creating an account on GitHub.github.com

    7. Vue Keen-UI

    A lightweight collection of essential UI components written with Vue and inspired by Material Design, with 3.5K stars. Note that unlike others, the library doesn’t include a grid system, typography styles, etc. Instead, it focuses on interactive components that require Javascript. Here are the components.

    JosephusPaye/Keen-UI
    A lightweight collection of essential UI components written with Vue and inspired by Material Design …github.com

    8. Vue Muse UI

    At 7K stars this popular Vue.js UI components library implements Material Design guidelines. The library aims at developers building mobile applications and some desktop applications with strict requirements for browser compatibility. On top of components, built-in themes are included.

    museui/muse-ui
    Material Design UI library for Vuejs 2.0. Contribute to museui/muse-ui development by creating an account on GitHub.github.com

    9. Angular Material2

    Material2 is Google’s Angular (2+) and TypeScript implementation of Google’s Material Design. At 16K stars and with over 320 contributors, it’s the most popular NG component library on earth. It provides over 40 components and built-in themes, with cross-browser support. Here’s a live example.

    angular/material2
    Material Design components for Angular. Contribute to angular/material2 development by creating an account on GitHub.github.com

    10. AngularJS Material

    Also at 16K stars, this UI component library implements Material Design for AngularJS. it was built to deliver a lean, lightweight set of AngularJS-native UI elements that implement the material design specification for use in AngularJS single-page applications (SPAs). Note that using AngularJS Material requires the use of AngularJS 1.4.x or higher.

    angular/material
    Material design for AngularJS. Contribute to angular/material development by creating an account on GitHub.github.com

    11. Material-design-lite & Materlize

    At 30K stars, MDL is a set of useful Material Design Components in HTML/CSS/JS. Although on limited support, the project lets you add a Material Design look and feel to your static content websites. It doesn’t rely on any JavaScript frameworks or libraries and is cross-device optimized, gracefully degrades in older browsers, and offers an accessible experience.

    google/material-design-lite
    Material Design Components in HTML/CSS/JS. Contribute to google/material-design-lite development by creating an account…github.com

    At 35K stars Materialize is a A modern responsive front-end CSS framework based on Material Design. The project provides components and animations that provide feedback to users. Additionally, a single underlying responsive system across all platforms allow for a more unified user experience.

    Dogfalo/materialize
    Materialize, a CSS Framework based on Material Design – Dogfalo/materializegithub.com

    Honorable mentions

    Comment to add some more UI libraries built with Material Design! ✨


    Learn more

    11 React UI Component Libraries you Should Know in 2018
    11 React component libraries with great components for building your next app’s UI interface in 2018.blog.bitsrc.io
    5 Tools For Faster Development In React
    5 tools to speed the development of your React application, focusing on components.blog.bitsrc.io
    11 Vue UI Component Libraries You Should Know In 2018
    11 Vue.js component libraries tools and frameworks for your next app in 2018.blog.bitsrc.io

    每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg

  • 2018年10月21日:开源日报第227期

    21 10 月, 2018

    每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg


    今日推荐开源项目:《时间分析器 py-spy》传送门:GitHub链接

    推荐理由:这玩意可以让你不需要给你的 Python 程序做些手脚就能够分析出在程序中哪些部分最花时间,即使这个程序正在运行。每个部分消耗的时间和来源都会显示在命令行界面中,所以如果你发现某个地方特别慢,只需要看看是哪个函数出了问题然后顺藤摸瓜改过去就行了。如果你想要把这个记录下来,它也能给你生成一个 Flame Graph 用于保存记录。

    Flame Graph:Flame graphs are a visualization of profiled software, allowing the most frequent code-paths to be identified quickly and accurately. They can be generated using my open source programs on github.com/brendangregg/FlameGraph, which create interactive SVGs. See the Updates section for other implementations. Recently I’ve been helping with d3-flame-graph.


    今日推荐英文原文:《All You need to know about Git P1.》作者:David Hany

    原文链接:https://medium.com/@Galoomba/all-you-need-to-know-about-git-p-1-ac2f29e8ee93

    推荐理由:Git 是一个版本控制系统,这篇文章介绍了在 Git 中你要了解的地方,推荐刚刚接触 Git 的新手一读

    All You need to know about Git P1.

    What is Git!

    Git is a version control system. For example, if you have a file on which you’ve been working and reworking for a long time, all it’s versions are saved in Git, and you can easily get back to any version.

    Are there any other version control systems like Git ?

    Yes, There are many others like Mercurial, Apache Subversion (SVN) and Concurrent Versions System (CVS), But we will only talk about Git in this article.

    Why Git ?!

    There are many advantages to use Git with your project,Some of which are detailed in this link→https://www.git-tower.com/learn/git/ebook/en/command-line/appendix/why-git

    — →Git Download Link

    Now that we became sure about using Git, There are 2 keystones we have to know about before starting

    1-What is a repository?

    2-What is a commit?

    →What is a repository !

    Let’s say we have a recipe for the tastiest burger, but the Chef thinks he can improve it. So he starts to pick apart his recipe and changing some of the ingredients. When he tried his new and improved burger, it wasn’t that good and he no longer remembered the old recipe.

    This scenario was going to have a better ending if the Chef was familiar with Git. In another world with Git he could easily return to his old savoury recipe rather than the new terrible one in just a few steps.

    In information technology, a repository is a central place in which an aggregation of data is kept and maintained in an organized way, There are two scenarios for creating a repository and that will lead to the first two commands you should be familiar with.

    Making a Local repository

    After installing Git, It’s the time to start helping the chef make his first repo to save his recipes, To make a new repo all you have to do is to open your terminal, make a new directory and type the command git init.

    Now we have our repository, But it’s all empty and it’s the time to add some recipes to it.

    Let’s start by creating a new text file which will contain our beloved burger recipe (For vegans you can consider it a vegan burger if that will cheer you up). I’m using nano as my text editor but you can use the text editor you prefer

    After making the new text file and adding your recipe ingredients, You are ready to try the Second command which is git log to see if any changes occurred to your repo, And don’t be shocked if you find a message like this

    We could debug using the command git status

    It looks like our file is untraceable, which sets us up to discuss one of the core concepts of Git

    Staging is a step before the commit process in Git. let’s back to our chef. Do you think that he only has that single recipe!

    In most of the cases there will be more than one recipe he will have pasta, pizza, soup, and some vegan recipes

    In that case which of those recipes should be committed ?!
    That’s where the staging area plays. We have to add the files we want to commit to the the staging area first. And that where we get introduced to a new command where is git add.

    There are 2 ways to use this command the first is to use it like git add <file_name>to add specific files to the staging area. The second git add . which adds all the files to the staging area, In our case we will use it to add only 2 recipes for the moment, The Burger recipe and the Pizza recipe

    All seems to works fine, So let’s try git status again to see if there is any change

    Woohaa!, both of the files are now on the staging area and ready to be committed, Here is where the next command introduces itself, git commit and you can always use it this way git commit -m "<descriptive but short message about my commit>"

    Now we can check our commits by using command git log to check the commits history

    The hash above is the commit id you can refer to by the first 4 digits. each commit has a specific id you could return to any time you need, But we will delay that to the next article .

    Until now we’ve been creating a Git Repo, Adding files to it, chose which files we will need to commit and do our first commit, Next article we will make other commits learning how to move between them and getting familiar with Branches

    →Today’s Commands 
    git init Create an empty Git repository or reinitialize an existing one
    git log Show commit logs
    git status Show the working tree status
    git add Add file contents to the index “Staging Area”
    git commit Record changes to the repository


    每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg

  • 2018年10月20日:开源日报第226期

    20 10 月, 2018

    每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg


    今日推荐开源项目:《相信我你不可能把它们都看一遍 pwc》传送门:GitHub链接

    推荐理由:Paper with code,看项目名就知道这个项目里记录了相当数量的 Paper,每一个 Paper 的后面都附带上了代码(大部分以 GitHub 上的项目形式提供)。顺带一提,你可以在上面看到的不仅是最近的项目和 Paper,到目前为止你已经可以看到2014年的资料了,兴许等项目继续更新下去,我们就能看到十年前的 Paper 大部分关注点都放在了哪里。


    今日推荐英文原文:《Write Better Python Functions》作者:Jeff Knupp

    原文链接:https://hackernoon.com/write-better-python-functions-c3a9a36382a6

    推荐理由:什么是好的 Python 函数以及如何写出好的函数,实际上文中提到的好的函数的要点不仅仅适用于 Python,你会发现在任何时候它们中的大部分都能够派上用场。

    Write Better Python Functions

    In Python, like most modern programming languages, the function is a primary method of abstraction and encapsulation. You’ve probably written hundreds of functions in your time as a developer. But not all functions are created equal. And writing “bad” functions directly affects the readability and maintainability of your code. So what, then, is a “bad” function and, more importantly, what makes a “good” function?

    A Quick Refresher

    Math is lousy with functions, though we might not remember them, so let’s think back to everyone’s favorite topic: calculus. You may remember seeing formulas like the following f(x) = 2x + 3. This is a function, called f, that takes an argument x, and “returns” two times x + 3. While it may not look like the functions we’re used to in Python, this is directly analogous to the following code:

    Functions have long existed in math, but have far more power in computer science. With this power, though, comes various pitfalls. Let’s now discuss what makes a “good” function and warning signs of functions that may need some refactoring.

    Keys To A Good Function

    What differentiates a “good” Python function from a crappy one? You’d be surprised at how many definitions of “good” one can use. For our purposes, I’ll consider a Python function “good” if it can tick off most of the items on this checklist (some are not always possible):

    • Is sensibly named
    • Has a single responsibility
    • Includes a docstring
    • Returns a value
    • Is not longer than 50 lines
    • Is idempotent and, if possible, pure

    For many of you, this list may seem overly draconian. I promise you, though, if your functions follow these rules, your code will be so beautiful it will make unicorns weep. Below, I’ll devote a section to each of the items, then wrap things up with how they work in harmony to create “good” functions.

    Naming

    There’s a favorite saying of mine on the subject, often misatributed to Donald Knuth, but which actually came from Phil Karlton:

    There are only two hard things in Computer Science: cache invalidation and naming things. -- Phil Karlton

    As silly as it sounds, naming things well is difficult. Here’s an example of a “bad” function name:

    Now, I’ve seen bad names literally everywhere, but this example comes from Data Science (really, Machine Learning), where its practitioners typically write code in Jupyter notebooks and later try to turn those various cells into a comprehensible program.

    The first issue with the name of this function is its use of acronyms/abbreviations. Prefer full English words to abbreviations and non-universally known acronyms. The only reason one might abbreviate words is to save typing, but every modern editor has autocomplete, so you’ll only be typing that full name once. Abbreviations are an issue because they are often domain specific. In the code above, knn refers to “K-Nearest Neighbors”, and df refers to “DataFrame”, the ubiquitous pandas data structure. If another programmer not familiar with those acronyms is reading the code, almost nothing about the name will be comprehensible to her.

    There are two other minor gripes about this function’s name: the word “get” is extraneous. For most well-named functions, it will be clear that something is being returned from the function, and its name will reflect that. The from_df bit is also unnecessary. Either the function’s docstring or (if living on the edge) type annotation will describe the type of the parameter if it’s not already made clear by the parameter’s name.

    So how might we rename this function? Simple:

    def k_nearest_neighbors(dataframe):

    It is now clear even to the lay person what this function calculates, and the parameter’s name (dataframe) makes it clear what type of argument should be passed to it.

    Single Responsibility

    Straight from “Uncle” Bob Martin, the Single Responsibility Principle applies just as much to functions as it does classes and modules (Mr. Martin’s original targets). It states that (in our case) a function should have a single responsibility. That is, it should do one thing and only one thing. One great reason is that if every function only does one thing, there is only one reason ever to change it: if the way in which it does that thing must change. It also becomes clear when a function can be deleted: if, when making changes elsewhere, it becomes clear the function’s single responsibility is no longer needed, simply remove it.

    An example will help. Here’s a function that does more than one “thing”:

    This function does two things: it calculates a set of statistics about a list of numbers and prints them to STDOUT. The function is in violation of the rule that there should be only one reason to change a function. There are two obvious reasons this function would need to change: new or different statistics might need to be calculated or the format of the output might need to be changed. This function is better written as two separate functions: one which performs and returns the results of the calculations and another that takes those results and prints them. One dead giveaway that a function has multiple responsibilities is the word and in the functions name.

    This separation also allows for much easier testing of the function’s behavior and also allows the two parts to be separated not just into two functions in the same module, but possibly live in different modules altogether if appropriate. This, too, leads to cleaner testing and easier maintenance.

    Finding a function that only does two things is actually rare. Much more often, you’ll find functions that do many, many more things. Again, for readability and testability purposes, these jack-of-all-trade functions should be broken up into smaller functions that each encapsulate a single unit of work.

    Docstrings

    While everyone seems to be aware of PEP-8, defining the style guide for Python, far fewer seem to be aware of PEP-257, which does the same for docstrings. Rather than simply rehash the contents of PEP-257, feel free to read it at your leisure. The main takeaways, however, are:

    • Every function requires a docstring
    • Use proper grammar and punctuation; write in complete sentences
    • Begins with a one-sentence summary of what the function does
    • Uses prescriptive rather than descriptive language

    This is an easy one to tick off when writing functions. Just get in the habit of always writing docstrings, and try to write them before you write the code for the function. If you can’t write a clear docstring describing what the function will do, it’s a good indication you need to think more about why you’re writing the function in the first place.

    Return Values

    Functions can (and should) be thought of as little self-contained programs. They take some input in the form of parameters and return some result. Parameters are, of course, optional. Return values, however, are not optional, from a Python internals perspective. Even if you try to create a function that doesn’t return a value, you can’t. If a function would otherwise not return a value, the Python interpreter “forces it” to return None. Don’t believe me? Test out the following yourself:

    ❯ python3
    Python 3.7.0 (default, Jul 23 2018, 20:22:55)
    [Clang 9.1.0 (clang-902.0.39.2)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> def add(a, b):
    ...   print(a + b)
    ...
    >>> b = add(1, 2)
    3
    >>> b
    >>> b is None
    True

    You’ll see that the value of b really is None. So, even if you write a function with no return statement, it’s still going to return something. And it should return something. After all, it’s a little program, right. How useful are programs that produce no output, including whether or not they executed correctly? But most importantly, how would you test such a program?

    I’ll even go so far as to make the following statement: every function should return a useful value, even if only for testability purposes. Code that you write should be tested (that’s not up for debate). Just think of how gnarly testing the add function above would be (hint: you’d have to redirect I/O and things go south from there quickly). Also, returning a value allows for method chaining, a concept that allows us to write code like this:

    with open('foo.txt', 'r') as input_file:
        for line in input_file:
            if line.strip().lower().endswith('cat'):
                # ... do something useful with these lines

    The line if line.strip().lower().endswith('cat'): works because each of the string methods (strip(), lower(), endswith()) return a string as the result of calling the function.

    Here are some common reasons people give when asked why a given function they wrote doesn’t return a value:

    “All it does is [some I/O related thing like saving a value to a database]. I can’t return anything useful.”

    I disagree. The function can return True if the operation completed successfully.

    “We modify one of the parameters in place, using it like a reference parameter.”””

    Two points, here. First, do your best to avoid this practice. For others, providing something as an argument to your function only to find that it has been changed can be surprising in the best case and downright dangerous in the worst. Instead, much like the string methods, prefer returning a new instance of the parameter with the changes applied to it. Even when this isn’t feasible because making a copy of some parameter is prohibitively expensive, you can still fall back to the old “Return True if the operation completed successfully” suggestion.

    “I need to return multiple values. There is no single value I could return that would make sense.”

    This is a bit of a straw-man argument, but I have heard it. The answer, of course, is to do exactly what the author wanted to do but didn’t know how to do: use a tuple to return more than one value.

    And perhaps the most compelling argument for always returning a useful value is that callers are always free to ignore them. In short, returning a value from a function is almost certainly a good idea and very unlikely to break anything, even in existing code bases.

    Function Length

    I’ve said a number of times that I’m pretty dumb. I can only hold about 3 things in my head at once. If you make me read a 200 line function and ask what it does, my eyes are likely to glaze over after about 10 seconds. The length of a function directly affects readability and, thus, maintainability. So keep your functions short. 50 lines is a totally arbitrary number that seemed reasonable to me. Most functions you write will (hopefully) be quite a bit shorter.

    If a function is following the Single Responsibility Principle, it is likely to be quite short. If it is pure or idempotent (discussed below), it is also likely to be short. These ideas all work in concert together to produce good, clean code.

    So what do you do if a function is too long? REFACTOR! Refactoring is something you probably do all the time, even if the term isn’t familiar to you. It simply means changing a program’s structure without changing its behavior. So extracting a few lines of code from a long function and turning them into a function of their own is a type of refactoring. It’s also happens to be the fastest and most common way to shorten a long function in a productive way. And since you’re giving all those new functions appropriate names, the resulting code reads much more easily. I could write a whole book on refactoring (in fact it’s been done many times) and won’t go into specifics here. Just know that if you have a function that’s too long, the way to fix it is through refactoring.

    Idempotency and Functional Purity

    The title of this subsection may sound a bit intimidating, but the concepts are simple. An idempotent function always returns the same value given the same set of arguments, regardless of how many times it is called. The result does not depend on non-local variables, the mutability of arguments, or data from any I/O streams. The following add_three(number) function is idempotent:

    def add_three(number):
        """Return *number* + 3."""
        return number + 3

    No matter how many times one calls add_three(7), the answer will always be 10. Here’s a different take on the function that is not idempotent:

    def add_three():
        """Return 3 + the number entered by the user."""
        number = int(input('Enter a number: '))
        return number + 3

    This admittedly contrived example is not idempotent because the return value of the function depends on I/O, namely the number entered by the user. It’s clearly not true that every call to add_three() will return the same value. If it is called twice, the user could enter 3 the first time and 7 the second, making the call to add_three() return 6 and 10, respectively.

    A real-world example of idempotency is hitting the “up” button in front of an elevator. The first time it’s pushed, the elevator is “notified” that you want to go up. Because the pressing the button is idempotent, pressing it over and over again is harmless. The result is always the same.

    Why is idempotency important?

    Testability and maintainability. Idempotent functions are easy to test because they are guaranteed to always return the same result when called with the same arguments. Testing is simply a matter of checking that the value returned by various different calls to the function return the expected value. What’s more, these tests will be fast, an important and often overlooked issue in Unit Testing. And refactoring when dealing with idempotent functions is a breeze. No matter how you change your code outside the function, the result of calling it with the same arguments will always be the same.

    What is a “pure” function?

    In functional programming, a function is considered pure if it is both idempotent and has no observable side effects. Remember, a function is idempotent if it always returns the same value for a given set of arguments. Nothing external to the function can be used to compute that value. However, that doesn’t mean the function can’t affect things like non-local variables or I/O streams. For example, if the idempotent version of add_three(number) above printed the result before returning it, it is still considered idempotent because while it accessed an I/O stream, that access had no bearing on the value returned from the function. The call to print() is simply a side effect: some interaction with the rest of the program or the system itself aside from returning a value.

    Let’s take our add_three(number) example one step further. We can write the following snippet of code to determine how many times add_three(number) was called:

    add_three_calls = 0
    
    def add_three(number):
        """Return *number* + 3."""
        global add_three_calls
        print(f'Returning {number + 3}')
        add_three_calls += 1
        return number + 3
    
    def num_calls():
        """Return the number of times *add_three* was called."""
        return add_three_calls

    We’re now printing to the console (a side effect) and modifying a non-local variable (another side effect), but since neither of these affect the value returned by the function, it is still idempotent.

    A pure function has no side effects. Not only does it not use any “outside data” to compute its value, it has no interaction with the rest of the system/program other than computing and returning said value. Thus while our new add_three(number) definition is still idempotent, it is no longer pure.

    Pure functions do not have logging statements or print() calls. They do not make use of database or internet connections. They don’t access or modify non-local variables. And they don’t call any other non-pure functions.

    In short, they are incapable of what Einstein called “spooky action at a distance” (in a Computer Science setting). They don’t modify the rest of the program or system in any way. In imperative programming (the kind you’re doing when you write Python code), they are the safest functions of all. They are eminently testable and maintainable and, even more so than mere idempotent functions, testing them is guaranteed to basically be as fast as executing them. And the test(s) itself is simple: there are no database connections or other external resources to mock, no setup code required, and nothing to clean up afterwards.

    To be clear, idempotency and purity are aspirational, not required. That is, we’d love to only write pure or idempotent functions because of the benefits mentioned, but that isn’t always possible. The key, though, is that we naturally begin to arrange our code to isolate side effects and external dependencies. This has the effect of making every line of code we write easier to test, even if we’re not always writing pure or idempotent functions.

    Summing Up

    So that’s it. The secret to writing good functions is not a secret at all. It just involves following a number of established best-practices and rules-of-thumb. I hope you found this article helpful. Now go forth and tell your friends! Let’s all agree to just always write great code in all cases :). Or at least do our best not to put more “bad” code into the world. I’d be able to live with that…

    Posted on Oct 11, 2018 by Jeff Knupp


    每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg

←上一页
1 … 202 203 204 205 206 … 262
下一页→

Proudly powered by WordPress