A building block of software and wise
Over the years, many industry giants have made different metaphors for software building. Although you may not know them, you may not want to understand the heroic poems of these giants, but you should understand their views on software building. After all, they are senior players in this game. I don't want to discuss the rationality of these metaphors. I just want the following metaphor to help you rethink software building activities.
WritingThis metaphor implies that the software development process is a costly trial and error process focusing on code writing, rather than careful planning and design.
FarmingThis metaphor implies that the software is just like farming. Every time you only process a small part of it, 1.1 points are added to the entire system, so that the system "grows" at 1.1 points ". It also implies that work should be performed step by step. Just like the spring Harvest, each link has a strong logic.
House BuildingThis metaphor illustrates the importance of planning and design in building activities. It also implies that the cost of fixing defects at the beginning of the software is much lower than the cost of fixing defects at the later stage.
Tar PitThe first chapter of the classic book "man-month myth" mentioned: "The development of large systems is like a tar pit where many large and strong animals are struggling, most of them have developed a running system-but only a few projects meet the requirements for goals, schedules, and budgets."
Whether or not you agree with the above ideas, they have indeed affected some people in a certain period of time. I want to understand software building from the perspective of a programmer. I think the software building process is like playing with Lego blocks for programmers. Many languages provide us with a variety of APIS, just like blocks of different shapes and colors. Industry standards constitute the contact between blocks, so that the blocks can be seamlessly connected. A single small building block is combined into a large module of any shape and function you want by means of contacts. modules and modules are combined to form a larger system. Both software building and playing blocks are mental-test intellectual activities. You can play blocks (designed by others) based on drawings ), you can also use blocks to assemble anything you want (design by yourself ). (PS. When I was a child, I used Lego's "Submarine" to construct the "Gloria" in interstellar I ".) That is to say, the language and platform are there. What you can do depends on what you think and what your team can achieve.
Software Building is a very complex task. It is not a one-person task, but a team activity. Below are the most common activities of software building:
- Definition problems
- Requirement Analysis
- Planning and Building
- Software Architecture
- Detailed Design
- Coding and debugging
- Unit Test
- Integration Test
- Integration
- System Test
- Assurance and Maintenance
The above activities are carried out repeatedly and alternately throughout the software build process. These activities are only technology-based product-oriented processes, but do not include corresponding management activities. For programmers, coding and debugging often take most of our time. Other activities are often "cropped" with the type and scale of the project ". It can be seen that the software construction process is very complicated because of its complexity. To ensure the success of software projects, people try to find a set of structured methods. So far, however, no way has been found to ensure 100% of the software project success. Although there is no such thing in software projects, we still get useful methods or guidelines to increase the chances of project success and reproduce this success, for example, the software engineering theory, the Project Management Guide (PMBOK) developed by PMI, and the related ideas of agile development.
There is no silver bullet in the second language, just as it is difficult to find the Holy Grail in the world"
If we regard the development language as a foreign language, our programmers will undoubtedly Master many "foreign languages", even if they are not able to translate foreign languages. Just like a foreign language, different languages have different characteristics and must create different camps and advocates. When you attack each other in different camps, are you still hesitant and have the impulse to switch? An industry expert said that good programmers should master three types of languages: 1. fast development language; 2. Eating language; 3. Favorite language. This is only three languages, not three. You can learn a language and say that it is excellent in these three aspects. (PS. At present, I think PHP has this sign .) There is also a saying that "too much learning, too much learning". Whether you want to have a deep understanding of a language or a wide understanding of multiple languages, you must realize that development languages do not have the so-called "Silver Bullet". Maybe some languages can stand alone, when no language is complete, it has advantages and disadvantages. Over time, the language of today's beautiful scenery may be eliminated tomorrow. If you love a language, you should not be easily moved by passers-by, rather than posting to others. Learning Language is a constant task. When you want to change the school, you may want to ask, is this language really good? Have you really understood your current language, is it really what you want? The true meaning of programming lies in the idea that language programming is the correct path.
Different experiences may have different language bases. I chose C # among many languages, and I don't think C # is suitable for everyone, however, I cannot give up on its many advantages. The following are my reasons for choosing C.
. NET platform is very powerfulThe. NET platform provides a wide range of class libraries covering almost all fields of applications. Almost all applications can be developed without using other languages. Of course, a large number of APIS also require continuous learning.
Powerful Development EnvironmentVisual Studio is the king of IDE. After it is used, it will be attracted by its powerful functions. In combination with Microsoft's TFS, Visual Studio will play a significant role in software project management.
Abundant ResourcesMicrosoft's msdn and Microsoft community also have a large number of reference books and a large user base, which creates a huge resource treasure. You are in such a huge group, knowledge Mining is faster and easier.
Easy to get startedC # itself is an object-oriented high-level language. Compared with low-level languages, the syntax and code are more readable and easy to accept. You can use books to learn and develop your own skills.
Fast development cycleC # Or. the net class library has already done a lot of work for us. Compared with other languages, you have less code, and your development system has a shorter cycle, both large and small projects will benefit from this rapid development. Of course, the short development cycle also benefits from the powerful functions of Visual Studio.
Seamless integration with various Microsoft productsYou can seamlessly integrate with other Microsoft products, such as SQL Server, office, Sharepoint, and OC.
Of course, C # also has some disadvantages:
Not cross-platformC # can only be used for development. net Program, although. net is designed as a platform independent, but it cannot run stably on Linux and other platforms. net Program, although there is an open-source mono, but its reliability needs to be tested. This will make you lose a lot of space to play, even if you can build the software that the customer needs, if the customer insists on using the Linux system, you can only give up. Maybe one day,. Net can be used on other platforms, but now let's play on Windows.
Few open source resourcesCompared to other languages, there are still a few open-source projects written in C #. Sometimes you can only write the framework by yourself.
To sum up, there is no silver bullet in the language. If you enjoy the convenience provided by C #, accept its shortcomings, and decide to study in depth, I hope the following article will help you.
Iii. NET platform structure
From the programmer's perspective,. Net can be understood as a Runtime Library environment (mscoree. dll) and a comprehensive base class library (mscorlib. dll ). As shown in:
(1) base class library
. NET Framework contains the framework class library (FCL), which is also known as bcl in some books. Microsoft is improving FCL at an astonishing speed, facilitating us to build Large-Scale Systems. If you want to fully understand FCL, I recommend the book C # advanced programming, which is now in the seventh edition. The book is famous for its number of pages and comprehensiveness, but its disadvantage is that its content is relatively basic and needs to be combined with other books for further study. FCL is very large and is constantly improving. It is best to learn a branch in a targeted manner to avoid decentralization.
(2) Public Language Runtime
Runtime can be understood as a set of external services required to execute a given compilation code unit. As shown in,. Net Runtime is called CLR (Common Language Runtime), which is a "RunTime" that can be used by multiple development languages ". CLR does not care about which development language to use, as long as the compiler of the corresponding development language is oriented to CLR. Microsoft has created several CLR-oriented languages, including C ++/CLI, C #, VB, F #, Python, Ruby, and its own compiler. Other organizations have developed development languages and compilers for "CLR. However, Microsoft's C # language is the most widely used language. Core CLR functions include memory management, assembly loading, security, exception handling, and thread synchronization. Generally, the code running under the control of CLR is called managed code. The source code compilation and execution process is as follows:
1. source code compilation
Step 1 of compilation-compile the source code into a managed Module(C ++ compiler is special. It can generate hosted and unmanaged code at the same time and generate it into the same module .)
Hosting moduleThe hosted module is a standard 32 (64)-bit windows portable carrier pe32 (pe32 +) file that requires CLR to execute. The composition of the hosting module is as follows:
MetadataMetadata is a set of data tables. Some data tables describe the content defined in the module, such as the class and its members. Some metadata describes the reference content of the managed code module, such as referenced classes and members. These metadata describes the types (classes, structures, enumerations, etc.) defined in each binary file, and Members (attributes, methods, events, and so on) of each type ). Visual
Studio and other development tools implement SMART awareness through metadata, and metadata has become the backbone of technologies such as WCF, Web Service, reflection, late binding, and Object serialization.
MsilMicrosoft intermediate language (msil) is a Microsoft intermediate language. It is also called a common intermediate language or IL for short. It is essentially the mother tongue of the. NET platform. Any language that supports. NET must support il in logic and be compiled into Il.
Il has the following features:
- Object-oriented and user interfaces
- The huge difference between the value type and the reference type
- Strong Data Types
- Handle errors with exceptions
- Features
Benefits of Il:
- Language integration-each language that supports. Net generates almost the same Il
- Platform independence
We do not need to directly use Il to write programs, but in.. net, using system. reflect. the namespace emit provides the types that can be generated in the memory during development. net assembly program, that is, "dynamic assembly ". Because proprietary il instruction sets are required when constructing an assembly, you need to master il if you want to use this function to develop software.
Step 2 of Compilation -- merge the managed module into an assembly
CLR does not work with the module. It only works with the Assembly. An assembly is a logical grouping of one or more modules/resource files. It is the minimum unit for reuse, security, and version control. Through the concept of Assembly, we can treat a group of files as a file. The process of merging managed modules into an assembly is as follows:
The Assembly contains enough information to make it descriptive. CLR can determine what is the direct dependency object of the assembly to execute code in the Assembly, without saving additional information in the registry or Active Directory domain services (ADDs. Therefore, an assembly is easier to deploy than an unmanaged component.
2 General type system and public language specifications
Public-type systems and public language specifications are the cornerstone of. Net's language interoperability. The true meaning of language interoperability is that classes written in one language should be able to communicate directly with classes written in another language, especially:
- Classes written in one language should inherit classes written in another language.
- A class should be able to contain instances of another class, regardless of the language in which they are written.
- An object should be able to directly call the method of another object written in other languages.
- Objects should be passed between methods.
- When calling methods between different languages, you should be able to debug these method calls in the debugger, that is, to debug the source code written in different languages.
2.1 cts
Type refers to any member in the set {class, interface, structure, enumeration, delegate. CLR is fully centered on types. Microsoft has developed a formal specification, that is, "Common Type System (CTS)", which describes the definition and behavior of types. CTS specifies that a type can contain zero or more members, and sets the type Visibility rules and access types of the type members, defines corresponding rules for type inheritance, virtual methods, and object lifetime. No matter which language we use, the class behavior is completely consistent, because CTS is used to define the class behavior.
CTS defines five types:
- Class type
- Interface Type
- Structure Type
- Enumeration type
- Delegate type
The preceding five types contain a large number of type members, namely the collection {constructor, destructor, static constructor, nested type, operator, method, attribute, indexer, field, and read-only field, constant, one of the elements in event.
CTS also defines a rich type hierarchy that contains well-designed locations where the Code allows you to define its own type. The CTS hierarchy is as follows:
In addition, CTS establishes a set of clearly defined core data types, taking string type as an example: string (VB. net), string (C #), string ^ (C ++/CLI) is finally interpreted as the CTS data type system. string.
2.2 CLS
Microsoft defines a common language specification (CLS) to apply to multiple languages. It describes in detail a minimum set of functions, any Type generated by the compiler must be compatible with components generated by other CLS-compliant and CLR-oriented languages. Since Il is a rich language, most compiler compilers may limit the functionality of a given compiler to only some of the features provided by IL and Cls. For CLs, the functions of each compiler do not have to be powerful enough. net. Second, CLS provides the following guarantees: If the restricted class can only use the CLS compatibility feature, it is necessary to ensure that the code written in other compatible languages can use this class. Writing non-CLS-compatible code is completely acceptable, but after writing this code, it cannot guarantee that the compiled il Code fully supports language interoperability. That is to say, when developing types and methods, if you want them to be "visible" to external users and be accessible from any CLS-compliant programming language, you must follow the rules defined by Cls. When defining a type in one language, if you want to use this type in another language, do not
Public and protected members use any function outside Cls. Otherwise, other languages may not be able to access members of this type. The following code defines a type that does not conform to CLS:
Using system; // check CLS compatibility [Assembly: clscompliant (true)] namespace clrtest {// because it is a public class, therefore, the verification compatibility public sealed class test {// The returned type does not conform to CLS public uint32 get () {return 0;} // It is only a case-insensitive identifier and does not conform to CLS Public String get () {return "0";} // The Private method may not comply with CLs, and the private uint32 get () {return 0 ;}} warning is not displayed ;}}}
The [Assembly: clscompliant (true)] feature is applied to an assembly and tells the compiler to check whether the public type complies with the CLS specification. The advantage of this method is that the limitations on CLS compatibility apply only to members and public classes of public and protected classes. In the private Implementation of classes, you can write non-CLS code, because the code in other assembly cannot access this part of code.
The basic rule of CLS is "each member of a type is either a field (data) or a method (behavior )." The compiler encounters enumeration, array, attribute, indexer, Delegate, event, constructor, destructor, operator overload, conversion operator, and other structures, it must be converted into fields and methods so that Clr and other languages can access these structures. (Note: For a complete list of CLR rules, see http://msdn.microsoft.com/zh-cn/library/a2c7tshk.aspx .)
3. Load CLR
The generated assembly can be either an executable application or a DLL. Theoretically, any IL-based assembly can run on any CPU, but in fact, the Assembly may not be portable (64-bit programs cannot run on 32-bit platforms ). If IL does not contain content related to a specific CPU architecture or machine language, the JIT compiler generates machine commands for the target CPU at runtime. To develop an assembly that requires a specific CPU architecture, we must tell vs the CPU information so that it can merge the information into the binary file. When running an executable file, Windows checks the header of the EXE file to determine whether the application is 32-bit or 64-bit (64-bit Windows provides wow64 technology, run 32-bit programs, but there is performance loss ). Windows also checks the CPU architecture information embedded in the header file to ensure that the current computer meets the requirements. After Windows check, the header of the EXE file is determined to create a 32-bit, 64-bit, or wow64 process, mscoree will be loaded in the address space of the process. DLL (the most important part of CLR, called the "public object Runtime library execution engine", contains a large number of core types that encapsulate a variety of common programming tasks and core data types) x86, x64, or IA64. Then the main thread of the process calls a method defined in mscoree. dll. This method initializes CLR, loads the EXE assembly, and then calls its entry method (main ). Then, the hosted application starts and runs.
4. Run the Assembly Code
4.1 Assembly Execution Process
As mentioned above, the Assembly contains metadata and Il. To execute a method, you must first convert the Il to the local CPU command. This is the responsibility of the clr jit (just-in-time) compiler (also called "jitter. It shows what happens when the method is called:
Before executing the main method, CLR will detect all types referenced by the main code. This causes the CLR to allocate an internal data structure, which is used to manage access to all referenced types. The main method references a console class, which causes the CLR to allocate an internal structure. In this internal structure, each method defined in the console class has a corresponding entry ). Each record item contains an address. Based on this address, you can find the implementation method. During the initialization of this structure, CLR sets each record item to an undocumented function (pointing to) included in the CLR, that is, jitcompiler (CLR
Name used in Via C ). When the main method calls writeline for the first time, the jitcompiler function is called. The jitcompiler function is responsible for compiling the Il code of a method to CPU commands at a cost. Depending on the running environment, the JIT compiler generates the appropriate x86, x64, or IA64 commands. Then, the jitcompiler function searches for the Il of the called method in the metadata of the defined (this type) assembly. Then, jitcompiler verifies the Il code and compiles the Il code into a local CPU command. The local CPU command is saved to a dynamically allocated memory block. Then, jitcompiler returns the internal data structure created by CLR for the type, finds the record corresponding to the call method, and modifies the original reference to jitcompiler, let him point to the Code in the memory block (the specific implementation of writeline (string ). When the code is executed and returned, it is returned to the Code in main and continues to be executed.
When running to console. writeline ("world");, main calls writeline (string) again ). In this case, because the writeline (string) code has been verified and compiled, the code in the memory block will be executed directly. After writeline ("world") is executed, return to main again.
Jitter 4.2
The JIT compiler does not compile the entire program once, but only the part of the code it calls. After the code is compiled once, the internal executable code is stored until the application is terminated and the compiled code is lost. Therefore, if you run the program again or start two instances of the Program (using two different processes), the JIT compiler will re-compile Il. A method will only cause some performance loss when it is called for the first time, and then all calls to this method will run at full speed in the form of local code. Since the last part of the compilation process is executed at runtime, the JIT compiler can precisely know what type of processor the program is running on, you can use any of the features provided by the processor or specific machine code commands to optimize the final executable code to improve performance.