Thursday, 5 November 2020

Liskov Substitution Principle

 

Liskov Substitution Principle

The Liskov Substitution Principle is one of the SOLID principles of object-oriented programming (Single responsibilityOpen-closed, Liskov Substitution, Interface Segregation and Dependency Inversion). We have already written about the single responsibility principle, and these five principles combined are used to make object-oriented code more readable, maintainable and easier to upgrade and modify.

Liskov Substitution Principle states the following: “in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., objects of type S may substitute objects of type T) without altering any of the desirable properties of that program (correctness, task performed, etc.)”. Simply said, any object of some class in an object-oriented program can be replaced by an object of a child class. In order to understand this principle better, we’ll make a small digression to briefly remind ourselves about the concept of inheritance and its properties, as well as subtyping, a form of polymorphism.

Inheritance, Polymorphism, Subtyping

Inheritance is a concept fairly simple to understand. It is when an object or a class are based on another object or class. When a class is “inherited” from another class, it means that the inherited class (also called subclass, or child class) contains all the characteristics of the superclass (parent class), but can also contain new properties. Let’s illustrate this with a common example: if you have a class Watch , you can inherit from that class to get a class PocketWatch . A pocket watch is still a watch, it just has some additional features. Another example would be a class called Woman with a child class called Mother. A mother is still a woman, with the addition of having a child.

This brings us to the next term we should explain, which is called polymorphism: objects can behave in one way in a certain situation, and in another way in some other situation. In object-oriented programming, this is called context-dependent behavior. To use the last example: a mother, when taking a walk with her child or attending a school parent’s meeting, will behave as a mother. But when she is out with her friends, at work, or simply doing errands, she will behave as a woman. (As you can see, this difference is not that strict.)

Subtyping is a concept that is not identical to polymorphism. However, the two are so tightly connected and fused together in common languages like C++, Java and C#, that the difference between them is practically non-existent. We will still give a formal definition of subtyping though for the sake of completeness. But the details will not be discussed in this article. “In programming language theory, subtyping (also subtype polymorphism or inclusion polymorphism) is a form of type polymorphism in which a subtype is a datatype that is related to another datatype (the supertype) by some notion of substitutability, meaning that program elements, typically subroutines or functions, written to operate on elements of the supertype can also operate on elements of the subtype. If S is a subtype of T, the subtyping relation is often written S <: T, to mean that any term of type S can be safely used in a context where a term of type T is expected.”

This brings us to the original theme of the article – the Liskov Substitution Principle.

Liskov Substitution Principle Examples

The Liskov substitution principle, written by Barbara Liskov in 1988, states that functions that reference base classes must be able to use objects of derived (child) classes without knowing it. It’s important for a programmer to notice that, unlike some other Gang of Four principles, whose breaking might result in bad, but working code, the violation of this principle will most likely lead to buggy or difficult to maintain code.

LiskovSubtitutionPrinciple_Simon

Let’s illustrate this in Java:

  1. class TrasportationDevice
  2. {
  3. String name;
  4. String getName() { ... }
  5. void setName(String n) { ... }
  6. double speed;
  7. double getSpeed() { ... }
  8. void setSpeed(double d) { ... }
  9. Engine engine;
  10. Engine getEngine() { ... }
  11. void setEngine(Engine e) { ... }
  12. void startEngine() { ... }
  13. }
  1. class Car extends TransportationDevice
  2. {
  3. @Override
  4. void startEngine() { ... }
  5. }

There is no problem here, right? A car is definitely a transportation device, and here we can see that it overrides the startEngine()  method of its superclass.

Let’s add another transportation device:

  1. class Bicycle extends TransportationDevice
  2. {
  3. @Override
  4. void startEngine() /*problem!*/
  5. }

Everything isn’t going as planned now! Yes, a bicycle is a transportation device, however, it does not have an engine and hence, the method startEngine() cannot be implemented. l

These are the kinds of problems that violation of Liskov Substitution Principle leads to, and they can most usually be recognized by a method that does nothing, or even can’t be implemented.

The solution to these problems is a correct inheritance hierarchy, and in our case we would solve the problem by differentiating classes of transportation devices with and without engines. Even though a bicycle is a transportation device, it doesn’t have an engine. In this example our definition of transportation device is wrong. It should not have an engine.

We can refactor our TransportationDevice  class as follows:

  1. class TrasportationDevice
  2. {
  3. String name;
  4. String getName() { ... }
  5. void setName(String n) { ... }
  6. double speed;
  7. double getSpeed() { ... }
  8. void setSpeed(double d) { ... }
  9. }

Now we can extend TransportationDevice  for non-motorized devices.

  1. class DevicesWithoutEngines extends TransportationDevice
  2. {
  3. void startMoving() { ... }
  4. }

And extend TransportationDevice  for motorized devices. Here is is more appropriate to add the Engine  object.

  1. class DevicesWithEngines extends TransportationDevice
  2. {
  3. Engine engine;
  4. Engine getEngine() { ... }
  5. void setEngine(Engine e) { ... }
  6. void startEngine() { ... }
  7. }

Thus our Car  class becomes more specialized, while adhering to the Liskov Substitution Principle.

  1. class Car extends DevicesWithEngines
  2. {
  3. @Override
  4. void startEngine() { ... }
  5. }

And our Bicycle  class is also in compliance with the Liskov Substitution Principle.

  1. class Bicycle extends DevicesWithoutEngines
  2. {
  3. @Override
  4. void startMoving() { ... }
  5. }

Conclusion

Object Oriented languages such as Java are very powerful and offer you as a developer a tremendous amount of flexibility. You can misuse or abuse any language. In the Polymorphism post I explained the ‘Is-A’ test. If you’re writing objects which extend classes, but fails the ‘Is-A’ test, you’re likely violating the Liskov Substitution Principle.

Sunday, 13 September 2020

适配器模式(使用场景、比较、优点)

 适配器模式:让我们先模拟一下适配器模式的真实使用场景:一家互联网金融公司A,开发了一套股票交易系统,其包含客户端和服务器,用户登录接口是由客户端和服务器端自主协商的,目前这套系统已投入生产并稳定运行。某天,公司A接到一家证券公司的项目,需要把这套系统部署在这个证券公司中。此外,此证券公司还同时使用了公司B的客户端,因此,公司B的客户端需与公司A的服务器端相接。但公司B客户端的用户信息与公司a系统定义的类型不符,这时,该怎么办呢?

有三种解决方案。一,修改服务器的接口,以适应其他客户端的用户类型。二,增加接口,以处理另一个客户端的用户类型。三,在服务端执行用户处理接口前,调用一个方法,把其他客户端的用户类型转换成原本的用户类型。
方案一的缺点是他会修改到已经在生产环境上稳定运行的接口,影响系统的稳定性,且需要进行回归测试。方案二的缺点是,新增加的接口的业务逻辑会与原来的接口有所重复。而方案三即是适配器模式,它不仅有效地解决了问题,同时避免了前两种方案的弊端。
什么时候需要用适配器模式?只要记住一点。当你有动机修改一个已经投入生产的接口,这时候就可以考虑试用适配器模式。适配器模式是用于解决接口不兼容问题有效方法。


作者:我是电饭煲
链接:https://www.jianshu.com/p/53a19f5cb826
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Saturday, 12 September 2020

How to Impress in a Junior Developer Job Interview

 This article will go through tips on how to ace a junior developer job interview and is written by Natasha Postolovski, a Graduate Software Developer at ThoughtWorks. You can follow her on Twitter: @npostolovski.


The Junior Developer job interview process can seem a little bit scary. For some Junior devs, this might be their first job interview… ever. For others, it may not be their first job interview, but possibly their first software development interview. You might have read horror stories about having to solve really hard computer science problems at a whiteboard, or even over the phone. This may be true of the most competitive companies like Google and Facebook, but for 99% of Junior developer roles, the interview process is more about demonstrating a passion for technology and a great attitude than it is about flexing your technical muscles.

If you love to code and have a solid grasp of the fundamentals, then it’s time for your first Junior developer interview!


Want to ace your technical interview? Schedule a Technical Interview Practice Session with an expert now!


The Interview Sequence

Junior developers will often proceed through multiple rounds of interviews. This will usually start with a phone or email conversation, and then through the following rounds, though not necessarily in this order:

  • Coding Challenge
  • Cultural Interview/Initial Conversation
  • Code Challenge Review
  • Technical Interview

Some companies merge these interviews together, while others might split them over multiple interviews.

It can be daunting to approach an interview process when you don’t quite know what to expect. Luckily, there are ways to be prepared.

Come Armed With Knowledge

Sites like Glassdoor allow you to gain a peek inside the interview process. Candidates, both successful and unsuccessful, can use the site to post feedback about their interview experience. Reading through the interview feedback for the company you’re applying to can help you gain an understanding of the interview sequence. You may be able to learn what kinds of interviews you’ll go through, and roughly how they will be structured. The point is not to ‘cheat’ and try to preempt interview questions, but simply to get a broad-strokes picture of what the interview process is like. If you know that the interview process involves a stretch of problem solving at the whiteboard, for example, you can practice this kind of interview with a friend or mentor in advance.

If people do share details of specific questions asked or challenges given, it’s best to prepare for similar kinds of problems and questions, but not to focus on that specific example. Different interviewers like to ask different questions, and companies regularly refresh the challenges given to prospective employees. How you approach and work through a problem is often more important than getting to a particular solution, and memorizing answers will harm rather than help with this.

Lastly, your point of contact at the company should be willing to give you a run-down of the different stages of the interview process. However, I’ve found that while they are usually willing to tell you the type of interview you’ll be doing, they’ll be cagey about the kinds of things you’ll be asked to do. This is why online research is so invaluable. When it comes to interviewing, knowledge really is power.

The Cultural Interview or Initial Conversation

This interview will feel most like a conversation. It may happen near the start of the interview process, or later on, once your technical potential has been established. The interviewer is trying to answer a few basic questions about you:

  • Would you work well inside the existing team?
  • Are you a nice person? Are you likeable?
  • Do you seem to be passionate about technology?
  • Do you seem smart?
  • Can you communicate?

The interviewer can’t ask you these questions directly, so they will ask proxy questions to try to discover the answers about you. A few of the most common questions I’ve encountered are:

  • What kind of technologies are you excited to learn more about?
  • Can you tell us about a cool project you completed recently?
  • What is your favourite programming language?

All of these are proxy questions. In truth, the interviewer is trying to figure out whether you truly care about technology. As a Junior developer, the extent to which you are curious about and excited by technology is a good predictor of your rate of skill growth over time. Interviewers will, in general, be more concerned with where they can see you in a year or two than your skills right now.

It’s important to come to a cultural interview with some ideas on how you would answer these questions. Be friendly, curious, and conversational. Do a little bit of research about the company before-hand, but also ask the interviewers questions to broaden your understanding.

Another question you should be prepared to answer is: why us? Interviewers want to know that there is something specific that drew you to their company, whether it is an ambitious mission, cool technology, or a great team. “I need a job and you were hiring” isn’t a very compelling reason… even if it’s true!

The Coding Challenge

Coding Challenges are a very common stage in Junior developer interviews. Some will involve coming up with the appropriate algorithm to solve a problem, others will focus more on object-oriented concepts and designing a system. Either way, there are a few really simple things you can do to leapfrog 90% of applicants. I’ve reviewed a bunch of coding challenges, and here are a few things that stand out when applicants include them.

  • A comprehensive README. Include instructions for how to get your program running, and don’t make any assumptions about the system the reviewer will be running your program on. Try running your program from scratch guided only by your README. Then try it on a friend’s computer, preferably running a different OS! Lastly, a README is a fantastic place to share your thinking around your program. Address any limitations, and talk about how you would improve or extend upon your program if you had more time.
  • Automated tests. Few Junior developers include automated tests with their coding challenge. It is so rare that it can instantly catapult you into consideration for the next round. If you don’t know how to write unit tests, here’s a guide to learning unit testing with Rails.
  • Separation of concerns. Your program should not be entirely contained in one file. Separate the different parts of your program into classes or modules that have one responsibility. A good tip is this: try to describe what a particular class or module does. If your description involves the word ‘and’, it may be a good candidate to split out into smaller components.
  • Write small methods/functions that describe what they do. Variable names should describe what the variable contains. Functions/method names should describe what the code within them does. And remember, you don’t win any points for short names, and unless you’re working with algebraic equations, single letter variable names should be avoided at all costs. Really well-named classes, functions/methods, and variables make comments unnecessary. Lastly, split large methods into smaller ones using the extract method refactoring technique. It will make your code much easier to read.
  • Don’t gold-plate until your coding challenge is done. I often review coding challenge solutions that fail to pass with the provided test input, or just barely work, because the programmer sank a lot of time into trying to add unnecessary flexibility or extra features into the program before the base problem was solved. It’s clear that they ran out of time, half-finished the extra functionality, and slapped the program together just before the deadline. It’s much smarter to solve the problem at hand in the simplest way possible, then improve or extend on your solution if there is still time to do so. Sidenote: this is a good rule of thumb for software projects in general.

The Coding Challenge Review

It’s increasingly common for companies to call you in to review your coding challenge submission in person. This will almost always involve feedback, and may feel like the interviewer is trying to challenge your technical skills. However, for most Junior coding challenge reviews, the interviewer is trying to figure out something very important: how do you take constructive criticism? As a Junior developer working in a team, you’re expected to occasionally make mistakes, and to receive constructive criticism on your work. In general, it’s fine to make mistakes and take the wrong approach now and again, as long as you respond positively and are open to the feedback.

Here are the most important things to remember when an interviewer is giving feedback on your coding challenge:

  • Listen to the feedback. As a Junior developer, this is a fantastic opportunity to get great feedback from a (likely) more senior developer. Enjoy the learning opportunity!
  • Don’t get defensive. Even if you don’t agree, try to see things from the other person’s perspective.
  • Reflect aloud on what it would look like if you implemented the feedback. Restating the feedback in your own words helps the interviewer see that you are practicing active listening and taking the feedback on board.
  • Ask questions to deepen your understanding. If you agree with the feedback, this is a great way to gain a deeper understanding of why it could make your program better, and how you might implement it. If you disagree, it will help you to understand the interviewer’s perspective better, and to make a more informed decision about whether to adjust your habits, or chalk this one up to a matter of personal preference.

As part of a code review interview, you might also be asked to extend upon or refactor your program. For this reason, make sure to re-familiarize yourself with the program and the code you’ve written before you go into the interview. You may be asked to explain why you made a particular choice, or how a certain algorithm works. You want to have a better answer than “I don’t know” or “I don’t remember”.

The Technical Interview

This interview will usually consist of questions about technology, questions about your experience, and most likely, a session at the whiteboard.

Whiteboard coding interviews are polarizing in the developer community. Some people think the ability to hash out a problem at a whiteboard is a critical skill that all developers must possess. Others feel like the nerve-wracking circumstances are setting up less confident developers to fail. Like it or loathe it, problem-solving at the whiteboard is a recurring feature of most software development interviews.

Most interview processes will involve whiteboarding the main concepts or classes in a system, either a hypothetical system, or one you’ve designed in the past. It’s worth learning on how to draw UML diagrams prior to the interview, but don’t get caught up on the details. It’s more important that you come up with a good design at a high level than get caught up fretting about whether an attribute should be an int or a bigint.

Questions may be something like:

  • Draw the main classes and functions/methods in a Scrabble.
  • How would you design a database for a blog?
  • If you had to build a Twitter clone, how would you design the program?

It’s a good idea to practice these kinds of questions on a piece of paper or with a friend prior to the interview. As a starting point, try to think about the nouns and verbs involved in your system. These can often be broken out into classes and functions/methods respectively.

Another common aspect of the whiteboard technical interview is being asked to write an algorithm to solve a problem. I’ve found that sorting problems are very common in Junior developer interviews, for example:

  • Write code to sort a given array from smallest number to largest number, without using any convenience methods (i.e. #sort in Ruby)
  • How would you reverse a given word without using any convenience methods (i.e. #reverse in Ruby).

These kinds of challenges can be tough, as we’re much more likely to use our favourite language’s convenience method for tackling such problems, rather than writing a solution from scratch. For this reason it’s important to spend time practicing these kinds of problems. Get familiar with using loops and conditionals in your programming language of choice, as they’re likely to be a key part of any algorithm you will be asked to write. You can practice solving these kinds of programming problems at a site like CodeWars.

Remember, though, that solving problems at a whiteboard and solving problems in your favorite text editor or Terminal shell are two different beasts. It’s important to practice coding at a whiteboard. If you don’t have a whiteboard handy, a piece of paper will suffice. Ideally, have a friend give you a problem to solve that you’re unprepared for in advance, then have them act as an interviewer as you try to solve the problem. This will help you to be calmer in the actual interview.

When the interviewer gives you your whiteboard challenge, it’s incredibly tempting to start drawing on the whiteboard immediately. Instead, pause, and use your first few strokes with the whiteboard pen to write down the problem. Clarify your understanding of the problem as you do so, and ask the interviewer questions to clear up any ambiguity.

You will usually have the option to write pseudocode (sentences that describe what code should do), or real, syntactically correct code. Trying to do a hybrid of both will just seem to the interviewer like sloppy code, so pick one approach and stick with it. It can be a good idea to start with pseudocode and then rewrite your solution as code once you’re confident in your solution.

Remember, you don’t need to come up with a perfect solution. At a Junior developer level, it’s more important for an interviewer to see that you can think through a problem, and communicate as you do so. Think aloud if possible, and if you need some time to stand and think, let the interviewers know. It’s perfectly fine to say “I’m just going to take a minute or so to think about this.” If it starts to get awkward, you can always say “Sorry, just another 30 seconds.” Long periods of silence are fine, as long as the interviewers know that you’re working on the problem, and not just totally stuck. Remember, if in doubt, just keep talking! Let the interviewers know that you are working hard on the problem, not staring at the whiteboard and hoping for a miracle.

If you’re struggling, the interviewer will often drop small hints to point you in the right direction. Listen to these, and run with them. The interviewer is throwing you a life-line. It won’t be seen as a failure to listen to and use what the interviewer is saying. However, if you ignore their help and keep focusing on your own thoughts or frustration, it might be.

I struggle most with this part of the interview process. Every time I’ve had to do a coding challenge at a whiteboard, I’ve felt that I failed miserably: either I didn’t come up with a solution in time, or struggled too much while getting there. And yet, each time, I’ve progressed to the next stage in the interview process. It’s important to remember that these challenges are designed to stretch you, to stump you, and even frustrate you. If you can stay calm, keep communicating, and gradually get to a solution — even if you receive a helpful nudge along the way—you’re doing just fine.

Remember: You’re Interviewing Them Too!

If you have the luxury of interviewing at multiple companies, it’s worth taking the time to make sure that your prospective employer provides a supportive environment for Junior developers. Here are some questions that can help you learn more about your prospective company. As an additional benefit, these questions show that you care about your career and your development, which isn’t a bad thing!

  • How do developers on the team give each other feedback about their code? In my opinion, an environment where Junior developers are mostly pairing is excellent for learning. If the team doesn’t pair, developers should do regular code review, either through GitHub pull requests, or planned code review sessions. You won’t improve quickly unless you can regularly write code with others, see the code that others are writing, or get feedback on your code.
  • How often does the team do pair programming? As a Junior developer, ‘most of the time’ is ideal, but ‘sometimes’ is the norm at many companies.
  • What do you expect from a Junior developer? Answers based around learning, growing and curiosity are ideal. Answers around work hours, workload, bug fixing and increasing test coverage are not so ideal.

Go Forth and Conquer

Having participated in several Junior developer interviews, and more recently having been involved in them as an interviewer, I believe that following these tips will put you in the top 10% of Junior developer interviewees at many companies. Research, practice and preparation will give you a meaningful advantage against other candidates, and more importantly, the freedom to give the interview process your best effort.

Good luck, and go get hired!

The source :
https://www.codementor.io/learn-programming/junior-developer-interview-tips-to-success